aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-03-23 23:44:19 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-03-23 23:44:19 -0500
commit1ebbe2b20091d306453a5cf480a87e6cd28ae76f (patch)
treef5cd7a0fa69b8b1938cb5a0faed2e7b0628072a5 /net
parentac58c9059da8886b5e8cde012a80266b18ca146e (diff)
parent674a396c6d2ba0341ebdd7c1c9950f32f018e2dd (diff)
Merge branch 'linus'
Diffstat (limited to 'net')
-rw-r--r--net/802/psnap.c4
-rw-r--r--net/8021q/vlan.c43
-rw-r--r--net/8021q/vlan_dev.c6
-rw-r--r--net/atm/clip.c2
-rw-r--r--net/atm/common.c4
-rw-r--r--net/atm/ioctl.c15
-rw-r--r--net/atm/resources.c32
-rw-r--r--net/atm/resources.h3
-rw-r--r--net/bluetooth/bnep/core.c4
-rw-r--r--net/bluetooth/rfcomm/core.c8
-rw-r--r--net/bridge/Kconfig1
-rw-r--r--net/bridge/br.c12
-rw-r--r--net/bridge/br_device.c3
-rw-r--r--net/bridge/br_fdb.c6
-rw-r--r--net/bridge/br_if.c9
-rw-r--r--net/bridge/br_input.c43
-rw-r--r--net/bridge/br_netfilter.c225
-rw-r--r--net/bridge/br_private.h6
-rw-r--r--net/bridge/br_stp_bpdu.c196
-rw-r--r--net/bridge/br_stp_timer.c47
-rw-r--r--net/bridge/br_sysfs_br.c49
-rw-r--r--net/bridge/netfilter/ebtables.c101
-rw-r--r--net/compat.c114
-rw-r--r--net/core/dev.c32
-rw-r--r--net/core/flow.c7
-rw-r--r--net/core/link_watch.c44
-rw-r--r--net/core/neighbour.c12
-rw-r--r--net/core/net-sysfs.c41
-rw-r--r--net/core/netpoll.c6
-rw-r--r--net/core/pktgen.c2980
-rw-r--r--net/core/rtnetlink.c176
-rw-r--r--net/core/skbuff.c42
-rw-r--r--net/core/sock.c30
-rw-r--r--net/core/sysctl_net_core.c23
-rw-r--r--net/core/wireless.c911
-rw-r--r--net/dccp/Kconfig13
-rw-r--r--net/dccp/Makefile9
-rw-r--r--net/dccp/ackvec.c296
-rw-r--r--net/dccp/ackvec.h53
-rw-r--r--net/dccp/ccid.c189
-rw-r--r--net/dccp/ccid.h129
-rw-r--r--net/dccp/ccids/Kconfig43
-rw-r--r--net/dccp/ccids/Makefile4
-rw-r--r--net/dccp/ccids/ccid2.c779
-rw-r--r--net/dccp/ccids/ccid2.h85
-rw-r--r--net/dccp/ccids/ccid3.c112
-rw-r--r--net/dccp/ccids/ccid3.h5
-rw-r--r--net/dccp/dccp.h133
-rw-r--r--net/dccp/diag.c2
-rw-r--r--net/dccp/feat.c586
-rw-r--r--net/dccp/feat.h29
-rw-r--r--net/dccp/input.c28
-rw-r--r--net/dccp/ipv4.c333
-rw-r--r--net/dccp/ipv6.c371
-rw-r--r--net/dccp/minisocks.c37
-rw-r--r--net/dccp/options.c291
-rw-r--r--net/dccp/output.c88
-rw-r--r--net/dccp/proto.c440
-rw-r--r--net/dccp/sysctl.c124
-rw-r--r--net/dccp/timer.c14
-rw-r--r--net/decnet/af_decnet.c18
-rw-r--r--net/decnet/dn_dev.c34
-rw-r--r--net/decnet/dn_fib.c8
-rw-r--r--net/decnet/dn_neigh.c24
-rw-r--r--net/decnet/dn_nsp_in.c28
-rw-r--r--net/decnet/dn_nsp_out.c38
-rw-r--r--net/decnet/dn_route.c60
-rw-r--r--net/decnet/dn_rules.c115
-rw-r--r--net/decnet/dn_table.c12
-rw-r--r--net/decnet/sysctl_net_decnet.c12
-rw-r--r--net/ieee80211/Kconfig1
-rw-r--r--net/ieee80211/Makefile1
-rw-r--r--net/ieee80211/ieee80211_rx.c74
-rw-r--r--net/ieee80211/softmac/Kconfig10
-rw-r--r--net/ieee80211/softmac/Makefile9
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_assoc.c396
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_auth.c364
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_event.c159
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_io.c474
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_module.c457
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_priv.h230
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_scan.c244
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_wx.c412
-rw-r--r--net/ipv4/af_inet.c120
-rw-r--r--net/ipv4/ah4.c1
-rw-r--r--net/ipv4/arp.c20
-rw-r--r--net/ipv4/devinet.c8
-rw-r--r--net/ipv4/esp4.c1
-rw-r--r--net/ipv4/fib_rules.c140
-rw-r--r--net/ipv4/fib_trie.c24
-rw-r--r--net/ipv4/igmp.c26
-rw-r--r--net/ipv4/inet_connection_sock.c49
-rw-r--r--net/ipv4/ip_output.c6
-rw-r--r--net/ipv4/ip_sockglue.c170
-rw-r--r--net/ipv4/ipcomp.c17
-rw-r--r--net/ipv4/ipconfig.c10
-rw-r--r--net/ipv4/ipmr.c4
-rw-r--r--net/ipv4/ipvs/ip_vs_app.c19
-rw-r--r--net/ipv4/netfilter/Kconfig36
-rw-r--r--net/ipv4/netfilter/Makefile6
-rw-r--r--net/ipv4/netfilter/arp_tables.c27
-rw-r--r--net/ipv4/netfilter/arpt_mangle.c23
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c4
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323.c1731
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c870
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h98
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323_types.c1926
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323_types.h938
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netlink.c79
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_h323.c605
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_pptp.c8
-rw-r--r--net/ipv4/netfilter/ip_nat_rule.c45
-rw-r--r--net/ipv4/netfilter/ip_nat_snmp_basic.c5
-rw-r--r--net/ipv4/netfilter/ip_queue.c11
-rw-r--r--net/ipv4/netfilter/ip_tables.c84
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c27
-rw-r--r--net/ipv4/netfilter/ipt_DSCP.c17
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c18
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c11
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c18
-rw-r--r--net/ipv4/netfilter/ipt_NETMAP.c19
-rw-r--r--net/ipv4/netfilter/ipt_REDIRECT.c17
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c28
-rw-r--r--net/ipv4/netfilter/ipt_SAME.c19
-rw-r--r--net/ipv4/netfilter/ipt_TCPMSS.c16
-rw-r--r--net/ipv4/netfilter/ipt_TOS.c17
-rw-r--r--net/ipv4/netfilter/ipt_TTL.c25
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c12
-rw-r--r--net/ipv4/netfilter/ipt_addrtype.c20
-rw-r--r--net/ipv4/netfilter/ipt_ah.c25
-rw-r--r--net/ipv4/netfilter/ipt_dscp.c19
-rw-r--r--net/ipv4/netfilter/ipt_ecn.c14
-rw-r--r--net/ipv4/netfilter/ipt_esp.c25
-rw-r--r--net/ipv4/netfilter/ipt_hashlimit.c21
-rw-r--r--net/ipv4/netfilter/ipt_iprange.c28
-rw-r--r--net/ipv4/netfilter/ipt_multiport.c31
-rw-r--r--net/ipv4/netfilter/ipt_owner.c21
-rw-r--r--net/ipv4/netfilter/ipt_policy.c176
-rw-r--r--net/ipv4/netfilter/ipt_recent.c22
-rw-r--r--net/ipv4/netfilter/ipt_tos.c18
-rw-r--r--net/ipv4/netfilter/ipt_ttl.c19
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c23
-rw-r--r--net/ipv4/raw.c80
-rw-r--r--net/ipv4/sysctl_net_ipv4.c25
-rw-r--r--net/ipv4/tcp.c63
-rw-r--r--net/ipv4/tcp_htcp.c66
-rw-r--r--net/ipv4/tcp_input.c49
-rw-r--r--net/ipv4/tcp_ipv4.c44
-rw-r--r--net/ipv4/tcp_output.c259
-rw-r--r--net/ipv4/tcp_timer.c36
-rw-r--r--net/ipv4/udp.c83
-rw-r--r--net/ipv4/xfrm4_tunnel.c11
-rw-r--r--net/ipv6/Kconfig26
-rw-r--r--net/ipv6/addrconf.c346
-rw-r--r--net/ipv6/af_inet6.c120
-rw-r--r--net/ipv6/ah6.c5
-rw-r--r--net/ipv6/anycast.c7
-rw-r--r--net/ipv6/esp6.c5
-rw-r--r--net/ipv6/ip6_fib.c1
-rw-r--r--net/ipv6/ip6_flowlabel.c6
-rw-r--r--net/ipv6/ip6_output.c45
-rw-r--r--net/ipv6/ipcomp6.c22
-rw-r--r--net/ipv6/ipv6_sockglue.c163
-rw-r--r--net/ipv6/mcast.c17
-rw-r--r--net/ipv6/ndisc.c49
-rw-r--r--net/ipv6/netfilter/Kconfig10
-rw-r--r--net/ipv6/netfilter/Makefile1
-rw-r--r--net/ipv6/netfilter/ip6_queue.c11
-rw-r--r--net/ipv6/netfilter/ip6_tables.c102
-rw-r--r--net/ipv6/netfilter/ip6t_HL.c19
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c11
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c25
-rw-r--r--net/ipv6/netfilter/ip6t_ah.c12
-rw-r--r--net/ipv6/netfilter/ip6t_dst.c13
-rw-r--r--net/ipv6/netfilter/ip6t_esp.c12
-rw-r--r--net/ipv6/netfilter/ip6t_eui64.c27
-rw-r--r--net/ipv6/netfilter/ip6t_frag.c13
-rw-r--r--net/ipv6/netfilter/ip6t_hbh.c13
-rw-r--r--net/ipv6/netfilter/ip6t_hl.c22
-rw-r--r--net/ipv6/netfilter/ip6t_ipv6header.c8
-rw-r--r--net/ipv6/netfilter/ip6t_multiport.c11
-rw-r--r--net/ipv6/netfilter/ip6t_owner.c18
-rw-r--r--net/ipv6/netfilter/ip6t_policy.c176
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c12
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c40
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c8
-rw-r--r--net/ipv6/raw.c145
-rw-r--r--net/ipv6/reassembly.c35
-rw-r--r--net/ipv6/route.c680
-rw-r--r--net/ipv6/tcp_ipv6.c74
-rw-r--r--net/ipv6/udp.c84
-rw-r--r--net/ipv6/xfrm6_tunnel.c11
-rw-r--r--net/key/af_key.c6
-rw-r--r--net/llc/af_llc.c15
-rw-r--r--net/llc/llc_c_ac.c1
-rw-r--r--net/llc/llc_core.c1
-rw-r--r--net/llc/llc_output.c3
-rw-r--r--net/llc/llc_output.h20
-rw-r--r--net/llc/llc_s_ac.c2
-rw-r--r--net/netfilter/Kconfig16
-rw-r--r--net/netfilter/Makefile1
-rw-r--r--net/netfilter/nf_conntrack_core.c170
-rw-r--r--net/netfilter/nf_conntrack_ftp.c2
-rw-r--r--net/netfilter/nf_conntrack_netlink.c130
-rw-r--r--net/netfilter/nf_conntrack_standalone.c3
-rw-r--r--net/netfilter/nf_sockopt.c94
-rw-r--r--net/netfilter/nfnetlink.c6
-rw-r--r--net/netfilter/nfnetlink_log.c46
-rw-r--r--net/netfilter/nfnetlink_queue.c19
-rw-r--r--net/netfilter/x_tables.c88
-rw-r--r--net/netfilter/xt_CLASSIFY.c54
-rw-r--r--net/netfilter/xt_CONNMARK.c39
-rw-r--r--net/netfilter/xt_MARK.c58
-rw-r--r--net/netfilter/xt_NFQUEUE.c43
-rw-r--r--net/netfilter/xt_NOTRACK.c57
-rw-r--r--net/netfilter/xt_comment.c30
-rw-r--r--net/netfilter/xt_connbytes.c27
-rw-r--r--net/netfilter/xt_connmark.c57
-rw-r--r--net/netfilter/xt_conntrack.c41
-rw-r--r--net/netfilter/xt_dccp.c57
-rw-r--r--net/netfilter/xt_helper.c55
-rw-r--r--net/netfilter/xt_length.c36
-rw-r--r--net/netfilter/xt_limit.c19
-rw-r--r--net/netfilter/xt_mac.c46
-rw-r--r--net/netfilter/xt_mark.c28
-rw-r--r--net/netfilter/xt_physdev.c26
-rw-r--r--net/netfilter/xt_pkttype.c35
-rw-r--r--net/netfilter/xt_policy.c211
-rw-r--r--net/netfilter/xt_realm.c32
-rw-r--r--net/netfilter/xt_sctp.c78
-rw-r--r--net/netfilter/xt_state.c44
-rw-r--r--net/netfilter/xt_string.c22
-rw-r--r--net/netfilter/xt_tcpmss.c64
-rw-r--r--net/netfilter/xt_tcpudp.c138
-rw-r--r--net/netlink/af_netlink.c52
-rw-r--r--net/sched/Kconfig1
-rw-r--r--net/sched/act_ipt.c10
-rw-r--r--net/sched/cls_u32.c6
-rw-r--r--net/sched/sch_atm.c1
-rw-r--r--net/sched/sch_dsmark.c1
-rw-r--r--net/sched/sch_generic.c2
-rw-r--r--net/sched/sch_netem.c4
-rw-r--r--net/sched/sch_prio.c2
-rw-r--r--net/sched/sch_red.c179
-rw-r--r--net/sched/sch_sfq.c5
-rw-r--r--net/sched/sch_tbf.c9
-rw-r--r--net/sctp/ipv6.c92
-rw-r--r--net/sctp/protocol.c94
-rw-r--r--net/socket.c353
-rw-r--r--net/sunrpc/cache.c17
-rw-r--r--net/sunrpc/sched.c11
-rw-r--r--net/sunrpc/svcsock.c8
-rw-r--r--net/tipc/bcast.c58
-rw-r--r--net/tipc/bearer.c20
-rw-r--r--net/tipc/cluster.c22
-rw-r--r--net/tipc/cluster.h2
-rw-r--r--net/tipc/config.c4
-rw-r--r--net/tipc/dbg.c4
-rw-r--r--net/tipc/discover.c8
-rw-r--r--net/tipc/eth_media.c4
-rw-r--r--net/tipc/link.c89
-rw-r--r--net/tipc/name_distr.c6
-rw-r--r--net/tipc/name_table.c62
-rw-r--r--net/tipc/net.c7
-rw-r--r--net/tipc/node.c20
-rw-r--r--net/tipc/node.h2
-rw-r--r--net/tipc/node_subscr.c2
-rw-r--r--net/tipc/port.c57
-rw-r--r--net/tipc/ref.c8
-rw-r--r--net/tipc/ref.h4
-rw-r--r--net/tipc/socket.c28
-rw-r--r--net/tipc/subscr.c30
-rw-r--r--net/tipc/user_reg.c4
-rw-r--r--net/tipc/zone.c12
-rw-r--r--net/unix/af_unix.c32
-rw-r--r--net/unix/garbage.c7
-rw-r--r--net/x25/af_x25.c173
-rw-r--r--net/x25/x25_facilities.c82
-rw-r--r--net/x25/x25_in.c3
-rw-r--r--net/x25/x25_subr.c6
-rw-r--r--net/xfrm/xfrm_policy.c9
-rw-r--r--net/xfrm/xfrm_state.c108
-rw-r--r--net/xfrm/xfrm_user.c397
283 files changed, 21060 insertions, 6525 deletions
diff --git a/net/802/psnap.c b/net/802/psnap.c
index 34e42968b477..270b9d2cae65 100644
--- a/net/802/psnap.c
+++ b/net/802/psnap.c
@@ -59,10 +59,8 @@ static int snap_rcv(struct sk_buff *skb, struct net_device *dev,
59 proto = find_snap_client(skb->h.raw); 59 proto = find_snap_client(skb->h.raw);
60 if (proto) { 60 if (proto) {
61 /* Pass the frame on. */ 61 /* Pass the frame on. */
62 u8 *hdr = skb->data;
63 skb->h.raw += 5; 62 skb->h.raw += 5;
64 skb_pull(skb, 5); 63 skb_pull_rcsum(skb, 5);
65 skb_postpull_rcsum(skb, hdr, 5);
66 rc = proto->rcvfunc(skb, dev, &snap_packet_type, orig_dev); 64 rc = proto->rcvfunc(skb, dev, &snap_packet_type, orig_dev);
67 } else { 65 } else {
68 skb->sk = NULL; 66 skb->sk = NULL;
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index fa76220708ce..3948949a609a 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -69,7 +69,7 @@ static struct packet_type vlan_packet_type = {
69 69
70/* Bits of netdev state that are propagated from real device to virtual */ 70/* Bits of netdev state that are propagated from real device to virtual */
71#define VLAN_LINK_STATE_MASK \ 71#define VLAN_LINK_STATE_MASK \
72 ((1<<__LINK_STATE_PRESENT)|(1<<__LINK_STATE_NOCARRIER)) 72 ((1<<__LINK_STATE_PRESENT)|(1<<__LINK_STATE_NOCARRIER)|(1<<__LINK_STATE_DORMANT))
73 73
74/* End of global variables definitions. */ 74/* End of global variables definitions. */
75 75
@@ -344,6 +344,26 @@ static void vlan_setup(struct net_device *new_dev)
344 new_dev->do_ioctl = vlan_dev_ioctl; 344 new_dev->do_ioctl = vlan_dev_ioctl;
345} 345}
346 346
347static void vlan_transfer_operstate(const struct net_device *dev, struct net_device *vlandev)
348{
349 /* Have to respect userspace enforced dormant state
350 * of real device, also must allow supplicant running
351 * on VLAN device
352 */
353 if (dev->operstate == IF_OPER_DORMANT)
354 netif_dormant_on(vlandev);
355 else
356 netif_dormant_off(vlandev);
357
358 if (netif_carrier_ok(dev)) {
359 if (!netif_carrier_ok(vlandev))
360 netif_carrier_on(vlandev);
361 } else {
362 if (netif_carrier_ok(vlandev))
363 netif_carrier_off(vlandev);
364 }
365}
366
347/* Attach a VLAN device to a mac address (ie Ethernet Card). 367/* Attach a VLAN device to a mac address (ie Ethernet Card).
348 * Returns the device that was created, or NULL if there was 368 * Returns the device that was created, or NULL if there was
349 * an error of some kind. 369 * an error of some kind.
@@ -450,7 +470,7 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
450 new_dev->flags = real_dev->flags; 470 new_dev->flags = real_dev->flags;
451 new_dev->flags &= ~IFF_UP; 471 new_dev->flags &= ~IFF_UP;
452 472
453 new_dev->state = real_dev->state & VLAN_LINK_STATE_MASK; 473 new_dev->state = real_dev->state & ~(1<<__LINK_STATE_START);
454 474
455 /* need 4 bytes for extra VLAN header info, 475 /* need 4 bytes for extra VLAN header info,
456 * hope the underlying device can handle it. 476 * hope the underlying device can handle it.
@@ -498,6 +518,10 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
498 if (register_netdevice(new_dev)) 518 if (register_netdevice(new_dev))
499 goto out_free_newdev; 519 goto out_free_newdev;
500 520
521 new_dev->iflink = real_dev->ifindex;
522 vlan_transfer_operstate(real_dev, new_dev);
523 linkwatch_fire_event(new_dev); /* _MUST_ call rfc2863_policy() */
524
501 /* So, got the sucker initialized, now lets place 525 /* So, got the sucker initialized, now lets place
502 * it into our local structure. 526 * it into our local structure.
503 */ 527 */
@@ -573,25 +597,12 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
573 switch (event) { 597 switch (event) {
574 case NETDEV_CHANGE: 598 case NETDEV_CHANGE:
575 /* Propagate real device state to vlan devices */ 599 /* Propagate real device state to vlan devices */
576 flgs = dev->state & VLAN_LINK_STATE_MASK;
577 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { 600 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
578 vlandev = grp->vlan_devices[i]; 601 vlandev = grp->vlan_devices[i];
579 if (!vlandev) 602 if (!vlandev)
580 continue; 603 continue;
581 604
582 if (netif_carrier_ok(dev)) { 605 vlan_transfer_operstate(dev, vlandev);
583 if (!netif_carrier_ok(vlandev))
584 netif_carrier_on(vlandev);
585 } else {
586 if (netif_carrier_ok(vlandev))
587 netif_carrier_off(vlandev);
588 }
589
590 if ((vlandev->state & VLAN_LINK_STATE_MASK) != flgs) {
591 vlandev->state = (vlandev->state &~ VLAN_LINK_STATE_MASK)
592 | flgs;
593 netdev_state_change(vlandev);
594 }
595 } 606 }
596 break; 607 break;
597 608
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 0f604d227da2..da9cfe927158 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -163,10 +163,8 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
163 stats->rx_packets++; 163 stats->rx_packets++;
164 stats->rx_bytes += skb->len; 164 stats->rx_bytes += skb->len;
165 165
166 skb_pull(skb, VLAN_HLEN); /* take off the VLAN header (4 bytes currently) */ 166 /* Take off the VLAN header (4 bytes currently) */
167 167 skb_pull_rcsum(skb, VLAN_HLEN);
168 /* Need to correct hardware checksum */
169 skb_postpull_rcsum(skb, vhdr, VLAN_HLEN);
170 168
171 /* Ok, lets check to make sure the device (dev) we 169 /* Ok, lets check to make sure the device (dev) we
172 * came in on is what this VLAN is attached to. 170 * came in on is what this VLAN is attached to.
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 73370de97539..3ab4e7947bab 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -289,7 +289,6 @@ static void clip_neigh_error(struct neighbour *neigh,struct sk_buff *skb)
289 289
290static struct neigh_ops clip_neigh_ops = { 290static struct neigh_ops clip_neigh_ops = {
291 .family = AF_INET, 291 .family = AF_INET,
292 .destructor = clip_neigh_destroy,
293 .solicit = clip_neigh_solicit, 292 .solicit = clip_neigh_solicit,
294 .error_report = clip_neigh_error, 293 .error_report = clip_neigh_error,
295 .output = dev_queue_xmit, 294 .output = dev_queue_xmit,
@@ -347,6 +346,7 @@ static struct neigh_table clip_tbl = {
347 /* parameters are copied from ARP ... */ 346 /* parameters are copied from ARP ... */
348 .parms = { 347 .parms = {
349 .tbl = &clip_tbl, 348 .tbl = &clip_tbl,
349 .neigh_destructor = clip_neigh_destroy,
350 .base_reachable_time = 30 * HZ, 350 .base_reachable_time = 30 * HZ,
351 .retrans_time = 1 * HZ, 351 .retrans_time = 1 * HZ,
352 .gc_staletime = 60 * HZ, 352 .gc_staletime = 60 * HZ,
diff --git a/net/atm/common.c b/net/atm/common.c
index 6656b111cc05..ae002220fa99 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -451,12 +451,12 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci)
451 dev = try_then_request_module(atm_dev_lookup(itf), "atm-device-%d", itf); 451 dev = try_then_request_module(atm_dev_lookup(itf), "atm-device-%d", itf);
452 } else { 452 } else {
453 dev = NULL; 453 dev = NULL;
454 down(&atm_dev_mutex); 454 mutex_lock(&atm_dev_mutex);
455 if (!list_empty(&atm_devs)) { 455 if (!list_empty(&atm_devs)) {
456 dev = list_entry(atm_devs.next, struct atm_dev, dev_list); 456 dev = list_entry(atm_devs.next, struct atm_dev, dev_list);
457 atm_dev_hold(dev); 457 atm_dev_hold(dev);
458 } 458 }
459 up(&atm_dev_mutex); 459 mutex_unlock(&atm_dev_mutex);
460 } 460 }
461 if (!dev) 461 if (!dev)
462 return -ENODEV; 462 return -ENODEV;
diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c
index eb109af7eb4a..851cfa6312af 100644
--- a/net/atm/ioctl.c
+++ b/net/atm/ioctl.c
@@ -18,6 +18,7 @@
18#include <linux/atmmpc.h> 18#include <linux/atmmpc.h>
19#include <net/atmclip.h> 19#include <net/atmclip.h>
20#include <linux/atmlec.h> 20#include <linux/atmlec.h>
21#include <linux/mutex.h>
21#include <asm/ioctls.h> 22#include <asm/ioctls.h>
22 23
23#include "resources.h" 24#include "resources.h"
@@ -25,22 +26,22 @@
25#include "common.h" 26#include "common.h"
26 27
27 28
28static DECLARE_MUTEX(ioctl_mutex); 29static DEFINE_MUTEX(ioctl_mutex);
29static LIST_HEAD(ioctl_list); 30static LIST_HEAD(ioctl_list);
30 31
31 32
32void register_atm_ioctl(struct atm_ioctl *ioctl) 33void register_atm_ioctl(struct atm_ioctl *ioctl)
33{ 34{
34 down(&ioctl_mutex); 35 mutex_lock(&ioctl_mutex);
35 list_add_tail(&ioctl->list, &ioctl_list); 36 list_add_tail(&ioctl->list, &ioctl_list);
36 up(&ioctl_mutex); 37 mutex_unlock(&ioctl_mutex);
37} 38}
38 39
39void deregister_atm_ioctl(struct atm_ioctl *ioctl) 40void deregister_atm_ioctl(struct atm_ioctl *ioctl)
40{ 41{
41 down(&ioctl_mutex); 42 mutex_lock(&ioctl_mutex);
42 list_del(&ioctl->list); 43 list_del(&ioctl->list);
43 up(&ioctl_mutex); 44 mutex_unlock(&ioctl_mutex);
44} 45}
45 46
46EXPORT_SYMBOL(register_atm_ioctl); 47EXPORT_SYMBOL(register_atm_ioctl);
@@ -137,7 +138,7 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
137 138
138 error = -ENOIOCTLCMD; 139 error = -ENOIOCTLCMD;
139 140
140 down(&ioctl_mutex); 141 mutex_lock(&ioctl_mutex);
141 list_for_each(pos, &ioctl_list) { 142 list_for_each(pos, &ioctl_list) {
142 struct atm_ioctl * ic = list_entry(pos, struct atm_ioctl, list); 143 struct atm_ioctl * ic = list_entry(pos, struct atm_ioctl, list);
143 if (try_module_get(ic->owner)) { 144 if (try_module_get(ic->owner)) {
@@ -147,7 +148,7 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
147 break; 148 break;
148 } 149 }
149 } 150 }
150 up(&ioctl_mutex); 151 mutex_unlock(&ioctl_mutex);
151 152
152 if (error != -ENOIOCTLCMD) 153 if (error != -ENOIOCTLCMD)
153 goto done; 154 goto done;
diff --git a/net/atm/resources.c b/net/atm/resources.c
index 224190537c90..18ac80698f83 100644
--- a/net/atm/resources.c
+++ b/net/atm/resources.c
@@ -18,6 +18,8 @@
18#include <linux/bitops.h> 18#include <linux/bitops.h>
19#include <linux/capability.h> 19#include <linux/capability.h>
20#include <linux/delay.h> 20#include <linux/delay.h>
21#include <linux/mutex.h>
22
21#include <net/sock.h> /* for struct sock */ 23#include <net/sock.h> /* for struct sock */
22 24
23#include "common.h" 25#include "common.h"
@@ -26,7 +28,7 @@
26 28
27 29
28LIST_HEAD(atm_devs); 30LIST_HEAD(atm_devs);
29DECLARE_MUTEX(atm_dev_mutex); 31DEFINE_MUTEX(atm_dev_mutex);
30 32
31static struct atm_dev *__alloc_atm_dev(const char *type) 33static struct atm_dev *__alloc_atm_dev(const char *type)
32{ 34{
@@ -65,9 +67,9 @@ struct atm_dev *atm_dev_lookup(int number)
65{ 67{
66 struct atm_dev *dev; 68 struct atm_dev *dev;
67 69
68 down(&atm_dev_mutex); 70 mutex_lock(&atm_dev_mutex);
69 dev = __atm_dev_lookup(number); 71 dev = __atm_dev_lookup(number);
70 up(&atm_dev_mutex); 72 mutex_unlock(&atm_dev_mutex);
71 return dev; 73 return dev;
72} 74}
73 75
@@ -83,11 +85,11 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
83 type); 85 type);
84 return NULL; 86 return NULL;
85 } 87 }
86 down(&atm_dev_mutex); 88 mutex_lock(&atm_dev_mutex);
87 if (number != -1) { 89 if (number != -1) {
88 if ((inuse = __atm_dev_lookup(number))) { 90 if ((inuse = __atm_dev_lookup(number))) {
89 atm_dev_put(inuse); 91 atm_dev_put(inuse);
90 up(&atm_dev_mutex); 92 mutex_unlock(&atm_dev_mutex);
91 kfree(dev); 93 kfree(dev);
92 return NULL; 94 return NULL;
93 } 95 }
@@ -112,12 +114,12 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
112 printk(KERN_ERR "atm_dev_register: " 114 printk(KERN_ERR "atm_dev_register: "
113 "atm_proc_dev_register failed for dev %s\n", 115 "atm_proc_dev_register failed for dev %s\n",
114 type); 116 type);
115 up(&atm_dev_mutex); 117 mutex_unlock(&atm_dev_mutex);
116 kfree(dev); 118 kfree(dev);
117 return NULL; 119 return NULL;
118 } 120 }
119 list_add_tail(&dev->dev_list, &atm_devs); 121 list_add_tail(&dev->dev_list, &atm_devs);
120 up(&atm_dev_mutex); 122 mutex_unlock(&atm_dev_mutex);
121 123
122 return dev; 124 return dev;
123} 125}
@@ -133,9 +135,9 @@ void atm_dev_deregister(struct atm_dev *dev)
133 * with same number can appear, such we need deregister proc, 135 * with same number can appear, such we need deregister proc,
134 * release async all vccs and remove them from vccs list too 136 * release async all vccs and remove them from vccs list too
135 */ 137 */
136 down(&atm_dev_mutex); 138 mutex_lock(&atm_dev_mutex);
137 list_del(&dev->dev_list); 139 list_del(&dev->dev_list);
138 up(&atm_dev_mutex); 140 mutex_unlock(&atm_dev_mutex);
139 141
140 atm_dev_release_vccs(dev); 142 atm_dev_release_vccs(dev);
141 atm_proc_dev_deregister(dev); 143 atm_proc_dev_deregister(dev);
@@ -196,16 +198,16 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
196 return -EFAULT; 198 return -EFAULT;
197 if (get_user(len, &iobuf->length)) 199 if (get_user(len, &iobuf->length))
198 return -EFAULT; 200 return -EFAULT;
199 down(&atm_dev_mutex); 201 mutex_lock(&atm_dev_mutex);
200 list_for_each(p, &atm_devs) 202 list_for_each(p, &atm_devs)
201 size += sizeof(int); 203 size += sizeof(int);
202 if (size > len) { 204 if (size > len) {
203 up(&atm_dev_mutex); 205 mutex_unlock(&atm_dev_mutex);
204 return -E2BIG; 206 return -E2BIG;
205 } 207 }
206 tmp_buf = kmalloc(size, GFP_ATOMIC); 208 tmp_buf = kmalloc(size, GFP_ATOMIC);
207 if (!tmp_buf) { 209 if (!tmp_buf) {
208 up(&atm_dev_mutex); 210 mutex_unlock(&atm_dev_mutex);
209 return -ENOMEM; 211 return -ENOMEM;
210 } 212 }
211 tmp_p = tmp_buf; 213 tmp_p = tmp_buf;
@@ -213,7 +215,7 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
213 dev = list_entry(p, struct atm_dev, dev_list); 215 dev = list_entry(p, struct atm_dev, dev_list);
214 *tmp_p++ = dev->number; 216 *tmp_p++ = dev->number;
215 } 217 }
216 up(&atm_dev_mutex); 218 mutex_unlock(&atm_dev_mutex);
217 error = ((copy_to_user(buf, tmp_buf, size)) || 219 error = ((copy_to_user(buf, tmp_buf, size)) ||
218 put_user(size, &iobuf->length)) 220 put_user(size, &iobuf->length))
219 ? -EFAULT : 0; 221 ? -EFAULT : 0;
@@ -400,13 +402,13 @@ static __inline__ void *dev_get_idx(loff_t left)
400 402
401void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos) 403void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos)
402{ 404{
403 down(&atm_dev_mutex); 405 mutex_lock(&atm_dev_mutex);
404 return *pos ? dev_get_idx(*pos) : (void *) 1; 406 return *pos ? dev_get_idx(*pos) : (void *) 1;
405} 407}
406 408
407void atm_dev_seq_stop(struct seq_file *seq, void *v) 409void atm_dev_seq_stop(struct seq_file *seq, void *v)
408{ 410{
409 up(&atm_dev_mutex); 411 mutex_unlock(&atm_dev_mutex);
410} 412}
411 413
412void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) 414void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
diff --git a/net/atm/resources.h b/net/atm/resources.h
index b7fb82a93b42..ac7222fee7a8 100644
--- a/net/atm/resources.h
+++ b/net/atm/resources.h
@@ -8,10 +8,11 @@
8 8
9#include <linux/config.h> 9#include <linux/config.h>
10#include <linux/atmdev.h> 10#include <linux/atmdev.h>
11#include <linux/mutex.h>
11 12
12 13
13extern struct list_head atm_devs; 14extern struct list_head atm_devs;
14extern struct semaphore atm_dev_mutex; 15extern struct mutex atm_dev_mutex;
15 16
16int atm_dev_ioctl(unsigned int cmd, void __user *arg); 17int atm_dev_ioctl(unsigned int cmd, void __user *arg);
17 18
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index cbb20c32a6c8..d908d49dc9f8 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -532,8 +532,8 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
532 dev = alloc_netdev(sizeof(struct bnep_session), 532 dev = alloc_netdev(sizeof(struct bnep_session),
533 (*req->device) ? req->device : "bnep%d", 533 (*req->device) ? req->device : "bnep%d",
534 bnep_net_setup); 534 bnep_net_setup);
535 if (!dev) 535 if (!dev)
536 return ENOMEM; 536 return -ENOMEM;
537 537
538 538
539 down_write(&bnep_session_sem); 539 down_write(&bnep_session_sem);
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 5b4253c61f62..e99010ce8bb2 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -37,6 +37,8 @@
37#include <linux/wait.h> 37#include <linux/wait.h>
38#include <linux/device.h> 38#include <linux/device.h>
39#include <linux/net.h> 39#include <linux/net.h>
40#include <linux/mutex.h>
41
40#include <net/sock.h> 42#include <net/sock.h>
41#include <asm/uaccess.h> 43#include <asm/uaccess.h>
42#include <asm/unaligned.h> 44#include <asm/unaligned.h>
@@ -57,9 +59,9 @@ static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU;
57 59
58static struct task_struct *rfcomm_thread; 60static struct task_struct *rfcomm_thread;
59 61
60static DECLARE_MUTEX(rfcomm_sem); 62static DEFINE_MUTEX(rfcomm_mutex);
61#define rfcomm_lock() down(&rfcomm_sem); 63#define rfcomm_lock() mutex_lock(&rfcomm_mutex)
62#define rfcomm_unlock() up(&rfcomm_sem); 64#define rfcomm_unlock() mutex_unlock(&rfcomm_mutex)
63 65
64static unsigned long rfcomm_event; 66static unsigned long rfcomm_event;
65 67
diff --git a/net/bridge/Kconfig b/net/bridge/Kconfig
index db23d59746cf..12265aff7099 100644
--- a/net/bridge/Kconfig
+++ b/net/bridge/Kconfig
@@ -4,6 +4,7 @@
4 4
5config BRIDGE 5config BRIDGE
6 tristate "802.1d Ethernet Bridging" 6 tristate "802.1d Ethernet Bridging"
7 select LLC
7 ---help--- 8 ---help---
8 If you say Y here, then your Linux box will be able to act as an 9 If you say Y here, then your Linux box will be able to act as an
9 Ethernet bridge, which means that the different Ethernet segments it 10 Ethernet bridge, which means that the different Ethernet segments it
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 188cc1ac49eb..22d806cf40ca 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -19,13 +19,23 @@
19#include <linux/netdevice.h> 19#include <linux/netdevice.h>
20#include <linux/etherdevice.h> 20#include <linux/etherdevice.h>
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/llc.h>
23#include <net/llc.h>
22 24
23#include "br_private.h" 25#include "br_private.h"
24 26
25int (*br_should_route_hook) (struct sk_buff **pskb) = NULL; 27int (*br_should_route_hook) (struct sk_buff **pskb) = NULL;
26 28
29static struct llc_sap *br_stp_sap;
30
27static int __init br_init(void) 31static int __init br_init(void)
28{ 32{
33 br_stp_sap = llc_sap_open(LLC_SAP_BSPAN, br_stp_rcv);
34 if (!br_stp_sap) {
35 printk(KERN_ERR "bridge: can't register sap for STP\n");
36 return -EBUSY;
37 }
38
29 br_fdb_init(); 39 br_fdb_init();
30 40
31#ifdef CONFIG_BRIDGE_NETFILTER 41#ifdef CONFIG_BRIDGE_NETFILTER
@@ -45,6 +55,8 @@ static int __init br_init(void)
45 55
46static void __exit br_deinit(void) 56static void __exit br_deinit(void)
47{ 57{
58 llc_sap_close(br_stp_sap);
59
48#ifdef CONFIG_BRIDGE_NETFILTER 60#ifdef CONFIG_BRIDGE_NETFILTER
49 br_netfilter_fini(); 61 br_netfilter_fini();
50#endif 62#endif
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 0b33a7b3a00c..0c88a2ac32c1 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -27,6 +27,7 @@ static struct net_device_stats *br_dev_get_stats(struct net_device *dev)
27 return &br->statistics; 27 return &br->statistics;
28} 28}
29 29
30/* net device transmit always called with no BH (preempt_disabled) */
30int br_dev_xmit(struct sk_buff *skb, struct net_device *dev) 31int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
31{ 32{
32 struct net_bridge *br = netdev_priv(dev); 33 struct net_bridge *br = netdev_priv(dev);
@@ -39,7 +40,6 @@ int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
39 skb->mac.raw = skb->data; 40 skb->mac.raw = skb->data;
40 skb_pull(skb, ETH_HLEN); 41 skb_pull(skb, ETH_HLEN);
41 42
42 rcu_read_lock();
43 if (dest[0] & 1) 43 if (dest[0] & 1)
44 br_flood_deliver(br, skb, 0); 44 br_flood_deliver(br, skb, 0);
45 else if ((dst = __br_fdb_get(br, dest)) != NULL) 45 else if ((dst = __br_fdb_get(br, dest)) != NULL)
@@ -47,7 +47,6 @@ int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
47 else 47 else
48 br_flood_deliver(br, skb, 0); 48 br_flood_deliver(br, skb, 0);
49 49
50 rcu_read_unlock();
51 return 0; 50 return 0;
52} 51}
53 52
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 1f08a59b51ea..3a73b8c94271 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -341,7 +341,6 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
341 if (hold_time(br) == 0) 341 if (hold_time(br) == 0)
342 return; 342 return;
343 343
344 rcu_read_lock();
345 fdb = fdb_find(head, addr); 344 fdb = fdb_find(head, addr);
346 if (likely(fdb)) { 345 if (likely(fdb)) {
347 /* attempt to update an entry for a local interface */ 346 /* attempt to update an entry for a local interface */
@@ -356,13 +355,12 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
356 fdb->ageing_timer = jiffies; 355 fdb->ageing_timer = jiffies;
357 } 356 }
358 } else { 357 } else {
359 spin_lock_bh(&br->hash_lock); 358 spin_lock(&br->hash_lock);
360 if (!fdb_find(head, addr)) 359 if (!fdb_find(head, addr))
361 fdb_create(head, source, addr, 0); 360 fdb_create(head, source, addr, 0);
362 /* else we lose race and someone else inserts 361 /* else we lose race and someone else inserts
363 * it first, don't bother updating 362 * it first, don't bother updating
364 */ 363 */
365 spin_unlock_bh(&br->hash_lock); 364 spin_unlock(&br->hash_lock);
366 } 365 }
367 rcu_read_unlock();
368} 366}
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index f36b35edd60c..59eef42d4a42 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -210,7 +210,8 @@ static struct net_device *new_bridge_dev(const char *name)
210 210
211 br->bridge_id.prio[0] = 0x80; 211 br->bridge_id.prio[0] = 0x80;
212 br->bridge_id.prio[1] = 0x00; 212 br->bridge_id.prio[1] = 0x00;
213 memset(br->bridge_id.addr, 0, ETH_ALEN); 213
214 memcpy(br->group_addr, br_group_address, ETH_ALEN);
214 215
215 br->feature_mask = dev->features; 216 br->feature_mask = dev->features;
216 br->stp_enabled = 0; 217 br->stp_enabled = 0;
@@ -237,12 +238,11 @@ static int find_portno(struct net_bridge *br)
237 struct net_bridge_port *p; 238 struct net_bridge_port *p;
238 unsigned long *inuse; 239 unsigned long *inuse;
239 240
240 inuse = kmalloc(BITS_TO_LONGS(BR_MAX_PORTS)*sizeof(unsigned long), 241 inuse = kcalloc(BITS_TO_LONGS(BR_MAX_PORTS), sizeof(unsigned long),
241 GFP_KERNEL); 242 GFP_KERNEL);
242 if (!inuse) 243 if (!inuse)
243 return -ENOMEM; 244 return -ENOMEM;
244 245
245 memset(inuse, 0, BITS_TO_LONGS(BR_MAX_PORTS)*sizeof(unsigned long));
246 set_bit(0, inuse); /* zero is reserved */ 246 set_bit(0, inuse); /* zero is reserved */
247 list_for_each_entry(p, &br->port_list, list) { 247 list_for_each_entry(p, &br->port_list, list) {
248 set_bit(p->port_no, inuse); 248 set_bit(p->port_no, inuse);
@@ -264,11 +264,10 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
264 if (index < 0) 264 if (index < 0)
265 return ERR_PTR(index); 265 return ERR_PTR(index);
266 266
267 p = kmalloc(sizeof(*p), GFP_KERNEL); 267 p = kzalloc(sizeof(*p), GFP_KERNEL);
268 if (p == NULL) 268 if (p == NULL)
269 return ERR_PTR(-ENOMEM); 269 return ERR_PTR(-ENOMEM);
270 270
271 memset(p, 0, sizeof(*p));
272 p->br = br; 271 p->br = br;
273 dev_hold(dev); 272 dev_hold(dev);
274 p->dev = dev; 273 p->dev = dev;
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 4eef83755315..b7766562d72c 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -19,13 +19,8 @@
19#include <linux/netfilter_bridge.h> 19#include <linux/netfilter_bridge.h>
20#include "br_private.h" 20#include "br_private.h"
21 21
22const unsigned char bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; 22/* Bridge group multicast address 802.1d (pg 51). */
23 23const u8 br_group_address[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
24static int br_pass_frame_up_finish(struct sk_buff *skb)
25{
26 netif_receive_skb(skb);
27 return 0;
28}
29 24
30static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) 25static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
31{ 26{
@@ -38,7 +33,7 @@ static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
38 skb->dev = br->dev; 33 skb->dev = br->dev;
39 34
40 NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, 35 NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL,
41 br_pass_frame_up_finish); 36 netif_receive_skb);
42} 37}
43 38
44/* note: already called with rcu_read_lock (preempt_disabled) */ 39/* note: already called with rcu_read_lock (preempt_disabled) */
@@ -100,6 +95,25 @@ drop:
100 goto out; 95 goto out;
101} 96}
102 97
98/* note: already called with rcu_read_lock (preempt_disabled) */
99static int br_handle_local_finish(struct sk_buff *skb)
100{
101 struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
102
103 if (p && p->state != BR_STATE_DISABLED)
104 br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
105
106 return 0; /* process further */
107}
108
109/* Does address match the link local multicast address.
110 * 01:80:c2:00:00:0X
111 */
112static inline int is_link_local(const unsigned char *dest)
113{
114 return memcmp(dest, br_group_address, 5) == 0 && (dest[5] & 0xf0) == 0;
115}
116
103/* 117/*
104 * Called via br_handle_frame_hook. 118 * Called via br_handle_frame_hook.
105 * Return 0 if *pskb should be processed furthur 119 * Return 0 if *pskb should be processed furthur
@@ -117,15 +131,10 @@ int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
117 if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) 131 if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
118 goto err; 132 goto err;
119 133
120 if (p->br->stp_enabled && 134 if (unlikely(is_link_local(dest))) {
121 !memcmp(dest, bridge_ula, 5) && 135 skb->pkt_type = PACKET_HOST;
122 !(dest[5] & 0xF0)) { 136 return NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
123 if (!dest[5]) { 137 NULL, br_handle_local_finish) != 0;
124 NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
125 NULL, br_stp_handle_bpdu);
126 return 1;
127 }
128 goto err;
129 } 138 }
130 139
131 if (p->state == BR_STATE_FORWARDING || p->state == BR_STATE_LEARNING) { 140 if (p->state == BR_STATE_FORWARDING || p->state == BR_STATE_LEARNING) {
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index e060aad8624d..f29450b788be 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -61,15 +61,25 @@ static int brnf_filter_vlan_tagged = 1;
61#define brnf_filter_vlan_tagged 1 61#define brnf_filter_vlan_tagged 1
62#endif 62#endif
63 63
64#define IS_VLAN_IP (skb->protocol == __constant_htons(ETH_P_8021Q) && \ 64static __be16 inline vlan_proto(const struct sk_buff *skb)
65 hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP) && \ 65{
66 brnf_filter_vlan_tagged) 66 return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
67#define IS_VLAN_IPV6 (skb->protocol == __constant_htons(ETH_P_8021Q) && \ 67}
68 hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IPV6) && \ 68
69 brnf_filter_vlan_tagged) 69#define IS_VLAN_IP(skb) \
70#define IS_VLAN_ARP (skb->protocol == __constant_htons(ETH_P_8021Q) && \ 70 (skb->protocol == htons(ETH_P_8021Q) && \
71 hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_ARP) && \ 71 vlan_proto(skb) == htons(ETH_P_IP) && \
72 brnf_filter_vlan_tagged) 72 brnf_filter_vlan_tagged)
73
74#define IS_VLAN_IPV6(skb) \
75 (skb->protocol == htons(ETH_P_8021Q) && \
76 vlan_proto(skb) == htons(ETH_P_IPV6) &&\
77 brnf_filter_vlan_tagged)
78
79#define IS_VLAN_ARP(skb) \
80 (skb->protocol == htons(ETH_P_8021Q) && \
81 vlan_proto(skb) == htons(ETH_P_ARP) && \
82 brnf_filter_vlan_tagged)
73 83
74/* We need these fake structures to make netfilter happy -- 84/* We need these fake structures to make netfilter happy --
75 * lots of places assume that skb->dst != NULL, which isn't 85 * lots of places assume that skb->dst != NULL, which isn't
@@ -103,6 +113,25 @@ static inline struct net_device *bridge_parent(const struct net_device *dev)
103 return port ? port->br->dev : NULL; 113 return port ? port->br->dev : NULL;
104} 114}
105 115
116static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb)
117{
118 skb->nf_bridge = kzalloc(sizeof(struct nf_bridge_info), GFP_ATOMIC);
119 if (likely(skb->nf_bridge))
120 atomic_set(&(skb->nf_bridge->use), 1);
121
122 return skb->nf_bridge;
123}
124
125static inline void nf_bridge_save_header(struct sk_buff *skb)
126{
127 int header_size = 16;
128
129 if (skb->protocol == htons(ETH_P_8021Q))
130 header_size = 18;
131
132 memcpy(skb->nf_bridge->data, skb->data - header_size, header_size);
133}
134
106/* PF_BRIDGE/PRE_ROUTING *********************************************/ 135/* PF_BRIDGE/PRE_ROUTING *********************************************/
107/* Undo the changes made for ip6tables PREROUTING and continue the 136/* Undo the changes made for ip6tables PREROUTING and continue the
108 * bridge PRE_ROUTING hook. */ 137 * bridge PRE_ROUTING hook. */
@@ -120,7 +149,7 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb)
120 dst_hold(skb->dst); 149 dst_hold(skb->dst);
121 150
122 skb->dev = nf_bridge->physindev; 151 skb->dev = nf_bridge->physindev;
123 if (skb->protocol == __constant_htons(ETH_P_8021Q)) { 152 if (skb->protocol == htons(ETH_P_8021Q)) {
124 skb_push(skb, VLAN_HLEN); 153 skb_push(skb, VLAN_HLEN);
125 skb->nh.raw -= VLAN_HLEN; 154 skb->nh.raw -= VLAN_HLEN;
126 } 155 }
@@ -136,7 +165,7 @@ static void __br_dnat_complain(void)
136 165
137 if (jiffies - last_complaint >= 5 * HZ) { 166 if (jiffies - last_complaint >= 5 * HZ) {
138 printk(KERN_WARNING "Performing cross-bridge DNAT requires IP " 167 printk(KERN_WARNING "Performing cross-bridge DNAT requires IP "
139 "forwarding to be enabled\n"); 168 "forwarding to be enabled\n");
140 last_complaint = jiffies; 169 last_complaint = jiffies;
141 } 170 }
142} 171}
@@ -196,7 +225,7 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
196 if (!skb->dev) 225 if (!skb->dev)
197 kfree_skb(skb); 226 kfree_skb(skb);
198 else { 227 else {
199 if (skb->protocol == __constant_htons(ETH_P_8021Q)) { 228 if (skb->protocol == htons(ETH_P_8021Q)) {
200 skb_pull(skb, VLAN_HLEN); 229 skb_pull(skb, VLAN_HLEN);
201 skb->nh.raw += VLAN_HLEN; 230 skb->nh.raw += VLAN_HLEN;
202 } 231 }
@@ -218,12 +247,17 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
218 nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; 247 nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
219 248
220 if (dnat_took_place(skb)) { 249 if (dnat_took_place(skb)) {
221 if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, 250 if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev)) {
222 dev)) {
223 struct rtable *rt; 251 struct rtable *rt;
224 struct flowi fl = { .nl_u = 252 struct flowi fl = {
225 { .ip4_u = { .daddr = iph->daddr, .saddr = 0 , 253 .nl_u = {
226 .tos = RT_TOS(iph->tos)} }, .proto = 0}; 254 .ip4_u = {
255 .daddr = iph->daddr,
256 .saddr = 0,
257 .tos = RT_TOS(iph->tos) },
258 },
259 .proto = 0,
260 };
227 261
228 if (!ip_route_output_key(&rt, &fl)) { 262 if (!ip_route_output_key(&rt, &fl)) {
229 /* - Bridged-and-DNAT'ed traffic doesn't 263 /* - Bridged-and-DNAT'ed traffic doesn't
@@ -247,7 +281,7 @@ bridged_dnat:
247 nf_bridge->mask |= BRNF_BRIDGED_DNAT; 281 nf_bridge->mask |= BRNF_BRIDGED_DNAT;
248 skb->dev = nf_bridge->physindev; 282 skb->dev = nf_bridge->physindev;
249 if (skb->protocol == 283 if (skb->protocol ==
250 __constant_htons(ETH_P_8021Q)) { 284 htons(ETH_P_8021Q)) {
251 skb_push(skb, VLAN_HLEN); 285 skb_push(skb, VLAN_HLEN);
252 skb->nh.raw -= VLAN_HLEN; 286 skb->nh.raw -= VLAN_HLEN;
253 } 287 }
@@ -257,8 +291,7 @@ bridged_dnat:
257 1); 291 1);
258 return 0; 292 return 0;
259 } 293 }
260 memcpy(eth_hdr(skb)->h_dest, dev->dev_addr, 294 memcpy(eth_hdr(skb)->h_dest, dev->dev_addr, ETH_ALEN);
261 ETH_ALEN);
262 skb->pkt_type = PACKET_HOST; 295 skb->pkt_type = PACKET_HOST;
263 } 296 }
264 } else { 297 } else {
@@ -267,7 +300,7 @@ bridged_dnat:
267 } 300 }
268 301
269 skb->dev = nf_bridge->physindev; 302 skb->dev = nf_bridge->physindev;
270 if (skb->protocol == __constant_htons(ETH_P_8021Q)) { 303 if (skb->protocol == htons(ETH_P_8021Q)) {
271 skb_push(skb, VLAN_HLEN); 304 skb_push(skb, VLAN_HLEN);
272 skb->nh.raw -= VLAN_HLEN; 305 skb->nh.raw -= VLAN_HLEN;
273 } 306 }
@@ -297,10 +330,10 @@ static struct net_device *setup_pre_routing(struct sk_buff *skb)
297/* We only check the length. A bridge shouldn't do any hop-by-hop stuff anyway */ 330/* We only check the length. A bridge shouldn't do any hop-by-hop stuff anyway */
298static int check_hbh_len(struct sk_buff *skb) 331static int check_hbh_len(struct sk_buff *skb)
299{ 332{
300 unsigned char *raw = (u8*)(skb->nh.ipv6h+1); 333 unsigned char *raw = (u8 *) (skb->nh.ipv6h + 1);
301 u32 pkt_len; 334 u32 pkt_len;
302 int off = raw - skb->nh.raw; 335 int off = raw - skb->nh.raw;
303 int len = (raw[1]+1)<<3; 336 int len = (raw[1] + 1) << 3;
304 337
305 if ((raw + len) - skb->data > skb_headlen(skb)) 338 if ((raw + len) - skb->data > skb_headlen(skb))
306 goto bad; 339 goto bad;
@@ -309,7 +342,7 @@ static int check_hbh_len(struct sk_buff *skb)
309 len -= 2; 342 len -= 2;
310 343
311 while (len > 0) { 344 while (len > 0) {
312 int optlen = skb->nh.raw[off+1]+2; 345 int optlen = skb->nh.raw[off + 1] + 2;
313 346
314 switch (skb->nh.raw[off]) { 347 switch (skb->nh.raw[off]) {
315 case IPV6_TLV_PAD0: 348 case IPV6_TLV_PAD0:
@@ -320,16 +353,16 @@ static int check_hbh_len(struct sk_buff *skb)
320 break; 353 break;
321 354
322 case IPV6_TLV_JUMBO: 355 case IPV6_TLV_JUMBO:
323 if (skb->nh.raw[off+1] != 4 || (off&3) != 2) 356 if (skb->nh.raw[off + 1] != 4 || (off & 3) != 2)
324 goto bad; 357 goto bad;
325 pkt_len = ntohl(*(u32*)(skb->nh.raw+off+2)); 358 pkt_len = ntohl(*(u32 *) (skb->nh.raw + off + 2));
326 if (pkt_len <= IPV6_MAXPLEN || 359 if (pkt_len <= IPV6_MAXPLEN ||
327 skb->nh.ipv6h->payload_len) 360 skb->nh.ipv6h->payload_len)
328 goto bad; 361 goto bad;
329 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) 362 if (pkt_len > skb->len - sizeof(struct ipv6hdr))
330 goto bad; 363 goto bad;
331 if (pskb_trim_rcsum(skb, 364 if (pskb_trim_rcsum(skb,
332 pkt_len+sizeof(struct ipv6hdr))) 365 pkt_len + sizeof(struct ipv6hdr)))
333 goto bad; 366 goto bad;
334 break; 367 break;
335 default: 368 default:
@@ -350,12 +383,13 @@ bad:
350/* Replicate the checks that IPv6 does on packet reception and pass the packet 383/* Replicate the checks that IPv6 does on packet reception and pass the packet
351 * to ip6tables, which doesn't support NAT, so things are fairly simple. */ 384 * to ip6tables, which doesn't support NAT, so things are fairly simple. */
352static unsigned int br_nf_pre_routing_ipv6(unsigned int hook, 385static unsigned int br_nf_pre_routing_ipv6(unsigned int hook,
353 struct sk_buff *skb, const struct net_device *in, 386 struct sk_buff *skb,
354 const struct net_device *out, int (*okfn)(struct sk_buff *)) 387 const struct net_device *in,
388 const struct net_device *out,
389 int (*okfn)(struct sk_buff *))
355{ 390{
356 struct ipv6hdr *hdr; 391 struct ipv6hdr *hdr;
357 u32 pkt_len; 392 u32 pkt_len;
358 struct nf_bridge_info *nf_bridge;
359 393
360 if (skb->len < sizeof(struct ipv6hdr)) 394 if (skb->len < sizeof(struct ipv6hdr))
361 goto inhdr_error; 395 goto inhdr_error;
@@ -381,10 +415,10 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook,
381 } 415 }
382 } 416 }
383 if (hdr->nexthdr == NEXTHDR_HOP && check_hbh_len(skb)) 417 if (hdr->nexthdr == NEXTHDR_HOP && check_hbh_len(skb))
384 goto inhdr_error; 418 goto inhdr_error;
385 419
386 nf_bridge_put(skb->nf_bridge); 420 nf_bridge_put(skb->nf_bridge);
387 if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) 421 if (!nf_bridge_alloc(skb))
388 return NF_DROP; 422 return NF_DROP;
389 if (!setup_pre_routing(skb)) 423 if (!setup_pre_routing(skb))
390 return NF_DROP; 424 return NF_DROP;
@@ -412,10 +446,8 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
412 struct iphdr *iph; 446 struct iphdr *iph;
413 __u32 len; 447 __u32 len;
414 struct sk_buff *skb = *pskb; 448 struct sk_buff *skb = *pskb;
415 struct nf_bridge_info *nf_bridge;
416 struct vlan_ethhdr *hdr = vlan_eth_hdr(*pskb);
417 449
418 if (skb->protocol == __constant_htons(ETH_P_IPV6) || IS_VLAN_IPV6) { 450 if (skb->protocol == htons(ETH_P_IPV6) || IS_VLAN_IPV6(skb)) {
419#ifdef CONFIG_SYSCTL 451#ifdef CONFIG_SYSCTL
420 if (!brnf_call_ip6tables) 452 if (!brnf_call_ip6tables)
421 return NF_ACCEPT; 453 return NF_ACCEPT;
@@ -423,10 +455,8 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
423 if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL) 455 if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
424 goto out; 456 goto out;
425 457
426 if (skb->protocol == __constant_htons(ETH_P_8021Q)) { 458 if (skb->protocol == htons(ETH_P_8021Q)) {
427 u8 *vhdr = skb->data; 459 skb_pull_rcsum(skb, VLAN_HLEN);
428 skb_pull(skb, VLAN_HLEN);
429 skb_postpull_rcsum(skb, vhdr, VLAN_HLEN);
430 skb->nh.raw += VLAN_HLEN; 460 skb->nh.raw += VLAN_HLEN;
431 } 461 }
432 return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); 462 return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn);
@@ -436,16 +466,14 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
436 return NF_ACCEPT; 466 return NF_ACCEPT;
437#endif 467#endif
438 468
439 if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP) 469 if (skb->protocol != htons(ETH_P_IP) && !IS_VLAN_IP(skb))
440 return NF_ACCEPT; 470 return NF_ACCEPT;
441 471
442 if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL) 472 if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
443 goto out; 473 goto out;
444 474
445 if (skb->protocol == __constant_htons(ETH_P_8021Q)) { 475 if (skb->protocol == htons(ETH_P_8021Q)) {
446 u8 *vhdr = skb->data; 476 skb_pull_rcsum(skb, VLAN_HLEN);
447 skb_pull(skb, VLAN_HLEN);
448 skb_postpull_rcsum(skb, vhdr, VLAN_HLEN);
449 skb->nh.raw += VLAN_HLEN; 477 skb->nh.raw += VLAN_HLEN;
450 } 478 }
451 479
@@ -456,15 +484,15 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
456 if (iph->ihl < 5 || iph->version != 4) 484 if (iph->ihl < 5 || iph->version != 4)
457 goto inhdr_error; 485 goto inhdr_error;
458 486
459 if (!pskb_may_pull(skb, 4*iph->ihl)) 487 if (!pskb_may_pull(skb, 4 * iph->ihl))
460 goto inhdr_error; 488 goto inhdr_error;
461 489
462 iph = skb->nh.iph; 490 iph = skb->nh.iph;
463 if (ip_fast_csum((__u8 *)iph, iph->ihl) != 0) 491 if (ip_fast_csum((__u8 *) iph, iph->ihl) != 0)
464 goto inhdr_error; 492 goto inhdr_error;
465 493
466 len = ntohs(iph->tot_len); 494 len = ntohs(iph->tot_len);
467 if (skb->len < len || len < 4*iph->ihl) 495 if (skb->len < len || len < 4 * iph->ihl)
468 goto inhdr_error; 496 goto inhdr_error;
469 497
470 if (skb->len > len) { 498 if (skb->len > len) {
@@ -473,8 +501,8 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
473 skb->ip_summed = CHECKSUM_NONE; 501 skb->ip_summed = CHECKSUM_NONE;
474 } 502 }
475 503
476 nf_bridge_put(skb->nf_bridge); 504 nf_bridge_put(skb->nf_bridge);
477 if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) 505 if (!nf_bridge_alloc(skb))
478 return NF_DROP; 506 return NF_DROP;
479 if (!setup_pre_routing(skb)) 507 if (!setup_pre_routing(skb))
480 return NF_DROP; 508 return NF_DROP;
@@ -486,7 +514,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
486 return NF_STOLEN; 514 return NF_STOLEN;
487 515
488inhdr_error: 516inhdr_error:
489// IP_INC_STATS_BH(IpInHdrErrors); 517// IP_INC_STATS_BH(IpInHdrErrors);
490out: 518out:
491 return NF_DROP; 519 return NF_DROP;
492} 520}
@@ -500,8 +528,9 @@ out:
500 * register an IPv4 PRE_ROUTING 'sabotage' hook that will 528 * register an IPv4 PRE_ROUTING 'sabotage' hook that will
501 * prevent this from happening. */ 529 * prevent this from happening. */
502static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb, 530static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb,
503 const struct net_device *in, const struct net_device *out, 531 const struct net_device *in,
504 int (*okfn)(struct sk_buff *)) 532 const struct net_device *out,
533 int (*okfn)(struct sk_buff *))
505{ 534{
506 struct sk_buff *skb = *pskb; 535 struct sk_buff *skb = *pskb;
507 536
@@ -513,15 +542,13 @@ static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb,
513 return NF_ACCEPT; 542 return NF_ACCEPT;
514} 543}
515 544
516
517/* PF_BRIDGE/FORWARD *************************************************/ 545/* PF_BRIDGE/FORWARD *************************************************/
518static int br_nf_forward_finish(struct sk_buff *skb) 546static int br_nf_forward_finish(struct sk_buff *skb)
519{ 547{
520 struct nf_bridge_info *nf_bridge = skb->nf_bridge; 548 struct nf_bridge_info *nf_bridge = skb->nf_bridge;
521 struct net_device *in; 549 struct net_device *in;
522 struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
523 550
524 if (skb->protocol != __constant_htons(ETH_P_ARP) && !IS_VLAN_ARP) { 551 if (skb->protocol != htons(ETH_P_ARP) && !IS_VLAN_ARP(skb)) {
525 in = nf_bridge->physindev; 552 in = nf_bridge->physindev;
526 if (nf_bridge->mask & BRNF_PKT_TYPE) { 553 if (nf_bridge->mask & BRNF_PKT_TYPE) {
527 skb->pkt_type = PACKET_OTHERHOST; 554 skb->pkt_type = PACKET_OTHERHOST;
@@ -530,12 +557,12 @@ static int br_nf_forward_finish(struct sk_buff *skb)
530 } else { 557 } else {
531 in = *((struct net_device **)(skb->cb)); 558 in = *((struct net_device **)(skb->cb));
532 } 559 }
533 if (skb->protocol == __constant_htons(ETH_P_8021Q)) { 560 if (skb->protocol == htons(ETH_P_8021Q)) {
534 skb_push(skb, VLAN_HLEN); 561 skb_push(skb, VLAN_HLEN);
535 skb->nh.raw -= VLAN_HLEN; 562 skb->nh.raw -= VLAN_HLEN;
536 } 563 }
537 NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in, 564 NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in,
538 skb->dev, br_forward_finish, 1); 565 skb->dev, br_forward_finish, 1);
539 return 0; 566 return 0;
540} 567}
541 568
@@ -545,12 +572,12 @@ static int br_nf_forward_finish(struct sk_buff *skb)
545 * because of the physdev module. For ARP, indev and outdev are the 572 * because of the physdev module. For ARP, indev and outdev are the
546 * bridge ports. */ 573 * bridge ports. */
547static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb, 574static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
548 const struct net_device *in, const struct net_device *out, 575 const struct net_device *in,
549 int (*okfn)(struct sk_buff *)) 576 const struct net_device *out,
577 int (*okfn)(struct sk_buff *))
550{ 578{
551 struct sk_buff *skb = *pskb; 579 struct sk_buff *skb = *pskb;
552 struct nf_bridge_info *nf_bridge; 580 struct nf_bridge_info *nf_bridge;
553 struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
554 struct net_device *parent; 581 struct net_device *parent;
555 int pf; 582 int pf;
556 583
@@ -561,12 +588,12 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
561 if (!parent) 588 if (!parent)
562 return NF_DROP; 589 return NF_DROP;
563 590
564 if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) 591 if (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb))
565 pf = PF_INET; 592 pf = PF_INET;
566 else 593 else
567 pf = PF_INET6; 594 pf = PF_INET6;
568 595
569 if (skb->protocol == __constant_htons(ETH_P_8021Q)) { 596 if (skb->protocol == htons(ETH_P_8021Q)) {
570 skb_pull(*pskb, VLAN_HLEN); 597 skb_pull(*pskb, VLAN_HLEN);
571 (*pskb)->nh.raw += VLAN_HLEN; 598 (*pskb)->nh.raw += VLAN_HLEN;
572 } 599 }
@@ -588,11 +615,11 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
588} 615}
589 616
590static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb, 617static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
591 const struct net_device *in, const struct net_device *out, 618 const struct net_device *in,
592 int (*okfn)(struct sk_buff *)) 619 const struct net_device *out,
620 int (*okfn)(struct sk_buff *))
593{ 621{
594 struct sk_buff *skb = *pskb; 622 struct sk_buff *skb = *pskb;
595 struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
596 struct net_device **d = (struct net_device **)(skb->cb); 623 struct net_device **d = (struct net_device **)(skb->cb);
597 624
598#ifdef CONFIG_SYSCTL 625#ifdef CONFIG_SYSCTL
@@ -600,15 +627,15 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
600 return NF_ACCEPT; 627 return NF_ACCEPT;
601#endif 628#endif
602 629
603 if (skb->protocol != __constant_htons(ETH_P_ARP)) { 630 if (skb->protocol != htons(ETH_P_ARP)) {
604 if (!IS_VLAN_ARP) 631 if (!IS_VLAN_ARP(skb))
605 return NF_ACCEPT; 632 return NF_ACCEPT;
606 skb_pull(*pskb, VLAN_HLEN); 633 skb_pull(*pskb, VLAN_HLEN);
607 (*pskb)->nh.raw += VLAN_HLEN; 634 (*pskb)->nh.raw += VLAN_HLEN;
608 } 635 }
609 636
610 if (skb->nh.arph->ar_pln != 4) { 637 if (skb->nh.arph->ar_pln != 4) {
611 if (IS_VLAN_ARP) { 638 if (IS_VLAN_ARP(skb)) {
612 skb_push(*pskb, VLAN_HLEN); 639 skb_push(*pskb, VLAN_HLEN);
613 (*pskb)->nh.raw -= VLAN_HLEN; 640 (*pskb)->nh.raw -= VLAN_HLEN;
614 } 641 }
@@ -621,17 +648,16 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
621 return NF_STOLEN; 648 return NF_STOLEN;
622} 649}
623 650
624
625/* PF_BRIDGE/LOCAL_OUT ***********************************************/ 651/* PF_BRIDGE/LOCAL_OUT ***********************************************/
626static int br_nf_local_out_finish(struct sk_buff *skb) 652static int br_nf_local_out_finish(struct sk_buff *skb)
627{ 653{
628 if (skb->protocol == __constant_htons(ETH_P_8021Q)) { 654 if (skb->protocol == htons(ETH_P_8021Q)) {
629 skb_push(skb, VLAN_HLEN); 655 skb_push(skb, VLAN_HLEN);
630 skb->nh.raw -= VLAN_HLEN; 656 skb->nh.raw -= VLAN_HLEN;
631 } 657 }
632 658
633 NF_HOOK_THRESH(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, 659 NF_HOOK_THRESH(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
634 br_forward_finish, NF_BR_PRI_FIRST + 1); 660 br_forward_finish, NF_BR_PRI_FIRST + 1);
635 661
636 return 0; 662 return 0;
637} 663}
@@ -657,19 +683,19 @@ static int br_nf_local_out_finish(struct sk_buff *skb)
657 * even routed packets that didn't arrive on a bridge interface have their 683 * even routed packets that didn't arrive on a bridge interface have their
658 * nf_bridge->physindev set. */ 684 * nf_bridge->physindev set. */
659static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb, 685static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
660 const struct net_device *in, const struct net_device *out, 686 const struct net_device *in,
661 int (*okfn)(struct sk_buff *)) 687 const struct net_device *out,
688 int (*okfn)(struct sk_buff *))
662{ 689{
663 struct net_device *realindev, *realoutdev; 690 struct net_device *realindev, *realoutdev;
664 struct sk_buff *skb = *pskb; 691 struct sk_buff *skb = *pskb;
665 struct nf_bridge_info *nf_bridge; 692 struct nf_bridge_info *nf_bridge;
666 struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
667 int pf; 693 int pf;
668 694
669 if (!skb->nf_bridge) 695 if (!skb->nf_bridge)
670 return NF_ACCEPT; 696 return NF_ACCEPT;
671 697
672 if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) 698 if (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb))
673 pf = PF_INET; 699 pf = PF_INET;
674 else 700 else
675 pf = PF_INET6; 701 pf = PF_INET6;
@@ -695,7 +721,7 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
695 skb->pkt_type = PACKET_OTHERHOST; 721 skb->pkt_type = PACKET_OTHERHOST;
696 nf_bridge->mask ^= BRNF_PKT_TYPE; 722 nf_bridge->mask ^= BRNF_PKT_TYPE;
697 } 723 }
698 if (skb->protocol == __constant_htons(ETH_P_8021Q)) { 724 if (skb->protocol == htons(ETH_P_8021Q)) {
699 skb_push(skb, VLAN_HLEN); 725 skb_push(skb, VLAN_HLEN);
700 skb->nh.raw -= VLAN_HLEN; 726 skb->nh.raw -= VLAN_HLEN;
701 } 727 }
@@ -713,14 +739,14 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
713 if (nf_bridge->netoutdev) 739 if (nf_bridge->netoutdev)
714 realoutdev = nf_bridge->netoutdev; 740 realoutdev = nf_bridge->netoutdev;
715#endif 741#endif
716 if (skb->protocol == __constant_htons(ETH_P_8021Q)) { 742 if (skb->protocol == htons(ETH_P_8021Q)) {
717 skb_pull(skb, VLAN_HLEN); 743 skb_pull(skb, VLAN_HLEN);
718 (*pskb)->nh.raw += VLAN_HLEN; 744 (*pskb)->nh.raw += VLAN_HLEN;
719 } 745 }
720 /* IP forwarded traffic has a physindev, locally 746 /* IP forwarded traffic has a physindev, locally
721 * generated traffic hasn't. */ 747 * generated traffic hasn't. */
722 if (realindev != NULL) { 748 if (realindev != NULL) {
723 if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT) ) { 749 if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT)) {
724 struct net_device *parent = bridge_parent(realindev); 750 struct net_device *parent = bridge_parent(realindev);
725 if (parent) 751 if (parent)
726 realindev = parent; 752 realindev = parent;
@@ -742,12 +768,12 @@ out:
742 768
743/* PF_BRIDGE/POST_ROUTING ********************************************/ 769/* PF_BRIDGE/POST_ROUTING ********************************************/
744static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, 770static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
745 const struct net_device *in, const struct net_device *out, 771 const struct net_device *in,
746 int (*okfn)(struct sk_buff *)) 772 const struct net_device *out,
773 int (*okfn)(struct sk_buff *))
747{ 774{
748 struct sk_buff *skb = *pskb; 775 struct sk_buff *skb = *pskb;
749 struct nf_bridge_info *nf_bridge = (*pskb)->nf_bridge; 776 struct nf_bridge_info *nf_bridge = (*pskb)->nf_bridge;
750 struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
751 struct net_device *realoutdev = bridge_parent(skb->dev); 777 struct net_device *realoutdev = bridge_parent(skb->dev);
752 int pf; 778 int pf;
753 779
@@ -756,7 +782,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
756 * keep the check just to be sure... */ 782 * keep the check just to be sure... */
757 if (skb->mac.raw < skb->head || skb->mac.raw + ETH_HLEN > skb->data) { 783 if (skb->mac.raw < skb->head || skb->mac.raw + ETH_HLEN > skb->data) {
758 printk(KERN_CRIT "br_netfilter: Argh!! br_nf_post_routing: " 784 printk(KERN_CRIT "br_netfilter: Argh!! br_nf_post_routing: "
759 "bad mac.raw pointer."); 785 "bad mac.raw pointer.");
760 goto print_error; 786 goto print_error;
761 } 787 }
762#endif 788#endif
@@ -767,7 +793,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
767 if (!realoutdev) 793 if (!realoutdev)
768 return NF_DROP; 794 return NF_DROP;
769 795
770 if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) 796 if (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb))
771 pf = PF_INET; 797 pf = PF_INET;
772 else 798 else
773 pf = PF_INET6; 799 pf = PF_INET6;
@@ -786,7 +812,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
786 nf_bridge->mask |= BRNF_PKT_TYPE; 812 nf_bridge->mask |= BRNF_PKT_TYPE;
787 } 813 }
788 814
789 if (skb->protocol == __constant_htons(ETH_P_8021Q)) { 815 if (skb->protocol == htons(ETH_P_8021Q)) {
790 skb_pull(skb, VLAN_HLEN); 816 skb_pull(skb, VLAN_HLEN);
791 skb->nh.raw += VLAN_HLEN; 817 skb->nh.raw += VLAN_HLEN;
792 } 818 }
@@ -798,7 +824,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
798 realoutdev = nf_bridge->netoutdev; 824 realoutdev = nf_bridge->netoutdev;
799#endif 825#endif
800 NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev, 826 NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev,
801 br_dev_queue_push_xmit); 827 br_dev_queue_push_xmit);
802 828
803 return NF_STOLEN; 829 return NF_STOLEN;
804 830
@@ -810,18 +836,18 @@ print_error:
810 printk("[%s]", realoutdev->name); 836 printk("[%s]", realoutdev->name);
811 } 837 }
812 printk(" head:%p, raw:%p, data:%p\n", skb->head, skb->mac.raw, 838 printk(" head:%p, raw:%p, data:%p\n", skb->head, skb->mac.raw,
813 skb->data); 839 skb->data);
814 return NF_ACCEPT; 840 return NF_ACCEPT;
815#endif 841#endif
816} 842}
817 843
818
819/* IP/SABOTAGE *****************************************************/ 844/* IP/SABOTAGE *****************************************************/
820/* Don't hand locally destined packets to PF_INET(6)/PRE_ROUTING 845/* Don't hand locally destined packets to PF_INET(6)/PRE_ROUTING
821 * for the second time. */ 846 * for the second time. */
822static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb, 847static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb,
823 const struct net_device *in, const struct net_device *out, 848 const struct net_device *in,
824 int (*okfn)(struct sk_buff *)) 849 const struct net_device *out,
850 int (*okfn)(struct sk_buff *))
825{ 851{
826 if ((*pskb)->nf_bridge && 852 if ((*pskb)->nf_bridge &&
827 !((*pskb)->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) { 853 !((*pskb)->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) {
@@ -835,18 +861,18 @@ static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb,
835 * and PF_INET(6)/POST_ROUTING until we have done the forwarding 861 * and PF_INET(6)/POST_ROUTING until we have done the forwarding
836 * decision in the bridge code and have determined nf_bridge->physoutdev. */ 862 * decision in the bridge code and have determined nf_bridge->physoutdev. */
837static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb, 863static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb,
838 const struct net_device *in, const struct net_device *out, 864 const struct net_device *in,
839 int (*okfn)(struct sk_buff *)) 865 const struct net_device *out,
866 int (*okfn)(struct sk_buff *))
840{ 867{
841 struct sk_buff *skb = *pskb; 868 struct sk_buff *skb = *pskb;
842 869
843 if ((out->hard_start_xmit == br_dev_xmit && 870 if ((out->hard_start_xmit == br_dev_xmit &&
844 okfn != br_nf_forward_finish && 871 okfn != br_nf_forward_finish &&
845 okfn != br_nf_local_out_finish && 872 okfn != br_nf_local_out_finish && okfn != br_dev_queue_push_xmit)
846 okfn != br_dev_queue_push_xmit)
847#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) 873#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
848 || ((out->priv_flags & IFF_802_1Q_VLAN) && 874 || ((out->priv_flags & IFF_802_1Q_VLAN) &&
849 VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit) 875 VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit)
850#endif 876#endif
851 ) { 877 ) {
852 struct nf_bridge_info *nf_bridge; 878 struct nf_bridge_info *nf_bridge;
@@ -971,8 +997,8 @@ static struct nf_hook_ops br_nf_ops[] = {
971 997
972#ifdef CONFIG_SYSCTL 998#ifdef CONFIG_SYSCTL
973static 999static
974int brnf_sysctl_call_tables(ctl_table *ctl, int write, struct file * filp, 1000int brnf_sysctl_call_tables(ctl_table * ctl, int write, struct file *filp,
975 void __user *buffer, size_t *lenp, loff_t *ppos) 1001 void __user * buffer, size_t * lenp, loff_t * ppos)
976{ 1002{
977 int ret; 1003 int ret;
978 1004
@@ -1059,7 +1085,8 @@ int br_netfilter_init(void)
1059#ifdef CONFIG_SYSCTL 1085#ifdef CONFIG_SYSCTL
1060 brnf_sysctl_header = register_sysctl_table(brnf_net_table, 0); 1086 brnf_sysctl_header = register_sysctl_table(brnf_net_table, 0);
1061 if (brnf_sysctl_header == NULL) { 1087 if (brnf_sysctl_header == NULL) {
1062 printk(KERN_WARNING "br_netfilter: can't register to sysctl.\n"); 1088 printk(KERN_WARNING
1089 "br_netfilter: can't register to sysctl.\n");
1063 for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++) 1090 for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++)
1064 nf_unregister_hook(&br_nf_ops[i]); 1091 nf_unregister_hook(&br_nf_ops[i]);
1065 return -EFAULT; 1092 return -EFAULT;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 8f10e09f251b..86ecea7ed372 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -109,6 +109,7 @@ struct net_bridge
109 unsigned long bridge_hello_time; 109 unsigned long bridge_hello_time;
110 unsigned long bridge_forward_delay; 110 unsigned long bridge_forward_delay;
111 111
112 u8 group_addr[ETH_ALEN];
112 u16 root_port; 113 u16 root_port;
113 unsigned char stp_enabled; 114 unsigned char stp_enabled;
114 unsigned char topology_change; 115 unsigned char topology_change;
@@ -122,7 +123,7 @@ struct net_bridge
122}; 123};
123 124
124extern struct notifier_block br_device_notifier; 125extern struct notifier_block br_device_notifier;
125extern const unsigned char bridge_ula[6]; 126extern const u8 br_group_address[ETH_ALEN];
126 127
127/* called under bridge lock */ 128/* called under bridge lock */
128static inline int br_is_root_bridge(const struct net_bridge *br) 129static inline int br_is_root_bridge(const struct net_bridge *br)
@@ -217,7 +218,8 @@ extern void br_stp_set_path_cost(struct net_bridge_port *p,
217extern ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id); 218extern ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id);
218 219
219/* br_stp_bpdu.c */ 220/* br_stp_bpdu.c */
220extern int br_stp_handle_bpdu(struct sk_buff *skb); 221extern int br_stp_rcv(struct sk_buff *skb, struct net_device *dev,
222 struct packet_type *pt, struct net_device *orig_dev);
221 223
222/* br_stp_timer.c */ 224/* br_stp_timer.c */
223extern void br_stp_timer_init(struct net_bridge *br); 225extern void br_stp_timer_init(struct net_bridge *br);
diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c
index 296f6a487c52..8934a54792be 100644
--- a/net/bridge/br_stp_bpdu.c
+++ b/net/bridge/br_stp_bpdu.c
@@ -15,158 +15,162 @@
15 15
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/netfilter_bridge.h> 17#include <linux/netfilter_bridge.h>
18#include <linux/etherdevice.h>
19#include <linux/llc.h>
20#include <net/llc.h>
21#include <net/llc_pdu.h>
18 22
19#include "br_private.h" 23#include "br_private.h"
20#include "br_private_stp.h" 24#include "br_private_stp.h"
21 25
22#define JIFFIES_TO_TICKS(j) (((j) << 8) / HZ) 26#define STP_HZ 256
23#define TICKS_TO_JIFFIES(j) (((j) * HZ) >> 8)
24 27
25static void br_send_bpdu(struct net_bridge_port *p, unsigned char *data, int length) 28#define LLC_RESERVE sizeof(struct llc_pdu_un)
29
30static void br_send_bpdu(struct net_bridge_port *p,
31 const unsigned char *data, int length)
26{ 32{
27 struct net_device *dev;
28 struct sk_buff *skb; 33 struct sk_buff *skb;
29 int size;
30 34
31 if (!p->br->stp_enabled) 35 if (!p->br->stp_enabled)
32 return; 36 return;
33 37
34 size = length + 2*ETH_ALEN + 2; 38 skb = dev_alloc_skb(length+LLC_RESERVE);
35 if (size < 60) 39 if (!skb)
36 size = 60;
37
38 dev = p->dev;
39
40 if ((skb = dev_alloc_skb(size)) == NULL) {
41 printk(KERN_INFO "br: memory squeeze!\n");
42 return; 40 return;
43 }
44 41
45 skb->dev = dev; 42 skb->dev = p->dev;
46 skb->protocol = htons(ETH_P_802_2); 43 skb->protocol = htons(ETH_P_802_2);
47 skb->mac.raw = skb_put(skb, size); 44
48 memcpy(skb->mac.raw, bridge_ula, ETH_ALEN); 45 skb_reserve(skb, LLC_RESERVE);
49 memcpy(skb->mac.raw+ETH_ALEN, dev->dev_addr, ETH_ALEN); 46 memcpy(__skb_put(skb, length), data, length);
50 skb->mac.raw[2*ETH_ALEN] = 0; 47
51 skb->mac.raw[2*ETH_ALEN+1] = length; 48 llc_pdu_header_init(skb, LLC_PDU_TYPE_U, LLC_SAP_BSPAN,
52 skb->nh.raw = skb->mac.raw + 2*ETH_ALEN + 2; 49 LLC_SAP_BSPAN, LLC_PDU_CMD);
53 memcpy(skb->nh.raw, data, length); 50 llc_pdu_init_as_ui_cmd(skb);
54 memset(skb->nh.raw + length, 0xa5, size - length - 2*ETH_ALEN - 2); 51
52 llc_mac_hdr_init(skb, p->dev->dev_addr, p->br->group_addr);
55 53
56 NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, 54 NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
57 dev_queue_xmit); 55 dev_queue_xmit);
58} 56}
59 57
60static __inline__ void br_set_ticks(unsigned char *dest, int jiff) 58static inline void br_set_ticks(unsigned char *dest, int j)
61{ 59{
62 __u16 ticks; 60 unsigned long ticks = (STP_HZ * j)/ HZ;
63 61
64 ticks = JIFFIES_TO_TICKS(jiff); 62 *((__be16 *) dest) = htons(ticks);
65 dest[0] = (ticks >> 8) & 0xFF;
66 dest[1] = ticks & 0xFF;
67} 63}
68 64
69static __inline__ int br_get_ticks(unsigned char *dest) 65static inline int br_get_ticks(const unsigned char *src)
70{ 66{
71 return TICKS_TO_JIFFIES((dest[0] << 8) | dest[1]); 67 unsigned long ticks = ntohs(*(__be16 *)src);
68
69 return (ticks * HZ + STP_HZ - 1) / STP_HZ;
72} 70}
73 71
74/* called under bridge lock */ 72/* called under bridge lock */
75void br_send_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu) 73void br_send_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
76{ 74{
77 unsigned char buf[38]; 75 unsigned char buf[35];
78 76
79 buf[0] = 0x42; 77 buf[0] = 0;
80 buf[1] = 0x42; 78 buf[1] = 0;
81 buf[2] = 0x03; 79 buf[2] = 0;
82 buf[3] = 0; 80 buf[3] = BPDU_TYPE_CONFIG;
83 buf[4] = 0; 81 buf[4] = (bpdu->topology_change ? 0x01 : 0) |
84 buf[5] = 0;
85 buf[6] = BPDU_TYPE_CONFIG;
86 buf[7] = (bpdu->topology_change ? 0x01 : 0) |
87 (bpdu->topology_change_ack ? 0x80 : 0); 82 (bpdu->topology_change_ack ? 0x80 : 0);
88 buf[8] = bpdu->root.prio[0]; 83 buf[5] = bpdu->root.prio[0];
89 buf[9] = bpdu->root.prio[1]; 84 buf[6] = bpdu->root.prio[1];
90 buf[10] = bpdu->root.addr[0]; 85 buf[7] = bpdu->root.addr[0];
91 buf[11] = bpdu->root.addr[1]; 86 buf[8] = bpdu->root.addr[1];
92 buf[12] = bpdu->root.addr[2]; 87 buf[9] = bpdu->root.addr[2];
93 buf[13] = bpdu->root.addr[3]; 88 buf[10] = bpdu->root.addr[3];
94 buf[14] = bpdu->root.addr[4]; 89 buf[11] = bpdu->root.addr[4];
95 buf[15] = bpdu->root.addr[5]; 90 buf[12] = bpdu->root.addr[5];
96 buf[16] = (bpdu->root_path_cost >> 24) & 0xFF; 91 buf[13] = (bpdu->root_path_cost >> 24) & 0xFF;
97 buf[17] = (bpdu->root_path_cost >> 16) & 0xFF; 92 buf[14] = (bpdu->root_path_cost >> 16) & 0xFF;
98 buf[18] = (bpdu->root_path_cost >> 8) & 0xFF; 93 buf[15] = (bpdu->root_path_cost >> 8) & 0xFF;
99 buf[19] = bpdu->root_path_cost & 0xFF; 94 buf[16] = bpdu->root_path_cost & 0xFF;
100 buf[20] = bpdu->bridge_id.prio[0]; 95 buf[17] = bpdu->bridge_id.prio[0];
101 buf[21] = bpdu->bridge_id.prio[1]; 96 buf[18] = bpdu->bridge_id.prio[1];
102 buf[22] = bpdu->bridge_id.addr[0]; 97 buf[19] = bpdu->bridge_id.addr[0];
103 buf[23] = bpdu->bridge_id.addr[1]; 98 buf[20] = bpdu->bridge_id.addr[1];
104 buf[24] = bpdu->bridge_id.addr[2]; 99 buf[21] = bpdu->bridge_id.addr[2];
105 buf[25] = bpdu->bridge_id.addr[3]; 100 buf[22] = bpdu->bridge_id.addr[3];
106 buf[26] = bpdu->bridge_id.addr[4]; 101 buf[23] = bpdu->bridge_id.addr[4];
107 buf[27] = bpdu->bridge_id.addr[5]; 102 buf[24] = bpdu->bridge_id.addr[5];
108 buf[28] = (bpdu->port_id >> 8) & 0xFF; 103 buf[25] = (bpdu->port_id >> 8) & 0xFF;
109 buf[29] = bpdu->port_id & 0xFF; 104 buf[26] = bpdu->port_id & 0xFF;
110 105
111 br_set_ticks(buf+30, bpdu->message_age); 106 br_set_ticks(buf+27, bpdu->message_age);
112 br_set_ticks(buf+32, bpdu->max_age); 107 br_set_ticks(buf+29, bpdu->max_age);
113 br_set_ticks(buf+34, bpdu->hello_time); 108 br_set_ticks(buf+31, bpdu->hello_time);
114 br_set_ticks(buf+36, bpdu->forward_delay); 109 br_set_ticks(buf+33, bpdu->forward_delay);
115 110
116 br_send_bpdu(p, buf, 38); 111 br_send_bpdu(p, buf, 35);
117} 112}
118 113
119/* called under bridge lock */ 114/* called under bridge lock */
120void br_send_tcn_bpdu(struct net_bridge_port *p) 115void br_send_tcn_bpdu(struct net_bridge_port *p)
121{ 116{
122 unsigned char buf[7]; 117 unsigned char buf[4];
123 118
124 buf[0] = 0x42; 119 buf[0] = 0;
125 buf[1] = 0x42; 120 buf[1] = 0;
126 buf[2] = 0x03; 121 buf[2] = 0;
127 buf[3] = 0; 122 buf[3] = BPDU_TYPE_TCN;
128 buf[4] = 0;
129 buf[5] = 0;
130 buf[6] = BPDU_TYPE_TCN;
131 br_send_bpdu(p, buf, 7); 123 br_send_bpdu(p, buf, 7);
132} 124}
133 125
134static const unsigned char header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00}; 126/*
135 127 * Called from llc.
136/* NO locks, but rcu_read_lock (preempt_disabled) */ 128 *
137int br_stp_handle_bpdu(struct sk_buff *skb) 129 * NO locks, but rcu_read_lock (preempt_disabled)
130 */
131int br_stp_rcv(struct sk_buff *skb, struct net_device *dev,
132 struct packet_type *pt, struct net_device *orig_dev)
138{ 133{
139 struct net_bridge_port *p = rcu_dereference(skb->dev->br_port); 134 const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
135 const unsigned char *dest = eth_hdr(skb)->h_dest;
136 struct net_bridge_port *p = rcu_dereference(dev->br_port);
140 struct net_bridge *br; 137 struct net_bridge *br;
141 unsigned char *buf; 138 const unsigned char *buf;
142 139
143 if (!p) 140 if (!p)
144 goto err; 141 goto err;
145 142
146 br = p->br; 143 if (pdu->ssap != LLC_SAP_BSPAN
147 spin_lock(&br->lock); 144 || pdu->dsap != LLC_SAP_BSPAN
145 || pdu->ctrl_1 != LLC_PDU_TYPE_U)
146 goto err;
148 147
149 if (p->state == BR_STATE_DISABLED || !(br->dev->flags & IFF_UP)) 148 if (!pskb_may_pull(skb, 4))
150 goto out; 149 goto err;
150
151 /* compare of protocol id and version */
152 buf = skb->data;
153 if (buf[0] != 0 || buf[1] != 0 || buf[2] != 0)
154 goto err;
151 155
152 /* insert into forwarding database after filtering to avoid spoofing */ 156 br = p->br;
153 br_fdb_update(br, p, eth_hdr(skb)->h_source); 157 spin_lock(&br->lock);
154 158
155 if (!br->stp_enabled) 159 if (p->state == BR_STATE_DISABLED
160 || !br->stp_enabled
161 || !(br->dev->flags & IFF_UP))
156 goto out; 162 goto out;
157 163
158 /* need at least the 802 and STP headers */ 164 if (compare_ether_addr(dest, br->group_addr) != 0)
159 if (!pskb_may_pull(skb, sizeof(header)+1) ||
160 memcmp(skb->data, header, sizeof(header)))
161 goto out; 165 goto out;
162 166
163 buf = skb_pull(skb, sizeof(header)); 167 buf = skb_pull(skb, 3);
164 168
165 if (buf[0] == BPDU_TYPE_CONFIG) { 169 if (buf[0] == BPDU_TYPE_CONFIG) {
166 struct br_config_bpdu bpdu; 170 struct br_config_bpdu bpdu;
167 171
168 if (!pskb_may_pull(skb, 32)) 172 if (!pskb_may_pull(skb, 32))
169 goto out; 173 goto out;
170 174
171 buf = skb->data; 175 buf = skb->data;
172 bpdu.topology_change = (buf[1] & 0x01) ? 1 : 0; 176 bpdu.topology_change = (buf[1] & 0x01) ? 1 : 0;
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c
index 9bef55f56425..d0fcde82c6fc 100644
--- a/net/bridge/br_stp_timer.c
+++ b/net/bridge/br_stp_timer.c
@@ -39,13 +39,13 @@ static void br_hello_timer_expired(unsigned long arg)
39 struct net_bridge *br = (struct net_bridge *)arg; 39 struct net_bridge *br = (struct net_bridge *)arg;
40 40
41 pr_debug("%s: hello timer expired\n", br->dev->name); 41 pr_debug("%s: hello timer expired\n", br->dev->name);
42 spin_lock_bh(&br->lock); 42 spin_lock(&br->lock);
43 if (br->dev->flags & IFF_UP) { 43 if (br->dev->flags & IFF_UP) {
44 br_config_bpdu_generation(br); 44 br_config_bpdu_generation(br);
45 45
46 mod_timer(&br->hello_timer, jiffies + br->hello_time); 46 mod_timer(&br->hello_timer, jiffies + br->hello_time);
47 } 47 }
48 spin_unlock_bh(&br->lock); 48 spin_unlock(&br->lock);
49} 49}
50 50
51static void br_message_age_timer_expired(unsigned long arg) 51static void br_message_age_timer_expired(unsigned long arg)
@@ -71,7 +71,7 @@ static void br_message_age_timer_expired(unsigned long arg)
71 * running when we are the root bridge. So.. this was_root 71 * running when we are the root bridge. So.. this was_root
72 * check is redundant. I'm leaving it in for now, though. 72 * check is redundant. I'm leaving it in for now, though.
73 */ 73 */
74 spin_lock_bh(&br->lock); 74 spin_lock(&br->lock);
75 if (p->state == BR_STATE_DISABLED) 75 if (p->state == BR_STATE_DISABLED)
76 goto unlock; 76 goto unlock;
77 was_root = br_is_root_bridge(br); 77 was_root = br_is_root_bridge(br);
@@ -82,7 +82,7 @@ static void br_message_age_timer_expired(unsigned long arg)
82 if (br_is_root_bridge(br) && !was_root) 82 if (br_is_root_bridge(br) && !was_root)
83 br_become_root_bridge(br); 83 br_become_root_bridge(br);
84 unlock: 84 unlock:
85 spin_unlock_bh(&br->lock); 85 spin_unlock(&br->lock);
86} 86}
87 87
88static void br_forward_delay_timer_expired(unsigned long arg) 88static void br_forward_delay_timer_expired(unsigned long arg)
@@ -92,7 +92,7 @@ static void br_forward_delay_timer_expired(unsigned long arg)
92 92
93 pr_debug("%s: %d(%s) forward delay timer\n", 93 pr_debug("%s: %d(%s) forward delay timer\n",
94 br->dev->name, p->port_no, p->dev->name); 94 br->dev->name, p->port_no, p->dev->name);
95 spin_lock_bh(&br->lock); 95 spin_lock(&br->lock);
96 if (p->state == BR_STATE_LISTENING) { 96 if (p->state == BR_STATE_LISTENING) {
97 p->state = BR_STATE_LEARNING; 97 p->state = BR_STATE_LEARNING;
98 mod_timer(&p->forward_delay_timer, 98 mod_timer(&p->forward_delay_timer,
@@ -103,7 +103,7 @@ static void br_forward_delay_timer_expired(unsigned long arg)
103 br_topology_change_detection(br); 103 br_topology_change_detection(br);
104 } 104 }
105 br_log_state(p); 105 br_log_state(p);
106 spin_unlock_bh(&br->lock); 106 spin_unlock(&br->lock);
107} 107}
108 108
109static void br_tcn_timer_expired(unsigned long arg) 109static void br_tcn_timer_expired(unsigned long arg)
@@ -111,13 +111,13 @@ static void br_tcn_timer_expired(unsigned long arg)
111 struct net_bridge *br = (struct net_bridge *) arg; 111 struct net_bridge *br = (struct net_bridge *) arg;
112 112
113 pr_debug("%s: tcn timer expired\n", br->dev->name); 113 pr_debug("%s: tcn timer expired\n", br->dev->name);
114 spin_lock_bh(&br->lock); 114 spin_lock(&br->lock);
115 if (br->dev->flags & IFF_UP) { 115 if (br->dev->flags & IFF_UP) {
116 br_transmit_tcn(br); 116 br_transmit_tcn(br);
117 117
118 mod_timer(&br->tcn_timer,jiffies + br->bridge_hello_time); 118 mod_timer(&br->tcn_timer,jiffies + br->bridge_hello_time);
119 } 119 }
120 spin_unlock_bh(&br->lock); 120 spin_unlock(&br->lock);
121} 121}
122 122
123static void br_topology_change_timer_expired(unsigned long arg) 123static void br_topology_change_timer_expired(unsigned long arg)
@@ -125,10 +125,10 @@ static void br_topology_change_timer_expired(unsigned long arg)
125 struct net_bridge *br = (struct net_bridge *) arg; 125 struct net_bridge *br = (struct net_bridge *) arg;
126 126
127 pr_debug("%s: topo change timer expired\n", br->dev->name); 127 pr_debug("%s: topo change timer expired\n", br->dev->name);
128 spin_lock_bh(&br->lock); 128 spin_lock(&br->lock);
129 br->topology_change_detected = 0; 129 br->topology_change_detected = 0;
130 br->topology_change = 0; 130 br->topology_change = 0;
131 spin_unlock_bh(&br->lock); 131 spin_unlock(&br->lock);
132} 132}
133 133
134static void br_hold_timer_expired(unsigned long arg) 134static void br_hold_timer_expired(unsigned long arg)
@@ -138,45 +138,36 @@ static void br_hold_timer_expired(unsigned long arg)
138 pr_debug("%s: %d(%s) hold timer expired\n", 138 pr_debug("%s: %d(%s) hold timer expired\n",
139 p->br->dev->name, p->port_no, p->dev->name); 139 p->br->dev->name, p->port_no, p->dev->name);
140 140
141 spin_lock_bh(&p->br->lock); 141 spin_lock(&p->br->lock);
142 if (p->config_pending) 142 if (p->config_pending)
143 br_transmit_config(p); 143 br_transmit_config(p);
144 spin_unlock_bh(&p->br->lock); 144 spin_unlock(&p->br->lock);
145}
146
147static inline void br_timer_init(struct timer_list *timer,
148 void (*_function)(unsigned long),
149 unsigned long _data)
150{
151 init_timer(timer);
152 timer->function = _function;
153 timer->data = _data;
154} 145}
155 146
156void br_stp_timer_init(struct net_bridge *br) 147void br_stp_timer_init(struct net_bridge *br)
157{ 148{
158 br_timer_init(&br->hello_timer, br_hello_timer_expired, 149 setup_timer(&br->hello_timer, br_hello_timer_expired,
159 (unsigned long) br); 150 (unsigned long) br);
160 151
161 br_timer_init(&br->tcn_timer, br_tcn_timer_expired, 152 setup_timer(&br->tcn_timer, br_tcn_timer_expired,
162 (unsigned long) br); 153 (unsigned long) br);
163 154
164 br_timer_init(&br->topology_change_timer, 155 setup_timer(&br->topology_change_timer,
165 br_topology_change_timer_expired, 156 br_topology_change_timer_expired,
166 (unsigned long) br); 157 (unsigned long) br);
167 158
168 br_timer_init(&br->gc_timer, br_fdb_cleanup, (unsigned long) br); 159 setup_timer(&br->gc_timer, br_fdb_cleanup, (unsigned long) br);
169} 160}
170 161
171void br_stp_port_timer_init(struct net_bridge_port *p) 162void br_stp_port_timer_init(struct net_bridge_port *p)
172{ 163{
173 br_timer_init(&p->message_age_timer, br_message_age_timer_expired, 164 setup_timer(&p->message_age_timer, br_message_age_timer_expired,
174 (unsigned long) p); 165 (unsigned long) p);
175 166
176 br_timer_init(&p->forward_delay_timer, br_forward_delay_timer_expired, 167 setup_timer(&p->forward_delay_timer, br_forward_delay_timer_expired,
177 (unsigned long) p); 168 (unsigned long) p);
178 169
179 br_timer_init(&p->hold_timer, br_hold_timer_expired, 170 setup_timer(&p->hold_timer, br_hold_timer_expired,
180 (unsigned long) p); 171 (unsigned long) p);
181} 172}
182 173
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index 6f577f16c4c0..96bcb2ff59ab 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -242,6 +242,54 @@ static ssize_t show_gc_timer(struct class_device *cd, char *buf)
242} 242}
243static CLASS_DEVICE_ATTR(gc_timer, S_IRUGO, show_gc_timer, NULL); 243static CLASS_DEVICE_ATTR(gc_timer, S_IRUGO, show_gc_timer, NULL);
244 244
245static ssize_t show_group_addr(struct class_device *cd, char *buf)
246{
247 struct net_bridge *br = to_bridge(cd);
248 return sprintf(buf, "%x:%x:%x:%x:%x:%x\n",
249 br->group_addr[0], br->group_addr[1],
250 br->group_addr[2], br->group_addr[3],
251 br->group_addr[4], br->group_addr[5]);
252}
253
254static ssize_t store_group_addr(struct class_device *cd, const char *buf,
255 size_t len)
256{
257 struct net_bridge *br = to_bridge(cd);
258 unsigned new_addr[6];
259 int i;
260
261 if (!capable(CAP_NET_ADMIN))
262 return -EPERM;
263
264 if (sscanf(buf, "%x:%x:%x:%x:%x:%x",
265 &new_addr[0], &new_addr[1], &new_addr[2],
266 &new_addr[3], &new_addr[4], &new_addr[5]) != 6)
267 return -EINVAL;
268
269 /* Must be 01:80:c2:00:00:0X */
270 for (i = 0; i < 5; i++)
271 if (new_addr[i] != br_group_address[i])
272 return -EINVAL;
273
274 if (new_addr[5] & ~0xf)
275 return -EINVAL;
276
277 if (new_addr[5] == 1 /* 802.3x Pause address */
278 || new_addr[5] == 2 /* 802.3ad Slow protocols */
279 || new_addr[5] == 3) /* 802.1X PAE address */
280 return -EINVAL;
281
282 spin_lock_bh(&br->lock);
283 for (i = 0; i < 6; i++)
284 br->group_addr[i] = new_addr[i];
285 spin_unlock_bh(&br->lock);
286 return len;
287}
288
289static CLASS_DEVICE_ATTR(group_addr, S_IRUGO | S_IWUSR,
290 show_group_addr, store_group_addr);
291
292
245static struct attribute *bridge_attrs[] = { 293static struct attribute *bridge_attrs[] = {
246 &class_device_attr_forward_delay.attr, 294 &class_device_attr_forward_delay.attr,
247 &class_device_attr_hello_time.attr, 295 &class_device_attr_hello_time.attr,
@@ -259,6 +307,7 @@ static struct attribute *bridge_attrs[] = {
259 &class_device_attr_tcn_timer.attr, 307 &class_device_attr_tcn_timer.attr,
260 &class_device_attr_topology_change_timer.attr, 308 &class_device_attr_topology_change_timer.attr,
261 &class_device_attr_gc_timer.attr, 309 &class_device_attr_gc_timer.attr,
310 &class_device_attr_group_addr.attr,
262 NULL 311 NULL
263}; 312};
264 313
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index cbd4020cc84d..997953367204 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -35,6 +35,7 @@
35#define ASSERT_READ_LOCK(x) 35#define ASSERT_READ_LOCK(x)
36#define ASSERT_WRITE_LOCK(x) 36#define ASSERT_WRITE_LOCK(x)
37#include <linux/netfilter_ipv4/listhelp.h> 37#include <linux/netfilter_ipv4/listhelp.h>
38#include <linux/mutex.h>
38 39
39#if 0 40#if 0
40/* use this for remote debugging 41/* use this for remote debugging
@@ -81,7 +82,7 @@ static void print_string(char *str)
81 82
82 83
83 84
84static DECLARE_MUTEX(ebt_mutex); 85static DEFINE_MUTEX(ebt_mutex);
85static LIST_HEAD(ebt_tables); 86static LIST_HEAD(ebt_tables);
86static LIST_HEAD(ebt_targets); 87static LIST_HEAD(ebt_targets);
87static LIST_HEAD(ebt_matches); 88static LIST_HEAD(ebt_matches);
@@ -296,18 +297,18 @@ letscontinue:
296/* If it succeeds, returns element and locks mutex */ 297/* If it succeeds, returns element and locks mutex */
297static inline void * 298static inline void *
298find_inlist_lock_noload(struct list_head *head, const char *name, int *error, 299find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
299 struct semaphore *mutex) 300 struct mutex *mutex)
300{ 301{
301 void *ret; 302 void *ret;
302 303
303 *error = down_interruptible(mutex); 304 *error = mutex_lock_interruptible(mutex);
304 if (*error != 0) 305 if (*error != 0)
305 return NULL; 306 return NULL;
306 307
307 ret = list_named_find(head, name); 308 ret = list_named_find(head, name);
308 if (!ret) { 309 if (!ret) {
309 *error = -ENOENT; 310 *error = -ENOENT;
310 up(mutex); 311 mutex_unlock(mutex);
311 } 312 }
312 return ret; 313 return ret;
313} 314}
@@ -317,7 +318,7 @@ find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
317#else 318#else
318static void * 319static void *
319find_inlist_lock(struct list_head *head, const char *name, const char *prefix, 320find_inlist_lock(struct list_head *head, const char *name, const char *prefix,
320 int *error, struct semaphore *mutex) 321 int *error, struct mutex *mutex)
321{ 322{
322 void *ret; 323 void *ret;
323 324
@@ -331,25 +332,25 @@ find_inlist_lock(struct list_head *head, const char *name, const char *prefix,
331#endif 332#endif
332 333
333static inline struct ebt_table * 334static inline struct ebt_table *
334find_table_lock(const char *name, int *error, struct semaphore *mutex) 335find_table_lock(const char *name, int *error, struct mutex *mutex)
335{ 336{
336 return find_inlist_lock(&ebt_tables, name, "ebtable_", error, mutex); 337 return find_inlist_lock(&ebt_tables, name, "ebtable_", error, mutex);
337} 338}
338 339
339static inline struct ebt_match * 340static inline struct ebt_match *
340find_match_lock(const char *name, int *error, struct semaphore *mutex) 341find_match_lock(const char *name, int *error, struct mutex *mutex)
341{ 342{
342 return find_inlist_lock(&ebt_matches, name, "ebt_", error, mutex); 343 return find_inlist_lock(&ebt_matches, name, "ebt_", error, mutex);
343} 344}
344 345
345static inline struct ebt_watcher * 346static inline struct ebt_watcher *
346find_watcher_lock(const char *name, int *error, struct semaphore *mutex) 347find_watcher_lock(const char *name, int *error, struct mutex *mutex)
347{ 348{
348 return find_inlist_lock(&ebt_watchers, name, "ebt_", error, mutex); 349 return find_inlist_lock(&ebt_watchers, name, "ebt_", error, mutex);
349} 350}
350 351
351static inline struct ebt_target * 352static inline struct ebt_target *
352find_target_lock(const char *name, int *error, struct semaphore *mutex) 353find_target_lock(const char *name, int *error, struct mutex *mutex)
353{ 354{
354 return find_inlist_lock(&ebt_targets, name, "ebt_", error, mutex); 355 return find_inlist_lock(&ebt_targets, name, "ebt_", error, mutex);
355} 356}
@@ -369,10 +370,10 @@ ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
369 return ret; 370 return ret;
370 m->u.match = match; 371 m->u.match = match;
371 if (!try_module_get(match->me)) { 372 if (!try_module_get(match->me)) {
372 up(&ebt_mutex); 373 mutex_unlock(&ebt_mutex);
373 return -ENOENT; 374 return -ENOENT;
374 } 375 }
375 up(&ebt_mutex); 376 mutex_unlock(&ebt_mutex);
376 if (match->check && 377 if (match->check &&
377 match->check(name, hookmask, e, m->data, m->match_size) != 0) { 378 match->check(name, hookmask, e, m->data, m->match_size) != 0) {
378 BUGPRINT("match->check failed\n"); 379 BUGPRINT("match->check failed\n");
@@ -398,10 +399,10 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
398 return ret; 399 return ret;
399 w->u.watcher = watcher; 400 w->u.watcher = watcher;
400 if (!try_module_get(watcher->me)) { 401 if (!try_module_get(watcher->me)) {
401 up(&ebt_mutex); 402 mutex_unlock(&ebt_mutex);
402 return -ENOENT; 403 return -ENOENT;
403 } 404 }
404 up(&ebt_mutex); 405 mutex_unlock(&ebt_mutex);
405 if (watcher->check && 406 if (watcher->check &&
406 watcher->check(name, hookmask, e, w->data, w->watcher_size) != 0) { 407 watcher->check(name, hookmask, e, w->data, w->watcher_size) != 0) {
407 BUGPRINT("watcher->check failed\n"); 408 BUGPRINT("watcher->check failed\n");
@@ -638,11 +639,11 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
638 if (!target) 639 if (!target)
639 goto cleanup_watchers; 640 goto cleanup_watchers;
640 if (!try_module_get(target->me)) { 641 if (!try_module_get(target->me)) {
641 up(&ebt_mutex); 642 mutex_unlock(&ebt_mutex);
642 ret = -ENOENT; 643 ret = -ENOENT;
643 goto cleanup_watchers; 644 goto cleanup_watchers;
644 } 645 }
645 up(&ebt_mutex); 646 mutex_unlock(&ebt_mutex);
646 647
647 t->u.target = target; 648 t->u.target = target;
648 if (t->u.target == &ebt_standard_target) { 649 if (t->u.target == &ebt_standard_target) {
@@ -1015,7 +1016,7 @@ static int do_replace(void __user *user, unsigned int len)
1015 1016
1016 t->private = newinfo; 1017 t->private = newinfo;
1017 write_unlock_bh(&t->lock); 1018 write_unlock_bh(&t->lock);
1018 up(&ebt_mutex); 1019 mutex_unlock(&ebt_mutex);
1019 /* so, a user can change the chains while having messed up her counter 1020 /* so, a user can change the chains while having messed up her counter
1020 allocation. Only reason why this is done is because this way the lock 1021 allocation. Only reason why this is done is because this way the lock
1021 is held only once, while this doesn't bring the kernel into a 1022 is held only once, while this doesn't bring the kernel into a
@@ -1045,7 +1046,7 @@ static int do_replace(void __user *user, unsigned int len)
1045 return ret; 1046 return ret;
1046 1047
1047free_unlock: 1048free_unlock:
1048 up(&ebt_mutex); 1049 mutex_unlock(&ebt_mutex);
1049free_iterate: 1050free_iterate:
1050 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, 1051 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
1051 ebt_cleanup_entry, NULL); 1052 ebt_cleanup_entry, NULL);
@@ -1068,69 +1069,69 @@ int ebt_register_target(struct ebt_target *target)
1068{ 1069{
1069 int ret; 1070 int ret;
1070 1071
1071 ret = down_interruptible(&ebt_mutex); 1072 ret = mutex_lock_interruptible(&ebt_mutex);
1072 if (ret != 0) 1073 if (ret != 0)
1073 return ret; 1074 return ret;
1074 if (!list_named_insert(&ebt_targets, target)) { 1075 if (!list_named_insert(&ebt_targets, target)) {
1075 up(&ebt_mutex); 1076 mutex_unlock(&ebt_mutex);
1076 return -EEXIST; 1077 return -EEXIST;
1077 } 1078 }
1078 up(&ebt_mutex); 1079 mutex_unlock(&ebt_mutex);
1079 1080
1080 return 0; 1081 return 0;
1081} 1082}
1082 1083
1083void ebt_unregister_target(struct ebt_target *target) 1084void ebt_unregister_target(struct ebt_target *target)
1084{ 1085{
1085 down(&ebt_mutex); 1086 mutex_lock(&ebt_mutex);
1086 LIST_DELETE(&ebt_targets, target); 1087 LIST_DELETE(&ebt_targets, target);
1087 up(&ebt_mutex); 1088 mutex_unlock(&ebt_mutex);
1088} 1089}
1089 1090
1090int ebt_register_match(struct ebt_match *match) 1091int ebt_register_match(struct ebt_match *match)
1091{ 1092{
1092 int ret; 1093 int ret;
1093 1094
1094 ret = down_interruptible(&ebt_mutex); 1095 ret = mutex_lock_interruptible(&ebt_mutex);
1095 if (ret != 0) 1096 if (ret != 0)
1096 return ret; 1097 return ret;
1097 if (!list_named_insert(&ebt_matches, match)) { 1098 if (!list_named_insert(&ebt_matches, match)) {
1098 up(&ebt_mutex); 1099 mutex_unlock(&ebt_mutex);
1099 return -EEXIST; 1100 return -EEXIST;
1100 } 1101 }
1101 up(&ebt_mutex); 1102 mutex_unlock(&ebt_mutex);
1102 1103
1103 return 0; 1104 return 0;
1104} 1105}
1105 1106
1106void ebt_unregister_match(struct ebt_match *match) 1107void ebt_unregister_match(struct ebt_match *match)
1107{ 1108{
1108 down(&ebt_mutex); 1109 mutex_lock(&ebt_mutex);
1109 LIST_DELETE(&ebt_matches, match); 1110 LIST_DELETE(&ebt_matches, match);
1110 up(&ebt_mutex); 1111 mutex_unlock(&ebt_mutex);
1111} 1112}
1112 1113
1113int ebt_register_watcher(struct ebt_watcher *watcher) 1114int ebt_register_watcher(struct ebt_watcher *watcher)
1114{ 1115{
1115 int ret; 1116 int ret;
1116 1117
1117 ret = down_interruptible(&ebt_mutex); 1118 ret = mutex_lock_interruptible(&ebt_mutex);
1118 if (ret != 0) 1119 if (ret != 0)
1119 return ret; 1120 return ret;
1120 if (!list_named_insert(&ebt_watchers, watcher)) { 1121 if (!list_named_insert(&ebt_watchers, watcher)) {
1121 up(&ebt_mutex); 1122 mutex_unlock(&ebt_mutex);
1122 return -EEXIST; 1123 return -EEXIST;
1123 } 1124 }
1124 up(&ebt_mutex); 1125 mutex_unlock(&ebt_mutex);
1125 1126
1126 return 0; 1127 return 0;
1127} 1128}
1128 1129
1129void ebt_unregister_watcher(struct ebt_watcher *watcher) 1130void ebt_unregister_watcher(struct ebt_watcher *watcher)
1130{ 1131{
1131 down(&ebt_mutex); 1132 mutex_lock(&ebt_mutex);
1132 LIST_DELETE(&ebt_watchers, watcher); 1133 LIST_DELETE(&ebt_watchers, watcher);
1133 up(&ebt_mutex); 1134 mutex_unlock(&ebt_mutex);
1134} 1135}
1135 1136
1136int ebt_register_table(struct ebt_table *table) 1137int ebt_register_table(struct ebt_table *table)
@@ -1178,7 +1179,7 @@ int ebt_register_table(struct ebt_table *table)
1178 1179
1179 table->private = newinfo; 1180 table->private = newinfo;
1180 rwlock_init(&table->lock); 1181 rwlock_init(&table->lock);
1181 ret = down_interruptible(&ebt_mutex); 1182 ret = mutex_lock_interruptible(&ebt_mutex);
1182 if (ret != 0) 1183 if (ret != 0)
1183 goto free_chainstack; 1184 goto free_chainstack;
1184 1185
@@ -1194,10 +1195,10 @@ int ebt_register_table(struct ebt_table *table)
1194 goto free_unlock; 1195 goto free_unlock;
1195 } 1196 }
1196 list_prepend(&ebt_tables, table); 1197 list_prepend(&ebt_tables, table);
1197 up(&ebt_mutex); 1198 mutex_unlock(&ebt_mutex);
1198 return 0; 1199 return 0;
1199free_unlock: 1200free_unlock:
1200 up(&ebt_mutex); 1201 mutex_unlock(&ebt_mutex);
1201free_chainstack: 1202free_chainstack:
1202 if (newinfo->chainstack) { 1203 if (newinfo->chainstack) {
1203 for_each_cpu(i) 1204 for_each_cpu(i)
@@ -1218,9 +1219,9 @@ void ebt_unregister_table(struct ebt_table *table)
1218 BUGPRINT("Request to unregister NULL table!!!\n"); 1219 BUGPRINT("Request to unregister NULL table!!!\n");
1219 return; 1220 return;
1220 } 1221 }
1221 down(&ebt_mutex); 1222 mutex_lock(&ebt_mutex);
1222 LIST_DELETE(&ebt_tables, table); 1223 LIST_DELETE(&ebt_tables, table);
1223 up(&ebt_mutex); 1224 mutex_unlock(&ebt_mutex);
1224 vfree(table->private->entries); 1225 vfree(table->private->entries);
1225 if (table->private->chainstack) { 1226 if (table->private->chainstack) {
1226 for_each_cpu(i) 1227 for_each_cpu(i)
@@ -1281,7 +1282,7 @@ static int update_counters(void __user *user, unsigned int len)
1281 write_unlock_bh(&t->lock); 1282 write_unlock_bh(&t->lock);
1282 ret = 0; 1283 ret = 0;
1283unlock_mutex: 1284unlock_mutex:
1284 up(&ebt_mutex); 1285 mutex_unlock(&ebt_mutex);
1285free_tmp: 1286free_tmp:
1286 vfree(tmp); 1287 vfree(tmp);
1287 return ret; 1288 return ret;
@@ -1328,7 +1329,7 @@ static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase)
1328 return 0; 1329 return 0;
1329} 1330}
1330 1331
1331/* called with ebt_mutex down */ 1332/* called with ebt_mutex locked */
1332static int copy_everything_to_user(struct ebt_table *t, void __user *user, 1333static int copy_everything_to_user(struct ebt_table *t, void __user *user,
1333 int *len, int cmd) 1334 int *len, int cmd)
1334{ 1335{
@@ -1440,7 +1441,7 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1440 case EBT_SO_GET_INIT_INFO: 1441 case EBT_SO_GET_INIT_INFO:
1441 if (*len != sizeof(struct ebt_replace)){ 1442 if (*len != sizeof(struct ebt_replace)){
1442 ret = -EINVAL; 1443 ret = -EINVAL;
1443 up(&ebt_mutex); 1444 mutex_unlock(&ebt_mutex);
1444 break; 1445 break;
1445 } 1446 }
1446 if (cmd == EBT_SO_GET_INFO) { 1447 if (cmd == EBT_SO_GET_INFO) {
@@ -1452,7 +1453,7 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1452 tmp.entries_size = t->table->entries_size; 1453 tmp.entries_size = t->table->entries_size;
1453 tmp.valid_hooks = t->table->valid_hooks; 1454 tmp.valid_hooks = t->table->valid_hooks;
1454 } 1455 }
1455 up(&ebt_mutex); 1456 mutex_unlock(&ebt_mutex);
1456 if (copy_to_user(user, &tmp, *len) != 0){ 1457 if (copy_to_user(user, &tmp, *len) != 0){
1457 BUGPRINT("c2u Didn't work\n"); 1458 BUGPRINT("c2u Didn't work\n");
1458 ret = -EFAULT; 1459 ret = -EFAULT;
@@ -1464,11 +1465,11 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1464 case EBT_SO_GET_ENTRIES: 1465 case EBT_SO_GET_ENTRIES:
1465 case EBT_SO_GET_INIT_ENTRIES: 1466 case EBT_SO_GET_INIT_ENTRIES:
1466 ret = copy_everything_to_user(t, user, len, cmd); 1467 ret = copy_everything_to_user(t, user, len, cmd);
1467 up(&ebt_mutex); 1468 mutex_unlock(&ebt_mutex);
1468 break; 1469 break;
1469 1470
1470 default: 1471 default:
1471 up(&ebt_mutex); 1472 mutex_unlock(&ebt_mutex);
1472 ret = -EINVAL; 1473 ret = -EINVAL;
1473 } 1474 }
1474 1475
@@ -1476,17 +1477,23 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1476} 1477}
1477 1478
1478static struct nf_sockopt_ops ebt_sockopts = 1479static struct nf_sockopt_ops ebt_sockopts =
1479{ { NULL, NULL }, PF_INET, EBT_BASE_CTL, EBT_SO_SET_MAX + 1, do_ebt_set_ctl, 1480{
1480 EBT_BASE_CTL, EBT_SO_GET_MAX + 1, do_ebt_get_ctl, 0, NULL 1481 .pf = PF_INET,
1482 .set_optmin = EBT_BASE_CTL,
1483 .set_optmax = EBT_SO_SET_MAX + 1,
1484 .set = do_ebt_set_ctl,
1485 .get_optmin = EBT_BASE_CTL,
1486 .get_optmax = EBT_SO_GET_MAX + 1,
1487 .get = do_ebt_get_ctl,
1481}; 1488};
1482 1489
1483static int __init init(void) 1490static int __init init(void)
1484{ 1491{
1485 int ret; 1492 int ret;
1486 1493
1487 down(&ebt_mutex); 1494 mutex_lock(&ebt_mutex);
1488 list_named_insert(&ebt_targets, &ebt_standard_target); 1495 list_named_insert(&ebt_targets, &ebt_standard_target);
1489 up(&ebt_mutex); 1496 mutex_unlock(&ebt_mutex);
1490 if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0) 1497 if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0)
1491 return ret; 1498 return ret;
1492 1499
diff --git a/net/compat.c b/net/compat.c
index e593dace2fdb..8fd37cd7b501 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -416,7 +416,7 @@ struct compat_sock_fprog {
416 compat_uptr_t filter; /* struct sock_filter * */ 416 compat_uptr_t filter; /* struct sock_filter * */
417}; 417};
418 418
419static int do_set_attach_filter(int fd, int level, int optname, 419static int do_set_attach_filter(struct socket *sock, int level, int optname,
420 char __user *optval, int optlen) 420 char __user *optval, int optlen)
421{ 421{
422 struct compat_sock_fprog __user *fprog32 = (struct compat_sock_fprog __user *)optval; 422 struct compat_sock_fprog __user *fprog32 = (struct compat_sock_fprog __user *)optval;
@@ -432,11 +432,12 @@ static int do_set_attach_filter(int fd, int level, int optname,
432 __put_user(compat_ptr(ptr), &kfprog->filter)) 432 __put_user(compat_ptr(ptr), &kfprog->filter))
433 return -EFAULT; 433 return -EFAULT;
434 434
435 return sys_setsockopt(fd, level, optname, (char __user *)kfprog, 435 return sock_setsockopt(sock, level, optname, (char __user *)kfprog,
436 sizeof(struct sock_fprog)); 436 sizeof(struct sock_fprog));
437} 437}
438 438
439static int do_set_sock_timeout(int fd, int level, int optname, char __user *optval, int optlen) 439static int do_set_sock_timeout(struct socket *sock, int level,
440 int optname, char __user *optval, int optlen)
440{ 441{
441 struct compat_timeval __user *up = (struct compat_timeval __user *) optval; 442 struct compat_timeval __user *up = (struct compat_timeval __user *) optval;
442 struct timeval ktime; 443 struct timeval ktime;
@@ -451,30 +452,61 @@ static int do_set_sock_timeout(int fd, int level, int optname, char __user *optv
451 return -EFAULT; 452 return -EFAULT;
452 old_fs = get_fs(); 453 old_fs = get_fs();
453 set_fs(KERNEL_DS); 454 set_fs(KERNEL_DS);
454 err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime)); 455 err = sock_setsockopt(sock, level, optname, (char *) &ktime, sizeof(ktime));
455 set_fs(old_fs); 456 set_fs(old_fs);
456 457
457 return err; 458 return err;
458} 459}
459 460
461static int compat_sock_setsockopt(struct socket *sock, int level, int optname,
462 char __user *optval, int optlen)
463{
464 if (optname == SO_ATTACH_FILTER)
465 return do_set_attach_filter(sock, level, optname,
466 optval, optlen);
467 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
468 return do_set_sock_timeout(sock, level, optname, optval, optlen);
469
470 return sock_setsockopt(sock, level, optname, optval, optlen);
471}
472
460asmlinkage long compat_sys_setsockopt(int fd, int level, int optname, 473asmlinkage long compat_sys_setsockopt(int fd, int level, int optname,
461 char __user *optval, int optlen) 474 char __user *optval, int optlen)
462{ 475{
476 int err;
477 struct socket *sock;
478
463 /* SO_SET_REPLACE seems to be the same in all levels */ 479 /* SO_SET_REPLACE seems to be the same in all levels */
464 if (optname == IPT_SO_SET_REPLACE) 480 if (optname == IPT_SO_SET_REPLACE)
465 return do_netfilter_replace(fd, level, optname, 481 return do_netfilter_replace(fd, level, optname,
466 optval, optlen); 482 optval, optlen);
467 if (level == SOL_SOCKET && optname == SO_ATTACH_FILTER)
468 return do_set_attach_filter(fd, level, optname,
469 optval, optlen);
470 if (level == SOL_SOCKET &&
471 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO))
472 return do_set_sock_timeout(fd, level, optname, optval, optlen);
473 483
474 return sys_setsockopt(fd, level, optname, optval, optlen); 484 if (optlen < 0)
485 return -EINVAL;
486
487 if ((sock = sockfd_lookup(fd, &err))!=NULL)
488 {
489 err = security_socket_setsockopt(sock,level,optname);
490 if (err) {
491 sockfd_put(sock);
492 return err;
493 }
494
495 if (level == SOL_SOCKET)
496 err = compat_sock_setsockopt(sock, level,
497 optname, optval, optlen);
498 else if (sock->ops->compat_setsockopt)
499 err = sock->ops->compat_setsockopt(sock, level,
500 optname, optval, optlen);
501 else
502 err = sock->ops->setsockopt(sock, level,
503 optname, optval, optlen);
504 sockfd_put(sock);
505 }
506 return err;
475} 507}
476 508
477static int do_get_sock_timeout(int fd, int level, int optname, 509static int do_get_sock_timeout(struct socket *sock, int level, int optname,
478 char __user *optval, int __user *optlen) 510 char __user *optval, int __user *optlen)
479{ 511{
480 struct compat_timeval __user *up; 512 struct compat_timeval __user *up;
@@ -490,7 +522,7 @@ static int do_get_sock_timeout(int fd, int level, int optname,
490 len = sizeof(ktime); 522 len = sizeof(ktime);
491 old_fs = get_fs(); 523 old_fs = get_fs();
492 set_fs(KERNEL_DS); 524 set_fs(KERNEL_DS);
493 err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len); 525 err = sock_getsockopt(sock, level, optname, (char *) &ktime, &len);
494 set_fs(old_fs); 526 set_fs(old_fs);
495 527
496 if (!err) { 528 if (!err) {
@@ -503,15 +535,61 @@ static int do_get_sock_timeout(int fd, int level, int optname,
503 return err; 535 return err;
504} 536}
505 537
506asmlinkage long compat_sys_getsockopt(int fd, int level, int optname, 538static int compat_sock_getsockopt(struct socket *sock, int level, int optname,
507 char __user *optval, int __user *optlen) 539 char __user *optval, int __user *optlen)
508{ 540{
509 if (level == SOL_SOCKET && 541 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
510 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) 542 return do_get_sock_timeout(sock, level, optname, optval, optlen);
511 return do_get_sock_timeout(fd, level, optname, optval, optlen); 543 return sock_getsockopt(sock, level, optname, optval, optlen);
512 return sys_getsockopt(fd, level, optname, optval, optlen); 544}
545
546int compat_sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp)
547{
548 struct compat_timeval __user *ctv =
549 (struct compat_timeval __user*) userstamp;
550 int err = -ENOENT;
551
552 if (!sock_flag(sk, SOCK_TIMESTAMP))
553 sock_enable_timestamp(sk);
554 if (sk->sk_stamp.tv_sec == -1)
555 return err;
556 if (sk->sk_stamp.tv_sec == 0)
557 do_gettimeofday(&sk->sk_stamp);
558 if (put_user(sk->sk_stamp.tv_sec, &ctv->tv_sec) ||
559 put_user(sk->sk_stamp.tv_usec, &ctv->tv_usec))
560 err = -EFAULT;
561 return err;
513} 562}
563EXPORT_SYMBOL(compat_sock_get_timestamp);
564
565asmlinkage long compat_sys_getsockopt(int fd, int level, int optname,
566 char __user *optval, int __user *optlen)
567{
568 int err;
569 struct socket *sock;
570
571 if ((sock = sockfd_lookup(fd, &err))!=NULL)
572 {
573 err = security_socket_getsockopt(sock, level,
574 optname);
575 if (err) {
576 sockfd_put(sock);
577 return err;
578 }
514 579
580 if (level == SOL_SOCKET)
581 err = compat_sock_getsockopt(sock, level,
582 optname, optval, optlen);
583 else if (sock->ops->compat_getsockopt)
584 err = sock->ops->compat_getsockopt(sock, level,
585 optname, optval, optlen);
586 else
587 err = sock->ops->getsockopt(sock, level,
588 optname, optval, optlen);
589 sockfd_put(sock);
590 }
591 return err;
592}
515/* Argument list sizes for compat_sys_socketcall */ 593/* Argument list sizes for compat_sys_socketcall */
516#define AL(x) ((x) * sizeof(u32)) 594#define AL(x) ((x) * sizeof(u32))
517static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), 595static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
diff --git a/net/core/dev.c b/net/core/dev.c
index ef56c035d44e..08dec6eb922b 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -81,6 +81,7 @@
81#include <linux/types.h> 81#include <linux/types.h>
82#include <linux/kernel.h> 82#include <linux/kernel.h>
83#include <linux/sched.h> 83#include <linux/sched.h>
84#include <linux/mutex.h>
84#include <linux/string.h> 85#include <linux/string.h>
85#include <linux/mm.h> 86#include <linux/mm.h>
86#include <linux/socket.h> 87#include <linux/socket.h>
@@ -1759,8 +1760,7 @@ static void net_rx_action(struct softirq_action *h)
1759 if (dev->quota <= 0 || dev->poll(dev, &budget)) { 1760 if (dev->quota <= 0 || dev->poll(dev, &budget)) {
1760 netpoll_poll_unlock(have); 1761 netpoll_poll_unlock(have);
1761 local_irq_disable(); 1762 local_irq_disable();
1762 list_del(&dev->poll_list); 1763 list_move_tail(&dev->poll_list, &queue->poll_list);
1763 list_add_tail(&dev->poll_list, &queue->poll_list);
1764 if (dev->quota < 0) 1764 if (dev->quota < 0)
1765 dev->quota += dev->weight; 1765 dev->quota += dev->weight;
1766 else 1766 else
@@ -2174,12 +2174,20 @@ unsigned dev_get_flags(const struct net_device *dev)
2174 2174
2175 flags = (dev->flags & ~(IFF_PROMISC | 2175 flags = (dev->flags & ~(IFF_PROMISC |
2176 IFF_ALLMULTI | 2176 IFF_ALLMULTI |
2177 IFF_RUNNING)) | 2177 IFF_RUNNING |
2178 IFF_LOWER_UP |
2179 IFF_DORMANT)) |
2178 (dev->gflags & (IFF_PROMISC | 2180 (dev->gflags & (IFF_PROMISC |
2179 IFF_ALLMULTI)); 2181 IFF_ALLMULTI));
2180 2182
2181 if (netif_running(dev) && netif_carrier_ok(dev)) 2183 if (netif_running(dev)) {
2182 flags |= IFF_RUNNING; 2184 if (netif_oper_up(dev))
2185 flags |= IFF_RUNNING;
2186 if (netif_carrier_ok(dev))
2187 flags |= IFF_LOWER_UP;
2188 if (netif_dormant(dev))
2189 flags |= IFF_DORMANT;
2190 }
2183 2191
2184 return flags; 2192 return flags;
2185} 2193}
@@ -2458,9 +2466,9 @@ int dev_ioctl(unsigned int cmd, void __user *arg)
2458 */ 2466 */
2459 2467
2460 if (cmd == SIOCGIFCONF) { 2468 if (cmd == SIOCGIFCONF) {
2461 rtnl_shlock(); 2469 rtnl_lock();
2462 ret = dev_ifconf((char __user *) arg); 2470 ret = dev_ifconf((char __user *) arg);
2463 rtnl_shunlock(); 2471 rtnl_unlock();
2464 return ret; 2472 return ret;
2465 } 2473 }
2466 if (cmd == SIOCGIFNAME) 2474 if (cmd == SIOCGIFNAME)
@@ -2869,7 +2877,7 @@ static void netdev_wait_allrefs(struct net_device *dev)
2869 rebroadcast_time = warning_time = jiffies; 2877 rebroadcast_time = warning_time = jiffies;
2870 while (atomic_read(&dev->refcnt) != 0) { 2878 while (atomic_read(&dev->refcnt) != 0) {
2871 if (time_after(jiffies, rebroadcast_time + 1 * HZ)) { 2879 if (time_after(jiffies, rebroadcast_time + 1 * HZ)) {
2872 rtnl_shlock(); 2880 rtnl_lock();
2873 2881
2874 /* Rebroadcast unregister notification */ 2882 /* Rebroadcast unregister notification */
2875 notifier_call_chain(&netdev_chain, 2883 notifier_call_chain(&netdev_chain,
@@ -2886,7 +2894,7 @@ static void netdev_wait_allrefs(struct net_device *dev)
2886 linkwatch_run_queue(); 2894 linkwatch_run_queue();
2887 } 2895 }
2888 2896
2889 rtnl_shunlock(); 2897 __rtnl_unlock();
2890 2898
2891 rebroadcast_time = jiffies; 2899 rebroadcast_time = jiffies;
2892 } 2900 }
@@ -2924,7 +2932,7 @@ static void netdev_wait_allrefs(struct net_device *dev)
2924 * 2) Since we run with the RTNL semaphore not held, we can sleep 2932 * 2) Since we run with the RTNL semaphore not held, we can sleep
2925 * safely in order to wait for the netdev refcnt to drop to zero. 2933 * safely in order to wait for the netdev refcnt to drop to zero.
2926 */ 2934 */
2927static DECLARE_MUTEX(net_todo_run_mutex); 2935static DEFINE_MUTEX(net_todo_run_mutex);
2928void netdev_run_todo(void) 2936void netdev_run_todo(void)
2929{ 2937{
2930 struct list_head list = LIST_HEAD_INIT(list); 2938 struct list_head list = LIST_HEAD_INIT(list);
@@ -2932,7 +2940,7 @@ void netdev_run_todo(void)
2932 2940
2933 2941
2934 /* Need to guard against multiple cpu's getting out of order. */ 2942 /* Need to guard against multiple cpu's getting out of order. */
2935 down(&net_todo_run_mutex); 2943 mutex_lock(&net_todo_run_mutex);
2936 2944
2937 /* Not safe to do outside the semaphore. We must not return 2945 /* Not safe to do outside the semaphore. We must not return
2938 * until all unregister events invoked by the local processor 2946 * until all unregister events invoked by the local processor
@@ -2989,7 +2997,7 @@ void netdev_run_todo(void)
2989 } 2997 }
2990 2998
2991out: 2999out:
2992 up(&net_todo_run_mutex); 3000 mutex_unlock(&net_todo_run_mutex);
2993} 3001}
2994 3002
2995/** 3003/**
diff --git a/net/core/flow.c b/net/core/flow.c
index c4f25385029f..55789f832eda 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -20,6 +20,7 @@
20#include <linux/notifier.h> 20#include <linux/notifier.h>
21#include <linux/cpu.h> 21#include <linux/cpu.h>
22#include <linux/cpumask.h> 22#include <linux/cpumask.h>
23#include <linux/mutex.h>
23#include <net/flow.h> 24#include <net/flow.h>
24#include <asm/atomic.h> 25#include <asm/atomic.h>
25#include <asm/semaphore.h> 26#include <asm/semaphore.h>
@@ -287,11 +288,11 @@ static void flow_cache_flush_per_cpu(void *data)
287void flow_cache_flush(void) 288void flow_cache_flush(void)
288{ 289{
289 struct flow_flush_info info; 290 struct flow_flush_info info;
290 static DECLARE_MUTEX(flow_flush_sem); 291 static DEFINE_MUTEX(flow_flush_sem);
291 292
292 /* Don't want cpus going down or up during this. */ 293 /* Don't want cpus going down or up during this. */
293 lock_cpu_hotplug(); 294 lock_cpu_hotplug();
294 down(&flow_flush_sem); 295 mutex_lock(&flow_flush_sem);
295 atomic_set(&info.cpuleft, num_online_cpus()); 296 atomic_set(&info.cpuleft, num_online_cpus());
296 init_completion(&info.completion); 297 init_completion(&info.completion);
297 298
@@ -301,7 +302,7 @@ void flow_cache_flush(void)
301 local_bh_enable(); 302 local_bh_enable();
302 303
303 wait_for_completion(&info.completion); 304 wait_for_completion(&info.completion);
304 up(&flow_flush_sem); 305 mutex_unlock(&flow_flush_sem);
305 unlock_cpu_hotplug(); 306 unlock_cpu_hotplug();
306} 307}
307 308
diff --git a/net/core/link_watch.c b/net/core/link_watch.c
index d43d1201275c..341de44c7ed1 100644
--- a/net/core/link_watch.c
+++ b/net/core/link_watch.c
@@ -49,6 +49,45 @@ struct lw_event {
49/* Avoid kmalloc() for most systems */ 49/* Avoid kmalloc() for most systems */
50static struct lw_event singleevent; 50static struct lw_event singleevent;
51 51
52static unsigned char default_operstate(const struct net_device *dev)
53{
54 if (!netif_carrier_ok(dev))
55 return (dev->ifindex != dev->iflink ?
56 IF_OPER_LOWERLAYERDOWN : IF_OPER_DOWN);
57
58 if (netif_dormant(dev))
59 return IF_OPER_DORMANT;
60
61 return IF_OPER_UP;
62}
63
64
65static void rfc2863_policy(struct net_device *dev)
66{
67 unsigned char operstate = default_operstate(dev);
68
69 if (operstate == dev->operstate)
70 return;
71
72 write_lock_bh(&dev_base_lock);
73
74 switch(dev->link_mode) {
75 case IF_LINK_MODE_DORMANT:
76 if (operstate == IF_OPER_UP)
77 operstate = IF_OPER_DORMANT;
78 break;
79
80 case IF_LINK_MODE_DEFAULT:
81 default:
82 break;
83 };
84
85 dev->operstate = operstate;
86
87 write_unlock_bh(&dev_base_lock);
88}
89
90
52/* Must be called with the rtnl semaphore held */ 91/* Must be called with the rtnl semaphore held */
53void linkwatch_run_queue(void) 92void linkwatch_run_queue(void)
54{ 93{
@@ -74,6 +113,7 @@ void linkwatch_run_queue(void)
74 */ 113 */
75 clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state); 114 clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state);
76 115
116 rfc2863_policy(dev);
77 if (dev->flags & IFF_UP) { 117 if (dev->flags & IFF_UP) {
78 if (netif_carrier_ok(dev)) { 118 if (netif_carrier_ok(dev)) {
79 WARN_ON(dev->qdisc_sleeping == &noop_qdisc); 119 WARN_ON(dev->qdisc_sleeping == &noop_qdisc);
@@ -99,9 +139,9 @@ static void linkwatch_event(void *dummy)
99 linkwatch_nextevent = jiffies + HZ; 139 linkwatch_nextevent = jiffies + HZ;
100 clear_bit(LW_RUNNING, &linkwatch_flags); 140 clear_bit(LW_RUNNING, &linkwatch_flags);
101 141
102 rtnl_shlock(); 142 rtnl_lock();
103 linkwatch_run_queue(); 143 linkwatch_run_queue();
104 rtnl_shunlock(); 144 rtnl_unlock();
105} 145}
106 146
107 147
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index e68700f950a5..0c8666872d10 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -586,8 +586,8 @@ void neigh_destroy(struct neighbour *neigh)
586 kfree(hh); 586 kfree(hh);
587 } 587 }
588 588
589 if (neigh->ops && neigh->ops->destructor) 589 if (neigh->parms->neigh_destructor)
590 (neigh->ops->destructor)(neigh); 590 (neigh->parms->neigh_destructor)(neigh);
591 591
592 skb_queue_purge(&neigh->arp_queue); 592 skb_queue_purge(&neigh->arp_queue);
593 593
@@ -750,11 +750,13 @@ static void neigh_timer_handler(unsigned long arg)
750 neigh->used + neigh->parms->delay_probe_time)) { 750 neigh->used + neigh->parms->delay_probe_time)) {
751 NEIGH_PRINTK2("neigh %p is delayed.\n", neigh); 751 NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
752 neigh->nud_state = NUD_DELAY; 752 neigh->nud_state = NUD_DELAY;
753 neigh->updated = jiffies;
753 neigh_suspect(neigh); 754 neigh_suspect(neigh);
754 next = now + neigh->parms->delay_probe_time; 755 next = now + neigh->parms->delay_probe_time;
755 } else { 756 } else {
756 NEIGH_PRINTK2("neigh %p is suspected.\n", neigh); 757 NEIGH_PRINTK2("neigh %p is suspected.\n", neigh);
757 neigh->nud_state = NUD_STALE; 758 neigh->nud_state = NUD_STALE;
759 neigh->updated = jiffies;
758 neigh_suspect(neigh); 760 neigh_suspect(neigh);
759 } 761 }
760 } else if (state & NUD_DELAY) { 762 } else if (state & NUD_DELAY) {
@@ -762,11 +764,13 @@ static void neigh_timer_handler(unsigned long arg)
762 neigh->confirmed + neigh->parms->delay_probe_time)) { 764 neigh->confirmed + neigh->parms->delay_probe_time)) {
763 NEIGH_PRINTK2("neigh %p is now reachable.\n", neigh); 765 NEIGH_PRINTK2("neigh %p is now reachable.\n", neigh);
764 neigh->nud_state = NUD_REACHABLE; 766 neigh->nud_state = NUD_REACHABLE;
767 neigh->updated = jiffies;
765 neigh_connect(neigh); 768 neigh_connect(neigh);
766 next = neigh->confirmed + neigh->parms->reachable_time; 769 next = neigh->confirmed + neigh->parms->reachable_time;
767 } else { 770 } else {
768 NEIGH_PRINTK2("neigh %p is probed.\n", neigh); 771 NEIGH_PRINTK2("neigh %p is probed.\n", neigh);
769 neigh->nud_state = NUD_PROBE; 772 neigh->nud_state = NUD_PROBE;
773 neigh->updated = jiffies;
770 atomic_set(&neigh->probes, 0); 774 atomic_set(&neigh->probes, 0);
771 next = now + neigh->parms->retrans_time; 775 next = now + neigh->parms->retrans_time;
772 } 776 }
@@ -780,6 +784,7 @@ static void neigh_timer_handler(unsigned long arg)
780 struct sk_buff *skb; 784 struct sk_buff *skb;
781 785
782 neigh->nud_state = NUD_FAILED; 786 neigh->nud_state = NUD_FAILED;
787 neigh->updated = jiffies;
783 notify = 1; 788 notify = 1;
784 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed); 789 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
785 NEIGH_PRINTK2("neigh %p is failed.\n", neigh); 790 NEIGH_PRINTK2("neigh %p is failed.\n", neigh);
@@ -843,10 +848,12 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
843 if (neigh->parms->mcast_probes + neigh->parms->app_probes) { 848 if (neigh->parms->mcast_probes + neigh->parms->app_probes) {
844 atomic_set(&neigh->probes, neigh->parms->ucast_probes); 849 atomic_set(&neigh->probes, neigh->parms->ucast_probes);
845 neigh->nud_state = NUD_INCOMPLETE; 850 neigh->nud_state = NUD_INCOMPLETE;
851 neigh->updated = jiffies;
846 neigh_hold(neigh); 852 neigh_hold(neigh);
847 neigh_add_timer(neigh, now + 1); 853 neigh_add_timer(neigh, now + 1);
848 } else { 854 } else {
849 neigh->nud_state = NUD_FAILED; 855 neigh->nud_state = NUD_FAILED;
856 neigh->updated = jiffies;
850 write_unlock_bh(&neigh->lock); 857 write_unlock_bh(&neigh->lock);
851 858
852 if (skb) 859 if (skb)
@@ -857,6 +864,7 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
857 NEIGH_PRINTK2("neigh %p is delayed.\n", neigh); 864 NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
858 neigh_hold(neigh); 865 neigh_hold(neigh);
859 neigh->nud_state = NUD_DELAY; 866 neigh->nud_state = NUD_DELAY;
867 neigh->updated = jiffies;
860 neigh_add_timer(neigh, 868 neigh_add_timer(neigh,
861 jiffies + neigh->parms->delay_probe_time); 869 jiffies + neigh->parms->delay_probe_time);
862 } 870 }
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index e8b2acbc8ea2..21b68464cabb 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -91,6 +91,7 @@ NETDEVICE_SHOW(iflink, fmt_dec);
91NETDEVICE_SHOW(ifindex, fmt_dec); 91NETDEVICE_SHOW(ifindex, fmt_dec);
92NETDEVICE_SHOW(features, fmt_long_hex); 92NETDEVICE_SHOW(features, fmt_long_hex);
93NETDEVICE_SHOW(type, fmt_dec); 93NETDEVICE_SHOW(type, fmt_dec);
94NETDEVICE_SHOW(link_mode, fmt_dec);
94 95
95/* use same locking rules as GIFHWADDR ioctl's */ 96/* use same locking rules as GIFHWADDR ioctl's */
96static ssize_t format_addr(char *buf, const unsigned char *addr, int len) 97static ssize_t format_addr(char *buf, const unsigned char *addr, int len)
@@ -133,6 +134,43 @@ static ssize_t show_carrier(struct class_device *dev, char *buf)
133 return -EINVAL; 134 return -EINVAL;
134} 135}
135 136
137static ssize_t show_dormant(struct class_device *dev, char *buf)
138{
139 struct net_device *netdev = to_net_dev(dev);
140
141 if (netif_running(netdev))
142 return sprintf(buf, fmt_dec, !!netif_dormant(netdev));
143
144 return -EINVAL;
145}
146
147static const char *operstates[] = {
148 "unknown",
149 "notpresent", /* currently unused */
150 "down",
151 "lowerlayerdown",
152 "testing", /* currently unused */
153 "dormant",
154 "up"
155};
156
157static ssize_t show_operstate(struct class_device *dev, char *buf)
158{
159 const struct net_device *netdev = to_net_dev(dev);
160 unsigned char operstate;
161
162 read_lock(&dev_base_lock);
163 operstate = netdev->operstate;
164 if (!netif_running(netdev))
165 operstate = IF_OPER_DOWN;
166 read_unlock(&dev_base_lock);
167
168 if (operstate >= sizeof(operstates))
169 return -EINVAL; /* should not happen */
170
171 return sprintf(buf, "%s\n", operstates[operstate]);
172}
173
136/* read-write attributes */ 174/* read-write attributes */
137NETDEVICE_SHOW(mtu, fmt_dec); 175NETDEVICE_SHOW(mtu, fmt_dec);
138 176
@@ -190,9 +228,12 @@ static struct class_device_attribute net_class_attributes[] = {
190 __ATTR(ifindex, S_IRUGO, show_ifindex, NULL), 228 __ATTR(ifindex, S_IRUGO, show_ifindex, NULL),
191 __ATTR(features, S_IRUGO, show_features, NULL), 229 __ATTR(features, S_IRUGO, show_features, NULL),
192 __ATTR(type, S_IRUGO, show_type, NULL), 230 __ATTR(type, S_IRUGO, show_type, NULL),
231 __ATTR(link_mode, S_IRUGO, show_link_mode, NULL),
193 __ATTR(address, S_IRUGO, show_address, NULL), 232 __ATTR(address, S_IRUGO, show_address, NULL),
194 __ATTR(broadcast, S_IRUGO, show_broadcast, NULL), 233 __ATTR(broadcast, S_IRUGO, show_broadcast, NULL),
195 __ATTR(carrier, S_IRUGO, show_carrier, NULL), 234 __ATTR(carrier, S_IRUGO, show_carrier, NULL),
235 __ATTR(dormant, S_IRUGO, show_dormant, NULL),
236 __ATTR(operstate, S_IRUGO, show_operstate, NULL),
196 __ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu), 237 __ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu),
197 __ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags), 238 __ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags),
198 __ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len, 239 __ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len,
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index ea51f8d02eb8..e8e05cebd95a 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -669,14 +669,14 @@ int netpoll_setup(struct netpoll *np)
669 printk(KERN_INFO "%s: device %s not up yet, forcing it\n", 669 printk(KERN_INFO "%s: device %s not up yet, forcing it\n",
670 np->name, np->dev_name); 670 np->name, np->dev_name);
671 671
672 rtnl_shlock(); 672 rtnl_lock();
673 if (dev_change_flags(ndev, ndev->flags | IFF_UP) < 0) { 673 if (dev_change_flags(ndev, ndev->flags | IFF_UP) < 0) {
674 printk(KERN_ERR "%s: failed to open %s\n", 674 printk(KERN_ERR "%s: failed to open %s\n",
675 np->name, np->dev_name); 675 np->name, np->dev_name);
676 rtnl_shunlock(); 676 rtnl_unlock();
677 goto release; 677 goto release;
678 } 678 }
679 rtnl_shunlock(); 679 rtnl_unlock();
680 680
681 atleast = jiffies + HZ/10; 681 atleast = jiffies + HZ/10;
682 atmost = jiffies + 4*HZ; 682 atmost = jiffies + 4*HZ;
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index da16f8fd1494..c23e9c06ee23 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -106,6 +106,9 @@
106 * 106 *
107 * interruptible_sleep_on_timeout() replaced Nishanth Aravamudan <nacc@us.ibm.com> 107 * interruptible_sleep_on_timeout() replaced Nishanth Aravamudan <nacc@us.ibm.com>
108 * 050103 108 * 050103
109 *
110 * MPLS support by Steven Whitehouse <steve@chygwyn.com>
111 *
109 */ 112 */
110#include <linux/sys.h> 113#include <linux/sys.h>
111#include <linux/types.h> 114#include <linux/types.h>
@@ -113,6 +116,7 @@
113#include <linux/moduleparam.h> 116#include <linux/moduleparam.h>
114#include <linux/kernel.h> 117#include <linux/kernel.h>
115#include <linux/smp_lock.h> 118#include <linux/smp_lock.h>
119#include <linux/mutex.h>
116#include <linux/sched.h> 120#include <linux/sched.h>
117#include <linux/slab.h> 121#include <linux/slab.h>
118#include <linux/vmalloc.h> 122#include <linux/vmalloc.h>
@@ -125,6 +129,7 @@
125#include <linux/capability.h> 129#include <linux/capability.h>
126#include <linux/delay.h> 130#include <linux/delay.h>
127#include <linux/timer.h> 131#include <linux/timer.h>
132#include <linux/list.h>
128#include <linux/init.h> 133#include <linux/init.h>
129#include <linux/skbuff.h> 134#include <linux/skbuff.h>
130#include <linux/netdevice.h> 135#include <linux/netdevice.h>
@@ -149,38 +154,37 @@
149#include <asm/io.h> 154#include <asm/io.h>
150#include <asm/dma.h> 155#include <asm/dma.h>
151#include <asm/uaccess.h> 156#include <asm/uaccess.h>
152#include <asm/div64.h> /* do_div */ 157#include <asm/div64.h> /* do_div */
153#include <asm/timex.h> 158#include <asm/timex.h>
154 159
155 160#define VERSION "pktgen v2.67: Packet Generator for packet performance testing.\n"
156#define VERSION "pktgen v2.63: Packet Generator for packet performance testing.\n"
157 161
158/* #define PG_DEBUG(a) a */ 162/* #define PG_DEBUG(a) a */
159#define PG_DEBUG(a) 163#define PG_DEBUG(a)
160 164
161/* The buckets are exponential in 'width' */ 165/* The buckets are exponential in 'width' */
162#define LAT_BUCKETS_MAX 32 166#define LAT_BUCKETS_MAX 32
163#define IP_NAME_SZ 32 167#define IP_NAME_SZ 32
168#define MAX_MPLS_LABELS 16 /* This is the max label stack depth */
169#define MPLS_STACK_BOTTOM __constant_htonl(0x00000100)
164 170
165/* Device flag bits */ 171/* Device flag bits */
166#define F_IPSRC_RND (1<<0) /* IP-Src Random */ 172#define F_IPSRC_RND (1<<0) /* IP-Src Random */
167#define F_IPDST_RND (1<<1) /* IP-Dst Random */ 173#define F_IPDST_RND (1<<1) /* IP-Dst Random */
168#define F_UDPSRC_RND (1<<2) /* UDP-Src Random */ 174#define F_UDPSRC_RND (1<<2) /* UDP-Src Random */
169#define F_UDPDST_RND (1<<3) /* UDP-Dst Random */ 175#define F_UDPDST_RND (1<<3) /* UDP-Dst Random */
170#define F_MACSRC_RND (1<<4) /* MAC-Src Random */ 176#define F_MACSRC_RND (1<<4) /* MAC-Src Random */
171#define F_MACDST_RND (1<<5) /* MAC-Dst Random */ 177#define F_MACDST_RND (1<<5) /* MAC-Dst Random */
172#define F_TXSIZE_RND (1<<6) /* Transmit size is random */ 178#define F_TXSIZE_RND (1<<6) /* Transmit size is random */
173#define F_IPV6 (1<<7) /* Interface in IPV6 Mode */ 179#define F_IPV6 (1<<7) /* Interface in IPV6 Mode */
180#define F_MPLS_RND (1<<8) /* Random MPLS labels */
174 181
175/* Thread control flag bits */ 182/* Thread control flag bits */
176#define T_TERMINATE (1<<0) 183#define T_TERMINATE (1<<0)
177#define T_STOP (1<<1) /* Stop run */ 184#define T_STOP (1<<1) /* Stop run */
178#define T_RUN (1<<2) /* Start run */ 185#define T_RUN (1<<2) /* Start run */
179#define T_REMDEV (1<<3) /* Remove all devs */ 186#define T_REMDEVALL (1<<3) /* Remove all devs */
180 187#define T_REMDEV (1<<4) /* Remove one dev */
181/* Locks */
182#define thread_lock() down(&pktgen_sem)
183#define thread_unlock() up(&pktgen_sem)
184 188
185/* If lock -- can be removed after some work */ 189/* If lock -- can be removed after some work */
186#define if_lock(t) spin_lock(&(t->if_lock)); 190#define if_lock(t) spin_lock(&(t->if_lock));
@@ -194,10 +198,9 @@ static struct proc_dir_entry *pg_proc_dir = NULL;
194 198
195#define MAX_CFLOWS 65536 199#define MAX_CFLOWS 65536
196 200
197struct flow_state 201struct flow_state {
198{ 202 __u32 cur_daddr;
199 __u32 cur_daddr; 203 int count;
200 int count;
201}; 204};
202 205
203struct pktgen_dev { 206struct pktgen_dev {
@@ -206,141 +209,148 @@ struct pktgen_dev {
206 * Try to keep frequent/infrequent used vars. separated. 209 * Try to keep frequent/infrequent used vars. separated.
207 */ 210 */
208 211
209 char ifname[IFNAMSIZ]; 212 char ifname[IFNAMSIZ];
210 char result[512]; 213 char result[512];
211 214
212 struct pktgen_thread* pg_thread; /* the owner */ 215 struct pktgen_thread *pg_thread; /* the owner */
213 struct pktgen_dev *next; /* Used for chaining in the thread's run-queue */ 216 struct list_head list; /* Used for chaining in the thread's run-queue */
214 217
215 int running; /* if this changes to false, the test will stop */ 218 int running; /* if this changes to false, the test will stop */
216 219
217 /* If min != max, then we will either do a linear iteration, or 220 /* If min != max, then we will either do a linear iteration, or
218 * we will do a random selection from within the range. 221 * we will do a random selection from within the range.
219 */ 222 */
220 __u32 flags; 223 __u32 flags;
221 224 int removal_mark; /* non-zero => the device is marked for
222 int min_pkt_size; /* = ETH_ZLEN; */ 225 * removal by worker thread */
223 int max_pkt_size; /* = ETH_ZLEN; */ 226
224 int nfrags; 227 int min_pkt_size; /* = ETH_ZLEN; */
225 __u32 delay_us; /* Default delay */ 228 int max_pkt_size; /* = ETH_ZLEN; */
226 __u32 delay_ns; 229 int nfrags;
227 __u64 count; /* Default No packets to send */ 230 __u32 delay_us; /* Default delay */
228 __u64 sofar; /* How many pkts we've sent so far */ 231 __u32 delay_ns;
229 __u64 tx_bytes; /* How many bytes we've transmitted */ 232 __u64 count; /* Default No packets to send */
230 __u64 errors; /* Errors when trying to transmit, pkts will be re-sent */ 233 __u64 sofar; /* How many pkts we've sent so far */
231 234 __u64 tx_bytes; /* How many bytes we've transmitted */
232 /* runtime counters relating to clone_skb */ 235 __u64 errors; /* Errors when trying to transmit, pkts will be re-sent */
233 __u64 next_tx_us; /* timestamp of when to tx next */ 236
234 __u32 next_tx_ns; 237 /* runtime counters relating to clone_skb */
235 238 __u64 next_tx_us; /* timestamp of when to tx next */
236 __u64 allocated_skbs; 239 __u32 next_tx_ns;
237 __u32 clone_count; 240
238 int last_ok; /* Was last skb sent? 241 __u64 allocated_skbs;
239 * Or a failed transmit of some sort? This will keep 242 __u32 clone_count;
240 * sequence numbers in order, for example. 243 int last_ok; /* Was last skb sent?
241 */ 244 * Or a failed transmit of some sort? This will keep
242 __u64 started_at; /* micro-seconds */ 245 * sequence numbers in order, for example.
243 __u64 stopped_at; /* micro-seconds */ 246 */
244 __u64 idle_acc; /* micro-seconds */ 247 __u64 started_at; /* micro-seconds */
245 __u32 seq_num; 248 __u64 stopped_at; /* micro-seconds */
246 249 __u64 idle_acc; /* micro-seconds */
247 int clone_skb; /* Use multiple SKBs during packet gen. If this number 250 __u32 seq_num;
248 * is greater than 1, then that many copies of the same 251
249 * packet will be sent before a new packet is allocated. 252 int clone_skb; /* Use multiple SKBs during packet gen. If this number
250 * For instance, if you want to send 1024 identical packets 253 * is greater than 1, then that many copies of the same
251 * before creating a new packet, set clone_skb to 1024. 254 * packet will be sent before a new packet is allocated.
252 */ 255 * For instance, if you want to send 1024 identical packets
253 256 * before creating a new packet, set clone_skb to 1024.
254 char dst_min[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */ 257 */
255 char dst_max[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */ 258
256 char src_min[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */ 259 char dst_min[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */
257 char src_max[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */ 260 char dst_max[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */
258 261 char src_min[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */
259 struct in6_addr in6_saddr; 262 char src_max[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */
260 struct in6_addr in6_daddr; 263
261 struct in6_addr cur_in6_daddr; 264 struct in6_addr in6_saddr;
262 struct in6_addr cur_in6_saddr; 265 struct in6_addr in6_daddr;
266 struct in6_addr cur_in6_daddr;
267 struct in6_addr cur_in6_saddr;
263 /* For ranges */ 268 /* For ranges */
264 struct in6_addr min_in6_daddr; 269 struct in6_addr min_in6_daddr;
265 struct in6_addr max_in6_daddr; 270 struct in6_addr max_in6_daddr;
266 struct in6_addr min_in6_saddr; 271 struct in6_addr min_in6_saddr;
267 struct in6_addr max_in6_saddr; 272 struct in6_addr max_in6_saddr;
268 273
269 /* If we're doing ranges, random or incremental, then this 274 /* If we're doing ranges, random or incremental, then this
270 * defines the min/max for those ranges. 275 * defines the min/max for those ranges.
271 */ 276 */
272 __u32 saddr_min; /* inclusive, source IP address */ 277 __u32 saddr_min; /* inclusive, source IP address */
273 __u32 saddr_max; /* exclusive, source IP address */ 278 __u32 saddr_max; /* exclusive, source IP address */
274 __u32 daddr_min; /* inclusive, dest IP address */ 279 __u32 daddr_min; /* inclusive, dest IP address */
275 __u32 daddr_max; /* exclusive, dest IP address */ 280 __u32 daddr_max; /* exclusive, dest IP address */
276 281
277 __u16 udp_src_min; /* inclusive, source UDP port */ 282 __u16 udp_src_min; /* inclusive, source UDP port */
278 __u16 udp_src_max; /* exclusive, source UDP port */ 283 __u16 udp_src_max; /* exclusive, source UDP port */
279 __u16 udp_dst_min; /* inclusive, dest UDP port */ 284 __u16 udp_dst_min; /* inclusive, dest UDP port */
280 __u16 udp_dst_max; /* exclusive, dest UDP port */ 285 __u16 udp_dst_max; /* exclusive, dest UDP port */
281 286
282 __u32 src_mac_count; /* How many MACs to iterate through */ 287 /* MPLS */
283 __u32 dst_mac_count; /* How many MACs to iterate through */ 288 unsigned nr_labels; /* Depth of stack, 0 = no MPLS */
284 289 __be32 labels[MAX_MPLS_LABELS];
285 unsigned char dst_mac[ETH_ALEN]; 290
286 unsigned char src_mac[ETH_ALEN]; 291 __u32 src_mac_count; /* How many MACs to iterate through */
287 292 __u32 dst_mac_count; /* How many MACs to iterate through */
288 __u32 cur_dst_mac_offset; 293
289 __u32 cur_src_mac_offset; 294 unsigned char dst_mac[ETH_ALEN];
290 __u32 cur_saddr; 295 unsigned char src_mac[ETH_ALEN];
291 __u32 cur_daddr; 296
292 __u16 cur_udp_dst; 297 __u32 cur_dst_mac_offset;
293 __u16 cur_udp_src; 298 __u32 cur_src_mac_offset;
294 __u32 cur_pkt_size; 299 __u32 cur_saddr;
295 300 __u32 cur_daddr;
296 __u8 hh[14]; 301 __u16 cur_udp_dst;
297 /* = { 302 __u16 cur_udp_src;
298 0x00, 0x80, 0xC8, 0x79, 0xB3, 0xCB, 303 __u32 cur_pkt_size;
299 304
300 We fill in SRC address later 305 __u8 hh[14];
301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 306 /* = {
302 0x08, 0x00 307 0x00, 0x80, 0xC8, 0x79, 0xB3, 0xCB,
303 }; 308
304 */ 309 We fill in SRC address later
305 __u16 pad; /* pad out the hh struct to an even 16 bytes */ 310 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
306 311 0x08, 0x00
307 struct sk_buff* skb; /* skb we are to transmit next, mainly used for when we 312 };
308 * are transmitting the same one multiple times 313 */
309 */ 314 __u16 pad; /* pad out the hh struct to an even 16 bytes */
310 struct net_device* odev; /* The out-going device. Note that the device should 315
311 * have it's pg_info pointer pointing back to this 316 struct sk_buff *skb; /* skb we are to transmit next, mainly used for when we
312 * device. This will be set when the user specifies 317 * are transmitting the same one multiple times
313 * the out-going device name (not when the inject is 318 */
314 * started as it used to do.) 319 struct net_device *odev; /* The out-going device. Note that the device should
315 */ 320 * have it's pg_info pointer pointing back to this
321 * device. This will be set when the user specifies
322 * the out-going device name (not when the inject is
323 * started as it used to do.)
324 */
316 struct flow_state *flows; 325 struct flow_state *flows;
317 unsigned cflows; /* Concurrent flows (config) */ 326 unsigned cflows; /* Concurrent flows (config) */
318 unsigned lflow; /* Flow length (config) */ 327 unsigned lflow; /* Flow length (config) */
319 unsigned nflows; /* accumulated flows (stats) */ 328 unsigned nflows; /* accumulated flows (stats) */
320}; 329};
321 330
322struct pktgen_hdr { 331struct pktgen_hdr {
323 __u32 pgh_magic; 332 __u32 pgh_magic;
324 __u32 seq_num; 333 __u32 seq_num;
325 __u32 tv_sec; 334 __u32 tv_sec;
326 __u32 tv_usec; 335 __u32 tv_usec;
327}; 336};
328 337
329struct pktgen_thread { 338struct pktgen_thread {
330 spinlock_t if_lock; 339 spinlock_t if_lock;
331 struct pktgen_dev *if_list; /* All device here */ 340 struct list_head if_list; /* All device here */
332 struct pktgen_thread* next; 341 struct list_head th_list;
333 char name[32]; 342 int removed;
334 char result[512]; 343 char name[32];
335 u32 max_before_softirq; /* We'll call do_softirq to prevent starvation. */ 344 char result[512];
336 345 u32 max_before_softirq; /* We'll call do_softirq to prevent starvation. */
337 /* Field for thread to receive "posted" events terminate, stop ifs etc.*/ 346
338 347 /* Field for thread to receive "posted" events terminate, stop ifs etc. */
339 u32 control; 348
349 u32 control;
340 int pid; 350 int pid;
341 int cpu; 351 int cpu;
342 352
343 wait_queue_head_t queue; 353 wait_queue_head_t queue;
344}; 354};
345 355
346#define REMOVE 1 356#define REMOVE 1
@@ -364,77 +374,76 @@ struct pktgen_thread {
364 */ 374 */
365static inline s64 divremdi3(s64 x, s64 y, int type) 375static inline s64 divremdi3(s64 x, s64 y, int type)
366{ 376{
367 u64 a = (x < 0) ? -x : x; 377 u64 a = (x < 0) ? -x : x;
368 u64 b = (y < 0) ? -y : y; 378 u64 b = (y < 0) ? -y : y;
369 u64 res = 0, d = 1; 379 u64 res = 0, d = 1;
370 380
371 if (b > 0) { 381 if (b > 0) {
372 while (b < a) { 382 while (b < a) {
373 b <<= 1; 383 b <<= 1;
374 d <<= 1; 384 d <<= 1;
375 } 385 }
376 } 386 }
377 387
378 do { 388 do {
379 if ( a >= b ) { 389 if (a >= b) {
380 a -= b; 390 a -= b;
381 res += d; 391 res += d;
382 } 392 }
383 b >>= 1; 393 b >>= 1;
384 d >>= 1; 394 d >>= 1;
385 } 395 }
386 while (d); 396 while (d);
387 397
388 if (PG_DIV == type) { 398 if (PG_DIV == type) {
389 return (((x ^ y) & (1ll<<63)) == 0) ? res : -(s64)res; 399 return (((x ^ y) & (1ll << 63)) == 0) ? res : -(s64) res;
390 } 400 } else {
391 else { 401 return ((x & (1ll << 63)) == 0) ? a : -(s64) a;
392 return ((x & (1ll<<63)) == 0) ? a : -(s64)a; 402 }
393 }
394} 403}
395 404
396/* End of hacks to deal with 64-bit math on x86 */ 405/* End of hacks to deal with 64-bit math on x86 */
397 406
398/** Convert to milliseconds */ 407/** Convert to milliseconds */
399static inline __u64 tv_to_ms(const struct timeval* tv) 408static inline __u64 tv_to_ms(const struct timeval *tv)
400{ 409{
401 __u64 ms = tv->tv_usec / 1000; 410 __u64 ms = tv->tv_usec / 1000;
402 ms += (__u64)tv->tv_sec * (__u64)1000; 411 ms += (__u64) tv->tv_sec * (__u64) 1000;
403 return ms; 412 return ms;
404} 413}
405 414
406
407/** Convert to micro-seconds */ 415/** Convert to micro-seconds */
408static inline __u64 tv_to_us(const struct timeval* tv) 416static inline __u64 tv_to_us(const struct timeval *tv)
409{ 417{
410 __u64 us = tv->tv_usec; 418 __u64 us = tv->tv_usec;
411 us += (__u64)tv->tv_sec * (__u64)1000000; 419 us += (__u64) tv->tv_sec * (__u64) 1000000;
412 return us; 420 return us;
413} 421}
414 422
415static inline __u64 pg_div(__u64 n, __u32 base) { 423static inline __u64 pg_div(__u64 n, __u32 base)
416 __u64 tmp = n; 424{
417 do_div(tmp, base); 425 __u64 tmp = n;
418 /* printk("pktgen: pg_div, n: %llu base: %d rv: %llu\n", 426 do_div(tmp, base);
419 n, base, tmp); */ 427 /* printk("pktgen: pg_div, n: %llu base: %d rv: %llu\n",
420 return tmp; 428 n, base, tmp); */
429 return tmp;
421} 430}
422 431
423static inline __u64 pg_div64(__u64 n, __u64 base) 432static inline __u64 pg_div64(__u64 n, __u64 base)
424{ 433{
425 __u64 tmp = n; 434 __u64 tmp = n;
426/* 435/*
427 * How do we know if the architecture we are running on 436 * How do we know if the architecture we are running on
428 * supports division with 64 bit base? 437 * supports division with 64 bit base?
429 * 438 *
430 */ 439 */
431#if defined(__sparc_v9__) || defined(__powerpc64__) || defined(__alpha__) || defined(__x86_64__) || defined(__ia64__) 440#if defined(__sparc_v9__) || defined(__powerpc64__) || defined(__alpha__) || defined(__x86_64__) || defined(__ia64__)
432 441
433 do_div(tmp, base); 442 do_div(tmp, base);
434#else 443#else
435 tmp = divremdi3(n, base, PG_DIV); 444 tmp = divremdi3(n, base, PG_DIV);
436#endif 445#endif
437 return tmp; 446 return tmp;
438} 447}
439 448
440static inline u32 pktgen_random(void) 449static inline u32 pktgen_random(void)
@@ -448,51 +457,51 @@ static inline u32 pktgen_random(void)
448#endif 457#endif
449} 458}
450 459
451static inline __u64 getCurMs(void) 460static inline __u64 getCurMs(void)
452{ 461{
453 struct timeval tv; 462 struct timeval tv;
454 do_gettimeofday(&tv); 463 do_gettimeofday(&tv);
455 return tv_to_ms(&tv); 464 return tv_to_ms(&tv);
456} 465}
457 466
458static inline __u64 getCurUs(void) 467static inline __u64 getCurUs(void)
459{ 468{
460 struct timeval tv; 469 struct timeval tv;
461 do_gettimeofday(&tv); 470 do_gettimeofday(&tv);
462 return tv_to_us(&tv); 471 return tv_to_us(&tv);
463} 472}
464 473
465static inline __u64 tv_diff(const struct timeval* a, const struct timeval* b) 474static inline __u64 tv_diff(const struct timeval *a, const struct timeval *b)
466{ 475{
467 return tv_to_us(a) - tv_to_us(b); 476 return tv_to_us(a) - tv_to_us(b);
468} 477}
469 478
470
471/* old include end */ 479/* old include end */
472 480
473static char version[] __initdata = VERSION; 481static char version[] __initdata = VERSION;
474 482
475static int pktgen_remove_device(struct pktgen_thread* t, struct pktgen_dev *i); 483static int pktgen_remove_device(struct pktgen_thread *t, struct pktgen_dev *i);
476static int pktgen_add_device(struct pktgen_thread* t, const char* ifname); 484static int pktgen_add_device(struct pktgen_thread *t, const char *ifname);
477static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread* t, const char* ifname); 485static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t,
486 const char *ifname);
478static int pktgen_device_event(struct notifier_block *, unsigned long, void *); 487static int pktgen_device_event(struct notifier_block *, unsigned long, void *);
479static void pktgen_run_all_threads(void); 488static void pktgen_run_all_threads(void);
480static void pktgen_stop_all_threads_ifs(void); 489static void pktgen_stop_all_threads_ifs(void);
481static int pktgen_stop_device(struct pktgen_dev *pkt_dev); 490static int pktgen_stop_device(struct pktgen_dev *pkt_dev);
482static void pktgen_stop(struct pktgen_thread* t); 491static void pktgen_stop(struct pktgen_thread *t);
483static void pktgen_clear_counters(struct pktgen_dev *pkt_dev); 492static void pktgen_clear_counters(struct pktgen_dev *pkt_dev);
484static struct pktgen_dev *pktgen_NN_threads(const char* dev_name, int remove); 493static int pktgen_mark_device(const char *ifname);
485static unsigned int scan_ip6(const char *s,char ip[16]); 494static unsigned int scan_ip6(const char *s, char ip[16]);
486static unsigned int fmt_ip6(char *s,const char ip[16]); 495static unsigned int fmt_ip6(char *s, const char ip[16]);
487 496
488/* Module parameters, defaults. */ 497/* Module parameters, defaults. */
489static int pg_count_d = 1000; /* 1000 pkts by default */ 498static int pg_count_d = 1000; /* 1000 pkts by default */
490static int pg_delay_d; 499static int pg_delay_d;
491static int pg_clone_skb_d; 500static int pg_clone_skb_d;
492static int debug; 501static int debug;
493 502
494static DECLARE_MUTEX(pktgen_sem); 503static DEFINE_MUTEX(pktgen_thread_lock);
495static struct pktgen_thread *pktgen_threads = NULL; 504static LIST_HEAD(pktgen_threads);
496 505
497static struct notifier_block pktgen_notifier_block = { 506static struct notifier_block pktgen_notifier_block = {
498 .notifier_call = pktgen_device_event, 507 .notifier_call = pktgen_device_event,
@@ -504,21 +513,21 @@ static struct notifier_block pktgen_notifier_block = {
504 */ 513 */
505 514
506static int pgctrl_show(struct seq_file *seq, void *v) 515static int pgctrl_show(struct seq_file *seq, void *v)
507{ 516{
508 seq_puts(seq, VERSION); 517 seq_puts(seq, VERSION);
509 return 0; 518 return 0;
510} 519}
511 520
512static ssize_t pgctrl_write(struct file* file,const char __user * buf, 521static ssize_t pgctrl_write(struct file *file, const char __user * buf,
513 size_t count, loff_t *ppos) 522 size_t count, loff_t * ppos)
514{ 523{
515 int err = 0; 524 int err = 0;
516 char data[128]; 525 char data[128];
517 526
518 if (!capable(CAP_NET_ADMIN)){ 527 if (!capable(CAP_NET_ADMIN)) {
519 err = -EPERM; 528 err = -EPERM;
520 goto out; 529 goto out;
521 } 530 }
522 531
523 if (count > sizeof(data)) 532 if (count > sizeof(data))
524 count = sizeof(data); 533 count = sizeof(data);
@@ -526,22 +535,22 @@ static ssize_t pgctrl_write(struct file* file,const char __user * buf,
526 if (copy_from_user(data, buf, count)) { 535 if (copy_from_user(data, buf, count)) {
527 err = -EFAULT; 536 err = -EFAULT;
528 goto out; 537 goto out;
529 } 538 }
530 data[count-1] = 0; /* Make string */ 539 data[count - 1] = 0; /* Make string */
531 540
532 if (!strcmp(data, "stop")) 541 if (!strcmp(data, "stop"))
533 pktgen_stop_all_threads_ifs(); 542 pktgen_stop_all_threads_ifs();
534 543
535 else if (!strcmp(data, "start")) 544 else if (!strcmp(data, "start"))
536 pktgen_run_all_threads(); 545 pktgen_run_all_threads();
537 546
538 else 547 else
539 printk("pktgen: Unknown command: %s\n", data); 548 printk("pktgen: Unknown command: %s\n", data);
540 549
541 err = count; 550 err = count;
542 551
543 out: 552out:
544 return err; 553 return err;
545} 554}
546 555
547static int pgctrl_open(struct inode *inode, struct file *file) 556static int pgctrl_open(struct inode *inode, struct file *file)
@@ -550,147 +559,194 @@ static int pgctrl_open(struct inode *inode, struct file *file)
550} 559}
551 560
552static struct file_operations pktgen_fops = { 561static struct file_operations pktgen_fops = {
553 .owner = THIS_MODULE, 562 .owner = THIS_MODULE,
554 .open = pgctrl_open, 563 .open = pgctrl_open,
555 .read = seq_read, 564 .read = seq_read,
556 .llseek = seq_lseek, 565 .llseek = seq_lseek,
557 .write = pgctrl_write, 566 .write = pgctrl_write,
558 .release = single_release, 567 .release = single_release,
559}; 568};
560 569
561static int pktgen_if_show(struct seq_file *seq, void *v) 570static int pktgen_if_show(struct seq_file *seq, void *v)
562{ 571{
563 int i; 572 int i;
564 struct pktgen_dev *pkt_dev = seq->private; 573 struct pktgen_dev *pkt_dev = seq->private;
565 __u64 sa; 574 __u64 sa;
566 __u64 stopped; 575 __u64 stopped;
567 __u64 now = getCurUs(); 576 __u64 now = getCurUs();
568 577
569 seq_printf(seq, "Params: count %llu min_pkt_size: %u max_pkt_size: %u\n", 578 seq_printf(seq,
570 (unsigned long long) pkt_dev->count, 579 "Params: count %llu min_pkt_size: %u max_pkt_size: %u\n",
571 pkt_dev->min_pkt_size, pkt_dev->max_pkt_size); 580 (unsigned long long)pkt_dev->count, pkt_dev->min_pkt_size,
581 pkt_dev->max_pkt_size);
582
583 seq_printf(seq,
584 " frags: %d delay: %u clone_skb: %d ifname: %s\n",
585 pkt_dev->nfrags,
586 1000 * pkt_dev->delay_us + pkt_dev->delay_ns,
587 pkt_dev->clone_skb, pkt_dev->ifname);
588
589 seq_printf(seq, " flows: %u flowlen: %u\n", pkt_dev->cflows,
590 pkt_dev->lflow);
591
592 if (pkt_dev->flags & F_IPV6) {
593 char b1[128], b2[128], b3[128];
594 fmt_ip6(b1, pkt_dev->in6_saddr.s6_addr);
595 fmt_ip6(b2, pkt_dev->min_in6_saddr.s6_addr);
596 fmt_ip6(b3, pkt_dev->max_in6_saddr.s6_addr);
597 seq_printf(seq,
598 " saddr: %s min_saddr: %s max_saddr: %s\n", b1,
599 b2, b3);
600
601 fmt_ip6(b1, pkt_dev->in6_daddr.s6_addr);
602 fmt_ip6(b2, pkt_dev->min_in6_daddr.s6_addr);
603 fmt_ip6(b3, pkt_dev->max_in6_daddr.s6_addr);
604 seq_printf(seq,
605 " daddr: %s min_daddr: %s max_daddr: %s\n", b1,
606 b2, b3);
607
608 } else
609 seq_printf(seq,
610 " dst_min: %s dst_max: %s\n src_min: %s src_max: %s\n",
611 pkt_dev->dst_min, pkt_dev->dst_max, pkt_dev->src_min,
612 pkt_dev->src_max);
613
614 seq_puts(seq, " src_mac: ");
615
616 if (is_zero_ether_addr(pkt_dev->src_mac))
617 for (i = 0; i < 6; i++)
618 seq_printf(seq, "%02X%s", pkt_dev->odev->dev_addr[i],
619 i == 5 ? " " : ":");
620 else
621 for (i = 0; i < 6; i++)
622 seq_printf(seq, "%02X%s", pkt_dev->src_mac[i],
623 i == 5 ? " " : ":");
624
625 seq_printf(seq, "dst_mac: ");
626 for (i = 0; i < 6; i++)
627 seq_printf(seq, "%02X%s", pkt_dev->dst_mac[i],
628 i == 5 ? "\n" : ":");
629
630 seq_printf(seq,
631 " udp_src_min: %d udp_src_max: %d udp_dst_min: %d udp_dst_max: %d\n",
632 pkt_dev->udp_src_min, pkt_dev->udp_src_max,
633 pkt_dev->udp_dst_min, pkt_dev->udp_dst_max);
634
635 seq_printf(seq,
636 " src_mac_count: %d dst_mac_count: %d\n",
637 pkt_dev->src_mac_count, pkt_dev->dst_mac_count);
572 638
573 seq_printf(seq, " frags: %d delay: %u clone_skb: %d ifname: %s\n", 639 if (pkt_dev->nr_labels) {
574 pkt_dev->nfrags, 1000*pkt_dev->delay_us+pkt_dev->delay_ns, pkt_dev->clone_skb, pkt_dev->ifname); 640 unsigned i;
641 seq_printf(seq, " mpls: ");
642 for(i = 0; i < pkt_dev->nr_labels; i++)
643 seq_printf(seq, "%08x%s", ntohl(pkt_dev->labels[i]),
644 i == pkt_dev->nr_labels-1 ? "\n" : ", ");
645 }
575 646
576 seq_printf(seq, " flows: %u flowlen: %u\n", pkt_dev->cflows, pkt_dev->lflow); 647 seq_printf(seq, " Flags: ");
577 648
649 if (pkt_dev->flags & F_IPV6)
650 seq_printf(seq, "IPV6 ");
578 651
579 if(pkt_dev->flags & F_IPV6) { 652 if (pkt_dev->flags & F_IPSRC_RND)
580 char b1[128], b2[128], b3[128]; 653 seq_printf(seq, "IPSRC_RND ");
581 fmt_ip6(b1, pkt_dev->in6_saddr.s6_addr);
582 fmt_ip6(b2, pkt_dev->min_in6_saddr.s6_addr);
583 fmt_ip6(b3, pkt_dev->max_in6_saddr.s6_addr);
584 seq_printf(seq, " saddr: %s min_saddr: %s max_saddr: %s\n", b1, b2, b3);
585 654
586 fmt_ip6(b1, pkt_dev->in6_daddr.s6_addr); 655 if (pkt_dev->flags & F_IPDST_RND)
587 fmt_ip6(b2, pkt_dev->min_in6_daddr.s6_addr); 656 seq_printf(seq, "IPDST_RND ");
588 fmt_ip6(b3, pkt_dev->max_in6_daddr.s6_addr);
589 seq_printf(seq, " daddr: %s min_daddr: %s max_daddr: %s\n", b1, b2, b3);
590 657
591 } 658 if (pkt_dev->flags & F_TXSIZE_RND)
592 else 659 seq_printf(seq, "TXSIZE_RND ");
593 seq_printf(seq," dst_min: %s dst_max: %s\n src_min: %s src_max: %s\n",
594 pkt_dev->dst_min, pkt_dev->dst_max, pkt_dev->src_min, pkt_dev->src_max);
595 660
596 seq_puts(seq, " src_mac: "); 661 if (pkt_dev->flags & F_UDPSRC_RND)
662 seq_printf(seq, "UDPSRC_RND ");
597 663
598 if (is_zero_ether_addr(pkt_dev->src_mac)) 664 if (pkt_dev->flags & F_UDPDST_RND)
599 for (i = 0; i < 6; i++) 665 seq_printf(seq, "UDPDST_RND ");
600 seq_printf(seq, "%02X%s", pkt_dev->odev->dev_addr[i], i == 5 ? " " : ":");
601 else
602 for (i = 0; i < 6; i++)
603 seq_printf(seq, "%02X%s", pkt_dev->src_mac[i], i == 5 ? " " : ":");
604 666
605 seq_printf(seq, "dst_mac: "); 667 if (pkt_dev->flags & F_MPLS_RND)
606 for (i = 0; i < 6; i++) 668 seq_printf(seq, "MPLS_RND ");
607 seq_printf(seq, "%02X%s", pkt_dev->dst_mac[i], i == 5 ? "\n" : ":");
608 669
609 seq_printf(seq, " udp_src_min: %d udp_src_max: %d udp_dst_min: %d udp_dst_max: %d\n", 670 if (pkt_dev->flags & F_MACSRC_RND)
610 pkt_dev->udp_src_min, pkt_dev->udp_src_max, pkt_dev->udp_dst_min, 671 seq_printf(seq, "MACSRC_RND ");
611 pkt_dev->udp_dst_max);
612 672
613 seq_printf(seq, " src_mac_count: %d dst_mac_count: %d \n Flags: ", 673 if (pkt_dev->flags & F_MACDST_RND)
614 pkt_dev->src_mac_count, pkt_dev->dst_mac_count); 674 seq_printf(seq, "MACDST_RND ");
615 675
676 seq_puts(seq, "\n");
616 677
617 if (pkt_dev->flags & F_IPV6) 678 sa = pkt_dev->started_at;
618 seq_printf(seq, "IPV6 "); 679 stopped = pkt_dev->stopped_at;
619 680 if (pkt_dev->running)
620 if (pkt_dev->flags & F_IPSRC_RND) 681 stopped = now; /* not really stopped, more like last-running-at */
621 seq_printf(seq, "IPSRC_RND "); 682
622 683 seq_printf(seq,
623 if (pkt_dev->flags & F_IPDST_RND) 684 "Current:\n pkts-sofar: %llu errors: %llu\n started: %lluus stopped: %lluus idle: %lluus\n",
624 seq_printf(seq, "IPDST_RND "); 685 (unsigned long long)pkt_dev->sofar,
625 686 (unsigned long long)pkt_dev->errors, (unsigned long long)sa,
626 if (pkt_dev->flags & F_TXSIZE_RND) 687 (unsigned long long)stopped,
627 seq_printf(seq, "TXSIZE_RND "); 688 (unsigned long long)pkt_dev->idle_acc);
628 689
629 if (pkt_dev->flags & F_UDPSRC_RND) 690 seq_printf(seq,
630 seq_printf(seq, "UDPSRC_RND "); 691 " seq_num: %d cur_dst_mac_offset: %d cur_src_mac_offset: %d\n",
631
632 if (pkt_dev->flags & F_UDPDST_RND)
633 seq_printf(seq, "UDPDST_RND ");
634
635 if (pkt_dev->flags & F_MACSRC_RND)
636 seq_printf(seq, "MACSRC_RND ");
637
638 if (pkt_dev->flags & F_MACDST_RND)
639 seq_printf(seq, "MACDST_RND ");
640
641
642 seq_puts(seq, "\n");
643
644 sa = pkt_dev->started_at;
645 stopped = pkt_dev->stopped_at;
646 if (pkt_dev->running)
647 stopped = now; /* not really stopped, more like last-running-at */
648
649 seq_printf(seq, "Current:\n pkts-sofar: %llu errors: %llu\n started: %lluus stopped: %lluus idle: %lluus\n",
650 (unsigned long long) pkt_dev->sofar,
651 (unsigned long long) pkt_dev->errors,
652 (unsigned long long) sa,
653 (unsigned long long) stopped,
654 (unsigned long long) pkt_dev->idle_acc);
655
656 seq_printf(seq, " seq_num: %d cur_dst_mac_offset: %d cur_src_mac_offset: %d\n",
657 pkt_dev->seq_num, pkt_dev->cur_dst_mac_offset, 692 pkt_dev->seq_num, pkt_dev->cur_dst_mac_offset,
658 pkt_dev->cur_src_mac_offset); 693 pkt_dev->cur_src_mac_offset);
659 694
660 if(pkt_dev->flags & F_IPV6) { 695 if (pkt_dev->flags & F_IPV6) {
661 char b1[128], b2[128]; 696 char b1[128], b2[128];
662 fmt_ip6(b1, pkt_dev->cur_in6_daddr.s6_addr); 697 fmt_ip6(b1, pkt_dev->cur_in6_daddr.s6_addr);
663 fmt_ip6(b2, pkt_dev->cur_in6_saddr.s6_addr); 698 fmt_ip6(b2, pkt_dev->cur_in6_saddr.s6_addr);
664 seq_printf(seq, " cur_saddr: %s cur_daddr: %s\n", b2, b1); 699 seq_printf(seq, " cur_saddr: %s cur_daddr: %s\n", b2, b1);
665 } 700 } else
666 else 701 seq_printf(seq, " cur_saddr: 0x%x cur_daddr: 0x%x\n",
667 seq_printf(seq, " cur_saddr: 0x%x cur_daddr: 0x%x\n",
668 pkt_dev->cur_saddr, pkt_dev->cur_daddr); 702 pkt_dev->cur_saddr, pkt_dev->cur_daddr);
669 703
670 704 seq_printf(seq, " cur_udp_dst: %d cur_udp_src: %d\n",
671 seq_printf(seq, " cur_udp_dst: %d cur_udp_src: %d\n",
672 pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src); 705 pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src);
673 706
674 seq_printf(seq, " flows: %u\n", pkt_dev->nflows); 707 seq_printf(seq, " flows: %u\n", pkt_dev->nflows);
675 708
676 if (pkt_dev->result[0]) 709 if (pkt_dev->result[0])
677 seq_printf(seq, "Result: %s\n", pkt_dev->result); 710 seq_printf(seq, "Result: %s\n", pkt_dev->result);
678 else 711 else
679 seq_printf(seq, "Result: Idle\n"); 712 seq_printf(seq, "Result: Idle\n");
680 713
681 return 0; 714 return 0;
682} 715}
683 716
684 717
685static int count_trail_chars(const char __user *user_buffer, unsigned int maxlen) 718static int hex32_arg(const char __user *user_buffer, __u32 *num)
719{
720 int i = 0;
721 *num = 0;
722
723 for(; i < 8; i++) {
724 char c;
725 *num <<= 4;
726 if (get_user(c, &user_buffer[i]))
727 return -EFAULT;
728 if ((c >= '0') && (c <= '9'))
729 *num |= c - '0';
730 else if ((c >= 'a') && (c <= 'f'))
731 *num |= c - 'a' + 10;
732 else if ((c >= 'A') && (c <= 'F'))
733 *num |= c - 'A' + 10;
734 else
735 break;
736 }
737 return i;
738}
739
740static int count_trail_chars(const char __user * user_buffer,
741 unsigned int maxlen)
686{ 742{
687 int i; 743 int i;
688 744
689 for (i = 0; i < maxlen; i++) { 745 for (i = 0; i < maxlen; i++) {
690 char c; 746 char c;
691 if (get_user(c, &user_buffer[i])) 747 if (get_user(c, &user_buffer[i]))
692 return -EFAULT; 748 return -EFAULT;
693 switch (c) { 749 switch (c) {
694 case '\"': 750 case '\"':
695 case '\n': 751 case '\n':
696 case '\r': 752 case '\r':
@@ -706,34 +762,34 @@ done:
706 return i; 762 return i;
707} 763}
708 764
709static unsigned long num_arg(const char __user *user_buffer, unsigned long maxlen, 765static unsigned long num_arg(const char __user * user_buffer,
710 unsigned long *num) 766 unsigned long maxlen, unsigned long *num)
711{ 767{
712 int i = 0; 768 int i = 0;
713 *num = 0; 769 *num = 0;
714 770
715 for(; i < maxlen; i++) { 771 for (; i < maxlen; i++) {
716 char c; 772 char c;
717 if (get_user(c, &user_buffer[i])) 773 if (get_user(c, &user_buffer[i]))
718 return -EFAULT; 774 return -EFAULT;
719 if ((c >= '0') && (c <= '9')) { 775 if ((c >= '0') && (c <= '9')) {
720 *num *= 10; 776 *num *= 10;
721 *num += c -'0'; 777 *num += c - '0';
722 } else 778 } else
723 break; 779 break;
724 } 780 }
725 return i; 781 return i;
726} 782}
727 783
728static int strn_len(const char __user *user_buffer, unsigned int maxlen) 784static int strn_len(const char __user * user_buffer, unsigned int maxlen)
729{ 785{
730 int i = 0; 786 int i = 0;
731 787
732 for(; i < maxlen; i++) { 788 for (; i < maxlen; i++) {
733 char c; 789 char c;
734 if (get_user(c, &user_buffer[i])) 790 if (get_user(c, &user_buffer[i]))
735 return -EFAULT; 791 return -EFAULT;
736 switch (c) { 792 switch (c) {
737 case '\"': 793 case '\"':
738 case '\n': 794 case '\n':
739 case '\r': 795 case '\r':
@@ -746,119 +802,162 @@ static int strn_len(const char __user *user_buffer, unsigned int maxlen)
746 }; 802 };
747 } 803 }
748done_str: 804done_str:
805 return i;
806}
807
808static ssize_t get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev)
809{
810 unsigned n = 0;
811 char c;
812 ssize_t i = 0;
813 int len;
814
815 pkt_dev->nr_labels = 0;
816 do {
817 __u32 tmp;
818 len = hex32_arg(&buffer[i], &tmp);
819 if (len <= 0)
820 return len;
821 pkt_dev->labels[n] = htonl(tmp);
822 if (pkt_dev->labels[n] & MPLS_STACK_BOTTOM)
823 pkt_dev->flags |= F_MPLS_RND;
824 i += len;
825 if (get_user(c, &buffer[i]))
826 return -EFAULT;
827 i++;
828 n++;
829 if (n >= MAX_MPLS_LABELS)
830 return -E2BIG;
831 } while(c == ',');
749 832
833 pkt_dev->nr_labels = n;
750 return i; 834 return i;
751} 835}
752 836
753static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer, 837static ssize_t pktgen_if_write(struct file *file,
754 size_t count, loff_t *offset) 838 const char __user * user_buffer, size_t count,
839 loff_t * offset)
755{ 840{
756 struct seq_file *seq = (struct seq_file *) file->private_data; 841 struct seq_file *seq = (struct seq_file *)file->private_data;
757 struct pktgen_dev *pkt_dev = seq->private; 842 struct pktgen_dev *pkt_dev = seq->private;
758 int i = 0, max, len; 843 int i = 0, max, len;
759 char name[16], valstr[32]; 844 char name[16], valstr[32];
760 unsigned long value = 0; 845 unsigned long value = 0;
761 char* pg_result = NULL; 846 char *pg_result = NULL;
762 int tmp = 0; 847 int tmp = 0;
763 char buf[128]; 848 char buf[128];
764 849
765 pg_result = &(pkt_dev->result[0]); 850 pg_result = &(pkt_dev->result[0]);
766 851
767 if (count < 1) { 852 if (count < 1) {
768 printk("pktgen: wrong command format\n"); 853 printk("pktgen: wrong command format\n");
769 return -EINVAL; 854 return -EINVAL;
770 } 855 }
771 856
772 max = count - i; 857 max = count - i;
773 tmp = count_trail_chars(&user_buffer[i], max); 858 tmp = count_trail_chars(&user_buffer[i], max);
774 if (tmp < 0) { 859 if (tmp < 0) {
775 printk("pktgen: illegal format\n"); 860 printk("pktgen: illegal format\n");
776 return tmp; 861 return tmp;
777 } 862 }
778 i += tmp; 863 i += tmp;
779 864
780 /* Read variable name */ 865 /* Read variable name */
781 866
782 len = strn_len(&user_buffer[i], sizeof(name) - 1); 867 len = strn_len(&user_buffer[i], sizeof(name) - 1);
783 if (len < 0) { return len; } 868 if (len < 0) {
869 return len;
870 }
784 memset(name, 0, sizeof(name)); 871 memset(name, 0, sizeof(name));
785 if (copy_from_user(name, &user_buffer[i], len) ) 872 if (copy_from_user(name, &user_buffer[i], len))
786 return -EFAULT; 873 return -EFAULT;
787 i += len; 874 i += len;
788 875
789 max = count -i; 876 max = count - i;
790 len = count_trail_chars(&user_buffer[i], max); 877 len = count_trail_chars(&user_buffer[i], max);
791 if (len < 0) 878 if (len < 0)
792 return len; 879 return len;
793 880
794 i += len; 881 i += len;
795 882
796 if (debug) { 883 if (debug) {
797 char tb[count + 1]; 884 char tb[count + 1];
798 if (copy_from_user(tb, user_buffer, count)) 885 if (copy_from_user(tb, user_buffer, count))
799 return -EFAULT; 886 return -EFAULT;
800 tb[count] = 0; 887 tb[count] = 0;
801 printk("pktgen: %s,%lu buffer -:%s:-\n", name, 888 printk("pktgen: %s,%lu buffer -:%s:-\n", name,
802 (unsigned long) count, tb); 889 (unsigned long)count, tb);
803 } 890 }
804 891
805 if (!strcmp(name, "min_pkt_size")) { 892 if (!strcmp(name, "min_pkt_size")) {
806 len = num_arg(&user_buffer[i], 10, &value); 893 len = num_arg(&user_buffer[i], 10, &value);
807 if (len < 0) { return len; } 894 if (len < 0) {
895 return len;
896 }
808 i += len; 897 i += len;
809 if (value < 14+20+8) 898 if (value < 14 + 20 + 8)
810 value = 14+20+8; 899 value = 14 + 20 + 8;
811 if (value != pkt_dev->min_pkt_size) { 900 if (value != pkt_dev->min_pkt_size) {
812 pkt_dev->min_pkt_size = value; 901 pkt_dev->min_pkt_size = value;
813 pkt_dev->cur_pkt_size = value; 902 pkt_dev->cur_pkt_size = value;
814 } 903 }
815 sprintf(pg_result, "OK: min_pkt_size=%u", pkt_dev->min_pkt_size); 904 sprintf(pg_result, "OK: min_pkt_size=%u",
905 pkt_dev->min_pkt_size);
816 return count; 906 return count;
817 } 907 }
818 908
819 if (!strcmp(name, "max_pkt_size")) { 909 if (!strcmp(name, "max_pkt_size")) {
820 len = num_arg(&user_buffer[i], 10, &value); 910 len = num_arg(&user_buffer[i], 10, &value);
821 if (len < 0) { return len; } 911 if (len < 0) {
912 return len;
913 }
822 i += len; 914 i += len;
823 if (value < 14+20+8) 915 if (value < 14 + 20 + 8)
824 value = 14+20+8; 916 value = 14 + 20 + 8;
825 if (value != pkt_dev->max_pkt_size) { 917 if (value != pkt_dev->max_pkt_size) {
826 pkt_dev->max_pkt_size = value; 918 pkt_dev->max_pkt_size = value;
827 pkt_dev->cur_pkt_size = value; 919 pkt_dev->cur_pkt_size = value;
828 } 920 }
829 sprintf(pg_result, "OK: max_pkt_size=%u", pkt_dev->max_pkt_size); 921 sprintf(pg_result, "OK: max_pkt_size=%u",
922 pkt_dev->max_pkt_size);
830 return count; 923 return count;
831 } 924 }
832 925
833 /* Shortcut for min = max */ 926 /* Shortcut for min = max */
834 927
835 if (!strcmp(name, "pkt_size")) { 928 if (!strcmp(name, "pkt_size")) {
836 len = num_arg(&user_buffer[i], 10, &value); 929 len = num_arg(&user_buffer[i], 10, &value);
837 if (len < 0) { return len; } 930 if (len < 0) {
931 return len;
932 }
838 i += len; 933 i += len;
839 if (value < 14+20+8) 934 if (value < 14 + 20 + 8)
840 value = 14+20+8; 935 value = 14 + 20 + 8;
841 if (value != pkt_dev->min_pkt_size) { 936 if (value != pkt_dev->min_pkt_size) {
842 pkt_dev->min_pkt_size = value; 937 pkt_dev->min_pkt_size = value;
843 pkt_dev->max_pkt_size = value; 938 pkt_dev->max_pkt_size = value;
844 pkt_dev->cur_pkt_size = value; 939 pkt_dev->cur_pkt_size = value;
845 } 940 }
846 sprintf(pg_result, "OK: pkt_size=%u", pkt_dev->min_pkt_size); 941 sprintf(pg_result, "OK: pkt_size=%u", pkt_dev->min_pkt_size);
847 return count; 942 return count;
848 } 943 }
849 944
850 if (!strcmp(name, "debug")) { 945 if (!strcmp(name, "debug")) {
851 len = num_arg(&user_buffer[i], 10, &value); 946 len = num_arg(&user_buffer[i], 10, &value);
852 if (len < 0) { return len; } 947 if (len < 0) {
948 return len;
949 }
853 i += len; 950 i += len;
854 debug = value; 951 debug = value;
855 sprintf(pg_result, "OK: debug=%u", debug); 952 sprintf(pg_result, "OK: debug=%u", debug);
856 return count; 953 return count;
857 } 954 }
858 955
859 if (!strcmp(name, "frags")) { 956 if (!strcmp(name, "frags")) {
860 len = num_arg(&user_buffer[i], 10, &value); 957 len = num_arg(&user_buffer[i], 10, &value);
861 if (len < 0) { return len; } 958 if (len < 0) {
959 return len;
960 }
862 i += len; 961 i += len;
863 pkt_dev->nfrags = value; 962 pkt_dev->nfrags = value;
864 sprintf(pg_result, "OK: frags=%u", pkt_dev->nfrags); 963 sprintf(pg_result, "OK: frags=%u", pkt_dev->nfrags);
@@ -866,7 +965,9 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer
866 } 965 }
867 if (!strcmp(name, "delay")) { 966 if (!strcmp(name, "delay")) {
868 len = num_arg(&user_buffer[i], 10, &value); 967 len = num_arg(&user_buffer[i], 10, &value);
869 if (len < 0) { return len; } 968 if (len < 0) {
969 return len;
970 }
870 i += len; 971 i += len;
871 if (value == 0x7FFFFFFF) { 972 if (value == 0x7FFFFFFF) {
872 pkt_dev->delay_us = 0x7FFFFFFF; 973 pkt_dev->delay_us = 0x7FFFFFFF;
@@ -875,308 +976,353 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer
875 pkt_dev->delay_us = value / 1000; 976 pkt_dev->delay_us = value / 1000;
876 pkt_dev->delay_ns = value % 1000; 977 pkt_dev->delay_ns = value % 1000;
877 } 978 }
878 sprintf(pg_result, "OK: delay=%u", 1000*pkt_dev->delay_us+pkt_dev->delay_ns); 979 sprintf(pg_result, "OK: delay=%u",
980 1000 * pkt_dev->delay_us + pkt_dev->delay_ns);
879 return count; 981 return count;
880 } 982 }
881 if (!strcmp(name, "udp_src_min")) { 983 if (!strcmp(name, "udp_src_min")) {
882 len = num_arg(&user_buffer[i], 10, &value); 984 len = num_arg(&user_buffer[i], 10, &value);
883 if (len < 0) { return len; } 985 if (len < 0) {
986 return len;
987 }
884 i += len; 988 i += len;
885 if (value != pkt_dev->udp_src_min) { 989 if (value != pkt_dev->udp_src_min) {
886 pkt_dev->udp_src_min = value; 990 pkt_dev->udp_src_min = value;
887 pkt_dev->cur_udp_src = value; 991 pkt_dev->cur_udp_src = value;
888 } 992 }
889 sprintf(pg_result, "OK: udp_src_min=%u", pkt_dev->udp_src_min); 993 sprintf(pg_result, "OK: udp_src_min=%u", pkt_dev->udp_src_min);
890 return count; 994 return count;
891 } 995 }
892 if (!strcmp(name, "udp_dst_min")) { 996 if (!strcmp(name, "udp_dst_min")) {
893 len = num_arg(&user_buffer[i], 10, &value); 997 len = num_arg(&user_buffer[i], 10, &value);
894 if (len < 0) { return len; } 998 if (len < 0) {
999 return len;
1000 }
895 i += len; 1001 i += len;
896 if (value != pkt_dev->udp_dst_min) { 1002 if (value != pkt_dev->udp_dst_min) {
897 pkt_dev->udp_dst_min = value; 1003 pkt_dev->udp_dst_min = value;
898 pkt_dev->cur_udp_dst = value; 1004 pkt_dev->cur_udp_dst = value;
899 } 1005 }
900 sprintf(pg_result, "OK: udp_dst_min=%u", pkt_dev->udp_dst_min); 1006 sprintf(pg_result, "OK: udp_dst_min=%u", pkt_dev->udp_dst_min);
901 return count; 1007 return count;
902 } 1008 }
903 if (!strcmp(name, "udp_src_max")) { 1009 if (!strcmp(name, "udp_src_max")) {
904 len = num_arg(&user_buffer[i], 10, &value); 1010 len = num_arg(&user_buffer[i], 10, &value);
905 if (len < 0) { return len; } 1011 if (len < 0) {
1012 return len;
1013 }
906 i += len; 1014 i += len;
907 if (value != pkt_dev->udp_src_max) { 1015 if (value != pkt_dev->udp_src_max) {
908 pkt_dev->udp_src_max = value; 1016 pkt_dev->udp_src_max = value;
909 pkt_dev->cur_udp_src = value; 1017 pkt_dev->cur_udp_src = value;
910 } 1018 }
911 sprintf(pg_result, "OK: udp_src_max=%u", pkt_dev->udp_src_max); 1019 sprintf(pg_result, "OK: udp_src_max=%u", pkt_dev->udp_src_max);
912 return count; 1020 return count;
913 } 1021 }
914 if (!strcmp(name, "udp_dst_max")) { 1022 if (!strcmp(name, "udp_dst_max")) {
915 len = num_arg(&user_buffer[i], 10, &value); 1023 len = num_arg(&user_buffer[i], 10, &value);
916 if (len < 0) { return len; } 1024 if (len < 0) {
1025 return len;
1026 }
917 i += len; 1027 i += len;
918 if (value != pkt_dev->udp_dst_max) { 1028 if (value != pkt_dev->udp_dst_max) {
919 pkt_dev->udp_dst_max = value; 1029 pkt_dev->udp_dst_max = value;
920 pkt_dev->cur_udp_dst = value; 1030 pkt_dev->cur_udp_dst = value;
921 } 1031 }
922 sprintf(pg_result, "OK: udp_dst_max=%u", pkt_dev->udp_dst_max); 1032 sprintf(pg_result, "OK: udp_dst_max=%u", pkt_dev->udp_dst_max);
923 return count; 1033 return count;
924 } 1034 }
925 if (!strcmp(name, "clone_skb")) { 1035 if (!strcmp(name, "clone_skb")) {
926 len = num_arg(&user_buffer[i], 10, &value); 1036 len = num_arg(&user_buffer[i], 10, &value);
927 if (len < 0) { return len; } 1037 if (len < 0) {
1038 return len;
1039 }
928 i += len; 1040 i += len;
929 pkt_dev->clone_skb = value; 1041 pkt_dev->clone_skb = value;
930 1042
931 sprintf(pg_result, "OK: clone_skb=%d", pkt_dev->clone_skb); 1043 sprintf(pg_result, "OK: clone_skb=%d", pkt_dev->clone_skb);
932 return count; 1044 return count;
933 } 1045 }
934 if (!strcmp(name, "count")) { 1046 if (!strcmp(name, "count")) {
935 len = num_arg(&user_buffer[i], 10, &value); 1047 len = num_arg(&user_buffer[i], 10, &value);
936 if (len < 0) { return len; } 1048 if (len < 0) {
1049 return len;
1050 }
937 i += len; 1051 i += len;
938 pkt_dev->count = value; 1052 pkt_dev->count = value;
939 sprintf(pg_result, "OK: count=%llu", 1053 sprintf(pg_result, "OK: count=%llu",
940 (unsigned long long) pkt_dev->count); 1054 (unsigned long long)pkt_dev->count);
941 return count; 1055 return count;
942 } 1056 }
943 if (!strcmp(name, "src_mac_count")) { 1057 if (!strcmp(name, "src_mac_count")) {
944 len = num_arg(&user_buffer[i], 10, &value); 1058 len = num_arg(&user_buffer[i], 10, &value);
945 if (len < 0) { return len; } 1059 if (len < 0) {
1060 return len;
1061 }
946 i += len; 1062 i += len;
947 if (pkt_dev->src_mac_count != value) { 1063 if (pkt_dev->src_mac_count != value) {
948 pkt_dev->src_mac_count = value; 1064 pkt_dev->src_mac_count = value;
949 pkt_dev->cur_src_mac_offset = 0; 1065 pkt_dev->cur_src_mac_offset = 0;
950 } 1066 }
951 sprintf(pg_result, "OK: src_mac_count=%d", pkt_dev->src_mac_count); 1067 sprintf(pg_result, "OK: src_mac_count=%d",
1068 pkt_dev->src_mac_count);
952 return count; 1069 return count;
953 } 1070 }
954 if (!strcmp(name, "dst_mac_count")) { 1071 if (!strcmp(name, "dst_mac_count")) {
955 len = num_arg(&user_buffer[i], 10, &value); 1072 len = num_arg(&user_buffer[i], 10, &value);
956 if (len < 0) { return len; } 1073 if (len < 0) {
1074 return len;
1075 }
957 i += len; 1076 i += len;
958 if (pkt_dev->dst_mac_count != value) { 1077 if (pkt_dev->dst_mac_count != value) {
959 pkt_dev->dst_mac_count = value; 1078 pkt_dev->dst_mac_count = value;
960 pkt_dev->cur_dst_mac_offset = 0; 1079 pkt_dev->cur_dst_mac_offset = 0;
961 } 1080 }
962 sprintf(pg_result, "OK: dst_mac_count=%d", pkt_dev->dst_mac_count); 1081 sprintf(pg_result, "OK: dst_mac_count=%d",
1082 pkt_dev->dst_mac_count);
963 return count; 1083 return count;
964 } 1084 }
965 if (!strcmp(name, "flag")) { 1085 if (!strcmp(name, "flag")) {
966 char f[32]; 1086 char f[32];
967 memset(f, 0, 32); 1087 memset(f, 0, 32);
968 len = strn_len(&user_buffer[i], sizeof(f) - 1); 1088 len = strn_len(&user_buffer[i], sizeof(f) - 1);
969 if (len < 0) { return len; } 1089 if (len < 0) {
1090 return len;
1091 }
970 if (copy_from_user(f, &user_buffer[i], len)) 1092 if (copy_from_user(f, &user_buffer[i], len))
971 return -EFAULT; 1093 return -EFAULT;
972 i += len; 1094 i += len;
973 if (strcmp(f, "IPSRC_RND") == 0) 1095 if (strcmp(f, "IPSRC_RND") == 0)
974 pkt_dev->flags |= F_IPSRC_RND; 1096 pkt_dev->flags |= F_IPSRC_RND;
975 1097
976 else if (strcmp(f, "!IPSRC_RND") == 0) 1098 else if (strcmp(f, "!IPSRC_RND") == 0)
977 pkt_dev->flags &= ~F_IPSRC_RND; 1099 pkt_dev->flags &= ~F_IPSRC_RND;
978 1100
979 else if (strcmp(f, "TXSIZE_RND") == 0) 1101 else if (strcmp(f, "TXSIZE_RND") == 0)
980 pkt_dev->flags |= F_TXSIZE_RND; 1102 pkt_dev->flags |= F_TXSIZE_RND;
981 1103
982 else if (strcmp(f, "!TXSIZE_RND") == 0) 1104 else if (strcmp(f, "!TXSIZE_RND") == 0)
983 pkt_dev->flags &= ~F_TXSIZE_RND; 1105 pkt_dev->flags &= ~F_TXSIZE_RND;
984 1106
985 else if (strcmp(f, "IPDST_RND") == 0) 1107 else if (strcmp(f, "IPDST_RND") == 0)
986 pkt_dev->flags |= F_IPDST_RND; 1108 pkt_dev->flags |= F_IPDST_RND;
987 1109
988 else if (strcmp(f, "!IPDST_RND") == 0) 1110 else if (strcmp(f, "!IPDST_RND") == 0)
989 pkt_dev->flags &= ~F_IPDST_RND; 1111 pkt_dev->flags &= ~F_IPDST_RND;
990 1112
991 else if (strcmp(f, "UDPSRC_RND") == 0) 1113 else if (strcmp(f, "UDPSRC_RND") == 0)
992 pkt_dev->flags |= F_UDPSRC_RND; 1114 pkt_dev->flags |= F_UDPSRC_RND;
993 1115
994 else if (strcmp(f, "!UDPSRC_RND") == 0) 1116 else if (strcmp(f, "!UDPSRC_RND") == 0)
995 pkt_dev->flags &= ~F_UDPSRC_RND; 1117 pkt_dev->flags &= ~F_UDPSRC_RND;
996 1118
997 else if (strcmp(f, "UDPDST_RND") == 0) 1119 else if (strcmp(f, "UDPDST_RND") == 0)
998 pkt_dev->flags |= F_UDPDST_RND; 1120 pkt_dev->flags |= F_UDPDST_RND;
999 1121
1000 else if (strcmp(f, "!UDPDST_RND") == 0) 1122 else if (strcmp(f, "!UDPDST_RND") == 0)
1001 pkt_dev->flags &= ~F_UDPDST_RND; 1123 pkt_dev->flags &= ~F_UDPDST_RND;
1002 1124
1003 else if (strcmp(f, "MACSRC_RND") == 0) 1125 else if (strcmp(f, "MACSRC_RND") == 0)
1004 pkt_dev->flags |= F_MACSRC_RND; 1126 pkt_dev->flags |= F_MACSRC_RND;
1005 1127
1006 else if (strcmp(f, "!MACSRC_RND") == 0) 1128 else if (strcmp(f, "!MACSRC_RND") == 0)
1007 pkt_dev->flags &= ~F_MACSRC_RND; 1129 pkt_dev->flags &= ~F_MACSRC_RND;
1008 1130
1009 else if (strcmp(f, "MACDST_RND") == 0) 1131 else if (strcmp(f, "MACDST_RND") == 0)
1010 pkt_dev->flags |= F_MACDST_RND; 1132 pkt_dev->flags |= F_MACDST_RND;
1011 1133
1012 else if (strcmp(f, "!MACDST_RND") == 0) 1134 else if (strcmp(f, "!MACDST_RND") == 0)
1013 pkt_dev->flags &= ~F_MACDST_RND; 1135 pkt_dev->flags &= ~F_MACDST_RND;
1014 1136
1015 else { 1137 else if (strcmp(f, "MPLS_RND") == 0)
1016 sprintf(pg_result, "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s", 1138 pkt_dev->flags |= F_MPLS_RND;
1017 f, 1139
1018 "IPSRC_RND, IPDST_RND, TXSIZE_RND, UDPSRC_RND, UDPDST_RND, MACSRC_RND, MACDST_RND\n"); 1140 else if (strcmp(f, "!MPLS_RND") == 0)
1019 return count; 1141 pkt_dev->flags &= ~F_MPLS_RND;
1020 } 1142
1143 else {
1144 sprintf(pg_result,
1145 "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
1146 f,
1147 "IPSRC_RND, IPDST_RND, TXSIZE_RND, UDPSRC_RND, UDPDST_RND, MACSRC_RND, MACDST_RND\n");
1148 return count;
1149 }
1021 sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags); 1150 sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags);
1022 return count; 1151 return count;
1023 } 1152 }
1024 if (!strcmp(name, "dst_min") || !strcmp(name, "dst")) { 1153 if (!strcmp(name, "dst_min") || !strcmp(name, "dst")) {
1025 len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_min) - 1); 1154 len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_min) - 1);
1026 if (len < 0) { return len; } 1155 if (len < 0) {
1156 return len;
1157 }
1027 1158
1028 if (copy_from_user(buf, &user_buffer[i], len)) 1159 if (copy_from_user(buf, &user_buffer[i], len))
1029 return -EFAULT; 1160 return -EFAULT;
1030 buf[len] = 0; 1161 buf[len] = 0;
1031 if (strcmp(buf, pkt_dev->dst_min) != 0) { 1162 if (strcmp(buf, pkt_dev->dst_min) != 0) {
1032 memset(pkt_dev->dst_min, 0, sizeof(pkt_dev->dst_min)); 1163 memset(pkt_dev->dst_min, 0, sizeof(pkt_dev->dst_min));
1033 strncpy(pkt_dev->dst_min, buf, len); 1164 strncpy(pkt_dev->dst_min, buf, len);
1034 pkt_dev->daddr_min = in_aton(pkt_dev->dst_min); 1165 pkt_dev->daddr_min = in_aton(pkt_dev->dst_min);
1035 pkt_dev->cur_daddr = pkt_dev->daddr_min; 1166 pkt_dev->cur_daddr = pkt_dev->daddr_min;
1036 } 1167 }
1037 if(debug) 1168 if (debug)
1038 printk("pktgen: dst_min set to: %s\n", pkt_dev->dst_min); 1169 printk("pktgen: dst_min set to: %s\n",
1039 i += len; 1170 pkt_dev->dst_min);
1171 i += len;
1040 sprintf(pg_result, "OK: dst_min=%s", pkt_dev->dst_min); 1172 sprintf(pg_result, "OK: dst_min=%s", pkt_dev->dst_min);
1041 return count; 1173 return count;
1042 } 1174 }
1043 if (!strcmp(name, "dst_max")) { 1175 if (!strcmp(name, "dst_max")) {
1044 len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_max) - 1); 1176 len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_max) - 1);
1045 if (len < 0) { return len; } 1177 if (len < 0) {
1178 return len;
1179 }
1046 1180
1047 if (copy_from_user(buf, &user_buffer[i], len)) 1181 if (copy_from_user(buf, &user_buffer[i], len))
1048 return -EFAULT; 1182 return -EFAULT;
1049 1183
1050 buf[len] = 0; 1184 buf[len] = 0;
1051 if (strcmp(buf, pkt_dev->dst_max) != 0) { 1185 if (strcmp(buf, pkt_dev->dst_max) != 0) {
1052 memset(pkt_dev->dst_max, 0, sizeof(pkt_dev->dst_max)); 1186 memset(pkt_dev->dst_max, 0, sizeof(pkt_dev->dst_max));
1053 strncpy(pkt_dev->dst_max, buf, len); 1187 strncpy(pkt_dev->dst_max, buf, len);
1054 pkt_dev->daddr_max = in_aton(pkt_dev->dst_max); 1188 pkt_dev->daddr_max = in_aton(pkt_dev->dst_max);
1055 pkt_dev->cur_daddr = pkt_dev->daddr_max; 1189 pkt_dev->cur_daddr = pkt_dev->daddr_max;
1056 } 1190 }
1057 if(debug) 1191 if (debug)
1058 printk("pktgen: dst_max set to: %s\n", pkt_dev->dst_max); 1192 printk("pktgen: dst_max set to: %s\n",
1193 pkt_dev->dst_max);
1059 i += len; 1194 i += len;
1060 sprintf(pg_result, "OK: dst_max=%s", pkt_dev->dst_max); 1195 sprintf(pg_result, "OK: dst_max=%s", pkt_dev->dst_max);
1061 return count; 1196 return count;
1062 } 1197 }
1063 if (!strcmp(name, "dst6")) { 1198 if (!strcmp(name, "dst6")) {
1064 len = strn_len(&user_buffer[i], sizeof(buf) - 1); 1199 len = strn_len(&user_buffer[i], sizeof(buf) - 1);
1065 if (len < 0) return len; 1200 if (len < 0)
1201 return len;
1066 1202
1067 pkt_dev->flags |= F_IPV6; 1203 pkt_dev->flags |= F_IPV6;
1068 1204
1069 if (copy_from_user(buf, &user_buffer[i], len)) 1205 if (copy_from_user(buf, &user_buffer[i], len))
1070 return -EFAULT; 1206 return -EFAULT;
1071 buf[len] = 0; 1207 buf[len] = 0;
1072 1208
1073 scan_ip6(buf, pkt_dev->in6_daddr.s6_addr); 1209 scan_ip6(buf, pkt_dev->in6_daddr.s6_addr);
1074 fmt_ip6(buf, pkt_dev->in6_daddr.s6_addr); 1210 fmt_ip6(buf, pkt_dev->in6_daddr.s6_addr);
1075 1211
1076 ipv6_addr_copy(&pkt_dev->cur_in6_daddr, &pkt_dev->in6_daddr); 1212 ipv6_addr_copy(&pkt_dev->cur_in6_daddr, &pkt_dev->in6_daddr);
1077 1213
1078 if(debug) 1214 if (debug)
1079 printk("pktgen: dst6 set to: %s\n", buf); 1215 printk("pktgen: dst6 set to: %s\n", buf);
1080 1216
1081 i += len; 1217 i += len;
1082 sprintf(pg_result, "OK: dst6=%s", buf); 1218 sprintf(pg_result, "OK: dst6=%s", buf);
1083 return count; 1219 return count;
1084 } 1220 }
1085 if (!strcmp(name, "dst6_min")) { 1221 if (!strcmp(name, "dst6_min")) {
1086 len = strn_len(&user_buffer[i], sizeof(buf) - 1); 1222 len = strn_len(&user_buffer[i], sizeof(buf) - 1);
1087 if (len < 0) return len; 1223 if (len < 0)
1224 return len;
1088 1225
1089 pkt_dev->flags |= F_IPV6; 1226 pkt_dev->flags |= F_IPV6;
1090 1227
1091 if (copy_from_user(buf, &user_buffer[i], len)) 1228 if (copy_from_user(buf, &user_buffer[i], len))
1092 return -EFAULT; 1229 return -EFAULT;
1093 buf[len] = 0; 1230 buf[len] = 0;
1094 1231
1095 scan_ip6(buf, pkt_dev->min_in6_daddr.s6_addr); 1232 scan_ip6(buf, pkt_dev->min_in6_daddr.s6_addr);
1096 fmt_ip6(buf, pkt_dev->min_in6_daddr.s6_addr); 1233 fmt_ip6(buf, pkt_dev->min_in6_daddr.s6_addr);
1097 1234
1098 ipv6_addr_copy(&pkt_dev->cur_in6_daddr, &pkt_dev->min_in6_daddr); 1235 ipv6_addr_copy(&pkt_dev->cur_in6_daddr,
1099 if(debug) 1236 &pkt_dev->min_in6_daddr);
1237 if (debug)
1100 printk("pktgen: dst6_min set to: %s\n", buf); 1238 printk("pktgen: dst6_min set to: %s\n", buf);
1101 1239
1102 i += len; 1240 i += len;
1103 sprintf(pg_result, "OK: dst6_min=%s", buf); 1241 sprintf(pg_result, "OK: dst6_min=%s", buf);
1104 return count; 1242 return count;
1105 } 1243 }
1106 if (!strcmp(name, "dst6_max")) { 1244 if (!strcmp(name, "dst6_max")) {
1107 len = strn_len(&user_buffer[i], sizeof(buf) - 1); 1245 len = strn_len(&user_buffer[i], sizeof(buf) - 1);
1108 if (len < 0) return len; 1246 if (len < 0)
1247 return len;
1109 1248
1110 pkt_dev->flags |= F_IPV6; 1249 pkt_dev->flags |= F_IPV6;
1111 1250
1112 if (copy_from_user(buf, &user_buffer[i], len)) 1251 if (copy_from_user(buf, &user_buffer[i], len))
1113 return -EFAULT; 1252 return -EFAULT;
1114 buf[len] = 0; 1253 buf[len] = 0;
1115 1254
1116 scan_ip6(buf, pkt_dev->max_in6_daddr.s6_addr); 1255 scan_ip6(buf, pkt_dev->max_in6_daddr.s6_addr);
1117 fmt_ip6(buf, pkt_dev->max_in6_daddr.s6_addr); 1256 fmt_ip6(buf, pkt_dev->max_in6_daddr.s6_addr);
1118 1257
1119 if(debug) 1258 if (debug)
1120 printk("pktgen: dst6_max set to: %s\n", buf); 1259 printk("pktgen: dst6_max set to: %s\n", buf);
1121 1260
1122 i += len; 1261 i += len;
1123 sprintf(pg_result, "OK: dst6_max=%s", buf); 1262 sprintf(pg_result, "OK: dst6_max=%s", buf);
1124 return count; 1263 return count;
1125 } 1264 }
1126 if (!strcmp(name, "src6")) { 1265 if (!strcmp(name, "src6")) {
1127 len = strn_len(&user_buffer[i], sizeof(buf) - 1); 1266 len = strn_len(&user_buffer[i], sizeof(buf) - 1);
1128 if (len < 0) return len; 1267 if (len < 0)
1268 return len;
1129 1269
1130 pkt_dev->flags |= F_IPV6; 1270 pkt_dev->flags |= F_IPV6;
1131 1271
1132 if (copy_from_user(buf, &user_buffer[i], len)) 1272 if (copy_from_user(buf, &user_buffer[i], len))
1133 return -EFAULT; 1273 return -EFAULT;
1134 buf[len] = 0; 1274 buf[len] = 0;
1135 1275
1136 scan_ip6(buf, pkt_dev->in6_saddr.s6_addr); 1276 scan_ip6(buf, pkt_dev->in6_saddr.s6_addr);
1137 fmt_ip6(buf, pkt_dev->in6_saddr.s6_addr); 1277 fmt_ip6(buf, pkt_dev->in6_saddr.s6_addr);
1138 1278
1139 ipv6_addr_copy(&pkt_dev->cur_in6_saddr, &pkt_dev->in6_saddr); 1279 ipv6_addr_copy(&pkt_dev->cur_in6_saddr, &pkt_dev->in6_saddr);
1140 1280
1141 if(debug) 1281 if (debug)
1142 printk("pktgen: src6 set to: %s\n", buf); 1282 printk("pktgen: src6 set to: %s\n", buf);
1143 1283
1144 i += len; 1284 i += len;
1145 sprintf(pg_result, "OK: src6=%s", buf); 1285 sprintf(pg_result, "OK: src6=%s", buf);
1146 return count; 1286 return count;
1147 } 1287 }
1148 if (!strcmp(name, "src_min")) { 1288 if (!strcmp(name, "src_min")) {
1149 len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_min) - 1); 1289 len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_min) - 1);
1150 if (len < 0) { return len; } 1290 if (len < 0) {
1151 if (copy_from_user(buf, &user_buffer[i], len)) 1291 return len;
1292 }
1293 if (copy_from_user(buf, &user_buffer[i], len))
1152 return -EFAULT; 1294 return -EFAULT;
1153 buf[len] = 0; 1295 buf[len] = 0;
1154 if (strcmp(buf, pkt_dev->src_min) != 0) { 1296 if (strcmp(buf, pkt_dev->src_min) != 0) {
1155 memset(pkt_dev->src_min, 0, sizeof(pkt_dev->src_min)); 1297 memset(pkt_dev->src_min, 0, sizeof(pkt_dev->src_min));
1156 strncpy(pkt_dev->src_min, buf, len); 1298 strncpy(pkt_dev->src_min, buf, len);
1157 pkt_dev->saddr_min = in_aton(pkt_dev->src_min); 1299 pkt_dev->saddr_min = in_aton(pkt_dev->src_min);
1158 pkt_dev->cur_saddr = pkt_dev->saddr_min; 1300 pkt_dev->cur_saddr = pkt_dev->saddr_min;
1159 } 1301 }
1160 if(debug) 1302 if (debug)
1161 printk("pktgen: src_min set to: %s\n", pkt_dev->src_min); 1303 printk("pktgen: src_min set to: %s\n",
1304 pkt_dev->src_min);
1162 i += len; 1305 i += len;
1163 sprintf(pg_result, "OK: src_min=%s", pkt_dev->src_min); 1306 sprintf(pg_result, "OK: src_min=%s", pkt_dev->src_min);
1164 return count; 1307 return count;
1165 } 1308 }
1166 if (!strcmp(name, "src_max")) { 1309 if (!strcmp(name, "src_max")) {
1167 len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_max) - 1); 1310 len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_max) - 1);
1168 if (len < 0) { return len; } 1311 if (len < 0) {
1169 if (copy_from_user(buf, &user_buffer[i], len)) 1312 return len;
1313 }
1314 if (copy_from_user(buf, &user_buffer[i], len))
1170 return -EFAULT; 1315 return -EFAULT;
1171 buf[len] = 0; 1316 buf[len] = 0;
1172 if (strcmp(buf, pkt_dev->src_max) != 0) { 1317 if (strcmp(buf, pkt_dev->src_max) != 0) {
1173 memset(pkt_dev->src_max, 0, sizeof(pkt_dev->src_max)); 1318 memset(pkt_dev->src_max, 0, sizeof(pkt_dev->src_max));
1174 strncpy(pkt_dev->src_max, buf, len); 1319 strncpy(pkt_dev->src_max, buf, len);
1175 pkt_dev->saddr_max = in_aton(pkt_dev->src_max); 1320 pkt_dev->saddr_max = in_aton(pkt_dev->src_max);
1176 pkt_dev->cur_saddr = pkt_dev->saddr_max; 1321 pkt_dev->cur_saddr = pkt_dev->saddr_max;
1177 } 1322 }
1178 if(debug) 1323 if (debug)
1179 printk("pktgen: src_max set to: %s\n", pkt_dev->src_max); 1324 printk("pktgen: src_max set to: %s\n",
1325 pkt_dev->src_max);
1180 i += len; 1326 i += len;
1181 sprintf(pg_result, "OK: src_max=%s", pkt_dev->src_max); 1327 sprintf(pg_result, "OK: src_max=%s", pkt_dev->src_max);
1182 return count; 1328 return count;
@@ -1186,15 +1332,17 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer
1186 unsigned char old_dmac[ETH_ALEN]; 1332 unsigned char old_dmac[ETH_ALEN];
1187 unsigned char *m = pkt_dev->dst_mac; 1333 unsigned char *m = pkt_dev->dst_mac;
1188 memcpy(old_dmac, pkt_dev->dst_mac, ETH_ALEN); 1334 memcpy(old_dmac, pkt_dev->dst_mac, ETH_ALEN);
1189 1335
1190 len = strn_len(&user_buffer[i], sizeof(valstr) - 1); 1336 len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
1191 if (len < 0) { return len; } 1337 if (len < 0) {
1338 return len;
1339 }
1192 memset(valstr, 0, sizeof(valstr)); 1340 memset(valstr, 0, sizeof(valstr));
1193 if( copy_from_user(valstr, &user_buffer[i], len)) 1341 if (copy_from_user(valstr, &user_buffer[i], len))
1194 return -EFAULT; 1342 return -EFAULT;
1195 i += len; 1343 i += len;
1196 1344
1197 for(*m = 0;*v && m < pkt_dev->dst_mac + 6; v++) { 1345 for (*m = 0; *v && m < pkt_dev->dst_mac + 6; v++) {
1198 if (*v >= '0' && *v <= '9') { 1346 if (*v >= '0' && *v <= '9') {
1199 *m *= 16; 1347 *m *= 16;
1200 *m += *v - '0'; 1348 *m += *v - '0';
@@ -1216,7 +1364,7 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer
1216 /* Set up Dest MAC */ 1364 /* Set up Dest MAC */
1217 if (compare_ether_addr(old_dmac, pkt_dev->dst_mac)) 1365 if (compare_ether_addr(old_dmac, pkt_dev->dst_mac))
1218 memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN); 1366 memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN);
1219 1367
1220 sprintf(pg_result, "OK: dstmac"); 1368 sprintf(pg_result, "OK: dstmac");
1221 return count; 1369 return count;
1222 } 1370 }
@@ -1225,13 +1373,15 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer
1225 unsigned char *m = pkt_dev->src_mac; 1373 unsigned char *m = pkt_dev->src_mac;
1226 1374
1227 len = strn_len(&user_buffer[i], sizeof(valstr) - 1); 1375 len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
1228 if (len < 0) { return len; } 1376 if (len < 0) {
1377 return len;
1378 }
1229 memset(valstr, 0, sizeof(valstr)); 1379 memset(valstr, 0, sizeof(valstr));
1230 if( copy_from_user(valstr, &user_buffer[i], len)) 1380 if (copy_from_user(valstr, &user_buffer[i], len))
1231 return -EFAULT; 1381 return -EFAULT;
1232 i += len; 1382 i += len;
1233 1383
1234 for(*m = 0;*v && m < pkt_dev->src_mac + 6; v++) { 1384 for (*m = 0; *v && m < pkt_dev->src_mac + 6; v++) {
1235 if (*v >= '0' && *v <= '9') { 1385 if (*v >= '0' && *v <= '9') {
1236 *m *= 16; 1386 *m *= 16;
1237 *m += *v - '0'; 1387 *m += *v - '0';
@@ -1248,21 +1398,23 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer
1248 m++; 1398 m++;
1249 *m = 0; 1399 *m = 0;
1250 } 1400 }
1251 } 1401 }
1252 1402
1253 sprintf(pg_result, "OK: srcmac"); 1403 sprintf(pg_result, "OK: srcmac");
1254 return count; 1404 return count;
1255 } 1405 }
1256 1406
1257 if (!strcmp(name, "clear_counters")) { 1407 if (!strcmp(name, "clear_counters")) {
1258 pktgen_clear_counters(pkt_dev); 1408 pktgen_clear_counters(pkt_dev);
1259 sprintf(pg_result, "OK: Clearing counters.\n"); 1409 sprintf(pg_result, "OK: Clearing counters.\n");
1260 return count; 1410 return count;
1261 } 1411 }
1262 1412
1263 if (!strcmp(name, "flows")) { 1413 if (!strcmp(name, "flows")) {
1264 len = num_arg(&user_buffer[i], 10, &value); 1414 len = num_arg(&user_buffer[i], 10, &value);
1265 if (len < 0) { return len; } 1415 if (len < 0) {
1416 return len;
1417 }
1266 i += len; 1418 i += len;
1267 if (value > MAX_CFLOWS) 1419 if (value > MAX_CFLOWS)
1268 value = MAX_CFLOWS; 1420 value = MAX_CFLOWS;
@@ -1274,13 +1426,28 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer
1274 1426
1275 if (!strcmp(name, "flowlen")) { 1427 if (!strcmp(name, "flowlen")) {
1276 len = num_arg(&user_buffer[i], 10, &value); 1428 len = num_arg(&user_buffer[i], 10, &value);
1277 if (len < 0) { return len; } 1429 if (len < 0) {
1430 return len;
1431 }
1278 i += len; 1432 i += len;
1279 pkt_dev->lflow = value; 1433 pkt_dev->lflow = value;
1280 sprintf(pg_result, "OK: flowlen=%u", pkt_dev->lflow); 1434 sprintf(pg_result, "OK: flowlen=%u", pkt_dev->lflow);
1281 return count; 1435 return count;
1282 } 1436 }
1283 1437
1438 if (!strcmp(name, "mpls")) {
1439 unsigned n, offset;
1440 len = get_labels(&user_buffer[i], pkt_dev);
1441 if (len < 0) { return len; }
1442 i += len;
1443 offset = sprintf(pg_result, "OK: mpls=");
1444 for(n = 0; n < pkt_dev->nr_labels; n++)
1445 offset += sprintf(pg_result + offset,
1446 "%08x%s", ntohl(pkt_dev->labels[n]),
1447 n == pkt_dev->nr_labels-1 ? "" : ",");
1448 return count;
1449 }
1450
1284 sprintf(pkt_dev->result, "No such parameter \"%s\"", name); 1451 sprintf(pkt_dev->result, "No such parameter \"%s\"", name);
1285 return -EINVAL; 1452 return -EINVAL;
1286} 1453}
@@ -1291,35 +1458,35 @@ static int pktgen_if_open(struct inode *inode, struct file *file)
1291} 1458}
1292 1459
1293static struct file_operations pktgen_if_fops = { 1460static struct file_operations pktgen_if_fops = {
1294 .owner = THIS_MODULE, 1461 .owner = THIS_MODULE,
1295 .open = pktgen_if_open, 1462 .open = pktgen_if_open,
1296 .read = seq_read, 1463 .read = seq_read,
1297 .llseek = seq_lseek, 1464 .llseek = seq_lseek,
1298 .write = pktgen_if_write, 1465 .write = pktgen_if_write,
1299 .release = single_release, 1466 .release = single_release,
1300}; 1467};
1301 1468
1302static int pktgen_thread_show(struct seq_file *seq, void *v) 1469static int pktgen_thread_show(struct seq_file *seq, void *v)
1303{ 1470{
1304 struct pktgen_thread *t = seq->private; 1471 struct pktgen_thread *t = seq->private;
1305 struct pktgen_dev *pkt_dev = NULL; 1472 struct pktgen_dev *pkt_dev;
1306 1473
1307 BUG_ON(!t); 1474 BUG_ON(!t);
1308 1475
1309 seq_printf(seq, "Name: %s max_before_softirq: %d\n", 1476 seq_printf(seq, "Name: %s max_before_softirq: %d\n",
1310 t->name, t->max_before_softirq); 1477 t->name, t->max_before_softirq);
1478
1479 seq_printf(seq, "Running: ");
1311 1480
1312 seq_printf(seq, "Running: "); 1481 if_lock(t);
1313 1482 list_for_each_entry(pkt_dev, &t->if_list, list)
1314 if_lock(t); 1483 if (pkt_dev->running)
1315 for(pkt_dev = t->if_list;pkt_dev; pkt_dev = pkt_dev->next)
1316 if(pkt_dev->running)
1317 seq_printf(seq, "%s ", pkt_dev->ifname); 1484 seq_printf(seq, "%s ", pkt_dev->ifname);
1318
1319 seq_printf(seq, "\nStopped: ");
1320 1485
1321 for(pkt_dev = t->if_list;pkt_dev; pkt_dev = pkt_dev->next) 1486 seq_printf(seq, "\nStopped: ");
1322 if(!pkt_dev->running) 1487
1488 list_for_each_entry(pkt_dev, &t->if_list, list)
1489 if (!pkt_dev->running)
1323 seq_printf(seq, "%s ", pkt_dev->ifname); 1490 seq_printf(seq, "%s ", pkt_dev->ifname);
1324 1491
1325 if (t->result[0]) 1492 if (t->result[0])
@@ -1327,30 +1494,30 @@ static int pktgen_thread_show(struct seq_file *seq, void *v)
1327 else 1494 else
1328 seq_printf(seq, "\nResult: NA\n"); 1495 seq_printf(seq, "\nResult: NA\n");
1329 1496
1330 if_unlock(t); 1497 if_unlock(t);
1331 1498
1332 return 0; 1499 return 0;
1333} 1500}
1334 1501
1335static ssize_t pktgen_thread_write(struct file *file, 1502static ssize_t pktgen_thread_write(struct file *file,
1336 const char __user *user_buffer, 1503 const char __user * user_buffer,
1337 size_t count, loff_t *offset) 1504 size_t count, loff_t * offset)
1338{ 1505{
1339 struct seq_file *seq = (struct seq_file *) file->private_data; 1506 struct seq_file *seq = (struct seq_file *)file->private_data;
1340 struct pktgen_thread *t = seq->private; 1507 struct pktgen_thread *t = seq->private;
1341 int i = 0, max, len, ret; 1508 int i = 0, max, len, ret;
1342 char name[40]; 1509 char name[40];
1343 char *pg_result; 1510 char *pg_result;
1344 unsigned long value = 0; 1511 unsigned long value = 0;
1345 1512
1346 if (count < 1) { 1513 if (count < 1) {
1347 // sprintf(pg_result, "Wrong command format"); 1514 // sprintf(pg_result, "Wrong command format");
1348 return -EINVAL; 1515 return -EINVAL;
1349 } 1516 }
1350 1517
1351 max = count - i; 1518 max = count - i;
1352 len = count_trail_chars(&user_buffer[i], max); 1519 len = count_trail_chars(&user_buffer[i], max);
1353 if (len < 0) 1520 if (len < 0)
1354 return len; 1521 return len;
1355 1522
1356 i += len; 1523 i += len;
@@ -1358,26 +1525,25 @@ static ssize_t pktgen_thread_write(struct file *file,
1358 /* Read variable name */ 1525 /* Read variable name */
1359 1526
1360 len = strn_len(&user_buffer[i], sizeof(name) - 1); 1527 len = strn_len(&user_buffer[i], sizeof(name) - 1);
1361 if (len < 0) 1528 if (len < 0)
1362 return len; 1529 return len;
1363 1530
1364 memset(name, 0, sizeof(name)); 1531 memset(name, 0, sizeof(name));
1365 if (copy_from_user(name, &user_buffer[i], len)) 1532 if (copy_from_user(name, &user_buffer[i], len))
1366 return -EFAULT; 1533 return -EFAULT;
1367 i += len; 1534 i += len;
1368 1535
1369 max = count -i; 1536 max = count - i;
1370 len = count_trail_chars(&user_buffer[i], max); 1537 len = count_trail_chars(&user_buffer[i], max);
1371 if (len < 0) 1538 if (len < 0)
1372 return len; 1539 return len;
1373 1540
1374 i += len; 1541 i += len;
1375 1542
1376 if (debug) 1543 if (debug)
1377 printk("pktgen: t=%s, count=%lu\n", name, 1544 printk("pktgen: t=%s, count=%lu\n", name, (unsigned long)count);
1378 (unsigned long) count);
1379 1545
1380 if(!t) { 1546 if (!t) {
1381 printk("pktgen: ERROR: No thread\n"); 1547 printk("pktgen: ERROR: No thread\n");
1382 ret = -EINVAL; 1548 ret = -EINVAL;
1383 goto out; 1549 goto out;
@@ -1385,48 +1551,47 @@ static ssize_t pktgen_thread_write(struct file *file,
1385 1551
1386 pg_result = &(t->result[0]); 1552 pg_result = &(t->result[0]);
1387 1553
1388 if (!strcmp(name, "add_device")) { 1554 if (!strcmp(name, "add_device")) {
1389 char f[32]; 1555 char f[32];
1390 memset(f, 0, 32); 1556 memset(f, 0, 32);
1391 len = strn_len(&user_buffer[i], sizeof(f) - 1); 1557 len = strn_len(&user_buffer[i], sizeof(f) - 1);
1392 if (len < 0) { 1558 if (len < 0) {
1393 ret = len; 1559 ret = len;
1394 goto out; 1560 goto out;
1395 } 1561 }
1396 if( copy_from_user(f, &user_buffer[i], len) ) 1562 if (copy_from_user(f, &user_buffer[i], len))
1397 return -EFAULT; 1563 return -EFAULT;
1398 i += len; 1564 i += len;
1399 thread_lock(); 1565 mutex_lock(&pktgen_thread_lock);
1400 pktgen_add_device(t, f); 1566 pktgen_add_device(t, f);
1401 thread_unlock(); 1567 mutex_unlock(&pktgen_thread_lock);
1402 ret = count; 1568 ret = count;
1403 sprintf(pg_result, "OK: add_device=%s", f); 1569 sprintf(pg_result, "OK: add_device=%s", f);
1404 goto out; 1570 goto out;
1405 } 1571 }
1406 1572
1407 if (!strcmp(name, "rem_device_all")) { 1573 if (!strcmp(name, "rem_device_all")) {
1408 thread_lock(); 1574 mutex_lock(&pktgen_thread_lock);
1409 t->control |= T_REMDEV; 1575 t->control |= T_REMDEVALL;
1410 thread_unlock(); 1576 mutex_unlock(&pktgen_thread_lock);
1411 schedule_timeout_interruptible(msecs_to_jiffies(125)); /* Propagate thread->control */ 1577 schedule_timeout_interruptible(msecs_to_jiffies(125)); /* Propagate thread->control */
1412 ret = count; 1578 ret = count;
1413 sprintf(pg_result, "OK: rem_device_all"); 1579 sprintf(pg_result, "OK: rem_device_all");
1414 goto out; 1580 goto out;
1415 } 1581 }
1416 1582
1417 if (!strcmp(name, "max_before_softirq")) { 1583 if (!strcmp(name, "max_before_softirq")) {
1418 len = num_arg(&user_buffer[i], 10, &value); 1584 len = num_arg(&user_buffer[i], 10, &value);
1419 thread_lock(); 1585 mutex_lock(&pktgen_thread_lock);
1420 t->max_before_softirq = value; 1586 t->max_before_softirq = value;
1421 thread_unlock(); 1587 mutex_unlock(&pktgen_thread_lock);
1422 ret = count; 1588 ret = count;
1423 sprintf(pg_result, "OK: max_before_softirq=%lu", value); 1589 sprintf(pg_result, "OK: max_before_softirq=%lu", value);
1424 goto out; 1590 goto out;
1425 } 1591 }
1426 1592
1427 ret = -EINVAL; 1593 ret = -EINVAL;
1428 out: 1594out:
1429
1430 return ret; 1595 return ret;
1431} 1596}
1432 1597
@@ -1436,47 +1601,78 @@ static int pktgen_thread_open(struct inode *inode, struct file *file)
1436} 1601}
1437 1602
1438static struct file_operations pktgen_thread_fops = { 1603static struct file_operations pktgen_thread_fops = {
1439 .owner = THIS_MODULE, 1604 .owner = THIS_MODULE,
1440 .open = pktgen_thread_open, 1605 .open = pktgen_thread_open,
1441 .read = seq_read, 1606 .read = seq_read,
1442 .llseek = seq_lseek, 1607 .llseek = seq_lseek,
1443 .write = pktgen_thread_write, 1608 .write = pktgen_thread_write,
1444 .release = single_release, 1609 .release = single_release,
1445}; 1610};
1446 1611
1447/* Think find or remove for NN */ 1612/* Think find or remove for NN */
1448static struct pktgen_dev *__pktgen_NN_threads(const char* ifname, int remove) 1613static struct pktgen_dev *__pktgen_NN_threads(const char *ifname, int remove)
1449{ 1614{
1450 struct pktgen_thread *t; 1615 struct pktgen_thread *t;
1451 struct pktgen_dev *pkt_dev = NULL; 1616 struct pktgen_dev *pkt_dev = NULL;
1452 1617
1453 t = pktgen_threads; 1618 list_for_each_entry(t, &pktgen_threads, th_list) {
1454
1455 while (t) {
1456 pkt_dev = pktgen_find_dev(t, ifname); 1619 pkt_dev = pktgen_find_dev(t, ifname);
1457 if (pkt_dev) { 1620 if (pkt_dev) {
1458 if(remove) { 1621 if (remove) {
1459 if_lock(t); 1622 if_lock(t);
1460 pktgen_remove_device(t, pkt_dev); 1623 pkt_dev->removal_mark = 1;
1461 if_unlock(t); 1624 t->control |= T_REMDEV;
1462 } 1625 if_unlock(t);
1626 }
1463 break; 1627 break;
1464 } 1628 }
1465 t = t->next;
1466 } 1629 }
1467 return pkt_dev; 1630 return pkt_dev;
1468} 1631}
1469 1632
1470static struct pktgen_dev *pktgen_NN_threads(const char* ifname, int remove) 1633/*
1634 * mark a device for removal
1635 */
1636static int pktgen_mark_device(const char *ifname)
1471{ 1637{
1472 struct pktgen_dev *pkt_dev = NULL; 1638 struct pktgen_dev *pkt_dev = NULL;
1473 thread_lock(); 1639 const int max_tries = 10, msec_per_try = 125;
1474 pkt_dev = __pktgen_NN_threads(ifname, remove); 1640 int i = 0;
1475 thread_unlock(); 1641 int ret = 0;
1476 return pkt_dev; 1642
1643 mutex_lock(&pktgen_thread_lock);
1644 PG_DEBUG(printk("pktgen: pktgen_mark_device marking %s for removal\n",
1645 ifname));
1646
1647 while (1) {
1648
1649 pkt_dev = __pktgen_NN_threads(ifname, REMOVE);
1650 if (pkt_dev == NULL)
1651 break; /* success */
1652
1653 mutex_unlock(&pktgen_thread_lock);
1654 PG_DEBUG(printk("pktgen: pktgen_mark_device waiting for %s "
1655 "to disappear....\n", ifname));
1656 schedule_timeout_interruptible(msecs_to_jiffies(msec_per_try));
1657 mutex_lock(&pktgen_thread_lock);
1658
1659 if (++i >= max_tries) {
1660 printk("pktgen_mark_device: timed out after waiting "
1661 "%d msec for device %s to be removed\n",
1662 msec_per_try * i, ifname);
1663 ret = 1;
1664 break;
1665 }
1666
1667 }
1668
1669 mutex_unlock(&pktgen_thread_lock);
1670
1671 return ret;
1477} 1672}
1478 1673
1479static int pktgen_device_event(struct notifier_block *unused, unsigned long event, void *ptr) 1674static int pktgen_device_event(struct notifier_block *unused,
1675 unsigned long event, void *ptr)
1480{ 1676{
1481 struct net_device *dev = (struct net_device *)(ptr); 1677 struct net_device *dev = (struct net_device *)(ptr);
1482 1678
@@ -1491,9 +1687,9 @@ static int pktgen_device_event(struct notifier_block *unused, unsigned long even
1491 case NETDEV_UP: 1687 case NETDEV_UP:
1492 /* Ignore for now */ 1688 /* Ignore for now */
1493 break; 1689 break;
1494 1690
1495 case NETDEV_UNREGISTER: 1691 case NETDEV_UNREGISTER:
1496 pktgen_NN_threads(dev->name, REMOVE); 1692 pktgen_mark_device(dev->name);
1497 break; 1693 break;
1498 }; 1694 };
1499 1695
@@ -1502,15 +1698,16 @@ static int pktgen_device_event(struct notifier_block *unused, unsigned long even
1502 1698
1503/* Associate pktgen_dev with a device. */ 1699/* Associate pktgen_dev with a device. */
1504 1700
1505static struct net_device* pktgen_setup_dev(struct pktgen_dev *pkt_dev) { 1701static struct net_device *pktgen_setup_dev(struct pktgen_dev *pkt_dev)
1702{
1506 struct net_device *odev; 1703 struct net_device *odev;
1507 1704
1508 /* Clean old setups */ 1705 /* Clean old setups */
1509 1706
1510 if (pkt_dev->odev) { 1707 if (pkt_dev->odev) {
1511 dev_put(pkt_dev->odev); 1708 dev_put(pkt_dev->odev);
1512 pkt_dev->odev = NULL; 1709 pkt_dev->odev = NULL;
1513 } 1710 }
1514 1711
1515 odev = dev_get_by_name(pkt_dev->ifname); 1712 odev = dev_get_by_name(pkt_dev->ifname);
1516 1713
@@ -1519,7 +1716,8 @@ static struct net_device* pktgen_setup_dev(struct pktgen_dev *pkt_dev) {
1519 goto out; 1716 goto out;
1520 } 1717 }
1521 if (odev->type != ARPHRD_ETHER) { 1718 if (odev->type != ARPHRD_ETHER) {
1522 printk("pktgen: not an ethernet device: \"%s\"\n", pkt_dev->ifname); 1719 printk("pktgen: not an ethernet device: \"%s\"\n",
1720 pkt_dev->ifname);
1523 goto out_put; 1721 goto out_put;
1524 } 1722 }
1525 if (!netif_running(odev)) { 1723 if (!netif_running(odev)) {
@@ -1527,13 +1725,13 @@ static struct net_device* pktgen_setup_dev(struct pktgen_dev *pkt_dev) {
1527 goto out_put; 1725 goto out_put;
1528 } 1726 }
1529 pkt_dev->odev = odev; 1727 pkt_dev->odev = odev;
1530 1728
1531 return pkt_dev->odev; 1729 return pkt_dev->odev;
1532 1730
1533out_put: 1731out_put:
1534 dev_put(odev); 1732 dev_put(odev);
1535out: 1733out:
1536 return NULL; 1734 return NULL;
1537 1735
1538} 1736}
1539 1737
@@ -1543,59 +1741,64 @@ out:
1543static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) 1741static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
1544{ 1742{
1545 /* Try once more, just in case it works now. */ 1743 /* Try once more, just in case it works now. */
1546 if (!pkt_dev->odev) 1744 if (!pkt_dev->odev)
1547 pktgen_setup_dev(pkt_dev); 1745 pktgen_setup_dev(pkt_dev);
1548 1746
1549 if (!pkt_dev->odev) { 1747 if (!pkt_dev->odev) {
1550 printk("pktgen: ERROR: pkt_dev->odev == NULL in setup_inject.\n"); 1748 printk("pktgen: ERROR: pkt_dev->odev == NULL in setup_inject.\n");
1551 sprintf(pkt_dev->result, "ERROR: pkt_dev->odev == NULL in setup_inject.\n"); 1749 sprintf(pkt_dev->result,
1552 return; 1750 "ERROR: pkt_dev->odev == NULL in setup_inject.\n");
1553 } 1751 return;
1554 1752 }
1555 /* Default to the interface's mac if not explicitly set. */ 1753
1754 /* Default to the interface's mac if not explicitly set. */
1556 1755
1557 if (is_zero_ether_addr(pkt_dev->src_mac)) 1756 if (is_zero_ether_addr(pkt_dev->src_mac))
1558 memcpy(&(pkt_dev->hh[6]), pkt_dev->odev->dev_addr, ETH_ALEN); 1757 memcpy(&(pkt_dev->hh[6]), pkt_dev->odev->dev_addr, ETH_ALEN);
1559 1758
1560 /* Set up Dest MAC */ 1759 /* Set up Dest MAC */
1561 memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN); 1760 memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN);
1562 1761
1563 /* Set up pkt size */ 1762 /* Set up pkt size */
1564 pkt_dev->cur_pkt_size = pkt_dev->min_pkt_size; 1763 pkt_dev->cur_pkt_size = pkt_dev->min_pkt_size;
1565 1764
1566 if(pkt_dev->flags & F_IPV6) { 1765 if (pkt_dev->flags & F_IPV6) {
1567 /* 1766 /*
1568 * Skip this automatic address setting until locks or functions 1767 * Skip this automatic address setting until locks or functions
1569 * gets exported 1768 * gets exported
1570 */ 1769 */
1571 1770
1572#ifdef NOTNOW 1771#ifdef NOTNOW
1573 int i, set = 0, err=1; 1772 int i, set = 0, err = 1;
1574 struct inet6_dev *idev; 1773 struct inet6_dev *idev;
1575 1774
1576 for(i=0; i< IN6_ADDR_HSIZE; i++) 1775 for (i = 0; i < IN6_ADDR_HSIZE; i++)
1577 if(pkt_dev->cur_in6_saddr.s6_addr[i]) { 1776 if (pkt_dev->cur_in6_saddr.s6_addr[i]) {
1578 set = 1; 1777 set = 1;
1579 break; 1778 break;
1580 } 1779 }
1581 1780
1582 if(!set) { 1781 if (!set) {
1583 1782
1584 /* 1783 /*
1585 * Use linklevel address if unconfigured. 1784 * Use linklevel address if unconfigured.
1586 * 1785 *
1587 * use ipv6_get_lladdr if/when it's get exported 1786 * use ipv6_get_lladdr if/when it's get exported
1588 */ 1787 */
1589 1788
1590
1591 read_lock(&addrconf_lock); 1789 read_lock(&addrconf_lock);
1592 if ((idev = __in6_dev_get(pkt_dev->odev)) != NULL) { 1790 if ((idev = __in6_dev_get(pkt_dev->odev)) != NULL) {
1593 struct inet6_ifaddr *ifp; 1791 struct inet6_ifaddr *ifp;
1594 1792
1595 read_lock_bh(&idev->lock); 1793 read_lock_bh(&idev->lock);
1596 for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { 1794 for (ifp = idev->addr_list; ifp;
1597 if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) { 1795 ifp = ifp->if_next) {
1598 ipv6_addr_copy(&pkt_dev->cur_in6_saddr, &ifp->addr); 1796 if (ifp->scope == IFA_LINK
1797 && !(ifp->
1798 flags & IFA_F_TENTATIVE)) {
1799 ipv6_addr_copy(&pkt_dev->
1800 cur_in6_saddr,
1801 &ifp->addr);
1599 err = 0; 1802 err = 0;
1600 break; 1803 break;
1601 } 1804 }
@@ -1603,28 +1806,28 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
1603 read_unlock_bh(&idev->lock); 1806 read_unlock_bh(&idev->lock);
1604 } 1807 }
1605 read_unlock(&addrconf_lock); 1808 read_unlock(&addrconf_lock);
1606 if(err) printk("pktgen: ERROR: IPv6 link address not availble.\n"); 1809 if (err)
1810 printk("pktgen: ERROR: IPv6 link address not availble.\n");
1607 } 1811 }
1608#endif 1812#endif
1609 } 1813 } else {
1610 else {
1611 pkt_dev->saddr_min = 0; 1814 pkt_dev->saddr_min = 0;
1612 pkt_dev->saddr_max = 0; 1815 pkt_dev->saddr_max = 0;
1613 if (strlen(pkt_dev->src_min) == 0) { 1816 if (strlen(pkt_dev->src_min) == 0) {
1614 1817
1615 struct in_device *in_dev; 1818 struct in_device *in_dev;
1616 1819
1617 rcu_read_lock(); 1820 rcu_read_lock();
1618 in_dev = __in_dev_get_rcu(pkt_dev->odev); 1821 in_dev = __in_dev_get_rcu(pkt_dev->odev);
1619 if (in_dev) { 1822 if (in_dev) {
1620 if (in_dev->ifa_list) { 1823 if (in_dev->ifa_list) {
1621 pkt_dev->saddr_min = in_dev->ifa_list->ifa_address; 1824 pkt_dev->saddr_min =
1825 in_dev->ifa_list->ifa_address;
1622 pkt_dev->saddr_max = pkt_dev->saddr_min; 1826 pkt_dev->saddr_max = pkt_dev->saddr_min;
1623 } 1827 }
1624 } 1828 }
1625 rcu_read_unlock(); 1829 rcu_read_unlock();
1626 } 1830 } else {
1627 else {
1628 pkt_dev->saddr_min = in_aton(pkt_dev->src_min); 1831 pkt_dev->saddr_min = in_aton(pkt_dev->src_min);
1629 pkt_dev->saddr_max = in_aton(pkt_dev->src_max); 1832 pkt_dev->saddr_max = in_aton(pkt_dev->src_max);
1630 } 1833 }
@@ -1632,13 +1835,13 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
1632 pkt_dev->daddr_min = in_aton(pkt_dev->dst_min); 1835 pkt_dev->daddr_min = in_aton(pkt_dev->dst_min);
1633 pkt_dev->daddr_max = in_aton(pkt_dev->dst_max); 1836 pkt_dev->daddr_max = in_aton(pkt_dev->dst_max);
1634 } 1837 }
1635 /* Initialize current values. */ 1838 /* Initialize current values. */
1636 pkt_dev->cur_dst_mac_offset = 0; 1839 pkt_dev->cur_dst_mac_offset = 0;
1637 pkt_dev->cur_src_mac_offset = 0; 1840 pkt_dev->cur_src_mac_offset = 0;
1638 pkt_dev->cur_saddr = pkt_dev->saddr_min; 1841 pkt_dev->cur_saddr = pkt_dev->saddr_min;
1639 pkt_dev->cur_daddr = pkt_dev->daddr_min; 1842 pkt_dev->cur_daddr = pkt_dev->daddr_min;
1640 pkt_dev->cur_udp_dst = pkt_dev->udp_dst_min; 1843 pkt_dev->cur_udp_dst = pkt_dev->udp_dst_min;
1641 pkt_dev->cur_udp_src = pkt_dev->udp_src_min; 1844 pkt_dev->cur_udp_src = pkt_dev->udp_src_min;
1642 pkt_dev->nflows = 0; 1845 pkt_dev->nflows = 0;
1643} 1846}
1644 1847
@@ -1651,7 +1854,7 @@ static void spin(struct pktgen_dev *pkt_dev, __u64 spin_until_us)
1651 printk(KERN_INFO "sleeping for %d\n", (int)(spin_until_us - now)); 1854 printk(KERN_INFO "sleeping for %d\n", (int)(spin_until_us - now));
1652 while (now < spin_until_us) { 1855 while (now < spin_until_us) {
1653 /* TODO: optimize sleeping behavior */ 1856 /* TODO: optimize sleeping behavior */
1654 if (spin_until_us - now > jiffies_to_usecs(1)+1) 1857 if (spin_until_us - now > jiffies_to_usecs(1) + 1)
1655 schedule_timeout_interruptible(1); 1858 schedule_timeout_interruptible(1);
1656 else if (spin_until_us - now > 100) { 1859 else if (spin_until_us - now > 100) {
1657 do_softirq(); 1860 do_softirq();
@@ -1667,102 +1870,119 @@ static void spin(struct pktgen_dev *pkt_dev, __u64 spin_until_us)
1667 pkt_dev->idle_acc += now - start; 1870 pkt_dev->idle_acc += now - start;
1668} 1871}
1669 1872
1670
1671/* Increment/randomize headers according to flags and current values 1873/* Increment/randomize headers according to flags and current values
1672 * for IP src/dest, UDP src/dst port, MAC-Addr src/dst 1874 * for IP src/dest, UDP src/dst port, MAC-Addr src/dst
1673 */ 1875 */
1674static void mod_cur_headers(struct pktgen_dev *pkt_dev) { 1876static void mod_cur_headers(struct pktgen_dev *pkt_dev)
1675 __u32 imn; 1877{
1676 __u32 imx; 1878 __u32 imn;
1677 int flow = 0; 1879 __u32 imx;
1880 int flow = 0;
1678 1881
1679 if(pkt_dev->cflows) { 1882 if (pkt_dev->cflows) {
1680 flow = pktgen_random() % pkt_dev->cflows; 1883 flow = pktgen_random() % pkt_dev->cflows;
1681 1884
1682 if (pkt_dev->flows[flow].count > pkt_dev->lflow) 1885 if (pkt_dev->flows[flow].count > pkt_dev->lflow)
1683 pkt_dev->flows[flow].count = 0; 1886 pkt_dev->flows[flow].count = 0;
1684 } 1887 }
1685
1686 1888
1687 /* Deal with source MAC */ 1889 /* Deal with source MAC */
1688 if (pkt_dev->src_mac_count > 1) { 1890 if (pkt_dev->src_mac_count > 1) {
1689 __u32 mc; 1891 __u32 mc;
1690 __u32 tmp; 1892 __u32 tmp;
1691 1893
1692 if (pkt_dev->flags & F_MACSRC_RND) 1894 if (pkt_dev->flags & F_MACSRC_RND)
1693 mc = pktgen_random() % (pkt_dev->src_mac_count); 1895 mc = pktgen_random() % (pkt_dev->src_mac_count);
1694 else { 1896 else {
1695 mc = pkt_dev->cur_src_mac_offset++; 1897 mc = pkt_dev->cur_src_mac_offset++;
1696 if (pkt_dev->cur_src_mac_offset > pkt_dev->src_mac_count) 1898 if (pkt_dev->cur_src_mac_offset >
1697 pkt_dev->cur_src_mac_offset = 0; 1899 pkt_dev->src_mac_count)
1698 } 1900 pkt_dev->cur_src_mac_offset = 0;
1699 1901 }
1700 tmp = pkt_dev->src_mac[5] + (mc & 0xFF); 1902
1701 pkt_dev->hh[11] = tmp; 1903 tmp = pkt_dev->src_mac[5] + (mc & 0xFF);
1702 tmp = (pkt_dev->src_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8)); 1904 pkt_dev->hh[11] = tmp;
1703 pkt_dev->hh[10] = tmp; 1905 tmp = (pkt_dev->src_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8));
1704 tmp = (pkt_dev->src_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8)); 1906 pkt_dev->hh[10] = tmp;
1705 pkt_dev->hh[9] = tmp; 1907 tmp = (pkt_dev->src_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8));
1706 tmp = (pkt_dev->src_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8)); 1908 pkt_dev->hh[9] = tmp;
1707 pkt_dev->hh[8] = tmp; 1909 tmp = (pkt_dev->src_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8));
1708 tmp = (pkt_dev->src_mac[1] + (tmp >> 8)); 1910 pkt_dev->hh[8] = tmp;
1709 pkt_dev->hh[7] = tmp; 1911 tmp = (pkt_dev->src_mac[1] + (tmp >> 8));
1710 } 1912 pkt_dev->hh[7] = tmp;
1711 1913 }
1712 /* Deal with Destination MAC */ 1914
1713 if (pkt_dev->dst_mac_count > 1) { 1915 /* Deal with Destination MAC */
1714 __u32 mc; 1916 if (pkt_dev->dst_mac_count > 1) {
1715 __u32 tmp; 1917 __u32 mc;
1716 1918 __u32 tmp;
1717 if (pkt_dev->flags & F_MACDST_RND) 1919
1718 mc = pktgen_random() % (pkt_dev->dst_mac_count); 1920 if (pkt_dev->flags & F_MACDST_RND)
1719 1921 mc = pktgen_random() % (pkt_dev->dst_mac_count);
1720 else { 1922
1721 mc = pkt_dev->cur_dst_mac_offset++; 1923 else {
1722 if (pkt_dev->cur_dst_mac_offset > pkt_dev->dst_mac_count) { 1924 mc = pkt_dev->cur_dst_mac_offset++;
1723 pkt_dev->cur_dst_mac_offset = 0; 1925 if (pkt_dev->cur_dst_mac_offset >
1724 } 1926 pkt_dev->dst_mac_count) {
1725 } 1927 pkt_dev->cur_dst_mac_offset = 0;
1726 1928 }
1727 tmp = pkt_dev->dst_mac[5] + (mc & 0xFF); 1929 }
1728 pkt_dev->hh[5] = tmp; 1930
1729 tmp = (pkt_dev->dst_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8)); 1931 tmp = pkt_dev->dst_mac[5] + (mc & 0xFF);
1730 pkt_dev->hh[4] = tmp; 1932 pkt_dev->hh[5] = tmp;
1731 tmp = (pkt_dev->dst_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8)); 1933 tmp = (pkt_dev->dst_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8));
1732 pkt_dev->hh[3] = tmp; 1934 pkt_dev->hh[4] = tmp;
1733 tmp = (pkt_dev->dst_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8)); 1935 tmp = (pkt_dev->dst_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8));
1734 pkt_dev->hh[2] = tmp; 1936 pkt_dev->hh[3] = tmp;
1735 tmp = (pkt_dev->dst_mac[1] + (tmp >> 8)); 1937 tmp = (pkt_dev->dst_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8));
1736 pkt_dev->hh[1] = tmp; 1938 pkt_dev->hh[2] = tmp;
1737 } 1939 tmp = (pkt_dev->dst_mac[1] + (tmp >> 8));
1738 1940 pkt_dev->hh[1] = tmp;
1739 if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) { 1941 }
1740 if (pkt_dev->flags & F_UDPSRC_RND) 1942
1741 pkt_dev->cur_udp_src = ((pktgen_random() % (pkt_dev->udp_src_max - pkt_dev->udp_src_min)) + pkt_dev->udp_src_min); 1943 if (pkt_dev->flags & F_MPLS_RND) {
1742 1944 unsigned i;
1743 else { 1945 for(i = 0; i < pkt_dev->nr_labels; i++)
1946 if (pkt_dev->labels[i] & MPLS_STACK_BOTTOM)
1947 pkt_dev->labels[i] = MPLS_STACK_BOTTOM |
1948 (pktgen_random() &
1949 htonl(0x000fffff));
1950 }
1951
1952 if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) {
1953 if (pkt_dev->flags & F_UDPSRC_RND)
1954 pkt_dev->cur_udp_src =
1955 ((pktgen_random() %
1956 (pkt_dev->udp_src_max - pkt_dev->udp_src_min)) +
1957 pkt_dev->udp_src_min);
1958
1959 else {
1744 pkt_dev->cur_udp_src++; 1960 pkt_dev->cur_udp_src++;
1745 if (pkt_dev->cur_udp_src >= pkt_dev->udp_src_max) 1961 if (pkt_dev->cur_udp_src >= pkt_dev->udp_src_max)
1746 pkt_dev->cur_udp_src = pkt_dev->udp_src_min; 1962 pkt_dev->cur_udp_src = pkt_dev->udp_src_min;
1747 } 1963 }
1748 } 1964 }
1749 1965
1750 if (pkt_dev->udp_dst_min < pkt_dev->udp_dst_max) { 1966 if (pkt_dev->udp_dst_min < pkt_dev->udp_dst_max) {
1751 if (pkt_dev->flags & F_UDPDST_RND) { 1967 if (pkt_dev->flags & F_UDPDST_RND) {
1752 pkt_dev->cur_udp_dst = ((pktgen_random() % (pkt_dev->udp_dst_max - pkt_dev->udp_dst_min)) + pkt_dev->udp_dst_min); 1968 pkt_dev->cur_udp_dst =
1753 } 1969 ((pktgen_random() %
1754 else { 1970 (pkt_dev->udp_dst_max - pkt_dev->udp_dst_min)) +
1971 pkt_dev->udp_dst_min);
1972 } else {
1755 pkt_dev->cur_udp_dst++; 1973 pkt_dev->cur_udp_dst++;
1756 if (pkt_dev->cur_udp_dst >= pkt_dev->udp_dst_max) 1974 if (pkt_dev->cur_udp_dst >= pkt_dev->udp_dst_max)
1757 pkt_dev->cur_udp_dst = pkt_dev->udp_dst_min; 1975 pkt_dev->cur_udp_dst = pkt_dev->udp_dst_min;
1758 } 1976 }
1759 } 1977 }
1760 1978
1761 if (!(pkt_dev->flags & F_IPV6)) { 1979 if (!(pkt_dev->flags & F_IPV6)) {
1762 1980
1763 if ((imn = ntohl(pkt_dev->saddr_min)) < (imx = ntohl(pkt_dev->saddr_max))) { 1981 if ((imn = ntohl(pkt_dev->saddr_min)) < (imx =
1982 ntohl(pkt_dev->
1983 saddr_max))) {
1764 __u32 t; 1984 __u32 t;
1765 if (pkt_dev->flags & F_IPSRC_RND) 1985 if (pkt_dev->flags & F_IPSRC_RND)
1766 t = ((pktgen_random() % (imx - imn)) + imn); 1986 t = ((pktgen_random() % (imx - imn)) + imn);
1767 else { 1987 else {
1768 t = ntohl(pkt_dev->cur_saddr); 1988 t = ntohl(pkt_dev->cur_saddr);
@@ -1773,25 +1993,32 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) {
1773 } 1993 }
1774 pkt_dev->cur_saddr = htonl(t); 1994 pkt_dev->cur_saddr = htonl(t);
1775 } 1995 }
1776 1996
1777 if (pkt_dev->cflows && pkt_dev->flows[flow].count != 0) { 1997 if (pkt_dev->cflows && pkt_dev->flows[flow].count != 0) {
1778 pkt_dev->cur_daddr = pkt_dev->flows[flow].cur_daddr; 1998 pkt_dev->cur_daddr = pkt_dev->flows[flow].cur_daddr;
1779 } else { 1999 } else {
1780 2000
1781 if ((imn = ntohl(pkt_dev->daddr_min)) < (imx = ntohl(pkt_dev->daddr_max))) { 2001 if ((imn = ntohl(pkt_dev->daddr_min)) < (imx =
2002 ntohl(pkt_dev->
2003 daddr_max)))
2004 {
1782 __u32 t; 2005 __u32 t;
1783 if (pkt_dev->flags & F_IPDST_RND) { 2006 if (pkt_dev->flags & F_IPDST_RND) {
1784 2007
1785 t = ((pktgen_random() % (imx - imn)) + imn); 2008 t = ((pktgen_random() % (imx - imn)) +
2009 imn);
1786 t = htonl(t); 2010 t = htonl(t);
1787 2011
1788 while( LOOPBACK(t) || MULTICAST(t) || BADCLASS(t) || ZERONET(t) || LOCAL_MCAST(t) ) { 2012 while (LOOPBACK(t) || MULTICAST(t)
1789 t = ((pktgen_random() % (imx - imn)) + imn); 2013 || BADCLASS(t) || ZERONET(t)
2014 || LOCAL_MCAST(t)) {
2015 t = ((pktgen_random() %
2016 (imx - imn)) + imn);
1790 t = htonl(t); 2017 t = htonl(t);
1791 } 2018 }
1792 pkt_dev->cur_daddr = t; 2019 pkt_dev->cur_daddr = t;
1793 } 2020 }
1794 2021
1795 else { 2022 else {
1796 t = ntohl(pkt_dev->cur_daddr); 2023 t = ntohl(pkt_dev->cur_daddr);
1797 t++; 2024 t++;
@@ -1801,67 +2028,82 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) {
1801 pkt_dev->cur_daddr = htonl(t); 2028 pkt_dev->cur_daddr = htonl(t);
1802 } 2029 }
1803 } 2030 }
1804 if(pkt_dev->cflows) { 2031 if (pkt_dev->cflows) {
1805 pkt_dev->flows[flow].cur_daddr = pkt_dev->cur_daddr; 2032 pkt_dev->flows[flow].cur_daddr =
2033 pkt_dev->cur_daddr;
1806 pkt_dev->nflows++; 2034 pkt_dev->nflows++;
1807 } 2035 }
1808 } 2036 }
1809 } 2037 } else { /* IPV6 * */
1810 else /* IPV6 * */ 2038
1811 { 2039 if (pkt_dev->min_in6_daddr.s6_addr32[0] == 0 &&
1812 if(pkt_dev->min_in6_daddr.s6_addr32[0] == 0 && 2040 pkt_dev->min_in6_daddr.s6_addr32[1] == 0 &&
1813 pkt_dev->min_in6_daddr.s6_addr32[1] == 0 && 2041 pkt_dev->min_in6_daddr.s6_addr32[2] == 0 &&
1814 pkt_dev->min_in6_daddr.s6_addr32[2] == 0 && 2042 pkt_dev->min_in6_daddr.s6_addr32[3] == 0) ;
1815 pkt_dev->min_in6_daddr.s6_addr32[3] == 0);
1816 else { 2043 else {
1817 int i; 2044 int i;
1818 2045
1819 /* Only random destinations yet */ 2046 /* Only random destinations yet */
1820 2047
1821 for(i=0; i < 4; i++) { 2048 for (i = 0; i < 4; i++) {
1822 pkt_dev->cur_in6_daddr.s6_addr32[i] = 2049 pkt_dev->cur_in6_daddr.s6_addr32[i] =
1823 ((pktgen_random() | 2050 ((pktgen_random() |
1824 pkt_dev->min_in6_daddr.s6_addr32[i]) & 2051 pkt_dev->min_in6_daddr.s6_addr32[i]) &
1825 pkt_dev->max_in6_daddr.s6_addr32[i]); 2052 pkt_dev->max_in6_daddr.s6_addr32[i]);
1826 } 2053 }
1827 } 2054 }
1828 } 2055 }
1829 2056
1830 if (pkt_dev->min_pkt_size < pkt_dev->max_pkt_size) { 2057 if (pkt_dev->min_pkt_size < pkt_dev->max_pkt_size) {
1831 __u32 t; 2058 __u32 t;
1832 if (pkt_dev->flags & F_TXSIZE_RND) { 2059 if (pkt_dev->flags & F_TXSIZE_RND) {
1833 t = ((pktgen_random() % (pkt_dev->max_pkt_size - pkt_dev->min_pkt_size)) 2060 t = ((pktgen_random() %
1834 + pkt_dev->min_pkt_size); 2061 (pkt_dev->max_pkt_size - pkt_dev->min_pkt_size))
1835 } 2062 + pkt_dev->min_pkt_size);
1836 else { 2063 } else {
1837 t = pkt_dev->cur_pkt_size + 1; 2064 t = pkt_dev->cur_pkt_size + 1;
1838 if (t > pkt_dev->max_pkt_size) 2065 if (t > pkt_dev->max_pkt_size)
1839 t = pkt_dev->min_pkt_size; 2066 t = pkt_dev->min_pkt_size;
1840 } 2067 }
1841 pkt_dev->cur_pkt_size = t; 2068 pkt_dev->cur_pkt_size = t;
1842 } 2069 }
1843 2070
1844 pkt_dev->flows[flow].count++; 2071 pkt_dev->flows[flow].count++;
1845} 2072}
1846 2073
2074static void mpls_push(__be32 *mpls, struct pktgen_dev *pkt_dev)
2075{
2076 unsigned i;
2077 for(i = 0; i < pkt_dev->nr_labels; i++) {
2078 *mpls++ = pkt_dev->labels[i] & ~MPLS_STACK_BOTTOM;
2079 }
2080 mpls--;
2081 *mpls |= MPLS_STACK_BOTTOM;
2082}
1847 2083
1848static struct sk_buff *fill_packet_ipv4(struct net_device *odev, 2084static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
1849 struct pktgen_dev *pkt_dev) 2085 struct pktgen_dev *pkt_dev)
1850{ 2086{
1851 struct sk_buff *skb = NULL; 2087 struct sk_buff *skb = NULL;
1852 __u8 *eth; 2088 __u8 *eth;
1853 struct udphdr *udph; 2089 struct udphdr *udph;
1854 int datalen, iplen; 2090 int datalen, iplen;
1855 struct iphdr *iph; 2091 struct iphdr *iph;
1856 struct pktgen_hdr *pgh = NULL; 2092 struct pktgen_hdr *pgh = NULL;
1857 2093 __be16 protocol = __constant_htons(ETH_P_IP);
2094 __be32 *mpls;
2095
2096 if (pkt_dev->nr_labels)
2097 protocol = __constant_htons(ETH_P_MPLS_UC);
2098
1858 /* Update any of the values, used when we're incrementing various 2099 /* Update any of the values, used when we're incrementing various
1859 * fields. 2100 * fields.
1860 */ 2101 */
1861 mod_cur_headers(pkt_dev); 2102 mod_cur_headers(pkt_dev);
1862 2103
1863 datalen = (odev->hard_header_len + 16) & ~0xf; 2104 datalen = (odev->hard_header_len + 16) & ~0xf;
1864 skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen, GFP_ATOMIC); 2105 skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen +
2106 pkt_dev->nr_labels*sizeof(u32), GFP_ATOMIC);
1865 if (!skb) { 2107 if (!skb) {
1866 sprintf(pkt_dev->result, "No memory"); 2108 sprintf(pkt_dev->result, "No memory");
1867 return NULL; 2109 return NULL;
@@ -1871,51 +2113,56 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
1871 2113
1872 /* Reserve for ethernet and IP header */ 2114 /* Reserve for ethernet and IP header */
1873 eth = (__u8 *) skb_push(skb, 14); 2115 eth = (__u8 *) skb_push(skb, 14);
2116 mpls = (__be32 *)skb_put(skb, pkt_dev->nr_labels*sizeof(__u32));
2117 if (pkt_dev->nr_labels)
2118 mpls_push(mpls, pkt_dev);
1874 iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr)); 2119 iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr));
1875 udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr)); 2120 udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
1876 2121
1877 memcpy(eth, pkt_dev->hh, 12); 2122 memcpy(eth, pkt_dev->hh, 12);
1878 *(u16*)&eth[12] = __constant_htons(ETH_P_IP); 2123 *(u16 *) & eth[12] = protocol;
1879 2124
1880 datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8; /* Eth + IPh + UDPh */ 2125 /* Eth + IPh + UDPh + mpls */
1881 if (datalen < sizeof(struct pktgen_hdr)) 2126 datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 -
2127 pkt_dev->nr_labels*sizeof(u32);
2128 if (datalen < sizeof(struct pktgen_hdr))
1882 datalen = sizeof(struct pktgen_hdr); 2129 datalen = sizeof(struct pktgen_hdr);
1883 2130
1884 udph->source = htons(pkt_dev->cur_udp_src); 2131 udph->source = htons(pkt_dev->cur_udp_src);
1885 udph->dest = htons(pkt_dev->cur_udp_dst); 2132 udph->dest = htons(pkt_dev->cur_udp_dst);
1886 udph->len = htons(datalen + 8); /* DATA + udphdr */ 2133 udph->len = htons(datalen + 8); /* DATA + udphdr */
1887 udph->check = 0; /* No checksum */ 2134 udph->check = 0; /* No checksum */
1888 2135
1889 iph->ihl = 5; 2136 iph->ihl = 5;
1890 iph->version = 4; 2137 iph->version = 4;
1891 iph->ttl = 32; 2138 iph->ttl = 32;
1892 iph->tos = 0; 2139 iph->tos = 0;
1893 iph->protocol = IPPROTO_UDP; /* UDP */ 2140 iph->protocol = IPPROTO_UDP; /* UDP */
1894 iph->saddr = pkt_dev->cur_saddr; 2141 iph->saddr = pkt_dev->cur_saddr;
1895 iph->daddr = pkt_dev->cur_daddr; 2142 iph->daddr = pkt_dev->cur_daddr;
1896 iph->frag_off = 0; 2143 iph->frag_off = 0;
1897 iplen = 20 + 8 + datalen; 2144 iplen = 20 + 8 + datalen;
1898 iph->tot_len = htons(iplen); 2145 iph->tot_len = htons(iplen);
1899 iph->check = 0; 2146 iph->check = 0;
1900 iph->check = ip_fast_csum((void *) iph, iph->ihl); 2147 iph->check = ip_fast_csum((void *)iph, iph->ihl);
1901 skb->protocol = __constant_htons(ETH_P_IP); 2148 skb->protocol = protocol;
1902 skb->mac.raw = ((u8 *)iph) - 14; 2149 skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32);
1903 skb->dev = odev; 2150 skb->dev = odev;
1904 skb->pkt_type = PACKET_HOST; 2151 skb->pkt_type = PACKET_HOST;
1905 2152
1906 if (pkt_dev->nfrags <= 0) 2153 if (pkt_dev->nfrags <= 0)
1907 pgh = (struct pktgen_hdr *)skb_put(skb, datalen); 2154 pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
1908 else { 2155 else {
1909 int frags = pkt_dev->nfrags; 2156 int frags = pkt_dev->nfrags;
1910 int i; 2157 int i;
1911 2158
1912 pgh = (struct pktgen_hdr*)(((char*)(udph)) + 8); 2159 pgh = (struct pktgen_hdr *)(((char *)(udph)) + 8);
1913 2160
1914 if (frags > MAX_SKB_FRAGS) 2161 if (frags > MAX_SKB_FRAGS)
1915 frags = MAX_SKB_FRAGS; 2162 frags = MAX_SKB_FRAGS;
1916 if (datalen > frags*PAGE_SIZE) { 2163 if (datalen > frags * PAGE_SIZE) {
1917 skb_put(skb, datalen-frags*PAGE_SIZE); 2164 skb_put(skb, datalen - frags * PAGE_SIZE);
1918 datalen = frags*PAGE_SIZE; 2165 datalen = frags * PAGE_SIZE;
1919 } 2166 }
1920 2167
1921 i = 0; 2168 i = 0;
@@ -1924,7 +2171,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
1924 skb_shinfo(skb)->frags[i].page = page; 2171 skb_shinfo(skb)->frags[i].page = page;
1925 skb_shinfo(skb)->frags[i].page_offset = 0; 2172 skb_shinfo(skb)->frags[i].page_offset = 0;
1926 skb_shinfo(skb)->frags[i].size = 2173 skb_shinfo(skb)->frags[i].size =
1927 (datalen < PAGE_SIZE ? datalen : PAGE_SIZE); 2174 (datalen < PAGE_SIZE ? datalen : PAGE_SIZE);
1928 datalen -= skb_shinfo(skb)->frags[i].size; 2175 datalen -= skb_shinfo(skb)->frags[i].size;
1929 skb->len += skb_shinfo(skb)->frags[i].size; 2176 skb->len += skb_shinfo(skb)->frags[i].size;
1930 skb->data_len += skb_shinfo(skb)->frags[i].size; 2177 skb->data_len += skb_shinfo(skb)->frags[i].size;
@@ -1944,30 +2191,33 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
1944 2191
1945 skb_shinfo(skb)->frags[i - 1].size -= rem; 2192 skb_shinfo(skb)->frags[i - 1].size -= rem;
1946 2193
1947 skb_shinfo(skb)->frags[i] = skb_shinfo(skb)->frags[i - 1]; 2194 skb_shinfo(skb)->frags[i] =
2195 skb_shinfo(skb)->frags[i - 1];
1948 get_page(skb_shinfo(skb)->frags[i].page); 2196 get_page(skb_shinfo(skb)->frags[i].page);
1949 skb_shinfo(skb)->frags[i].page = skb_shinfo(skb)->frags[i - 1].page; 2197 skb_shinfo(skb)->frags[i].page =
1950 skb_shinfo(skb)->frags[i].page_offset += skb_shinfo(skb)->frags[i - 1].size; 2198 skb_shinfo(skb)->frags[i - 1].page;
2199 skb_shinfo(skb)->frags[i].page_offset +=
2200 skb_shinfo(skb)->frags[i - 1].size;
1951 skb_shinfo(skb)->frags[i].size = rem; 2201 skb_shinfo(skb)->frags[i].size = rem;
1952 i++; 2202 i++;
1953 skb_shinfo(skb)->nr_frags = i; 2203 skb_shinfo(skb)->nr_frags = i;
1954 } 2204 }
1955 } 2205 }
1956 2206
1957 /* Stamp the time, and sequence number, convert them to network byte order */ 2207 /* Stamp the time, and sequence number, convert them to network byte order */
2208
2209 if (pgh) {
2210 struct timeval timestamp;
2211
2212 pgh->pgh_magic = htonl(PKTGEN_MAGIC);
2213 pgh->seq_num = htonl(pkt_dev->seq_num);
2214
2215 do_gettimeofday(&timestamp);
2216 pgh->tv_sec = htonl(timestamp.tv_sec);
2217 pgh->tv_usec = htonl(timestamp.tv_usec);
2218 }
2219 pkt_dev->seq_num++;
1958 2220
1959 if (pgh) {
1960 struct timeval timestamp;
1961
1962 pgh->pgh_magic = htonl(PKTGEN_MAGIC);
1963 pgh->seq_num = htonl(pkt_dev->seq_num);
1964
1965 do_gettimeofday(&timestamp);
1966 pgh->tv_sec = htonl(timestamp.tv_sec);
1967 pgh->tv_usec = htonl(timestamp.tv_usec);
1968 }
1969 pkt_dev->seq_num++;
1970
1971 return skb; 2221 return skb;
1972} 2222}
1973 2223
@@ -1980,23 +2230,24 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
1980 * --ro 2230 * --ro
1981 */ 2231 */
1982 2232
1983static unsigned int scan_ip6(const char *s,char ip[16]) 2233static unsigned int scan_ip6(const char *s, char ip[16])
1984{ 2234{
1985 unsigned int i; 2235 unsigned int i;
1986 unsigned int len=0; 2236 unsigned int len = 0;
1987 unsigned long u; 2237 unsigned long u;
1988 char suffix[16]; 2238 char suffix[16];
1989 unsigned int prefixlen=0; 2239 unsigned int prefixlen = 0;
1990 unsigned int suffixlen=0; 2240 unsigned int suffixlen = 0;
1991 __u32 tmp; 2241 __u32 tmp;
1992 2242
1993 for (i=0; i<16; i++) ip[i]=0; 2243 for (i = 0; i < 16; i++)
2244 ip[i] = 0;
1994 2245
1995 for (;;) { 2246 for (;;) {
1996 if (*s == ':') { 2247 if (*s == ':') {
1997 len++; 2248 len++;
1998 if (s[1] == ':') { /* Found "::", skip to part 2 */ 2249 if (s[1] == ':') { /* Found "::", skip to part 2 */
1999 s+=2; 2250 s += 2;
2000 len++; 2251 len++;
2001 break; 2252 break;
2002 } 2253 }
@@ -2004,136 +2255,162 @@ static unsigned int scan_ip6(const char *s,char ip[16])
2004 } 2255 }
2005 { 2256 {
2006 char *tmp; 2257 char *tmp;
2007 u=simple_strtoul(s,&tmp,16); 2258 u = simple_strtoul(s, &tmp, 16);
2008 i=tmp-s; 2259 i = tmp - s;
2009 } 2260 }
2010 2261
2011 if (!i) return 0; 2262 if (!i)
2012 if (prefixlen==12 && s[i]=='.') { 2263 return 0;
2264 if (prefixlen == 12 && s[i] == '.') {
2013 2265
2014 /* the last 4 bytes may be written as IPv4 address */ 2266 /* the last 4 bytes may be written as IPv4 address */
2015 2267
2016 tmp = in_aton(s); 2268 tmp = in_aton(s);
2017 memcpy((struct in_addr*)(ip+12), &tmp, sizeof(tmp)); 2269 memcpy((struct in_addr *)(ip + 12), &tmp, sizeof(tmp));
2018 return i+len; 2270 return i + len;
2019 } 2271 }
2020 ip[prefixlen++] = (u >> 8); 2272 ip[prefixlen++] = (u >> 8);
2021 ip[prefixlen++] = (u & 255); 2273 ip[prefixlen++] = (u & 255);
2022 s += i; len += i; 2274 s += i;
2023 if (prefixlen==16) 2275 len += i;
2276 if (prefixlen == 16)
2024 return len; 2277 return len;
2025 } 2278 }
2026 2279
2027/* part 2, after "::" */ 2280/* part 2, after "::" */
2028 for (;;) { 2281 for (;;) {
2029 if (*s == ':') { 2282 if (*s == ':') {
2030 if (suffixlen==0) 2283 if (suffixlen == 0)
2031 break; 2284 break;
2032 s++; 2285 s++;
2033 len++; 2286 len++;
2034 } else if (suffixlen!=0) 2287 } else if (suffixlen != 0)
2035 break; 2288 break;
2036 { 2289 {
2037 char *tmp; 2290 char *tmp;
2038 u=simple_strtol(s,&tmp,16); 2291 u = simple_strtol(s, &tmp, 16);
2039 i=tmp-s; 2292 i = tmp - s;
2040 } 2293 }
2041 if (!i) { 2294 if (!i) {
2042 if (*s) len--; 2295 if (*s)
2296 len--;
2043 break; 2297 break;
2044 } 2298 }
2045 if (suffixlen+prefixlen<=12 && s[i]=='.') { 2299 if (suffixlen + prefixlen <= 12 && s[i] == '.') {
2046 tmp = in_aton(s); 2300 tmp = in_aton(s);
2047 memcpy((struct in_addr*)(suffix+suffixlen), &tmp, sizeof(tmp)); 2301 memcpy((struct in_addr *)(suffix + suffixlen), &tmp,
2048 suffixlen+=4; 2302 sizeof(tmp));
2049 len+=strlen(s); 2303 suffixlen += 4;
2304 len += strlen(s);
2050 break; 2305 break;
2051 } 2306 }
2052 suffix[suffixlen++] = (u >> 8); 2307 suffix[suffixlen++] = (u >> 8);
2053 suffix[suffixlen++] = (u & 255); 2308 suffix[suffixlen++] = (u & 255);
2054 s += i; len += i; 2309 s += i;
2055 if (prefixlen+suffixlen==16) 2310 len += i;
2311 if (prefixlen + suffixlen == 16)
2056 break; 2312 break;
2057 } 2313 }
2058 for (i=0; i<suffixlen; i++) 2314 for (i = 0; i < suffixlen; i++)
2059 ip[16-suffixlen+i] = suffix[i]; 2315 ip[16 - suffixlen + i] = suffix[i];
2060 return len; 2316 return len;
2061} 2317}
2062 2318
2063static char tohex(char hexdigit) { 2319static char tohex(char hexdigit)
2064 return hexdigit>9?hexdigit+'a'-10:hexdigit+'0'; 2320{
2321 return hexdigit > 9 ? hexdigit + 'a' - 10 : hexdigit + '0';
2065} 2322}
2066 2323
2067static int fmt_xlong(char* s,unsigned int i) { 2324static int fmt_xlong(char *s, unsigned int i)
2068 char* bak=s; 2325{
2069 *s=tohex((i>>12)&0xf); if (s!=bak || *s!='0') ++s; 2326 char *bak = s;
2070 *s=tohex((i>>8)&0xf); if (s!=bak || *s!='0') ++s; 2327 *s = tohex((i >> 12) & 0xf);
2071 *s=tohex((i>>4)&0xf); if (s!=bak || *s!='0') ++s; 2328 if (s != bak || *s != '0')
2072 *s=tohex(i&0xf); 2329 ++s;
2073 return s-bak+1; 2330 *s = tohex((i >> 8) & 0xf);
2331 if (s != bak || *s != '0')
2332 ++s;
2333 *s = tohex((i >> 4) & 0xf);
2334 if (s != bak || *s != '0')
2335 ++s;
2336 *s = tohex(i & 0xf);
2337 return s - bak + 1;
2074} 2338}
2075 2339
2076static unsigned int fmt_ip6(char *s,const char ip[16]) { 2340static unsigned int fmt_ip6(char *s, const char ip[16])
2341{
2077 unsigned int len; 2342 unsigned int len;
2078 unsigned int i; 2343 unsigned int i;
2079 unsigned int temp; 2344 unsigned int temp;
2080 unsigned int compressing; 2345 unsigned int compressing;
2081 int j; 2346 int j;
2082 2347
2083 len = 0; compressing = 0; 2348 len = 0;
2084 for (j=0; j<16; j+=2) { 2349 compressing = 0;
2350 for (j = 0; j < 16; j += 2) {
2085 2351
2086#ifdef V4MAPPEDPREFIX 2352#ifdef V4MAPPEDPREFIX
2087 if (j==12 && !memcmp(ip,V4mappedprefix,12)) { 2353 if (j == 12 && !memcmp(ip, V4mappedprefix, 12)) {
2088 inet_ntoa_r(*(struct in_addr*)(ip+12),s); 2354 inet_ntoa_r(*(struct in_addr *)(ip + 12), s);
2089 temp=strlen(s); 2355 temp = strlen(s);
2090 return len+temp; 2356 return len + temp;
2091 } 2357 }
2092#endif 2358#endif
2093 temp = ((unsigned long) (unsigned char) ip[j] << 8) + 2359 temp = ((unsigned long)(unsigned char)ip[j] << 8) +
2094 (unsigned long) (unsigned char) ip[j+1]; 2360 (unsigned long)(unsigned char)ip[j + 1];
2095 if (temp == 0) { 2361 if (temp == 0) {
2096 if (!compressing) { 2362 if (!compressing) {
2097 compressing=1; 2363 compressing = 1;
2098 if (j==0) { 2364 if (j == 0) {
2099 *s++=':'; ++len; 2365 *s++ = ':';
2366 ++len;
2100 } 2367 }
2101 } 2368 }
2102 } else { 2369 } else {
2103 if (compressing) { 2370 if (compressing) {
2104 compressing=0; 2371 compressing = 0;
2105 *s++=':'; ++len; 2372 *s++ = ':';
2373 ++len;
2106 } 2374 }
2107 i = fmt_xlong(s,temp); len += i; s += i; 2375 i = fmt_xlong(s, temp);
2108 if (j<14) { 2376 len += i;
2377 s += i;
2378 if (j < 14) {
2109 *s++ = ':'; 2379 *s++ = ':';
2110 ++len; 2380 ++len;
2111 } 2381 }
2112 } 2382 }
2113 } 2383 }
2114 if (compressing) { 2384 if (compressing) {
2115 *s++=':'; ++len; 2385 *s++ = ':';
2386 ++len;
2116 } 2387 }
2117 *s=0; 2388 *s = 0;
2118 return len; 2389 return len;
2119} 2390}
2120 2391
2121static struct sk_buff *fill_packet_ipv6(struct net_device *odev, 2392static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2122 struct pktgen_dev *pkt_dev) 2393 struct pktgen_dev *pkt_dev)
2123{ 2394{
2124 struct sk_buff *skb = NULL; 2395 struct sk_buff *skb = NULL;
2125 __u8 *eth; 2396 __u8 *eth;
2126 struct udphdr *udph; 2397 struct udphdr *udph;
2127 int datalen; 2398 int datalen;
2128 struct ipv6hdr *iph; 2399 struct ipv6hdr *iph;
2129 struct pktgen_hdr *pgh = NULL; 2400 struct pktgen_hdr *pgh = NULL;
2401 __be16 protocol = __constant_htons(ETH_P_IPV6);
2402 __be32 *mpls;
2403
2404 if (pkt_dev->nr_labels)
2405 protocol = __constant_htons(ETH_P_MPLS_UC);
2130 2406
2131 /* Update any of the values, used when we're incrementing various 2407 /* Update any of the values, used when we're incrementing various
2132 * fields. 2408 * fields.
2133 */ 2409 */
2134 mod_cur_headers(pkt_dev); 2410 mod_cur_headers(pkt_dev);
2135 2411
2136 skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16, GFP_ATOMIC); 2412 skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16 +
2413 pkt_dev->nr_labels*sizeof(u32), GFP_ATOMIC);
2137 if (!skb) { 2414 if (!skb) {
2138 sprintf(pkt_dev->result, "No memory"); 2415 sprintf(pkt_dev->result, "No memory");
2139 return NULL; 2416 return NULL;
@@ -2143,27 +2420,33 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2143 2420
2144 /* Reserve for ethernet and IP header */ 2421 /* Reserve for ethernet and IP header */
2145 eth = (__u8 *) skb_push(skb, 14); 2422 eth = (__u8 *) skb_push(skb, 14);
2423 mpls = (__be32 *)skb_put(skb, pkt_dev->nr_labels*sizeof(__u32));
2424 if (pkt_dev->nr_labels)
2425 mpls_push(mpls, pkt_dev);
2146 iph = (struct ipv6hdr *)skb_put(skb, sizeof(struct ipv6hdr)); 2426 iph = (struct ipv6hdr *)skb_put(skb, sizeof(struct ipv6hdr));
2147 udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr)); 2427 udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
2148 2428
2149 memcpy(eth, pkt_dev->hh, 12); 2429 memcpy(eth, pkt_dev->hh, 12);
2150 *(u16*)&eth[12] = __constant_htons(ETH_P_IPV6); 2430 *(u16 *) & eth[12] = __constant_htons(ETH_P_IPV6);
2151 2431
2152 datalen = pkt_dev->cur_pkt_size-14- 2432 /* Eth + IPh + UDPh + mpls */
2153 sizeof(struct ipv6hdr)-sizeof(struct udphdr); /* Eth + IPh + UDPh */ 2433 datalen = pkt_dev->cur_pkt_size - 14 -
2434 sizeof(struct ipv6hdr) - sizeof(struct udphdr) -
2435 pkt_dev->nr_labels*sizeof(u32);
2154 2436
2155 if (datalen < sizeof(struct pktgen_hdr)) { 2437 if (datalen < sizeof(struct pktgen_hdr)) {
2156 datalen = sizeof(struct pktgen_hdr); 2438 datalen = sizeof(struct pktgen_hdr);
2157 if (net_ratelimit()) 2439 if (net_ratelimit())
2158 printk(KERN_INFO "pktgen: increased datalen to %d\n", datalen); 2440 printk(KERN_INFO "pktgen: increased datalen to %d\n",
2441 datalen);
2159 } 2442 }
2160 2443
2161 udph->source = htons(pkt_dev->cur_udp_src); 2444 udph->source = htons(pkt_dev->cur_udp_src);
2162 udph->dest = htons(pkt_dev->cur_udp_dst); 2445 udph->dest = htons(pkt_dev->cur_udp_dst);
2163 udph->len = htons(datalen + sizeof(struct udphdr)); 2446 udph->len = htons(datalen + sizeof(struct udphdr));
2164 udph->check = 0; /* No checksum */ 2447 udph->check = 0; /* No checksum */
2165 2448
2166 *(u32*)iph = __constant_htonl(0x60000000); /* Version + flow */ 2449 *(u32 *) iph = __constant_htonl(0x60000000); /* Version + flow */
2167 2450
2168 iph->hop_limit = 32; 2451 iph->hop_limit = 32;
2169 2452
@@ -2173,24 +2456,24 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2173 ipv6_addr_copy(&iph->daddr, &pkt_dev->cur_in6_daddr); 2456 ipv6_addr_copy(&iph->daddr, &pkt_dev->cur_in6_daddr);
2174 ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr); 2457 ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr);
2175 2458
2176 skb->mac.raw = ((u8 *)iph) - 14; 2459 skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32);
2177 skb->protocol = __constant_htons(ETH_P_IPV6); 2460 skb->protocol = protocol;
2178 skb->dev = odev; 2461 skb->dev = odev;
2179 skb->pkt_type = PACKET_HOST; 2462 skb->pkt_type = PACKET_HOST;
2180 2463
2181 if (pkt_dev->nfrags <= 0) 2464 if (pkt_dev->nfrags <= 0)
2182 pgh = (struct pktgen_hdr *)skb_put(skb, datalen); 2465 pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
2183 else { 2466 else {
2184 int frags = pkt_dev->nfrags; 2467 int frags = pkt_dev->nfrags;
2185 int i; 2468 int i;
2186 2469
2187 pgh = (struct pktgen_hdr*)(((char*)(udph)) + 8); 2470 pgh = (struct pktgen_hdr *)(((char *)(udph)) + 8);
2188 2471
2189 if (frags > MAX_SKB_FRAGS) 2472 if (frags > MAX_SKB_FRAGS)
2190 frags = MAX_SKB_FRAGS; 2473 frags = MAX_SKB_FRAGS;
2191 if (datalen > frags*PAGE_SIZE) { 2474 if (datalen > frags * PAGE_SIZE) {
2192 skb_put(skb, datalen-frags*PAGE_SIZE); 2475 skb_put(skb, datalen - frags * PAGE_SIZE);
2193 datalen = frags*PAGE_SIZE; 2476 datalen = frags * PAGE_SIZE;
2194 } 2477 }
2195 2478
2196 i = 0; 2479 i = 0;
@@ -2199,7 +2482,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2199 skb_shinfo(skb)->frags[i].page = page; 2482 skb_shinfo(skb)->frags[i].page = page;
2200 skb_shinfo(skb)->frags[i].page_offset = 0; 2483 skb_shinfo(skb)->frags[i].page_offset = 0;
2201 skb_shinfo(skb)->frags[i].size = 2484 skb_shinfo(skb)->frags[i].size =
2202 (datalen < PAGE_SIZE ? datalen : PAGE_SIZE); 2485 (datalen < PAGE_SIZE ? datalen : PAGE_SIZE);
2203 datalen -= skb_shinfo(skb)->frags[i].size; 2486 datalen -= skb_shinfo(skb)->frags[i].size;
2204 skb->len += skb_shinfo(skb)->frags[i].size; 2487 skb->len += skb_shinfo(skb)->frags[i].size;
2205 skb->data_len += skb_shinfo(skb)->frags[i].size; 2488 skb->data_len += skb_shinfo(skb)->frags[i].size;
@@ -2219,305 +2502,333 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2219 2502
2220 skb_shinfo(skb)->frags[i - 1].size -= rem; 2503 skb_shinfo(skb)->frags[i - 1].size -= rem;
2221 2504
2222 skb_shinfo(skb)->frags[i] = skb_shinfo(skb)->frags[i - 1]; 2505 skb_shinfo(skb)->frags[i] =
2506 skb_shinfo(skb)->frags[i - 1];
2223 get_page(skb_shinfo(skb)->frags[i].page); 2507 get_page(skb_shinfo(skb)->frags[i].page);
2224 skb_shinfo(skb)->frags[i].page = skb_shinfo(skb)->frags[i - 1].page; 2508 skb_shinfo(skb)->frags[i].page =
2225 skb_shinfo(skb)->frags[i].page_offset += skb_shinfo(skb)->frags[i - 1].size; 2509 skb_shinfo(skb)->frags[i - 1].page;
2510 skb_shinfo(skb)->frags[i].page_offset +=
2511 skb_shinfo(skb)->frags[i - 1].size;
2226 skb_shinfo(skb)->frags[i].size = rem; 2512 skb_shinfo(skb)->frags[i].size = rem;
2227 i++; 2513 i++;
2228 skb_shinfo(skb)->nr_frags = i; 2514 skb_shinfo(skb)->nr_frags = i;
2229 } 2515 }
2230 } 2516 }
2231 2517
2232 /* Stamp the time, and sequence number, convert them to network byte order */ 2518 /* Stamp the time, and sequence number, convert them to network byte order */
2233 /* should we update cloned packets too ? */ 2519 /* should we update cloned packets too ? */
2234 if (pgh) { 2520 if (pgh) {
2235 struct timeval timestamp; 2521 struct timeval timestamp;
2236 2522
2237 pgh->pgh_magic = htonl(PKTGEN_MAGIC); 2523 pgh->pgh_magic = htonl(PKTGEN_MAGIC);
2238 pgh->seq_num = htonl(pkt_dev->seq_num); 2524 pgh->seq_num = htonl(pkt_dev->seq_num);
2239 2525
2240 do_gettimeofday(&timestamp); 2526 do_gettimeofday(&timestamp);
2241 pgh->tv_sec = htonl(timestamp.tv_sec); 2527 pgh->tv_sec = htonl(timestamp.tv_sec);
2242 pgh->tv_usec = htonl(timestamp.tv_usec); 2528 pgh->tv_usec = htonl(timestamp.tv_usec);
2243 } 2529 }
2244 pkt_dev->seq_num++; 2530 pkt_dev->seq_num++;
2245 2531
2246 return skb; 2532 return skb;
2247} 2533}
2248 2534
2249static inline struct sk_buff *fill_packet(struct net_device *odev, 2535static inline struct sk_buff *fill_packet(struct net_device *odev,
2250 struct pktgen_dev *pkt_dev) 2536 struct pktgen_dev *pkt_dev)
2251{ 2537{
2252 if(pkt_dev->flags & F_IPV6) 2538 if (pkt_dev->flags & F_IPV6)
2253 return fill_packet_ipv6(odev, pkt_dev); 2539 return fill_packet_ipv6(odev, pkt_dev);
2254 else 2540 else
2255 return fill_packet_ipv4(odev, pkt_dev); 2541 return fill_packet_ipv4(odev, pkt_dev);
2256} 2542}
2257 2543
2258static void pktgen_clear_counters(struct pktgen_dev *pkt_dev) 2544static void pktgen_clear_counters(struct pktgen_dev *pkt_dev)
2259{ 2545{
2260 pkt_dev->seq_num = 1; 2546 pkt_dev->seq_num = 1;
2261 pkt_dev->idle_acc = 0; 2547 pkt_dev->idle_acc = 0;
2262 pkt_dev->sofar = 0; 2548 pkt_dev->sofar = 0;
2263 pkt_dev->tx_bytes = 0; 2549 pkt_dev->tx_bytes = 0;
2264 pkt_dev->errors = 0; 2550 pkt_dev->errors = 0;
2265} 2551}
2266 2552
2267/* Set up structure for sending pkts, clear counters */ 2553/* Set up structure for sending pkts, clear counters */
2268 2554
2269static void pktgen_run(struct pktgen_thread *t) 2555static void pktgen_run(struct pktgen_thread *t)
2270{ 2556{
2271 struct pktgen_dev *pkt_dev = NULL; 2557 struct pktgen_dev *pkt_dev;
2272 int started = 0; 2558 int started = 0;
2273 2559
2274 PG_DEBUG(printk("pktgen: entering pktgen_run. %p\n", t)); 2560 PG_DEBUG(printk("pktgen: entering pktgen_run. %p\n", t));
2275 2561
2276 if_lock(t); 2562 if_lock(t);
2277 for (pkt_dev = t->if_list; pkt_dev; pkt_dev = pkt_dev->next ) { 2563 list_for_each_entry(pkt_dev, &t->if_list, list) {
2278 2564
2279 /* 2565 /*
2280 * setup odev and create initial packet. 2566 * setup odev and create initial packet.
2281 */ 2567 */
2282 pktgen_setup_inject(pkt_dev); 2568 pktgen_setup_inject(pkt_dev);
2283 2569
2284 if(pkt_dev->odev) { 2570 if (pkt_dev->odev) {
2285 pktgen_clear_counters(pkt_dev); 2571 pktgen_clear_counters(pkt_dev);
2286 pkt_dev->running = 1; /* Cranke yeself! */ 2572 pkt_dev->running = 1; /* Cranke yeself! */
2287 pkt_dev->skb = NULL; 2573 pkt_dev->skb = NULL;
2288 pkt_dev->started_at = getCurUs(); 2574 pkt_dev->started_at = getCurUs();
2289 pkt_dev->next_tx_us = getCurUs(); /* Transmit immediately */ 2575 pkt_dev->next_tx_us = getCurUs(); /* Transmit immediately */
2290 pkt_dev->next_tx_ns = 0; 2576 pkt_dev->next_tx_ns = 0;
2291 2577
2292 strcpy(pkt_dev->result, "Starting"); 2578 strcpy(pkt_dev->result, "Starting");
2293 started++; 2579 started++;
2294 } 2580 } else
2295 else
2296 strcpy(pkt_dev->result, "Error starting"); 2581 strcpy(pkt_dev->result, "Error starting");
2297 } 2582 }
2298 if_unlock(t); 2583 if_unlock(t);
2299 if(started) t->control &= ~(T_STOP); 2584 if (started)
2585 t->control &= ~(T_STOP);
2300} 2586}
2301 2587
2302static void pktgen_stop_all_threads_ifs(void) 2588static void pktgen_stop_all_threads_ifs(void)
2303{ 2589{
2304 struct pktgen_thread *t = pktgen_threads; 2590 struct pktgen_thread *t;
2305 2591
2306 PG_DEBUG(printk("pktgen: entering pktgen_stop_all_threads.\n")); 2592 PG_DEBUG(printk("pktgen: entering pktgen_stop_all_threads_ifs.\n"));
2307 2593
2308 thread_lock(); 2594 mutex_lock(&pktgen_thread_lock);
2309 while(t) { 2595
2310 pktgen_stop(t); 2596 list_for_each_entry(t, &pktgen_threads, th_list)
2311 t = t->next; 2597 t->control |= T_STOP;
2312 } 2598
2313 thread_unlock(); 2599 mutex_unlock(&pktgen_thread_lock);
2314} 2600}
2315 2601
2316static int thread_is_running(struct pktgen_thread *t ) 2602static int thread_is_running(struct pktgen_thread *t)
2317{ 2603{
2318 struct pktgen_dev *next; 2604 struct pktgen_dev *pkt_dev;
2319 int res = 0; 2605 int res = 0;
2320 2606
2321 for(next=t->if_list; next; next=next->next) { 2607 list_for_each_entry(pkt_dev, &t->if_list, list)
2322 if(next->running) { 2608 if (pkt_dev->running) {
2323 res = 1; 2609 res = 1;
2324 break; 2610 break;
2325 } 2611 }
2326 } 2612 return res;
2327 return res;
2328} 2613}
2329 2614
2330static int pktgen_wait_thread_run(struct pktgen_thread *t ) 2615static int pktgen_wait_thread_run(struct pktgen_thread *t)
2331{ 2616{
2332 if_lock(t); 2617 if_lock(t);
2333 2618
2334 while(thread_is_running(t)) { 2619 while (thread_is_running(t)) {
2335 2620
2336 if_unlock(t); 2621 if_unlock(t);
2337 2622
2338 msleep_interruptible(100); 2623 msleep_interruptible(100);
2339 2624
2340 if (signal_pending(current)) 2625 if (signal_pending(current))
2341 goto signal; 2626 goto signal;
2342 if_lock(t); 2627 if_lock(t);
2343 } 2628 }
2344 if_unlock(t); 2629 if_unlock(t);
2345 return 1; 2630 return 1;
2346 signal: 2631signal:
2347 return 0; 2632 return 0;
2348} 2633}
2349 2634
2350static int pktgen_wait_all_threads_run(void) 2635static int pktgen_wait_all_threads_run(void)
2351{ 2636{
2352 struct pktgen_thread *t = pktgen_threads; 2637 struct pktgen_thread *t;
2353 int sig = 1; 2638 int sig = 1;
2354 2639
2355 while (t) { 2640 mutex_lock(&pktgen_thread_lock);
2641
2642 list_for_each_entry(t, &pktgen_threads, th_list) {
2356 sig = pktgen_wait_thread_run(t); 2643 sig = pktgen_wait_thread_run(t);
2357 if( sig == 0 ) break; 2644 if (sig == 0)
2358 thread_lock(); 2645 break;
2359 t=t->next;
2360 thread_unlock();
2361 }
2362 if(sig == 0) {
2363 thread_lock();
2364 while (t) {
2365 t->control |= (T_STOP);
2366 t=t->next;
2367 }
2368 thread_unlock();
2369 } 2646 }
2647
2648 if (sig == 0)
2649 list_for_each_entry(t, &pktgen_threads, th_list)
2650 t->control |= (T_STOP);
2651
2652 mutex_unlock(&pktgen_thread_lock);
2370 return sig; 2653 return sig;
2371} 2654}
2372 2655
2373static void pktgen_run_all_threads(void) 2656static void pktgen_run_all_threads(void)
2374{ 2657{
2375 struct pktgen_thread *t = pktgen_threads; 2658 struct pktgen_thread *t;
2376 2659
2377 PG_DEBUG(printk("pktgen: entering pktgen_run_all_threads.\n")); 2660 PG_DEBUG(printk("pktgen: entering pktgen_run_all_threads.\n"));
2378 2661
2379 thread_lock(); 2662 mutex_lock(&pktgen_thread_lock);
2380 2663
2381 while(t) { 2664 list_for_each_entry(t, &pktgen_threads, th_list)
2382 t->control |= (T_RUN); 2665 t->control |= (T_RUN);
2383 t = t->next;
2384 }
2385 thread_unlock();
2386 2666
2387 schedule_timeout_interruptible(msecs_to_jiffies(125)); /* Propagate thread->control */ 2667 mutex_unlock(&pktgen_thread_lock);
2388 2668
2669 schedule_timeout_interruptible(msecs_to_jiffies(125)); /* Propagate thread->control */
2670
2389 pktgen_wait_all_threads_run(); 2671 pktgen_wait_all_threads_run();
2390} 2672}
2391 2673
2392
2393static void show_results(struct pktgen_dev *pkt_dev, int nr_frags) 2674static void show_results(struct pktgen_dev *pkt_dev, int nr_frags)
2394{ 2675{
2395 __u64 total_us, bps, mbps, pps, idle; 2676 __u64 total_us, bps, mbps, pps, idle;
2396 char *p = pkt_dev->result; 2677 char *p = pkt_dev->result;
2397 2678
2398 total_us = pkt_dev->stopped_at - pkt_dev->started_at; 2679 total_us = pkt_dev->stopped_at - pkt_dev->started_at;
2399 2680
2400 idle = pkt_dev->idle_acc; 2681 idle = pkt_dev->idle_acc;
2401 2682
2402 p += sprintf(p, "OK: %llu(c%llu+d%llu) usec, %llu (%dbyte,%dfrags)\n", 2683 p += sprintf(p, "OK: %llu(c%llu+d%llu) usec, %llu (%dbyte,%dfrags)\n",
2403 (unsigned long long) total_us, 2684 (unsigned long long)total_us,
2404 (unsigned long long)(total_us - idle), 2685 (unsigned long long)(total_us - idle),
2405 (unsigned long long) idle, 2686 (unsigned long long)idle,
2406 (unsigned long long) pkt_dev->sofar, 2687 (unsigned long long)pkt_dev->sofar,
2407 pkt_dev->cur_pkt_size, nr_frags); 2688 pkt_dev->cur_pkt_size, nr_frags);
2408 2689
2409 pps = pkt_dev->sofar * USEC_PER_SEC; 2690 pps = pkt_dev->sofar * USEC_PER_SEC;
2410 2691
2411 while ((total_us >> 32) != 0) { 2692 while ((total_us >> 32) != 0) {
2412 pps >>= 1; 2693 pps >>= 1;
2413 total_us >>= 1; 2694 total_us >>= 1;
2414 } 2695 }
2415 2696
2416 do_div(pps, total_us); 2697 do_div(pps, total_us);
2417 2698
2418 bps = pps * 8 * pkt_dev->cur_pkt_size; 2699 bps = pps * 8 * pkt_dev->cur_pkt_size;
2419 2700
2420 mbps = bps; 2701 mbps = bps;
2421 do_div(mbps, 1000000); 2702 do_div(mbps, 1000000);
2422 p += sprintf(p, " %llupps %lluMb/sec (%llubps) errors: %llu", 2703 p += sprintf(p, " %llupps %lluMb/sec (%llubps) errors: %llu",
2423 (unsigned long long) pps, 2704 (unsigned long long)pps,
2424 (unsigned long long) mbps, 2705 (unsigned long long)mbps,
2425 (unsigned long long) bps, 2706 (unsigned long long)bps,
2426 (unsigned long long) pkt_dev->errors); 2707 (unsigned long long)pkt_dev->errors);
2427} 2708}
2428
2429 2709
2430/* Set stopped-at timer, remove from running list, do counters & statistics */ 2710/* Set stopped-at timer, remove from running list, do counters & statistics */
2431 2711
2432static int pktgen_stop_device(struct pktgen_dev *pkt_dev) 2712static int pktgen_stop_device(struct pktgen_dev *pkt_dev)
2433{ 2713{
2434 2714 int nr_frags = pkt_dev->skb ? skb_shinfo(pkt_dev->skb)->nr_frags : -1;
2435 if (!pkt_dev->running) {
2436 printk("pktgen: interface: %s is already stopped\n", pkt_dev->ifname);
2437 return -EINVAL;
2438 }
2439 2715
2440 pkt_dev->stopped_at = getCurUs(); 2716 if (!pkt_dev->running) {
2441 pkt_dev->running = 0; 2717 printk("pktgen: interface: %s is already stopped\n",
2718 pkt_dev->ifname);
2719 return -EINVAL;
2720 }
2442 2721
2443 show_results(pkt_dev, skb_shinfo(pkt_dev->skb)->nr_frags); 2722 pkt_dev->stopped_at = getCurUs();
2723 pkt_dev->running = 0;
2444 2724
2445 if (pkt_dev->skb) 2725 show_results(pkt_dev, nr_frags);
2446 kfree_skb(pkt_dev->skb);
2447 2726
2448 pkt_dev->skb = NULL; 2727 return 0;
2449
2450 return 0;
2451} 2728}
2452 2729
2453static struct pktgen_dev *next_to_run(struct pktgen_thread *t ) 2730static struct pktgen_dev *next_to_run(struct pktgen_thread *t)
2454{ 2731{
2455 struct pktgen_dev *next, *best = NULL; 2732 struct pktgen_dev *pkt_dev, *best = NULL;
2456 2733
2457 if_lock(t); 2734 if_lock(t);
2458 2735
2459 for(next=t->if_list; next ; next=next->next) { 2736 list_for_each_entry(pkt_dev, &t->if_list, list) {
2460 if(!next->running) continue; 2737 if (!pkt_dev->running)
2461 if(best == NULL) best=next; 2738 continue;
2462 else if ( next->next_tx_us < best->next_tx_us) 2739 if (best == NULL)
2463 best = next; 2740 best = pkt_dev;
2741 else if (pkt_dev->next_tx_us < best->next_tx_us)
2742 best = pkt_dev;
2464 } 2743 }
2465 if_unlock(t); 2744 if_unlock(t);
2466 return best; 2745 return best;
2467} 2746}
2468 2747
2469static void pktgen_stop(struct pktgen_thread *t) { 2748static void pktgen_stop(struct pktgen_thread *t)
2470 struct pktgen_dev *next = NULL; 2749{
2750 struct pktgen_dev *pkt_dev;
2471 2751
2472 PG_DEBUG(printk("pktgen: entering pktgen_stop.\n")); 2752 PG_DEBUG(printk("pktgen: entering pktgen_stop\n"));
2473 2753
2474 if_lock(t); 2754 if_lock(t);
2755
2756 list_for_each_entry(pkt_dev, &t->if_list, list) {
2757 pktgen_stop_device(pkt_dev);
2758 if (pkt_dev->skb)
2759 kfree_skb(pkt_dev->skb);
2475 2760
2476 for(next=t->if_list; next; next=next->next) 2761 pkt_dev->skb = NULL;
2477 pktgen_stop_device(next); 2762 }
2478 2763
2479 if_unlock(t); 2764 if_unlock(t);
2480} 2765}
2481 2766
2482static void pktgen_rem_all_ifs(struct pktgen_thread *t) 2767/*
2768 * one of our devices needs to be removed - find it
2769 * and remove it
2770 */
2771static void pktgen_rem_one_if(struct pktgen_thread *t)
2483{ 2772{
2484 struct pktgen_dev *cur, *next = NULL; 2773 struct list_head *q, *n;
2485 2774 struct pktgen_dev *cur;
2486 /* Remove all devices, free mem */ 2775
2487 2776 PG_DEBUG(printk("pktgen: entering pktgen_rem_one_if\n"));
2488 if_lock(t); 2777
2489 2778 if_lock(t);
2490 for(cur=t->if_list; cur; cur=next) { 2779
2491 next = cur->next; 2780 list_for_each_safe(q, n, &t->if_list) {
2781 cur = list_entry(q, struct pktgen_dev, list);
2782
2783 if (!cur->removal_mark)
2784 continue;
2785
2786 if (cur->skb)
2787 kfree_skb(cur->skb);
2788 cur->skb = NULL;
2789
2492 pktgen_remove_device(t, cur); 2790 pktgen_remove_device(t, cur);
2791
2792 break;
2493 } 2793 }
2494 2794
2495 if_unlock(t); 2795 if_unlock(t);
2496} 2796}
2497 2797
2498static void pktgen_rem_thread(struct pktgen_thread *t) 2798static void pktgen_rem_all_ifs(struct pktgen_thread *t)
2499{ 2799{
2500 /* Remove from the thread list */ 2800 struct list_head *q, *n;
2801 struct pktgen_dev *cur;
2501 2802
2502 struct pktgen_thread *tmp = pktgen_threads; 2803 /* Remove all devices, free mem */
2503 2804
2504 remove_proc_entry(t->name, pg_proc_dir); 2805 PG_DEBUG(printk("pktgen: entering pktgen_rem_all_ifs\n"));
2806 if_lock(t);
2505 2807
2506 thread_lock(); 2808 list_for_each_safe(q, n, &t->if_list) {
2809 cur = list_entry(q, struct pktgen_dev, list);
2507 2810
2508 if (tmp == t) 2811 if (cur->skb)
2509 pktgen_threads = tmp->next; 2812 kfree_skb(cur->skb);
2510 else { 2813 cur->skb = NULL;
2511 while (tmp) { 2814
2512 if (tmp->next == t) { 2815 pktgen_remove_device(t, cur);
2513 tmp->next = t->next;
2514 t->next = NULL;
2515 break;
2516 }
2517 tmp = tmp->next;
2518 }
2519 } 2816 }
2520 thread_unlock(); 2817
2818 if_unlock(t);
2819}
2820
2821static void pktgen_rem_thread(struct pktgen_thread *t)
2822{
2823 /* Remove from the thread list */
2824
2825 remove_proc_entry(t->name, pg_proc_dir);
2826
2827 mutex_lock(&pktgen_thread_lock);
2828
2829 list_del(&t->th_list);
2830
2831 mutex_unlock(&pktgen_thread_lock);
2521} 2832}
2522 2833
2523static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev) 2834static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
@@ -2527,7 +2838,7 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
2527 int ret; 2838 int ret;
2528 2839
2529 odev = pkt_dev->odev; 2840 odev = pkt_dev->odev;
2530 2841
2531 if (pkt_dev->delay_us || pkt_dev->delay_ns) { 2842 if (pkt_dev->delay_us || pkt_dev->delay_ns) {
2532 u64 now; 2843 u64 now;
2533 2844
@@ -2544,67 +2855,71 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
2544 goto out; 2855 goto out;
2545 } 2856 }
2546 } 2857 }
2547 2858
2548 if (netif_queue_stopped(odev) || need_resched()) { 2859 if (netif_queue_stopped(odev) || need_resched()) {
2549 idle_start = getCurUs(); 2860 idle_start = getCurUs();
2550 2861
2551 if (!netif_running(odev)) { 2862 if (!netif_running(odev)) {
2552 pktgen_stop_device(pkt_dev); 2863 pktgen_stop_device(pkt_dev);
2864 if (pkt_dev->skb)
2865 kfree_skb(pkt_dev->skb);
2866 pkt_dev->skb = NULL;
2553 goto out; 2867 goto out;
2554 } 2868 }
2555 if (need_resched()) 2869 if (need_resched())
2556 schedule(); 2870 schedule();
2557 2871
2558 pkt_dev->idle_acc += getCurUs() - idle_start; 2872 pkt_dev->idle_acc += getCurUs() - idle_start;
2559 2873
2560 if (netif_queue_stopped(odev)) { 2874 if (netif_queue_stopped(odev)) {
2561 pkt_dev->next_tx_us = getCurUs(); /* TODO */ 2875 pkt_dev->next_tx_us = getCurUs(); /* TODO */
2562 pkt_dev->next_tx_ns = 0; 2876 pkt_dev->next_tx_ns = 0;
2563 goto out; /* Try the next interface */ 2877 goto out; /* Try the next interface */
2564 } 2878 }
2565 } 2879 }
2566 2880
2567 if (pkt_dev->last_ok || !pkt_dev->skb) { 2881 if (pkt_dev->last_ok || !pkt_dev->skb) {
2568 if ((++pkt_dev->clone_count >= pkt_dev->clone_skb ) || (!pkt_dev->skb)) { 2882 if ((++pkt_dev->clone_count >= pkt_dev->clone_skb)
2883 || (!pkt_dev->skb)) {
2569 /* build a new pkt */ 2884 /* build a new pkt */
2570 if (pkt_dev->skb) 2885 if (pkt_dev->skb)
2571 kfree_skb(pkt_dev->skb); 2886 kfree_skb(pkt_dev->skb);
2572 2887
2573 pkt_dev->skb = fill_packet(odev, pkt_dev); 2888 pkt_dev->skb = fill_packet(odev, pkt_dev);
2574 if (pkt_dev->skb == NULL) { 2889 if (pkt_dev->skb == NULL) {
2575 printk("pktgen: ERROR: couldn't allocate skb in fill_packet.\n"); 2890 printk("pktgen: ERROR: couldn't allocate skb in fill_packet.\n");
2576 schedule(); 2891 schedule();
2577 pkt_dev->clone_count--; /* back out increment, OOM */ 2892 pkt_dev->clone_count--; /* back out increment, OOM */
2578 goto out; 2893 goto out;
2579 } 2894 }
2580 pkt_dev->allocated_skbs++; 2895 pkt_dev->allocated_skbs++;
2581 pkt_dev->clone_count = 0; /* reset counter */ 2896 pkt_dev->clone_count = 0; /* reset counter */
2582 } 2897 }
2583 } 2898 }
2584 2899
2585 spin_lock_bh(&odev->xmit_lock); 2900 spin_lock_bh(&odev->xmit_lock);
2586 if (!netif_queue_stopped(odev)) { 2901 if (!netif_queue_stopped(odev)) {
2587 2902
2588 atomic_inc(&(pkt_dev->skb->users)); 2903 atomic_inc(&(pkt_dev->skb->users));
2589retry_now: 2904 retry_now:
2590 ret = odev->hard_start_xmit(pkt_dev->skb, odev); 2905 ret = odev->hard_start_xmit(pkt_dev->skb, odev);
2591 if (likely(ret == NETDEV_TX_OK)) { 2906 if (likely(ret == NETDEV_TX_OK)) {
2592 pkt_dev->last_ok = 1; 2907 pkt_dev->last_ok = 1;
2593 pkt_dev->sofar++; 2908 pkt_dev->sofar++;
2594 pkt_dev->seq_num++; 2909 pkt_dev->seq_num++;
2595 pkt_dev->tx_bytes += pkt_dev->cur_pkt_size; 2910 pkt_dev->tx_bytes += pkt_dev->cur_pkt_size;
2596 2911
2597 } else if (ret == NETDEV_TX_LOCKED 2912 } else if (ret == NETDEV_TX_LOCKED
2598 && (odev->features & NETIF_F_LLTX)) { 2913 && (odev->features & NETIF_F_LLTX)) {
2599 cpu_relax(); 2914 cpu_relax();
2600 goto retry_now; 2915 goto retry_now;
2601 } else { /* Retry it next time */ 2916 } else { /* Retry it next time */
2602 2917
2603 atomic_dec(&(pkt_dev->skb->users)); 2918 atomic_dec(&(pkt_dev->skb->users));
2604 2919
2605 if (debug && net_ratelimit()) 2920 if (debug && net_ratelimit())
2606 printk(KERN_INFO "pktgen: Hard xmit error\n"); 2921 printk(KERN_INFO "pktgen: Hard xmit error\n");
2607 2922
2608 pkt_dev->errors++; 2923 pkt_dev->errors++;
2609 pkt_dev->last_ok = 0; 2924 pkt_dev->last_ok = 0;
2610 } 2925 }
@@ -2619,16 +2934,16 @@ retry_now:
2619 pkt_dev->next_tx_us++; 2934 pkt_dev->next_tx_us++;
2620 pkt_dev->next_tx_ns -= 1000; 2935 pkt_dev->next_tx_ns -= 1000;
2621 } 2936 }
2622 } 2937 }
2623 2938
2624 else { /* Retry it next time */ 2939 else { /* Retry it next time */
2625 pkt_dev->last_ok = 0; 2940 pkt_dev->last_ok = 0;
2626 pkt_dev->next_tx_us = getCurUs(); /* TODO */ 2941 pkt_dev->next_tx_us = getCurUs(); /* TODO */
2627 pkt_dev->next_tx_ns = 0; 2942 pkt_dev->next_tx_ns = 0;
2628 } 2943 }
2629 2944
2630 spin_unlock_bh(&odev->xmit_lock); 2945 spin_unlock_bh(&odev->xmit_lock);
2631 2946
2632 /* If pkt_dev->count is zero, then run forever */ 2947 /* If pkt_dev->count is zero, then run forever */
2633 if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) { 2948 if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) {
2634 if (atomic_read(&(pkt_dev->skb->users)) != 1) { 2949 if (atomic_read(&(pkt_dev->skb->users)) != 1) {
@@ -2641,72 +2956,74 @@ retry_now:
2641 } 2956 }
2642 pkt_dev->idle_acc += getCurUs() - idle_start; 2957 pkt_dev->idle_acc += getCurUs() - idle_start;
2643 } 2958 }
2644 2959
2645 /* Done with this */ 2960 /* Done with this */
2646 pktgen_stop_device(pkt_dev); 2961 pktgen_stop_device(pkt_dev);
2647 } 2962 if (pkt_dev->skb)
2648 out:; 2963 kfree_skb(pkt_dev->skb);
2649 } 2964 pkt_dev->skb = NULL;
2965 }
2966out:;
2967}
2650 2968
2651/* 2969/*
2652 * Main loop of the thread goes here 2970 * Main loop of the thread goes here
2653 */ 2971 */
2654 2972
2655static void pktgen_thread_worker(struct pktgen_thread *t) 2973static void pktgen_thread_worker(struct pktgen_thread *t)
2656{ 2974{
2657 DEFINE_WAIT(wait); 2975 DEFINE_WAIT(wait);
2658 struct pktgen_dev *pkt_dev = NULL; 2976 struct pktgen_dev *pkt_dev = NULL;
2659 int cpu = t->cpu; 2977 int cpu = t->cpu;
2660 sigset_t tmpsig; 2978 sigset_t tmpsig;
2661 u32 max_before_softirq; 2979 u32 max_before_softirq;
2662 u32 tx_since_softirq = 0; 2980 u32 tx_since_softirq = 0;
2663 2981
2664 daemonize("pktgen/%d", cpu); 2982 daemonize("pktgen/%d", cpu);
2665 2983
2666 /* Block all signals except SIGKILL, SIGSTOP and SIGTERM */ 2984 /* Block all signals except SIGKILL, SIGSTOP and SIGTERM */
2667 2985
2668 spin_lock_irq(&current->sighand->siglock); 2986 spin_lock_irq(&current->sighand->siglock);
2669 tmpsig = current->blocked; 2987 tmpsig = current->blocked;
2670 siginitsetinv(&current->blocked, 2988 siginitsetinv(&current->blocked,
2671 sigmask(SIGKILL) | 2989 sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGTERM));
2672 sigmask(SIGSTOP)|
2673 sigmask(SIGTERM));
2674 2990
2675 recalc_sigpending(); 2991 recalc_sigpending();
2676 spin_unlock_irq(&current->sighand->siglock); 2992 spin_unlock_irq(&current->sighand->siglock);
2677 2993
2678 /* Migrate to the right CPU */ 2994 /* Migrate to the right CPU */
2679 set_cpus_allowed(current, cpumask_of_cpu(cpu)); 2995 set_cpus_allowed(current, cpumask_of_cpu(cpu));
2680 if (smp_processor_id() != cpu) 2996 if (smp_processor_id() != cpu)
2681 BUG(); 2997 BUG();
2682 2998
2683 init_waitqueue_head(&t->queue); 2999 init_waitqueue_head(&t->queue);
2684 3000
2685 t->control &= ~(T_TERMINATE); 3001 t->control &= ~(T_TERMINATE);
2686 t->control &= ~(T_RUN); 3002 t->control &= ~(T_RUN);
2687 t->control &= ~(T_STOP); 3003 t->control &= ~(T_STOP);
3004 t->control &= ~(T_REMDEVALL);
2688 t->control &= ~(T_REMDEV); 3005 t->control &= ~(T_REMDEV);
2689 3006
2690 t->pid = current->pid; 3007 t->pid = current->pid;
2691 3008
2692 PG_DEBUG(printk("pktgen: starting pktgen/%d: pid=%d\n", cpu, current->pid)); 3009 PG_DEBUG(printk("pktgen: starting pktgen/%d: pid=%d\n", cpu, current->pid));
2693 3010
2694 max_before_softirq = t->max_before_softirq; 3011 max_before_softirq = t->max_before_softirq;
2695
2696 __set_current_state(TASK_INTERRUPTIBLE);
2697 mb();
2698 3012
2699 while (1) { 3013 __set_current_state(TASK_INTERRUPTIBLE);
2700 3014 mb();
3015
3016 while (1) {
3017
2701 __set_current_state(TASK_RUNNING); 3018 __set_current_state(TASK_RUNNING);
2702 3019
2703 /* 3020 /*
2704 * Get next dev to xmit -- if any. 3021 * Get next dev to xmit -- if any.
2705 */ 3022 */
2706 3023
2707 pkt_dev = next_to_run(t); 3024 pkt_dev = next_to_run(t);
2708 3025
2709 if (pkt_dev) { 3026 if (pkt_dev) {
2710 3027
2711 pktgen_xmit(pkt_dev); 3028 pktgen_xmit(pkt_dev);
2712 3029
@@ -2724,115 +3041,125 @@ static void pktgen_thread_worker(struct pktgen_thread *t)
2724 } 3041 }
2725 } else { 3042 } else {
2726 prepare_to_wait(&(t->queue), &wait, TASK_INTERRUPTIBLE); 3043 prepare_to_wait(&(t->queue), &wait, TASK_INTERRUPTIBLE);
2727 schedule_timeout(HZ/10); 3044 schedule_timeout(HZ / 10);
2728 finish_wait(&(t->queue), &wait); 3045 finish_wait(&(t->queue), &wait);
2729 } 3046 }
2730 3047
2731 /* 3048 /*
2732 * Back from sleep, either due to the timeout or signal. 3049 * Back from sleep, either due to the timeout or signal.
2733 * We check if we have any "posted" work for us. 3050 * We check if we have any "posted" work for us.
2734 */ 3051 */
2735 3052
2736 if (t->control & T_TERMINATE || signal_pending(current)) 3053 if (t->control & T_TERMINATE || signal_pending(current))
2737 /* we received a request to terminate ourself */ 3054 /* we received a request to terminate ourself */
2738 break; 3055 break;
2739
2740 3056
2741 if(t->control & T_STOP) { 3057 if (t->control & T_STOP) {
2742 pktgen_stop(t); 3058 pktgen_stop(t);
2743 t->control &= ~(T_STOP); 3059 t->control &= ~(T_STOP);
2744 } 3060 }
2745 3061
2746 if(t->control & T_RUN) { 3062 if (t->control & T_RUN) {
2747 pktgen_run(t); 3063 pktgen_run(t);
2748 t->control &= ~(T_RUN); 3064 t->control &= ~(T_RUN);
2749 } 3065 }
2750 3066
2751 if(t->control & T_REMDEV) { 3067 if (t->control & T_REMDEVALL) {
2752 pktgen_rem_all_ifs(t); 3068 pktgen_rem_all_ifs(t);
3069 t->control &= ~(T_REMDEVALL);
3070 }
3071
3072 if (t->control & T_REMDEV) {
3073 pktgen_rem_one_if(t);
2753 t->control &= ~(T_REMDEV); 3074 t->control &= ~(T_REMDEV);
2754 } 3075 }
2755 3076
2756 if (need_resched()) 3077 if (need_resched())
2757 schedule(); 3078 schedule();
2758 } 3079 }
3080
3081 PG_DEBUG(printk("pktgen: %s stopping all device\n", t->name));
3082 pktgen_stop(t);
2759 3083
2760 PG_DEBUG(printk("pktgen: %s stopping all device\n", t->name)); 3084 PG_DEBUG(printk("pktgen: %s removing all device\n", t->name));
2761 pktgen_stop(t); 3085 pktgen_rem_all_ifs(t);
2762 3086
2763 PG_DEBUG(printk("pktgen: %s removing all device\n", t->name)); 3087 PG_DEBUG(printk("pktgen: %s removing thread.\n", t->name));
2764 pktgen_rem_all_ifs(t); 3088 pktgen_rem_thread(t);
2765 3089
2766 PG_DEBUG(printk("pktgen: %s removing thread.\n", t->name)); 3090 t->removed = 1;
2767 pktgen_rem_thread(t);
2768} 3091}
2769 3092
2770static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t, const char* ifname) 3093static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t,
3094 const char *ifname)
2771{ 3095{
2772 struct pktgen_dev *pkt_dev = NULL; 3096 struct pktgen_dev *p, *pkt_dev = NULL;
2773 if_lock(t); 3097 if_lock(t);
2774 3098
2775 for(pkt_dev=t->if_list; pkt_dev; pkt_dev = pkt_dev->next ) { 3099 list_for_each_entry(p, &t->if_list, list)
2776 if (strncmp(pkt_dev->ifname, ifname, IFNAMSIZ) == 0) { 3100 if (strncmp(p->ifname, ifname, IFNAMSIZ) == 0) {
2777 break; 3101 pkt_dev = p;
2778 } 3102 break;
2779 } 3103 }
2780 3104
2781 if_unlock(t); 3105 if_unlock(t);
2782 PG_DEBUG(printk("pktgen: find_dev(%s) returning %p\n", ifname,pkt_dev)); 3106 PG_DEBUG(printk("pktgen: find_dev(%s) returning %p\n", ifname, pkt_dev));
2783 return pkt_dev; 3107 return pkt_dev;
2784} 3108}
2785 3109
2786/* 3110/*
2787 * Adds a dev at front of if_list. 3111 * Adds a dev at front of if_list.
2788 */ 3112 */
2789 3113
2790static int add_dev_to_thread(struct pktgen_thread *t, struct pktgen_dev *pkt_dev) 3114static int add_dev_to_thread(struct pktgen_thread *t,
3115 struct pktgen_dev *pkt_dev)
2791{ 3116{
2792 int rv = 0; 3117 int rv = 0;
2793 3118
2794 if_lock(t); 3119 if_lock(t);
2795 3120
2796 if (pkt_dev->pg_thread) { 3121 if (pkt_dev->pg_thread) {
2797 printk("pktgen: ERROR: already assigned to a thread.\n"); 3122 printk("pktgen: ERROR: already assigned to a thread.\n");
2798 rv = -EBUSY; 3123 rv = -EBUSY;
2799 goto out; 3124 goto out;
2800 } 3125 }
2801 pkt_dev->next =t->if_list; t->if_list=pkt_dev; 3126
2802 pkt_dev->pg_thread = t; 3127 list_add(&pkt_dev->list, &t->if_list);
3128 pkt_dev->pg_thread = t;
2803 pkt_dev->running = 0; 3129 pkt_dev->running = 0;
2804 3130
2805 out: 3131out:
2806 if_unlock(t); 3132 if_unlock(t);
2807 return rv; 3133 return rv;
2808} 3134}
2809 3135
2810/* Called under thread lock */ 3136/* Called under thread lock */
2811 3137
2812static int pktgen_add_device(struct pktgen_thread *t, const char* ifname) 3138static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
2813{ 3139{
2814 struct pktgen_dev *pkt_dev; 3140 struct pktgen_dev *pkt_dev;
2815 struct proc_dir_entry *pe; 3141 struct proc_dir_entry *pe;
2816 3142
2817 /* We don't allow a device to be on several threads */ 3143 /* We don't allow a device to be on several threads */
2818 3144
2819 pkt_dev = __pktgen_NN_threads(ifname, FIND); 3145 pkt_dev = __pktgen_NN_threads(ifname, FIND);
2820 if (pkt_dev) { 3146 if (pkt_dev) {
2821 printk("pktgen: ERROR: interface already used.\n"); 3147 printk("pktgen: ERROR: interface already used.\n");
2822 return -EBUSY; 3148 return -EBUSY;
2823 } 3149 }
2824 3150
2825 pkt_dev = kzalloc(sizeof(struct pktgen_dev), GFP_KERNEL); 3151 pkt_dev = kzalloc(sizeof(struct pktgen_dev), GFP_KERNEL);
2826 if (!pkt_dev) 3152 if (!pkt_dev)
2827 return -ENOMEM; 3153 return -ENOMEM;
2828 3154
2829 pkt_dev->flows = vmalloc(MAX_CFLOWS*sizeof(struct flow_state)); 3155 pkt_dev->flows = vmalloc(MAX_CFLOWS * sizeof(struct flow_state));
2830 if (pkt_dev->flows == NULL) { 3156 if (pkt_dev->flows == NULL) {
2831 kfree(pkt_dev); 3157 kfree(pkt_dev);
2832 return -ENOMEM; 3158 return -ENOMEM;
2833 } 3159 }
2834 memset(pkt_dev->flows, 0, MAX_CFLOWS*sizeof(struct flow_state)); 3160 memset(pkt_dev->flows, 0, MAX_CFLOWS * sizeof(struct flow_state));
2835 3161
3162 pkt_dev->removal_mark = 0;
2836 pkt_dev->min_pkt_size = ETH_ZLEN; 3163 pkt_dev->min_pkt_size = ETH_ZLEN;
2837 pkt_dev->max_pkt_size = ETH_ZLEN; 3164 pkt_dev->max_pkt_size = ETH_ZLEN;
2838 pkt_dev->nfrags = 0; 3165 pkt_dev->nfrags = 0;
@@ -2841,14 +3168,14 @@ static int pktgen_add_device(struct pktgen_thread *t, const char* ifname)
2841 pkt_dev->delay_ns = pg_delay_d % 1000; 3168 pkt_dev->delay_ns = pg_delay_d % 1000;
2842 pkt_dev->count = pg_count_d; 3169 pkt_dev->count = pg_count_d;
2843 pkt_dev->sofar = 0; 3170 pkt_dev->sofar = 0;
2844 pkt_dev->udp_src_min = 9; /* sink port */ 3171 pkt_dev->udp_src_min = 9; /* sink port */
2845 pkt_dev->udp_src_max = 9; 3172 pkt_dev->udp_src_max = 9;
2846 pkt_dev->udp_dst_min = 9; 3173 pkt_dev->udp_dst_min = 9;
2847 pkt_dev->udp_dst_max = 9; 3174 pkt_dev->udp_dst_max = 9;
2848 3175
2849 strncpy(pkt_dev->ifname, ifname, IFNAMSIZ); 3176 strncpy(pkt_dev->ifname, ifname, IFNAMSIZ);
2850 3177
2851 if (! pktgen_setup_dev(pkt_dev)) { 3178 if (!pktgen_setup_dev(pkt_dev)) {
2852 printk("pktgen: ERROR: pktgen_setup_dev failed.\n"); 3179 printk("pktgen: ERROR: pktgen_setup_dev failed.\n");
2853 if (pkt_dev->flows) 3180 if (pkt_dev->flows)
2854 vfree(pkt_dev->flows); 3181 vfree(pkt_dev->flows);
@@ -2871,65 +3198,74 @@ static int pktgen_add_device(struct pktgen_thread *t, const char* ifname)
2871 return add_dev_to_thread(t, pkt_dev); 3198 return add_dev_to_thread(t, pkt_dev);
2872} 3199}
2873 3200
2874static struct pktgen_thread * __init pktgen_find_thread(const char* name) 3201static struct pktgen_thread *__init pktgen_find_thread(const char *name)
2875{ 3202{
2876 struct pktgen_thread *t = NULL; 3203 struct pktgen_thread *t;
2877 3204
2878 thread_lock(); 3205 mutex_lock(&pktgen_thread_lock);
2879 3206
2880 t = pktgen_threads; 3207 list_for_each_entry(t, &pktgen_threads, th_list)
2881 while (t) { 3208 if (strcmp(t->name, name) == 0) {
2882 if (strcmp(t->name, name) == 0) 3209 mutex_unlock(&pktgen_thread_lock);
2883 break; 3210 return t;
3211 }
2884 3212
2885 t = t->next; 3213 mutex_unlock(&pktgen_thread_lock);
2886 } 3214 return NULL;
2887 thread_unlock();
2888 return t;
2889} 3215}
2890 3216
2891static int __init pktgen_create_thread(const char* name, int cpu) 3217static int __init pktgen_create_thread(const char *name, int cpu)
2892{ 3218{
2893 struct pktgen_thread *t = NULL; 3219 int err;
3220 struct pktgen_thread *t = NULL;
2894 struct proc_dir_entry *pe; 3221 struct proc_dir_entry *pe;
2895 3222
2896 if (strlen(name) > 31) { 3223 if (strlen(name) > 31) {
2897 printk("pktgen: ERROR: Thread name cannot be more than 31 characters.\n"); 3224 printk("pktgen: ERROR: Thread name cannot be more than 31 characters.\n");
2898 return -EINVAL; 3225 return -EINVAL;
2899 } 3226 }
2900 3227
2901 if (pktgen_find_thread(name)) { 3228 if (pktgen_find_thread(name)) {
2902 printk("pktgen: ERROR: thread: %s already exists\n", name); 3229 printk("pktgen: ERROR: thread: %s already exists\n", name);
2903 return -EINVAL; 3230 return -EINVAL;
2904 } 3231 }
2905 3232
2906 t = kzalloc(sizeof(struct pktgen_thread), GFP_KERNEL); 3233 t = kzalloc(sizeof(struct pktgen_thread), GFP_KERNEL);
2907 if (!t) { 3234 if (!t) {
2908 printk("pktgen: ERROR: out of memory, can't create new thread.\n"); 3235 printk("pktgen: ERROR: out of memory, can't create new thread.\n");
2909 return -ENOMEM; 3236 return -ENOMEM;
2910 } 3237 }
2911 3238
2912 strcpy(t->name, name); 3239 strcpy(t->name, name);
2913 spin_lock_init(&t->if_lock); 3240 spin_lock_init(&t->if_lock);
2914 t->cpu = cpu; 3241 t->cpu = cpu;
2915 3242
2916 pe = create_proc_entry(t->name, 0600, pg_proc_dir); 3243 pe = create_proc_entry(t->name, 0600, pg_proc_dir);
2917 if (!pe) { 3244 if (!pe) {
2918 printk("pktgen: cannot create %s/%s procfs entry.\n", 3245 printk("pktgen: cannot create %s/%s procfs entry.\n",
2919 PG_PROC_DIR, t->name); 3246 PG_PROC_DIR, t->name);
2920 kfree(t); 3247 kfree(t);
2921 return -EINVAL; 3248 return -EINVAL;
2922 } 3249 }
2923 3250
2924 pe->proc_fops = &pktgen_thread_fops; 3251 pe->proc_fops = &pktgen_thread_fops;
2925 pe->data = t; 3252 pe->data = t;
2926 3253
2927 t->next = pktgen_threads; 3254 INIT_LIST_HEAD(&t->if_list);
2928 pktgen_threads = t; 3255
3256 list_add_tail(&t->th_list, &pktgen_threads);
3257
3258 t->removed = 0;
2929 3259
2930 if (kernel_thread((void *) pktgen_thread_worker, (void *) t, 3260 err = kernel_thread((void *)pktgen_thread_worker, (void *)t,
2931 CLONE_FS | CLONE_FILES | CLONE_SIGHAND) < 0) 3261 CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
3262 if (err < 0) {
2932 printk("pktgen: kernel_thread() failed for cpu %d\n", t->cpu); 3263 printk("pktgen: kernel_thread() failed for cpu %d\n", t->cpu);
3264 remove_proc_entry(t->name, pg_proc_dir);
3265 list_del(&t->th_list);
3266 kfree(t);
3267 return err;
3268 }
2933 3269
2934 return 0; 3270 return 0;
2935} 3271}
@@ -2937,55 +3273,52 @@ static int __init pktgen_create_thread(const char* name, int cpu)
2937/* 3273/*
2938 * Removes a device from the thread if_list. 3274 * Removes a device from the thread if_list.
2939 */ 3275 */
2940static void _rem_dev_from_if_list(struct pktgen_thread *t, struct pktgen_dev *pkt_dev) 3276static void _rem_dev_from_if_list(struct pktgen_thread *t,
3277 struct pktgen_dev *pkt_dev)
2941{ 3278{
2942 struct pktgen_dev *i, *prev = NULL; 3279 struct list_head *q, *n;
2943 3280 struct pktgen_dev *p;
2944 i = t->if_list;
2945 3281
2946 while(i) { 3282 list_for_each_safe(q, n, &t->if_list) {
2947 if(i == pkt_dev) { 3283 p = list_entry(q, struct pktgen_dev, list);
2948 if(prev) prev->next = i->next; 3284 if (p == pkt_dev)
2949 else t->if_list = NULL; 3285 list_del(&p->list);
2950 break;
2951 }
2952 prev = i;
2953 i=i->next;
2954 } 3286 }
2955} 3287}
2956 3288
2957static int pktgen_remove_device(struct pktgen_thread *t, struct pktgen_dev *pkt_dev) 3289static int pktgen_remove_device(struct pktgen_thread *t,
3290 struct pktgen_dev *pkt_dev)
2958{ 3291{
2959 3292
2960 PG_DEBUG(printk("pktgen: remove_device pkt_dev=%p\n", pkt_dev)); 3293 PG_DEBUG(printk("pktgen: remove_device pkt_dev=%p\n", pkt_dev));
2961 3294
2962 if (pkt_dev->running) { 3295 if (pkt_dev->running) {
2963 printk("pktgen:WARNING: trying to remove a running interface, stopping it now.\n"); 3296 printk("pktgen:WARNING: trying to remove a running interface, stopping it now.\n");
2964 pktgen_stop_device(pkt_dev); 3297 pktgen_stop_device(pkt_dev);
2965 } 3298 }
2966 3299
2967 /* Dis-associate from the interface */ 3300 /* Dis-associate from the interface */
2968 3301
2969 if (pkt_dev->odev) { 3302 if (pkt_dev->odev) {
2970 dev_put(pkt_dev->odev); 3303 dev_put(pkt_dev->odev);
2971 pkt_dev->odev = NULL; 3304 pkt_dev->odev = NULL;
2972 } 3305 }
2973 3306
2974 /* And update the thread if_list */ 3307 /* And update the thread if_list */
2975 3308
2976 _rem_dev_from_if_list(t, pkt_dev); 3309 _rem_dev_from_if_list(t, pkt_dev);
2977 3310
2978 /* Clean up proc file system */ 3311 /* Clean up proc file system */
2979 3312
2980 remove_proc_entry(pkt_dev->ifname, pg_proc_dir); 3313 remove_proc_entry(pkt_dev->ifname, pg_proc_dir);
2981 3314
2982 if (pkt_dev->flows) 3315 if (pkt_dev->flows)
2983 vfree(pkt_dev->flows); 3316 vfree(pkt_dev->flows);
2984 kfree(pkt_dev); 3317 kfree(pkt_dev);
2985 return 0; 3318 return 0;
2986} 3319}
2987 3320
2988static int __init pg_init(void) 3321static int __init pg_init(void)
2989{ 3322{
2990 int cpu; 3323 int cpu;
2991 struct proc_dir_entry *pe; 3324 struct proc_dir_entry *pe;
@@ -2998,50 +3331,65 @@ static int __init pg_init(void)
2998 pg_proc_dir->owner = THIS_MODULE; 3331 pg_proc_dir->owner = THIS_MODULE;
2999 3332
3000 pe = create_proc_entry(PGCTRL, 0600, pg_proc_dir); 3333 pe = create_proc_entry(PGCTRL, 0600, pg_proc_dir);
3001 if (pe == NULL) { 3334 if (pe == NULL) {
3002 printk("pktgen: ERROR: cannot create %s procfs entry.\n", PGCTRL); 3335 printk("pktgen: ERROR: cannot create %s procfs entry.\n",
3336 PGCTRL);
3003 proc_net_remove(PG_PROC_DIR); 3337 proc_net_remove(PG_PROC_DIR);
3004 return -EINVAL; 3338 return -EINVAL;
3005 } 3339 }
3006 3340
3007 pe->proc_fops = &pktgen_fops; 3341 pe->proc_fops = &pktgen_fops;
3008 pe->data = NULL; 3342 pe->data = NULL;
3009 3343
3010 /* Register us to receive netdevice events */ 3344 /* Register us to receive netdevice events */
3011 register_netdevice_notifier(&pktgen_notifier_block); 3345 register_netdevice_notifier(&pktgen_notifier_block);
3012 3346
3013 for_each_online_cpu(cpu) { 3347 for_each_online_cpu(cpu) {
3348 int err;
3014 char buf[30]; 3349 char buf[30];
3015 3350
3016 sprintf(buf, "kpktgend_%i", cpu); 3351 sprintf(buf, "kpktgend_%i", cpu);
3017 pktgen_create_thread(buf, cpu); 3352 err = pktgen_create_thread(buf, cpu);
3018 } 3353 if (err)
3019 return 0; 3354 printk("pktgen: WARNING: Cannot create thread for cpu %d (%d)\n",
3355 cpu, err);
3356 }
3357
3358 if (list_empty(&pktgen_threads)) {
3359 printk("pktgen: ERROR: Initialization failed for all threads\n");
3360 unregister_netdevice_notifier(&pktgen_notifier_block);
3361 remove_proc_entry(PGCTRL, pg_proc_dir);
3362 proc_net_remove(PG_PROC_DIR);
3363 return -ENODEV;
3364 }
3365
3366 return 0;
3020} 3367}
3021 3368
3022static void __exit pg_cleanup(void) 3369static void __exit pg_cleanup(void)
3023{ 3370{
3371 struct pktgen_thread *t;
3372 struct list_head *q, *n;
3024 wait_queue_head_t queue; 3373 wait_queue_head_t queue;
3025 init_waitqueue_head(&queue); 3374 init_waitqueue_head(&queue);
3026 3375
3027 /* Stop all interfaces & threads */ 3376 /* Stop all interfaces & threads */
3028 3377
3029 while (pktgen_threads) { 3378 list_for_each_safe(q, n, &pktgen_threads) {
3030 struct pktgen_thread *t = pktgen_threads; 3379 t = list_entry(q, struct pktgen_thread, th_list);
3031 pktgen_threads->control |= (T_TERMINATE); 3380 t->control |= (T_TERMINATE);
3032 3381
3033 wait_event_interruptible_timeout(queue, (t != pktgen_threads), HZ); 3382 wait_event_interruptible_timeout(queue, (t->removed == 1), HZ);
3034 } 3383 }
3035 3384
3036 /* Un-register us from receiving netdevice events */ 3385 /* Un-register us from receiving netdevice events */
3037 unregister_netdevice_notifier(&pktgen_notifier_block); 3386 unregister_netdevice_notifier(&pktgen_notifier_block);
3038 3387
3039 /* Clean up proc file system */ 3388 /* Clean up proc file system */
3040 remove_proc_entry(PGCTRL, pg_proc_dir); 3389 remove_proc_entry(PGCTRL, pg_proc_dir);
3041 proc_net_remove(PG_PROC_DIR); 3390 proc_net_remove(PG_PROC_DIR);
3042} 3391}
3043 3392
3044
3045module_init(pg_init); 3393module_init(pg_init);
3046module_exit(pg_cleanup); 3394module_exit(pg_cleanup);
3047 3395
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index eca2976abb25..3fcfa9c59e1f 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -35,6 +35,7 @@
35#include <linux/skbuff.h> 35#include <linux/skbuff.h>
36#include <linux/init.h> 36#include <linux/init.h>
37#include <linux/security.h> 37#include <linux/security.h>
38#include <linux/mutex.h>
38 39
39#include <asm/uaccess.h> 40#include <asm/uaccess.h>
40#include <asm/system.h> 41#include <asm/system.h>
@@ -50,26 +51,36 @@
50#include <net/sock.h> 51#include <net/sock.h>
51#include <net/pkt_sched.h> 52#include <net/pkt_sched.h>
52#include <net/netlink.h> 53#include <net/netlink.h>
54#ifdef CONFIG_NET_WIRELESS_RTNETLINK
55#include <linux/wireless.h>
56#include <net/iw_handler.h>
57#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
53 58
54DECLARE_MUTEX(rtnl_sem); 59static DEFINE_MUTEX(rtnl_mutex);
55 60
56void rtnl_lock(void) 61void rtnl_lock(void)
57{ 62{
58 rtnl_shlock(); 63 mutex_lock(&rtnl_mutex);
59} 64}
60 65
61int rtnl_lock_interruptible(void) 66void __rtnl_unlock(void)
62{ 67{
63 return down_interruptible(&rtnl_sem); 68 mutex_unlock(&rtnl_mutex);
64} 69}
65 70
66void rtnl_unlock(void) 71void rtnl_unlock(void)
67{ 72{
68 rtnl_shunlock(); 73 mutex_unlock(&rtnl_mutex);
69 74 if (rtnl && rtnl->sk_receive_queue.qlen)
75 rtnl->sk_data_ready(rtnl, 0);
70 netdev_run_todo(); 76 netdev_run_todo();
71} 77}
72 78
79int rtnl_trylock(void)
80{
81 return mutex_trylock(&rtnl_mutex);
82}
83
73int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len) 84int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len)
74{ 85{
75 memset(tb, 0, sizeof(struct rtattr*)*maxattr); 86 memset(tb, 0, sizeof(struct rtattr*)*maxattr);
@@ -179,6 +190,33 @@ rtattr_failure:
179} 190}
180 191
181 192
193static void set_operstate(struct net_device *dev, unsigned char transition)
194{
195 unsigned char operstate = dev->operstate;
196
197 switch(transition) {
198 case IF_OPER_UP:
199 if ((operstate == IF_OPER_DORMANT ||
200 operstate == IF_OPER_UNKNOWN) &&
201 !netif_dormant(dev))
202 operstate = IF_OPER_UP;
203 break;
204
205 case IF_OPER_DORMANT:
206 if (operstate == IF_OPER_UP ||
207 operstate == IF_OPER_UNKNOWN)
208 operstate = IF_OPER_DORMANT;
209 break;
210 };
211
212 if (dev->operstate != operstate) {
213 write_lock_bh(&dev_base_lock);
214 dev->operstate = operstate;
215 write_unlock_bh(&dev_base_lock);
216 netdev_state_change(dev);
217 }
218}
219
182static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, 220static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
183 int type, u32 pid, u32 seq, u32 change, 221 int type, u32 pid, u32 seq, u32 change,
184 unsigned int flags) 222 unsigned int flags)
@@ -209,6 +247,13 @@ static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
209 } 247 }
210 248
211 if (1) { 249 if (1) {
250 u8 operstate = netif_running(dev)?dev->operstate:IF_OPER_DOWN;
251 u8 link_mode = dev->link_mode;
252 RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate);
253 RTA_PUT(skb, IFLA_LINKMODE, sizeof(link_mode), &link_mode);
254 }
255
256 if (1) {
212 struct rtnl_link_ifmap map = { 257 struct rtnl_link_ifmap map = {
213 .mem_start = dev->mem_start, 258 .mem_start = dev->mem_start,
214 .mem_end = dev->mem_end, 259 .mem_end = dev->mem_end,
@@ -399,6 +444,22 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
399 dev->weight = *((u32 *) RTA_DATA(ida[IFLA_WEIGHT - 1])); 444 dev->weight = *((u32 *) RTA_DATA(ida[IFLA_WEIGHT - 1]));
400 } 445 }
401 446
447 if (ida[IFLA_OPERSTATE - 1]) {
448 if (ida[IFLA_OPERSTATE - 1]->rta_len != RTA_LENGTH(sizeof(u8)))
449 goto out;
450
451 set_operstate(dev, *((u8 *) RTA_DATA(ida[IFLA_OPERSTATE - 1])));
452 }
453
454 if (ida[IFLA_LINKMODE - 1]) {
455 if (ida[IFLA_LINKMODE - 1]->rta_len != RTA_LENGTH(sizeof(u8)))
456 goto out;
457
458 write_lock_bh(&dev_base_lock);
459 dev->link_mode = *((u8 *) RTA_DATA(ida[IFLA_LINKMODE - 1]));
460 write_unlock_bh(&dev_base_lock);
461 }
462
402 if (ifm->ifi_index >= 0 && ida[IFLA_IFNAME - 1]) { 463 if (ifm->ifi_index >= 0 && ida[IFLA_IFNAME - 1]) {
403 char ifname[IFNAMSIZ]; 464 char ifname[IFNAMSIZ];
404 465
@@ -410,6 +471,17 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
410 goto out; 471 goto out;
411 } 472 }
412 473
474#ifdef CONFIG_NET_WIRELESS_RTNETLINK
475 if (ida[IFLA_WIRELESS - 1]) {
476
477 /* Call Wireless Extensions.
478 * Various stuff checked in there... */
479 err = wireless_rtnetlink_set(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len);
480 if (err)
481 goto out;
482 }
483#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
484
413 err = 0; 485 err = 0;
414 486
415out: 487out:
@@ -420,6 +492,83 @@ out:
420 return err; 492 return err;
421} 493}
422 494
495#ifdef CONFIG_NET_WIRELESS_RTNETLINK
496static int do_getlink(struct sk_buff *in_skb, struct nlmsghdr* in_nlh, void *arg)
497{
498 struct ifinfomsg *ifm = NLMSG_DATA(in_nlh);
499 struct rtattr **ida = arg;
500 struct net_device *dev;
501 struct ifinfomsg *r;
502 struct nlmsghdr *nlh;
503 int err = -ENOBUFS;
504 struct sk_buff *skb;
505 unsigned char *b;
506 char *iw_buf = NULL;
507 int iw_buf_len = 0;
508
509 if (ifm->ifi_index >= 0)
510 dev = dev_get_by_index(ifm->ifi_index);
511 else
512 return -EINVAL;
513 if (!dev)
514 return -ENODEV;
515
516#ifdef CONFIG_NET_WIRELESS_RTNETLINK
517 if (ida[IFLA_WIRELESS - 1]) {
518
519 /* Call Wireless Extensions. We need to know the size before
520 * we can alloc. Various stuff checked in there... */
521 err = wireless_rtnetlink_get(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len, &iw_buf, &iw_buf_len);
522 if (err)
523 goto out;
524 }
525#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
526
527 /* Create a skb big enough to include all the data.
528 * Some requests are way bigger than 4k... Jean II */
529 skb = alloc_skb((NLMSG_LENGTH(sizeof(*r))) + (RTA_SPACE(iw_buf_len)),
530 GFP_KERNEL);
531 if (!skb)
532 goto out;
533 b = skb->tail;
534
535 /* Put in the message the usual good stuff */
536 nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid, in_nlh->nlmsg_seq,
537 RTM_NEWLINK, sizeof(*r));
538 r = NLMSG_DATA(nlh);
539 r->ifi_family = AF_UNSPEC;
540 r->__ifi_pad = 0;
541 r->ifi_type = dev->type;
542 r->ifi_index = dev->ifindex;
543 r->ifi_flags = dev->flags;
544 r->ifi_change = 0;
545
546 /* Put the wireless payload if it exist */
547 if(iw_buf != NULL)
548 RTA_PUT(skb, IFLA_WIRELESS, iw_buf_len,
549 iw_buf + IW_EV_POINT_OFF);
550
551 nlh->nlmsg_len = skb->tail - b;
552
553 /* Needed ? */
554 NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
555
556 err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
557 if (err > 0)
558 err = 0;
559out:
560 if(iw_buf != NULL)
561 kfree(iw_buf);
562 dev_put(dev);
563 return err;
564
565rtattr_failure:
566nlmsg_failure:
567 kfree_skb(skb);
568 goto out;
569}
570#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
571
423static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb) 572static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
424{ 573{
425 int idx; 574 int idx;
@@ -575,9 +724,9 @@ static void rtnetlink_rcv(struct sock *sk, int len)
575 unsigned int qlen = 0; 724 unsigned int qlen = 0;
576 725
577 do { 726 do {
578 rtnl_lock(); 727 mutex_lock(&rtnl_mutex);
579 netlink_run_queue(sk, &qlen, &rtnetlink_rcv_msg); 728 netlink_run_queue(sk, &qlen, &rtnetlink_rcv_msg);
580 up(&rtnl_sem); 729 mutex_unlock(&rtnl_mutex);
581 730
582 netdev_run_todo(); 731 netdev_run_todo();
583 } while (qlen); 732 } while (qlen);
@@ -585,7 +734,11 @@ static void rtnetlink_rcv(struct sock *sk, int len)
585 734
586static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] = 735static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] =
587{ 736{
588 [RTM_GETLINK - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo }, 737 [RTM_GETLINK - RTM_BASE] = {
738#ifdef CONFIG_NET_WIRELESS_RTNETLINK
739 .doit = do_getlink,
740#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
741 .dumpit = rtnetlink_dump_ifinfo },
589 [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink }, 742 [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink },
590 [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, 743 [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
591 [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, 744 [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
@@ -654,6 +807,5 @@ EXPORT_SYMBOL(rtnetlink_links);
654EXPORT_SYMBOL(rtnetlink_put_metrics); 807EXPORT_SYMBOL(rtnetlink_put_metrics);
655EXPORT_SYMBOL(rtnl); 808EXPORT_SYMBOL(rtnl);
656EXPORT_SYMBOL(rtnl_lock); 809EXPORT_SYMBOL(rtnl_lock);
657EXPORT_SYMBOL(rtnl_lock_interruptible); 810EXPORT_SYMBOL(rtnl_trylock);
658EXPORT_SYMBOL(rtnl_sem);
659EXPORT_SYMBOL(rtnl_unlock); 811EXPORT_SYMBOL(rtnl_unlock);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 2144952d1c6c..c9f878454531 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -356,6 +356,24 @@ void __kfree_skb(struct sk_buff *skb)
356} 356}
357 357
358/** 358/**
359 * kfree_skb - free an sk_buff
360 * @skb: buffer to free
361 *
362 * Drop a reference to the buffer and free it if the usage count has
363 * hit zero.
364 */
365void kfree_skb(struct sk_buff *skb)
366{
367 if (unlikely(!skb))
368 return;
369 if (likely(atomic_read(&skb->users) == 1))
370 smp_rmb();
371 else if (likely(!atomic_dec_and_test(&skb->users)))
372 return;
373 __kfree_skb(skb);
374}
375
376/**
359 * skb_clone - duplicate an sk_buff 377 * skb_clone - duplicate an sk_buff
360 * @skb: buffer to clone 378 * @skb: buffer to clone
361 * @gfp_mask: allocation priority 379 * @gfp_mask: allocation priority
@@ -1777,6 +1795,29 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
1777 return 0; 1795 return 0;
1778} 1796}
1779 1797
1798/**
1799 * skb_pull_rcsum - pull skb and update receive checksum
1800 * @skb: buffer to update
1801 * @start: start of data before pull
1802 * @len: length of data pulled
1803 *
1804 * This function performs an skb_pull on the packet and updates
1805 * update the CHECKSUM_HW checksum. It should be used on receive
1806 * path processing instead of skb_pull unless you know that the
1807 * checksum difference is zero (e.g., a valid IP header) or you
1808 * are setting ip_summed to CHECKSUM_NONE.
1809 */
1810unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len)
1811{
1812 BUG_ON(len > skb->len);
1813 skb->len -= len;
1814 BUG_ON(skb->len < skb->data_len);
1815 skb_postpull_rcsum(skb, skb->data, len);
1816 return skb->data += len;
1817}
1818
1819EXPORT_SYMBOL_GPL(skb_pull_rcsum);
1820
1780void __init skb_init(void) 1821void __init skb_init(void)
1781{ 1822{
1782 skbuff_head_cache = kmem_cache_create("skbuff_head_cache", 1823 skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
@@ -1799,6 +1840,7 @@ void __init skb_init(void)
1799 1840
1800EXPORT_SYMBOL(___pskb_trim); 1841EXPORT_SYMBOL(___pskb_trim);
1801EXPORT_SYMBOL(__kfree_skb); 1842EXPORT_SYMBOL(__kfree_skb);
1843EXPORT_SYMBOL(kfree_skb);
1802EXPORT_SYMBOL(__pskb_pull_tail); 1844EXPORT_SYMBOL(__pskb_pull_tail);
1803EXPORT_SYMBOL(__alloc_skb); 1845EXPORT_SYMBOL(__alloc_skb);
1804EXPORT_SYMBOL(pskb_copy); 1846EXPORT_SYMBOL(pskb_copy);
diff --git a/net/core/sock.c b/net/core/sock.c
index 6e00811d44bc..1a7e6eac90b0 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -616,7 +616,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
616 break; 616 break;
617 617
618 case SO_PEERSEC: 618 case SO_PEERSEC:
619 return security_socket_getpeersec(sock, optval, optlen, len); 619 return security_socket_getpeersec_stream(sock, optval, optlen, len);
620 620
621 default: 621 default:
622 return(-ENOPROTOOPT); 622 return(-ENOPROTOOPT);
@@ -1385,6 +1385,20 @@ int sock_common_getsockopt(struct socket *sock, int level, int optname,
1385 1385
1386EXPORT_SYMBOL(sock_common_getsockopt); 1386EXPORT_SYMBOL(sock_common_getsockopt);
1387 1387
1388#ifdef CONFIG_COMPAT
1389int compat_sock_common_getsockopt(struct socket *sock, int level, int optname,
1390 char __user *optval, int __user *optlen)
1391{
1392 struct sock *sk = sock->sk;
1393
1394 if (sk->sk_prot->compat_setsockopt != NULL)
1395 return sk->sk_prot->compat_getsockopt(sk, level, optname,
1396 optval, optlen);
1397 return sk->sk_prot->getsockopt(sk, level, optname, optval, optlen);
1398}
1399EXPORT_SYMBOL(compat_sock_common_getsockopt);
1400#endif
1401
1388int sock_common_recvmsg(struct kiocb *iocb, struct socket *sock, 1402int sock_common_recvmsg(struct kiocb *iocb, struct socket *sock,
1389 struct msghdr *msg, size_t size, int flags) 1403 struct msghdr *msg, size_t size, int flags)
1390{ 1404{
@@ -1414,6 +1428,20 @@ int sock_common_setsockopt(struct socket *sock, int level, int optname,
1414 1428
1415EXPORT_SYMBOL(sock_common_setsockopt); 1429EXPORT_SYMBOL(sock_common_setsockopt);
1416 1430
1431#ifdef CONFIG_COMPAT
1432int compat_sock_common_setsockopt(struct socket *sock, int level, int optname,
1433 char __user *optval, int optlen)
1434{
1435 struct sock *sk = sock->sk;
1436
1437 if (sk->sk_prot->compat_setsockopt != NULL)
1438 return sk->sk_prot->compat_setsockopt(sk, level, optname,
1439 optval, optlen);
1440 return sk->sk_prot->setsockopt(sk, level, optname, optval, optlen);
1441}
1442EXPORT_SYMBOL(compat_sock_common_setsockopt);
1443#endif
1444
1417void sk_common_release(struct sock *sk) 1445void sk_common_release(struct sock *sk)
1418{ 1446{
1419 if (sk->sk_prot->destroy) 1447 if (sk->sk_prot->destroy)
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 2f278c8e4743..710453656721 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -26,6 +26,11 @@ extern int sysctl_core_destroy_delay;
26extern char sysctl_divert_version[]; 26extern char sysctl_divert_version[];
27#endif /* CONFIG_NET_DIVERT */ 27#endif /* CONFIG_NET_DIVERT */
28 28
29#ifdef CONFIG_XFRM
30extern u32 sysctl_xfrm_aevent_etime;
31extern u32 sysctl_xfrm_aevent_rseqth;
32#endif
33
29ctl_table core_table[] = { 34ctl_table core_table[] = {
30#ifdef CONFIG_NET 35#ifdef CONFIG_NET
31 { 36 {
@@ -111,6 +116,24 @@ ctl_table core_table[] = {
111 .proc_handler = &proc_dostring 116 .proc_handler = &proc_dostring
112 }, 117 },
113#endif /* CONFIG_NET_DIVERT */ 118#endif /* CONFIG_NET_DIVERT */
119#ifdef CONFIG_XFRM
120 {
121 .ctl_name = NET_CORE_AEVENT_ETIME,
122 .procname = "xfrm_aevent_etime",
123 .data = &sysctl_xfrm_aevent_etime,
124 .maxlen = sizeof(u32),
125 .mode = 0644,
126 .proc_handler = &proc_dointvec
127 },
128 {
129 .ctl_name = NET_CORE_AEVENT_RSEQTH,
130 .procname = "xfrm_aevent_rseqth",
131 .data = &sysctl_xfrm_aevent_rseqth,
132 .maxlen = sizeof(u32),
133 .mode = 0644,
134 .proc_handler = &proc_dointvec
135 },
136#endif /* CONFIG_XFRM */
114#endif /* CONFIG_NET */ 137#endif /* CONFIG_NET */
115 { 138 {
116 .ctl_name = NET_CORE_SOMAXCONN, 139 .ctl_name = NET_CORE_SOMAXCONN,
diff --git a/net/core/wireless.c b/net/core/wireless.c
index 2add7ed609e9..81d6995fcfdb 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -2,7 +2,7 @@
2 * This file implement the Wireless Extensions APIs. 2 * This file implement the Wireless Extensions APIs.
3 * 3 *
4 * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> 4 * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
5 * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved. 5 * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved.
6 * 6 *
7 * (As all part of the Linux kernel, this file is GPL) 7 * (As all part of the Linux kernel, this file is GPL)
8 */ 8 */
@@ -65,6 +65,9 @@
65 * o Start deprecating dev->get_wireless_stats, output a warning 65 * o Start deprecating dev->get_wireless_stats, output a warning
66 * o If IW_QUAL_DBM is set, show dBm values in /proc/net/wireless 66 * o If IW_QUAL_DBM is set, show dBm values in /proc/net/wireless
67 * o Don't loose INVALID/DBM flags when clearing UPDATED flags (iwstats) 67 * o Don't loose INVALID/DBM flags when clearing UPDATED flags (iwstats)
68 *
69 * v8 - 17.02.06 - Jean II
70 * o RtNetlink requests support (SET/GET)
68 */ 71 */
69 72
70/***************************** INCLUDES *****************************/ 73/***************************** INCLUDES *****************************/
@@ -89,11 +92,13 @@
89 92
90/* Debugging stuff */ 93/* Debugging stuff */
91#undef WE_IOCTL_DEBUG /* Debug IOCTL API */ 94#undef WE_IOCTL_DEBUG /* Debug IOCTL API */
95#undef WE_RTNETLINK_DEBUG /* Debug RtNetlink API */
92#undef WE_EVENT_DEBUG /* Debug Event dispatcher */ 96#undef WE_EVENT_DEBUG /* Debug Event dispatcher */
93#undef WE_SPY_DEBUG /* Debug enhanced spy support */ 97#undef WE_SPY_DEBUG /* Debug enhanced spy support */
94 98
95/* Options */ 99/* Options */
96#define WE_EVENT_NETLINK /* Propagate events using rtnetlink */ 100//CONFIG_NET_WIRELESS_RTNETLINK /* Wireless requests over RtNetlink */
101#define WE_EVENT_RTNETLINK /* Propagate events using RtNetlink */
97#define WE_SET_EVENT /* Generate an event on some set commands */ 102#define WE_SET_EVENT /* Generate an event on some set commands */
98 103
99/************************* GLOBAL VARIABLES *************************/ 104/************************* GLOBAL VARIABLES *************************/
@@ -156,13 +161,18 @@ static const struct iw_ioctl_description standard_ioctl[] = {
156 .header_type = IW_HEADER_TYPE_NULL, 161 .header_type = IW_HEADER_TYPE_NULL,
157 }, 162 },
158 [SIOCGIWPRIV - SIOCIWFIRST] = { /* (handled directly by us) */ 163 [SIOCGIWPRIV - SIOCIWFIRST] = { /* (handled directly by us) */
159 .header_type = IW_HEADER_TYPE_NULL, 164 .header_type = IW_HEADER_TYPE_POINT,
165 .token_size = sizeof(struct iw_priv_args),
166 .max_tokens = 16,
167 .flags = IW_DESCR_FLAG_NOMAX,
160 }, 168 },
161 [SIOCSIWSTATS - SIOCIWFIRST] = { 169 [SIOCSIWSTATS - SIOCIWFIRST] = {
162 .header_type = IW_HEADER_TYPE_NULL, 170 .header_type = IW_HEADER_TYPE_NULL,
163 }, 171 },
164 [SIOCGIWSTATS - SIOCIWFIRST] = { /* (handled directly by us) */ 172 [SIOCGIWSTATS - SIOCIWFIRST] = { /* (handled directly by us) */
165 .header_type = IW_HEADER_TYPE_NULL, 173 .header_type = IW_HEADER_TYPE_POINT,
174 .token_size = 1,
175 .max_tokens = sizeof(struct iw_statistics),
166 .flags = IW_DESCR_FLAG_DUMP, 176 .flags = IW_DESCR_FLAG_DUMP,
167 }, 177 },
168 [SIOCSIWSPY - SIOCIWFIRST] = { 178 [SIOCSIWSPY - SIOCIWFIRST] = {
@@ -529,6 +539,70 @@ static inline int adjust_priv_size(__u16 args,
529 return num * iw_priv_type_size[type]; 539 return num * iw_priv_type_size[type];
530} 540}
531 541
542/* ---------------------------------------------------------------- */
543/*
544 * Standard Wireless Handler : get wireless stats
545 * Allow programatic access to /proc/net/wireless even if /proc
546 * doesn't exist... Also more efficient...
547 */
548static int iw_handler_get_iwstats(struct net_device * dev,
549 struct iw_request_info * info,
550 union iwreq_data * wrqu,
551 char * extra)
552{
553 /* Get stats from the driver */
554 struct iw_statistics *stats;
555
556 stats = get_wireless_stats(dev);
557 if (stats != (struct iw_statistics *) NULL) {
558
559 /* Copy statistics to extra */
560 memcpy(extra, stats, sizeof(struct iw_statistics));
561 wrqu->data.length = sizeof(struct iw_statistics);
562
563 /* Check if we need to clear the updated flag */
564 if(wrqu->data.flags != 0)
565 stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
566 return 0;
567 } else
568 return -EOPNOTSUPP;
569}
570
571/* ---------------------------------------------------------------- */
572/*
573 * Standard Wireless Handler : get iwpriv definitions
574 * Export the driver private handler definition
575 * They will be picked up by tools like iwpriv...
576 */
577static int iw_handler_get_private(struct net_device * dev,
578 struct iw_request_info * info,
579 union iwreq_data * wrqu,
580 char * extra)
581{
582 /* Check if the driver has something to export */
583 if((dev->wireless_handlers->num_private_args == 0) ||
584 (dev->wireless_handlers->private_args == NULL))
585 return -EOPNOTSUPP;
586
587 /* Check if there is enough buffer up there */
588 if(wrqu->data.length < dev->wireless_handlers->num_private_args) {
589 /* User space can't know in advance how large the buffer
590 * needs to be. Give it a hint, so that we can support
591 * any size buffer we want somewhat efficiently... */
592 wrqu->data.length = dev->wireless_handlers->num_private_args;
593 return -E2BIG;
594 }
595
596 /* Set the number of available ioctls. */
597 wrqu->data.length = dev->wireless_handlers->num_private_args;
598
599 /* Copy structure to the user buffer. */
600 memcpy(extra, dev->wireless_handlers->private_args,
601 sizeof(struct iw_priv_args) * wrqu->data.length);
602
603 return 0;
604}
605
532 606
533/******************** /proc/net/wireless SUPPORT ********************/ 607/******************** /proc/net/wireless SUPPORT ********************/
534/* 608/*
@@ -630,81 +704,14 @@ int __init wireless_proc_init(void)
630 704
631/* ---------------------------------------------------------------- */ 705/* ---------------------------------------------------------------- */
632/* 706/*
633 * Allow programatic access to /proc/net/wireless even if /proc
634 * doesn't exist... Also more efficient...
635 */
636static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr)
637{
638 /* Get stats from the driver */
639 struct iw_statistics *stats;
640
641 stats = get_wireless_stats(dev);
642 if (stats != (struct iw_statistics *) NULL) {
643 struct iwreq * wrq = (struct iwreq *)ifr;
644
645 /* Copy statistics to the user buffer */
646 if(copy_to_user(wrq->u.data.pointer, stats,
647 sizeof(struct iw_statistics)))
648 return -EFAULT;
649
650 /* Check if we need to clear the updated flag */
651 if(wrq->u.data.flags != 0)
652 stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
653 return 0;
654 } else
655 return -EOPNOTSUPP;
656}
657
658/* ---------------------------------------------------------------- */
659/*
660 * Export the driver private handler definition
661 * They will be picked up by tools like iwpriv...
662 */
663static inline int ioctl_export_private(struct net_device * dev,
664 struct ifreq * ifr)
665{
666 struct iwreq * iwr = (struct iwreq *) ifr;
667
668 /* Check if the driver has something to export */
669 if((dev->wireless_handlers->num_private_args == 0) ||
670 (dev->wireless_handlers->private_args == NULL))
671 return -EOPNOTSUPP;
672
673 /* Check NULL pointer */
674 if(iwr->u.data.pointer == NULL)
675 return -EFAULT;
676
677 /* Check if there is enough buffer up there */
678 if(iwr->u.data.length < dev->wireless_handlers->num_private_args) {
679 /* User space can't know in advance how large the buffer
680 * needs to be. Give it a hint, so that we can support
681 * any size buffer we want somewhat efficiently... */
682 iwr->u.data.length = dev->wireless_handlers->num_private_args;
683 return -E2BIG;
684 }
685
686 /* Set the number of available ioctls. */
687 iwr->u.data.length = dev->wireless_handlers->num_private_args;
688
689 /* Copy structure to the user buffer. */
690 if (copy_to_user(iwr->u.data.pointer,
691 dev->wireless_handlers->private_args,
692 sizeof(struct iw_priv_args) * iwr->u.data.length))
693 return -EFAULT;
694
695 return 0;
696}
697
698/* ---------------------------------------------------------------- */
699/*
700 * Wrapper to call a standard Wireless Extension handler. 707 * Wrapper to call a standard Wireless Extension handler.
701 * We do various checks and also take care of moving data between 708 * We do various checks and also take care of moving data between
702 * user space and kernel space. 709 * user space and kernel space.
703 */ 710 */
704static inline int ioctl_standard_call(struct net_device * dev, 711static int ioctl_standard_call(struct net_device * dev,
705 struct ifreq * ifr, 712 struct ifreq * ifr,
706 unsigned int cmd, 713 unsigned int cmd,
707 iw_handler handler) 714 iw_handler handler)
708{ 715{
709 struct iwreq * iwr = (struct iwreq *) ifr; 716 struct iwreq * iwr = (struct iwreq *) ifr;
710 const struct iw_ioctl_description * descr; 717 const struct iw_ioctl_description * descr;
@@ -1048,14 +1055,20 @@ int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd)
1048 { 1055 {
1049 case SIOCGIWSTATS: 1056 case SIOCGIWSTATS:
1050 /* Get Wireless Stats */ 1057 /* Get Wireless Stats */
1051 return dev_iwstats(dev, ifr); 1058 return ioctl_standard_call(dev,
1059 ifr,
1060 cmd,
1061 &iw_handler_get_iwstats);
1052 1062
1053 case SIOCGIWPRIV: 1063 case SIOCGIWPRIV:
1054 /* Check if we have some wireless handlers defined */ 1064 /* Check if we have some wireless handlers defined */
1055 if(dev->wireless_handlers != NULL) { 1065 if(dev->wireless_handlers != NULL) {
1056 /* We export to user space the definition of 1066 /* We export to user space the definition of
1057 * the private handler ourselves */ 1067 * the private handler ourselves */
1058 return ioctl_export_private(dev, ifr); 1068 return ioctl_standard_call(dev,
1069 ifr,
1070 cmd,
1071 &iw_handler_get_private);
1059 } 1072 }
1060 // ## Fall-through for old API ## 1073 // ## Fall-through for old API ##
1061 default: 1074 default:
@@ -1088,16 +1101,739 @@ int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd)
1088 return -EINVAL; 1101 return -EINVAL;
1089} 1102}
1090 1103
1104/********************** RTNETLINK REQUEST API **********************/
1105/*
1106 * The alternate user space API to configure all those Wireless Extensions
1107 * is through RtNetlink.
1108 * This API support only the new driver API (iw_handler).
1109 *
1110 * This RtNetlink API use the same query/reply model as the ioctl API.
1111 * Maximum effort has been done to fit in the RtNetlink model, and
1112 * we support both RtNetlink Set and RtNelink Get operations.
1113 * On the other hand, we don't offer Dump operations because of the
1114 * following reasons :
1115 * o Large number of parameters, most optional
1116 * o Large size of some parameters (> 100 bytes)
1117 * o Each parameters need to be extracted from hardware
1118 * o Scan requests can take seconds and disable network activity.
1119 * Because of this high cost/overhead, we want to return only the
1120 * parameters the user application is really interested in.
1121 * We could offer partial Dump using the IW_DESCR_FLAG_DUMP flag.
1122 *
1123 * The API uses the standard RtNetlink socket. When the RtNetlink code
1124 * find a IFLA_WIRELESS field in a RtNetlink SET_LINK request,
1125 * it calls here.
1126 */
1127
1128#ifdef CONFIG_NET_WIRELESS_RTNETLINK
1129/* ---------------------------------------------------------------- */
1130/*
1131 * Wrapper to call a standard Wireless Extension GET handler.
1132 * We do various checks and call the handler with the proper args.
1133 */
1134static int rtnetlink_standard_get(struct net_device * dev,
1135 struct iw_event * request,
1136 int request_len,
1137 iw_handler handler,
1138 char ** p_buf,
1139 int * p_len)
1140{
1141 const struct iw_ioctl_description * descr = NULL;
1142 unsigned int cmd;
1143 union iwreq_data * wrqu;
1144 int hdr_len;
1145 struct iw_request_info info;
1146 char * buffer = NULL;
1147 int buffer_size = 0;
1148 int ret = -EINVAL;
1149
1150 /* Get the description of the Request */
1151 cmd = request->cmd;
1152 if((cmd - SIOCIWFIRST) >= standard_ioctl_num)
1153 return -EOPNOTSUPP;
1154 descr = &(standard_ioctl[cmd - SIOCIWFIRST]);
1155
1156#ifdef WE_RTNETLINK_DEBUG
1157 printk(KERN_DEBUG "%s (WE.r) : Found standard handler for 0x%04X\n",
1158 dev->name, cmd);
1159 printk(KERN_DEBUG "%s (WE.r) : Header type : %d, Token type : %d, size : %d, token : %d\n", dev->name, descr->header_type, descr->token_type, descr->token_size, descr->max_tokens);
1160#endif /* WE_RTNETLINK_DEBUG */
1161
1162 /* Check if wrqu is complete */
1163 hdr_len = event_type_size[descr->header_type];
1164 if(request_len < hdr_len) {
1165#ifdef WE_RTNETLINK_DEBUG
1166 printk(KERN_DEBUG
1167 "%s (WE.r) : Wireless request too short (%d)\n",
1168 dev->name, request_len);
1169#endif /* WE_RTNETLINK_DEBUG */
1170 return -EINVAL;
1171 }
1172
1173 /* Prepare the call */
1174 info.cmd = cmd;
1175 info.flags = 0;
1176
1177 /* Check if we have extra data in the reply or not */
1178 if(descr->header_type != IW_HEADER_TYPE_POINT) {
1179
1180 /* Create the kernel buffer that we will return.
1181 * It's at an offset to match the TYPE_POINT case... */
1182 buffer_size = request_len + IW_EV_POINT_OFF;
1183 buffer = kmalloc(buffer_size, GFP_KERNEL);
1184 if (buffer == NULL) {
1185 return -ENOMEM;
1186 }
1187 /* Copy event data */
1188 memcpy(buffer + IW_EV_POINT_OFF, request, request_len);
1189 /* Use our own copy of wrqu */
1190 wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF
1191 + IW_EV_LCP_LEN);
1192
1193 /* No extra arguments. Trivial to handle */
1194 ret = handler(dev, &info, wrqu, NULL);
1195
1196 } else {
1197 union iwreq_data wrqu_point;
1198 char * extra = NULL;
1199 int extra_size = 0;
1200
1201 /* Get a temp copy of wrqu (skip pointer) */
1202 memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF,
1203 ((char *) request) + IW_EV_LCP_LEN,
1204 IW_EV_POINT_LEN - IW_EV_LCP_LEN);
1205
1206 /* Calculate space needed by arguments. Always allocate
1207 * for max space. Easier, and won't last long... */
1208 extra_size = descr->max_tokens * descr->token_size;
1209 /* Support for very large requests */
1210 if((descr->flags & IW_DESCR_FLAG_NOMAX) &&
1211 (wrqu_point.data.length > descr->max_tokens))
1212 extra_size = (wrqu_point.data.length
1213 * descr->token_size);
1214 buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF;
1215#ifdef WE_RTNETLINK_DEBUG
1216 printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n",
1217 dev->name, extra_size, buffer_size);
1218#endif /* WE_RTNETLINK_DEBUG */
1219
1220 /* Create the kernel buffer that we will return */
1221 buffer = kmalloc(buffer_size, GFP_KERNEL);
1222 if (buffer == NULL) {
1223 return -ENOMEM;
1224 }
1225
1226 /* Put wrqu in the right place (just before extra).
1227 * Leave space for IWE header and dummy pointer...
1228 * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned...
1229 */
1230 memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
1231 ((char *) &wrqu_point) + IW_EV_POINT_OFF,
1232 IW_EV_POINT_LEN - IW_EV_LCP_LEN);
1233 wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN);
1234
1235 /* Extra comes logically after that. Offset +12 bytes. */
1236 extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN;
1237
1238 /* Call the handler */
1239 ret = handler(dev, &info, wrqu, extra);
1240
1241 /* Calculate real returned length */
1242 extra_size = (wrqu->data.length * descr->token_size);
1243 /* Re-adjust reply size */
1244 request->len = extra_size + IW_EV_POINT_LEN;
1245
1246 /* Put the iwe header where it should, i.e. scrap the
1247 * dummy pointer. */
1248 memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN);
1249
1250#ifdef WE_RTNETLINK_DEBUG
1251 printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size);
1252#endif /* WE_RTNETLINK_DEBUG */
1253
1254 /* Check if there is enough buffer up there */
1255 if(wrqu_point.data.length < wrqu->data.length)
1256 ret = -E2BIG;
1257 }
1258
1259 /* Return the buffer to the caller */
1260 if (!ret) {
1261 *p_buf = buffer;
1262 *p_len = request->len;
1263 } else {
1264 /* Cleanup */
1265 if(buffer)
1266 kfree(buffer);
1267 }
1268
1269 return ret;
1270}
1271
1272/* ---------------------------------------------------------------- */
1273/*
1274 * Wrapper to call a standard Wireless Extension SET handler.
1275 * We do various checks and call the handler with the proper args.
1276 */
1277static inline int rtnetlink_standard_set(struct net_device * dev,
1278 struct iw_event * request,
1279 int request_len,
1280 iw_handler handler)
1281{
1282 const struct iw_ioctl_description * descr = NULL;
1283 unsigned int cmd;
1284 union iwreq_data * wrqu;
1285 union iwreq_data wrqu_point;
1286 int hdr_len;
1287 char * extra = NULL;
1288 int extra_size = 0;
1289 struct iw_request_info info;
1290 int ret = -EINVAL;
1291
1292 /* Get the description of the Request */
1293 cmd = request->cmd;
1294 if((cmd - SIOCIWFIRST) >= standard_ioctl_num)
1295 return -EOPNOTSUPP;
1296 descr = &(standard_ioctl[cmd - SIOCIWFIRST]);
1297
1298#ifdef WE_RTNETLINK_DEBUG
1299 printk(KERN_DEBUG "%s (WE.r) : Found standard SET handler for 0x%04X\n",
1300 dev->name, cmd);
1301 printk(KERN_DEBUG "%s (WE.r) : Header type : %d, Token type : %d, size : %d, token : %d\n", dev->name, descr->header_type, descr->token_type, descr->token_size, descr->max_tokens);
1302#endif /* WE_RTNETLINK_DEBUG */
1303
1304 /* Extract fixed header from request. This is properly aligned. */
1305 wrqu = &request->u;
1306
1307 /* Check if wrqu is complete */
1308 hdr_len = event_type_size[descr->header_type];
1309 if(request_len < hdr_len) {
1310#ifdef WE_RTNETLINK_DEBUG
1311 printk(KERN_DEBUG
1312 "%s (WE.r) : Wireless request too short (%d)\n",
1313 dev->name, request_len);
1314#endif /* WE_RTNETLINK_DEBUG */
1315 return -EINVAL;
1316 }
1317
1318 /* Prepare the call */
1319 info.cmd = cmd;
1320 info.flags = 0;
1321
1322 /* Check if we have extra data in the request or not */
1323 if(descr->header_type != IW_HEADER_TYPE_POINT) {
1324
1325 /* No extra arguments. Trivial to handle */
1326 ret = handler(dev, &info, wrqu, NULL);
1327
1328 } else {
1329 int extra_len;
1330
1331 /* Put wrqu in the right place (skip pointer) */
1332 memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF,
1333 wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN);
1334 /* Don't forget about the event code... */
1335 wrqu = &wrqu_point;
1336
1337 /* Check if number of token fits within bounds */
1338 if(wrqu_point.data.length > descr->max_tokens)
1339 return -E2BIG;
1340 if(wrqu_point.data.length < descr->min_tokens)
1341 return -EINVAL;
1342
1343 /* Real length of payload */
1344 extra_len = wrqu_point.data.length * descr->token_size;
1345
1346 /* Check if request is self consistent */
1347 if((request_len - hdr_len) < extra_len) {
1348#ifdef WE_RTNETLINK_DEBUG
1349 printk(KERN_DEBUG "%s (WE.r) : Wireless request data too short (%d)\n",
1350 dev->name, extra_size);
1351#endif /* WE_RTNETLINK_DEBUG */
1352 return -EINVAL;
1353 }
1354
1355#ifdef WE_RTNETLINK_DEBUG
1356 printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes\n",
1357 dev->name, extra_size);
1358#endif /* WE_RTNETLINK_DEBUG */
1359
1360 /* Always allocate for max space. Easier, and won't last
1361 * long... */
1362 extra_size = descr->max_tokens * descr->token_size;
1363 extra = kmalloc(extra_size, GFP_KERNEL);
1364 if (extra == NULL)
1365 return -ENOMEM;
1366
1367 /* Copy extra in aligned buffer */
1368 memcpy(extra, ((char *) request) + hdr_len, extra_len);
1369
1370 /* Call the handler */
1371 ret = handler(dev, &info, &wrqu_point, extra);
1372 }
1373
1374#ifdef WE_SET_EVENT
1375 /* Generate an event to notify listeners of the change */
1376 if((descr->flags & IW_DESCR_FLAG_EVENT) &&
1377 ((ret == 0) || (ret == -EIWCOMMIT))) {
1378 if(descr->flags & IW_DESCR_FLAG_RESTRICT)
1379 /* If the event is restricted, don't
1380 * export the payload */
1381 wireless_send_event(dev, cmd, wrqu, NULL);
1382 else
1383 wireless_send_event(dev, cmd, wrqu, extra);
1384 }
1385#endif /* WE_SET_EVENT */
1386
1387 /* Cleanup - I told you it wasn't that long ;-) */
1388 if(extra)
1389 kfree(extra);
1390
1391 /* Call commit handler if needed and defined */
1392 if(ret == -EIWCOMMIT)
1393 ret = call_commit_handler(dev);
1394
1395 return ret;
1396}
1397
1398/* ---------------------------------------------------------------- */
1399/*
1400 * Wrapper to call a private Wireless Extension GET handler.
1401 * Same as above...
1402 * It's not as nice and slimline as the standard wrapper. The cause
1403 * is struct iw_priv_args, which was not really designed for the
1404 * job we are going here.
1405 *
1406 * IMPORTANT : This function prevent to set and get data on the same
1407 * IOCTL and enforce the SET/GET convention. Not doing it would be
1408 * far too hairy...
1409 * If you need to set and get data at the same time, please don't use
1410 * a iw_handler but process it in your ioctl handler (i.e. use the
1411 * old driver API).
1412 */
1413static inline int rtnetlink_private_get(struct net_device * dev,
1414 struct iw_event * request,
1415 int request_len,
1416 iw_handler handler,
1417 char ** p_buf,
1418 int * p_len)
1419{
1420 const struct iw_priv_args * descr = NULL;
1421 unsigned int cmd;
1422 union iwreq_data * wrqu;
1423 int hdr_len;
1424 struct iw_request_info info;
1425 int extra_size = 0;
1426 int i;
1427 char * buffer = NULL;
1428 int buffer_size = 0;
1429 int ret = -EINVAL;
1430
1431 /* Get the description of the Request */
1432 cmd = request->cmd;
1433 for(i = 0; i < dev->wireless_handlers->num_private_args; i++)
1434 if(cmd == dev->wireless_handlers->private_args[i].cmd) {
1435 descr = &(dev->wireless_handlers->private_args[i]);
1436 break;
1437 }
1438 if(descr == NULL)
1439 return -EOPNOTSUPP;
1440
1441#ifdef WE_RTNETLINK_DEBUG
1442 printk(KERN_DEBUG "%s (WE.r) : Found private handler for 0x%04X\n",
1443 dev->name, cmd);
1444 printk(KERN_DEBUG "%s (WE.r) : Name %s, set %X, get %X\n",
1445 dev->name, descr->name, descr->set_args, descr->get_args);
1446#endif /* WE_RTNETLINK_DEBUG */
1447
1448 /* Compute the max size of the get arguments */
1449 extra_size = get_priv_size(descr->get_args);
1450
1451 /* Does it fits in wrqu ? */
1452 if((descr->get_args & IW_PRIV_SIZE_FIXED) &&
1453 (extra_size <= IFNAMSIZ)) {
1454 hdr_len = extra_size;
1455 extra_size = 0;
1456 } else {
1457 hdr_len = IW_EV_POINT_LEN;
1458 }
1459
1460 /* Check if wrqu is complete */
1461 if(request_len < hdr_len) {
1462#ifdef WE_RTNETLINK_DEBUG
1463 printk(KERN_DEBUG
1464 "%s (WE.r) : Wireless request too short (%d)\n",
1465 dev->name, request_len);
1466#endif /* WE_RTNETLINK_DEBUG */
1467 return -EINVAL;
1468 }
1469
1470 /* Prepare the call */
1471 info.cmd = cmd;
1472 info.flags = 0;
1473
1474 /* Check if we have a pointer to user space data or not. */
1475 if(extra_size == 0) {
1476
1477 /* Create the kernel buffer that we will return.
1478 * It's at an offset to match the TYPE_POINT case... */
1479 buffer_size = request_len + IW_EV_POINT_OFF;
1480 buffer = kmalloc(buffer_size, GFP_KERNEL);
1481 if (buffer == NULL) {
1482 return -ENOMEM;
1483 }
1484 /* Copy event data */
1485 memcpy(buffer + IW_EV_POINT_OFF, request, request_len);
1486 /* Use our own copy of wrqu */
1487 wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF
1488 + IW_EV_LCP_LEN);
1489
1490 /* No extra arguments. Trivial to handle */
1491 ret = handler(dev, &info, wrqu, (char *) wrqu);
1492
1493 } else {
1494 char * extra;
1495
1496 /* Buffer for full reply */
1497 buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF;
1498
1499#ifdef WE_RTNETLINK_DEBUG
1500 printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n",
1501 dev->name, extra_size, buffer_size);
1502#endif /* WE_RTNETLINK_DEBUG */
1503
1504 /* Create the kernel buffer that we will return */
1505 buffer = kmalloc(buffer_size, GFP_KERNEL);
1506 if (buffer == NULL) {
1507 return -ENOMEM;
1508 }
1509
1510 /* Put wrqu in the right place (just before extra).
1511 * Leave space for IWE header and dummy pointer...
1512 * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned...
1513 */
1514 memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
1515 ((char *) request) + IW_EV_LCP_LEN,
1516 IW_EV_POINT_LEN - IW_EV_LCP_LEN);
1517 wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN);
1518
1519 /* Extra comes logically after that. Offset +12 bytes. */
1520 extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN;
1521
1522 /* Call the handler */
1523 ret = handler(dev, &info, wrqu, extra);
1524
1525 /* Adjust for the actual length if it's variable,
1526 * avoid leaking kernel bits outside. */
1527 if (!(descr->get_args & IW_PRIV_SIZE_FIXED))
1528 extra_size = adjust_priv_size(descr->get_args, wrqu);
1529 /* Re-adjust reply size */
1530 request->len = extra_size + IW_EV_POINT_LEN;
1531
1532 /* Put the iwe header where it should, i.e. scrap the
1533 * dummy pointer. */
1534 memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN);
1535
1536#ifdef WE_RTNETLINK_DEBUG
1537 printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size);
1538#endif /* WE_RTNETLINK_DEBUG */
1539 }
1540
1541 /* Return the buffer to the caller */
1542 if (!ret) {
1543 *p_buf = buffer;
1544 *p_len = request->len;
1545 } else {
1546 /* Cleanup */
1547 if(buffer)
1548 kfree(buffer);
1549 }
1550
1551 return ret;
1552}
1553
1554/* ---------------------------------------------------------------- */
1555/*
1556 * Wrapper to call a private Wireless Extension SET handler.
1557 * Same as above...
1558 * It's not as nice and slimline as the standard wrapper. The cause
1559 * is struct iw_priv_args, which was not really designed for the
1560 * job we are going here.
1561 *
1562 * IMPORTANT : This function prevent to set and get data on the same
1563 * IOCTL and enforce the SET/GET convention. Not doing it would be
1564 * far too hairy...
1565 * If you need to set and get data at the same time, please don't use
1566 * a iw_handler but process it in your ioctl handler (i.e. use the
1567 * old driver API).
1568 */
1569static inline int rtnetlink_private_set(struct net_device * dev,
1570 struct iw_event * request,
1571 int request_len,
1572 iw_handler handler)
1573{
1574 const struct iw_priv_args * descr = NULL;
1575 unsigned int cmd;
1576 union iwreq_data * wrqu;
1577 union iwreq_data wrqu_point;
1578 int hdr_len;
1579 char * extra = NULL;
1580 int extra_size = 0;
1581 int offset = 0; /* For sub-ioctls */
1582 struct iw_request_info info;
1583 int i;
1584 int ret = -EINVAL;
1585
1586 /* Get the description of the Request */
1587 cmd = request->cmd;
1588 for(i = 0; i < dev->wireless_handlers->num_private_args; i++)
1589 if(cmd == dev->wireless_handlers->private_args[i].cmd) {
1590 descr = &(dev->wireless_handlers->private_args[i]);
1591 break;
1592 }
1593 if(descr == NULL)
1594 return -EOPNOTSUPP;
1595
1596#ifdef WE_RTNETLINK_DEBUG
1597 printk(KERN_DEBUG "%s (WE.r) : Found private handler for 0x%04X\n",
1598 ifr->ifr_name, cmd);
1599 printk(KERN_DEBUG "%s (WE.r) : Name %s, set %X, get %X\n",
1600 dev->name, descr->name, descr->set_args, descr->get_args);
1601#endif /* WE_RTNETLINK_DEBUG */
1602
1603 /* Compute the size of the set arguments */
1604 /* Check for sub-ioctl handler */
1605 if(descr->name[0] == '\0')
1606 /* Reserve one int for sub-ioctl index */
1607 offset = sizeof(__u32);
1608
1609 /* Size of set arguments */
1610 extra_size = get_priv_size(descr->set_args);
1611
1612 /* Does it fits in wrqu ? */
1613 if((descr->set_args & IW_PRIV_SIZE_FIXED) &&
1614 (extra_size <= IFNAMSIZ)) {
1615 hdr_len = IW_EV_LCP_LEN + extra_size;
1616 extra_size = 0;
1617 } else {
1618 hdr_len = IW_EV_POINT_LEN;
1619 }
1620
1621 /* Extract fixed header from request. This is properly aligned. */
1622 wrqu = &request->u;
1623
1624 /* Check if wrqu is complete */
1625 if(request_len < hdr_len) {
1626#ifdef WE_RTNETLINK_DEBUG
1627 printk(KERN_DEBUG
1628 "%s (WE.r) : Wireless request too short (%d)\n",
1629 dev->name, request_len);
1630#endif /* WE_RTNETLINK_DEBUG */
1631 return -EINVAL;
1632 }
1633
1634 /* Prepare the call */
1635 info.cmd = cmd;
1636 info.flags = 0;
1637
1638 /* Check if we have a pointer to user space data or not. */
1639 if(extra_size == 0) {
1640
1641 /* No extra arguments. Trivial to handle */
1642 ret = handler(dev, &info, wrqu, (char *) wrqu);
1643
1644 } else {
1645 int extra_len;
1646
1647 /* Put wrqu in the right place (skip pointer) */
1648 memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF,
1649 wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN);
1650
1651 /* Does it fits within bounds ? */
1652 if(wrqu_point.data.length > (descr->set_args &
1653 IW_PRIV_SIZE_MASK))
1654 return -E2BIG;
1655
1656 /* Real length of payload */
1657 extra_len = adjust_priv_size(descr->set_args, &wrqu_point);
1658
1659 /* Check if request is self consistent */
1660 if((request_len - hdr_len) < extra_len) {
1661#ifdef WE_RTNETLINK_DEBUG
1662 printk(KERN_DEBUG "%s (WE.r) : Wireless request data too short (%d)\n",
1663 dev->name, extra_size);
1664#endif /* WE_RTNETLINK_DEBUG */
1665 return -EINVAL;
1666 }
1667
1668#ifdef WE_RTNETLINK_DEBUG
1669 printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes\n",
1670 dev->name, extra_size);
1671#endif /* WE_RTNETLINK_DEBUG */
1672
1673 /* Always allocate for max space. Easier, and won't last
1674 * long... */
1675 extra = kmalloc(extra_size, GFP_KERNEL);
1676 if (extra == NULL)
1677 return -ENOMEM;
1678
1679 /* Copy extra in aligned buffer */
1680 memcpy(extra, ((char *) request) + hdr_len, extra_len);
1681
1682 /* Call the handler */
1683 ret = handler(dev, &info, &wrqu_point, extra);
1684
1685 /* Cleanup - I told you it wasn't that long ;-) */
1686 kfree(extra);
1687 }
1688
1689 /* Call commit handler if needed and defined */
1690 if(ret == -EIWCOMMIT)
1691 ret = call_commit_handler(dev);
1692
1693 return ret;
1694}
1695
1696/* ---------------------------------------------------------------- */
1697/*
1698 * Main RtNetlink dispatcher. Called from the main networking code
1699 * (do_getlink() in net/core/rtnetlink.c).
1700 * Check the type of Request and call the appropriate wrapper...
1701 */
1702int wireless_rtnetlink_get(struct net_device * dev,
1703 char * data,
1704 int len,
1705 char ** p_buf,
1706 int * p_len)
1707{
1708 struct iw_event * request = (struct iw_event *) data;
1709 iw_handler handler;
1710
1711 /* Check length */
1712 if(len < IW_EV_LCP_LEN) {
1713 printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n",
1714 dev->name, len);
1715 return -EINVAL;
1716 }
1717
1718 /* ReCheck length (len may have padding) */
1719 if(request->len > len) {
1720 printk(KERN_DEBUG "%s (WE.r) : RtNetlink request len invalid (%d-%d)\n",
1721 dev->name, request->len, len);
1722 return -EINVAL;
1723 }
1724
1725 /* Only accept GET requests in here */
1726 if(!IW_IS_GET(request->cmd))
1727 return -EOPNOTSUPP;
1728
1729 /* Special cases */
1730 if(request->cmd == SIOCGIWSTATS)
1731 /* Get Wireless Stats */
1732 return rtnetlink_standard_get(dev,
1733 request,
1734 request->len,
1735 &iw_handler_get_iwstats,
1736 p_buf, p_len);
1737 if(request->cmd == SIOCGIWPRIV) {
1738 /* Check if we have some wireless handlers defined */
1739 if(dev->wireless_handlers == NULL)
1740 return -EOPNOTSUPP;
1741 /* Get Wireless Stats */
1742 return rtnetlink_standard_get(dev,
1743 request,
1744 request->len,
1745 &iw_handler_get_private,
1746 p_buf, p_len);
1747 }
1748
1749 /* Basic check */
1750 if (!netif_device_present(dev))
1751 return -ENODEV;
1752
1753 /* Try to find the handler */
1754 handler = get_handler(dev, request->cmd);
1755 if(handler != NULL) {
1756 /* Standard and private are not the same */
1757 if(request->cmd < SIOCIWFIRSTPRIV)
1758 return rtnetlink_standard_get(dev,
1759 request,
1760 request->len,
1761 handler,
1762 p_buf, p_len);
1763 else
1764 return rtnetlink_private_get(dev,
1765 request,
1766 request->len,
1767 handler,
1768 p_buf, p_len);
1769 }
1770
1771 return -EOPNOTSUPP;
1772}
1773
1774/* ---------------------------------------------------------------- */
1775/*
1776 * Main RtNetlink dispatcher. Called from the main networking code
1777 * (do_setlink() in net/core/rtnetlink.c).
1778 * Check the type of Request and call the appropriate wrapper...
1779 */
1780int wireless_rtnetlink_set(struct net_device * dev,
1781 char * data,
1782 int len)
1783{
1784 struct iw_event * request = (struct iw_event *) data;
1785 iw_handler handler;
1786
1787 /* Check length */
1788 if(len < IW_EV_LCP_LEN) {
1789 printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n",
1790 dev->name, len);
1791 return -EINVAL;
1792 }
1793
1794 /* ReCheck length (len may have padding) */
1795 if(request->len > len) {
1796 printk(KERN_DEBUG "%s (WE.r) : RtNetlink request len invalid (%d-%d)\n",
1797 dev->name, request->len, len);
1798 return -EINVAL;
1799 }
1800
1801 /* Only accept SET requests in here */
1802 if(!IW_IS_SET(request->cmd))
1803 return -EOPNOTSUPP;
1804
1805 /* Basic check */
1806 if (!netif_device_present(dev))
1807 return -ENODEV;
1808
1809 /* New driver API : try to find the handler */
1810 handler = get_handler(dev, request->cmd);
1811 if(handler != NULL) {
1812 /* Standard and private are not the same */
1813 if(request->cmd < SIOCIWFIRSTPRIV)
1814 return rtnetlink_standard_set(dev,
1815 request,
1816 request->len,
1817 handler);
1818 else
1819 return rtnetlink_private_set(dev,
1820 request,
1821 request->len,
1822 handler);
1823 }
1824
1825 return -EOPNOTSUPP;
1826}
1827#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
1828
1829
1091/************************* EVENT PROCESSING *************************/ 1830/************************* EVENT PROCESSING *************************/
1092/* 1831/*
1093 * Process events generated by the wireless layer or the driver. 1832 * Process events generated by the wireless layer or the driver.
1094 * Most often, the event will be propagated through rtnetlink 1833 * Most often, the event will be propagated through rtnetlink
1095 */ 1834 */
1096 1835
1097#ifdef WE_EVENT_NETLINK 1836#ifdef WE_EVENT_RTNETLINK
1098/* "rtnl" is defined in net/core/rtnetlink.c, but we need it here.
1099 * It is declared in <linux/rtnetlink.h> */
1100
1101/* ---------------------------------------------------------------- */ 1837/* ---------------------------------------------------------------- */
1102/* 1838/*
1103 * Fill a rtnetlink message with our event data. 1839 * Fill a rtnetlink message with our event data.
@@ -1121,12 +1857,11 @@ static inline int rtnetlink_fill_iwinfo(struct sk_buff * skb,
1121 r->__ifi_pad = 0; 1857 r->__ifi_pad = 0;
1122 r->ifi_type = dev->type; 1858 r->ifi_type = dev->type;
1123 r->ifi_index = dev->ifindex; 1859 r->ifi_index = dev->ifindex;
1124 r->ifi_flags = dev->flags; 1860 r->ifi_flags = dev_get_flags(dev);
1125 r->ifi_change = 0; /* Wireless changes don't affect those flags */ 1861 r->ifi_change = 0; /* Wireless changes don't affect those flags */
1126 1862
1127 /* Add the wireless events in the netlink packet */ 1863 /* Add the wireless events in the netlink packet */
1128 RTA_PUT(skb, IFLA_WIRELESS, 1864 RTA_PUT(skb, IFLA_WIRELESS, event_len, event);
1129 event_len, event);
1130 1865
1131 nlh->nlmsg_len = skb->tail - b; 1866 nlh->nlmsg_len = skb->tail - b;
1132 return skb->len; 1867 return skb->len;
@@ -1163,7 +1898,7 @@ static inline void rtmsg_iwinfo(struct net_device * dev,
1163 NETLINK_CB(skb).dst_group = RTNLGRP_LINK; 1898 NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
1164 netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC); 1899 netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC);
1165} 1900}
1166#endif /* WE_EVENT_NETLINK */ 1901#endif /* WE_EVENT_RTNETLINK */
1167 1902
1168/* ---------------------------------------------------------------- */ 1903/* ---------------------------------------------------------------- */
1169/* 1904/*
@@ -1255,10 +1990,10 @@ void wireless_send_event(struct net_device * dev,
1255 if(extra != NULL) 1990 if(extra != NULL)
1256 memcpy(((char *) event) + hdr_len, extra, extra_len); 1991 memcpy(((char *) event) + hdr_len, extra, extra_len);
1257 1992
1258#ifdef WE_EVENT_NETLINK 1993#ifdef WE_EVENT_RTNETLINK
1259 /* rtnetlink event channel */ 1994 /* Send via the RtNetlink event channel */
1260 rtmsg_iwinfo(dev, (char *) event, event_len); 1995 rtmsg_iwinfo(dev, (char *) event, event_len);
1261#endif /* WE_EVENT_NETLINK */ 1996#endif /* WE_EVENT_RTNETLINK */
1262 1997
1263 /* Cleanup */ 1998 /* Cleanup */
1264 kfree(event); 1999 kfree(event);
diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig
index 187ac182e24b..7e096ba8454f 100644
--- a/net/dccp/Kconfig
+++ b/net/dccp/Kconfig
@@ -24,6 +24,10 @@ config INET_DCCP_DIAG
24 def_tristate y if (IP_DCCP = y && INET_DIAG = y) 24 def_tristate y if (IP_DCCP = y && INET_DIAG = y)
25 def_tristate m 25 def_tristate m
26 26
27config IP_DCCP_ACKVEC
28 depends on IP_DCCP
29 def_bool N
30
27source "net/dccp/ccids/Kconfig" 31source "net/dccp/ccids/Kconfig"
28 32
29menu "DCCP Kernel Hacking" 33menu "DCCP Kernel Hacking"
@@ -36,15 +40,6 @@ config IP_DCCP_DEBUG
36 40
37 Just say N. 41 Just say N.
38 42
39config IP_DCCP_UNLOAD_HACK
40 depends on IP_DCCP=m && IP_DCCP_CCID3=m
41 bool "DCCP control sock unload hack"
42 ---help---
43 Enable this to be able to unload the dccp module when the it
44 has only one refcount held, the control sock one. Just execute
45 "rmmod dccp_ccid3 dccp"
46
47 Just say N.
48endmenu 43endmenu
49 44
50endmenu 45endmenu
diff --git a/net/dccp/Makefile b/net/dccp/Makefile
index 87b27fff6e3b..7696e219b05d 100644
--- a/net/dccp/Makefile
+++ b/net/dccp/Makefile
@@ -2,15 +2,18 @@ obj-$(CONFIG_IPV6) += dccp_ipv6.o
2 2
3dccp_ipv6-y := ipv6.o 3dccp_ipv6-y := ipv6.o
4 4
5obj-$(CONFIG_IP_DCCP) += dccp.o 5obj-$(CONFIG_IP_DCCP) += dccp.o dccp_ipv4.o
6 6
7dccp-y := ccid.o input.o ipv4.o minisocks.o options.o output.o proto.o \ 7dccp-y := ccid.o feat.o input.o minisocks.o options.o output.o proto.o timer.o
8 timer.o 8
9dccp_ipv4-y := ipv4.o
9 10
10dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o 11dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o
11 12
12obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o 13obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o
13 14
15dccp-$(CONFIG_SYSCTL) += sysctl.o
16
14dccp_diag-y := diag.o 17dccp_diag-y := diag.o
15 18
16obj-y += ccids/ 19obj-y += ccids/
diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c
index 2c77dafbd091..b5981e5f6b00 100644
--- a/net/dccp/ackvec.c
+++ b/net/dccp/ackvec.c
@@ -13,36 +13,83 @@
13#include "dccp.h" 13#include "dccp.h"
14 14
15#include <linux/dccp.h> 15#include <linux/dccp.h>
16#include <linux/init.h>
17#include <linux/errno.h>
18#include <linux/kernel.h>
16#include <linux/skbuff.h> 19#include <linux/skbuff.h>
20#include <linux/slab.h>
17 21
18#include <net/sock.h> 22#include <net/sock.h>
19 23
24static kmem_cache_t *dccp_ackvec_slab;
25static kmem_cache_t *dccp_ackvec_record_slab;
26
27static struct dccp_ackvec_record *dccp_ackvec_record_new(void)
28{
29 struct dccp_ackvec_record *avr =
30 kmem_cache_alloc(dccp_ackvec_record_slab, GFP_ATOMIC);
31
32 if (avr != NULL)
33 INIT_LIST_HEAD(&avr->dccpavr_node);
34
35 return avr;
36}
37
38static void dccp_ackvec_record_delete(struct dccp_ackvec_record *avr)
39{
40 if (unlikely(avr == NULL))
41 return;
42 /* Check if deleting a linked record */
43 WARN_ON(!list_empty(&avr->dccpavr_node));
44 kmem_cache_free(dccp_ackvec_record_slab, avr);
45}
46
47static void dccp_ackvec_insert_avr(struct dccp_ackvec *av,
48 struct dccp_ackvec_record *avr)
49{
50 /*
51 * AVRs are sorted by seqno. Since we are sending them in order, we
52 * just add the AVR at the head of the list.
53 * -sorbo.
54 */
55 if (!list_empty(&av->dccpav_records)) {
56 const struct dccp_ackvec_record *head =
57 list_entry(av->dccpav_records.next,
58 struct dccp_ackvec_record,
59 dccpavr_node);
60 BUG_ON(before48(avr->dccpavr_ack_seqno,
61 head->dccpavr_ack_seqno));
62 }
63
64 list_add(&avr->dccpavr_node, &av->dccpav_records);
65}
66
20int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) 67int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
21{ 68{
22 struct dccp_sock *dp = dccp_sk(sk); 69 struct dccp_sock *dp = dccp_sk(sk);
70#ifdef CONFIG_IP_DCCP_DEBUG
71 const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
72 "CLIENT tx: " : "server tx: ";
73#endif
23 struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec; 74 struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec;
24 int len = av->dccpav_vec_len + 2; 75 int len = av->dccpav_vec_len + 2;
25 struct timeval now; 76 struct timeval now;
26 u32 elapsed_time; 77 u32 elapsed_time;
27 unsigned char *to, *from; 78 unsigned char *to, *from;
79 struct dccp_ackvec_record *avr;
80
81 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
82 return -1;
28 83
29 dccp_timestamp(sk, &now); 84 dccp_timestamp(sk, &now);
30 elapsed_time = timeval_delta(&now, &av->dccpav_time) / 10; 85 elapsed_time = timeval_delta(&now, &av->dccpav_time) / 10;
31 86
32 if (elapsed_time != 0) 87 if (elapsed_time != 0 &&
33 dccp_insert_option_elapsed_time(sk, skb, elapsed_time); 88 dccp_insert_option_elapsed_time(sk, skb, elapsed_time))
34
35 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
36 return -1; 89 return -1;
37 90
38 /* 91 avr = dccp_ackvec_record_new();
39 * XXX: now we have just one ack vector sent record, so 92 if (avr == NULL)
40 * we have to wait for it to be cleared.
41 *
42 * Of course this is not acceptable, but this is just for
43 * basic testing now.
44 */
45 if (av->dccpav_ack_seqno != DCCP_MAX_SEQNO + 1)
46 return -1; 93 return -1;
47 94
48 DCCP_SKB_CB(skb)->dccpd_opt_len += len; 95 DCCP_SKB_CB(skb)->dccpd_opt_len += len;
@@ -55,8 +102,8 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
55 from = av->dccpav_buf + av->dccpav_buf_head; 102 from = av->dccpav_buf + av->dccpav_buf_head;
56 103
57 /* Check if buf_head wraps */ 104 /* Check if buf_head wraps */
58 if ((int)av->dccpav_buf_head + len > av->dccpav_vec_len) { 105 if ((int)av->dccpav_buf_head + len > DCCP_MAX_ACKVEC_LEN) {
59 const u32 tailsize = av->dccpav_vec_len - av->dccpav_buf_head; 106 const u32 tailsize = DCCP_MAX_ACKVEC_LEN - av->dccpav_buf_head;
60 107
61 memcpy(to, from, tailsize); 108 memcpy(to, from, tailsize);
62 to += tailsize; 109 to += tailsize;
@@ -73,45 +120,37 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
73 * sequence number it used for the ack packet; ack_ptr will equal 120 * sequence number it used for the ack packet; ack_ptr will equal
74 * buf_head; ack_ackno will equal buf_ackno; and ack_nonce will 121 * buf_head; ack_ackno will equal buf_ackno; and ack_nonce will
75 * equal buf_nonce. 122 * equal buf_nonce.
76 *
77 * This implemention uses just one ack record for now.
78 */ 123 */
79 av->dccpav_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq; 124 avr->dccpavr_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq;
80 av->dccpav_ack_ptr = av->dccpav_buf_head; 125 avr->dccpavr_ack_ptr = av->dccpav_buf_head;
81 av->dccpav_ack_ackno = av->dccpav_buf_ackno; 126 avr->dccpavr_ack_ackno = av->dccpav_buf_ackno;
82 av->dccpav_ack_nonce = av->dccpav_buf_nonce; 127 avr->dccpavr_ack_nonce = av->dccpav_buf_nonce;
83 av->dccpav_sent_len = av->dccpav_vec_len; 128 avr->dccpavr_sent_len = av->dccpav_vec_len;
129
130 dccp_ackvec_insert_avr(av, avr);
84 131
85 dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, " 132 dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, "
86 "ack_ackno=%llu\n", 133 "ack_ackno=%llu\n",
87 debug_prefix, av->dccpav_sent_len, 134 debug_prefix, avr->dccpavr_sent_len,
88 (unsigned long long)av->dccpav_ack_seqno, 135 (unsigned long long)avr->dccpavr_ack_seqno,
89 (unsigned long long)av->dccpav_ack_ackno); 136 (unsigned long long)avr->dccpavr_ack_ackno);
90 return -1; 137 return 0;
91} 138}
92 139
93struct dccp_ackvec *dccp_ackvec_alloc(const unsigned int len, 140struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority)
94 const gfp_t priority)
95{ 141{
96 struct dccp_ackvec *av; 142 struct dccp_ackvec *av = kmem_cache_alloc(dccp_ackvec_slab, priority);
97
98 BUG_ON(len == 0);
99 143
100 if (len > DCCP_MAX_ACKVEC_LEN)
101 return NULL;
102
103 av = kmalloc(sizeof(*av) + len, priority);
104 if (av != NULL) { 144 if (av != NULL) {
105 av->dccpav_buf_len = len;
106 av->dccpav_buf_head = 145 av->dccpav_buf_head =
107 av->dccpav_buf_tail = av->dccpav_buf_len - 1; 146 av->dccpav_buf_tail = DCCP_MAX_ACKVEC_LEN - 1;
108 av->dccpav_buf_ackno = 147 av->dccpav_buf_ackno = DCCP_MAX_SEQNO + 1;
109 av->dccpav_ack_ackno = av->dccpav_ack_seqno = ~0LLU;
110 av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0; 148 av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0;
111 av->dccpav_ack_ptr = 0; 149 av->dccpav_ack_ptr = 0;
112 av->dccpav_time.tv_sec = 0; 150 av->dccpav_time.tv_sec = 0;
113 av->dccpav_time.tv_usec = 0; 151 av->dccpav_time.tv_usec = 0;
114 av->dccpav_sent_len = av->dccpav_vec_len = 0; 152 av->dccpav_sent_len = av->dccpav_vec_len = 0;
153 INIT_LIST_HEAD(&av->dccpav_records);
115 } 154 }
116 155
117 return av; 156 return av;
@@ -119,7 +158,20 @@ struct dccp_ackvec *dccp_ackvec_alloc(const unsigned int len,
119 158
120void dccp_ackvec_free(struct dccp_ackvec *av) 159void dccp_ackvec_free(struct dccp_ackvec *av)
121{ 160{
122 kfree(av); 161 if (unlikely(av == NULL))
162 return;
163
164 if (!list_empty(&av->dccpav_records)) {
165 struct dccp_ackvec_record *avr, *next;
166
167 list_for_each_entry_safe(avr, next, &av->dccpav_records,
168 dccpavr_node) {
169 list_del_init(&avr->dccpavr_node);
170 dccp_ackvec_record_delete(avr);
171 }
172 }
173
174 kmem_cache_free(dccp_ackvec_slab, av);
123} 175}
124 176
125static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av, 177static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av,
@@ -146,7 +198,7 @@ static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av,
146 unsigned int gap; 198 unsigned int gap;
147 long new_head; 199 long new_head;
148 200
149 if (av->dccpav_vec_len + packets > av->dccpav_buf_len) 201 if (av->dccpav_vec_len + packets > DCCP_MAX_ACKVEC_LEN)
150 return -ENOBUFS; 202 return -ENOBUFS;
151 203
152 gap = packets - 1; 204 gap = packets - 1;
@@ -158,7 +210,7 @@ static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av,
158 gap + new_head + 1); 210 gap + new_head + 1);
159 gap = -new_head; 211 gap = -new_head;
160 } 212 }
161 new_head += av->dccpav_buf_len; 213 new_head += DCCP_MAX_ACKVEC_LEN;
162 } 214 }
163 215
164 av->dccpav_buf_head = new_head; 216 av->dccpav_buf_head = new_head;
@@ -251,7 +303,7 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
251 goto out_duplicate; 303 goto out_duplicate;
252 304
253 delta -= len + 1; 305 delta -= len + 1;
254 if (++index == av->dccpav_buf_len) 306 if (++index == DCCP_MAX_ACKVEC_LEN)
255 index = 0; 307 index = 0;
256 } 308 }
257 } 309 }
@@ -259,7 +311,6 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
259 av->dccpav_buf_ackno = ackno; 311 av->dccpav_buf_ackno = ackno;
260 dccp_timestamp(sk, &av->dccpav_time); 312 dccp_timestamp(sk, &av->dccpav_time);
261out: 313out:
262 dccp_pr_debug("");
263 return 0; 314 return 0;
264 315
265out_duplicate: 316out_duplicate:
@@ -297,44 +348,50 @@ void dccp_ackvec_print(const struct dccp_ackvec *av)
297} 348}
298#endif 349#endif
299 350
300static void dccp_ackvec_throw_away_ack_record(struct dccp_ackvec *av) 351static void dccp_ackvec_throw_record(struct dccp_ackvec *av,
352 struct dccp_ackvec_record *avr)
301{ 353{
302 /* 354 struct dccp_ackvec_record *next;
303 * As we're keeping track of the ack vector size (dccpav_vec_len) and 355
304 * the sent ack vector size (dccpav_sent_len) we don't need 356 av->dccpav_buf_tail = avr->dccpavr_ack_ptr - 1;
305 * dccpav_buf_tail at all, but keep this code here as in the future 357 if (av->dccpav_buf_tail == 0)
306 * we'll implement a vector of ack records, as suggested in 358 av->dccpav_buf_tail = DCCP_MAX_ACKVEC_LEN - 1;
307 * draft-ietf-dccp-spec-11.txt Appendix A. -acme 359
308 */ 360 av->dccpav_vec_len -= avr->dccpavr_sent_len;
309#if 0 361
310 u32 new_buf_tail = av->dccpav_ack_ptr + 1; 362 /* free records */
311 if (new_buf_tail >= av->dccpav_vec_len) 363 list_for_each_entry_safe_from(avr, next, &av->dccpav_records,
312 new_buf_tail -= av->dccpav_vec_len; 364 dccpavr_node) {
313 av->dccpav_buf_tail = new_buf_tail; 365 list_del_init(&avr->dccpavr_node);
314#endif 366 dccp_ackvec_record_delete(avr);
315 av->dccpav_vec_len -= av->dccpav_sent_len; 367 }
316} 368}
317 369
318void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk, 370void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk,
319 const u64 ackno) 371 const u64 ackno)
320{ 372{
321 /* Check if we actually sent an ACK vector */ 373 struct dccp_ackvec_record *avr;
322 if (av->dccpav_ack_seqno == DCCP_MAX_SEQNO + 1)
323 return;
324 374
325 if (ackno == av->dccpav_ack_seqno) { 375 /*
376 * If we traverse backwards, it should be faster when we have large
377 * windows. We will be receiving ACKs for stuff we sent a while back
378 * -sorbo.
379 */
380 list_for_each_entry_reverse(avr, &av->dccpav_records, dccpavr_node) {
381 if (ackno == avr->dccpavr_ack_seqno) {
326#ifdef CONFIG_IP_DCCP_DEBUG 382#ifdef CONFIG_IP_DCCP_DEBUG
327 struct dccp_sock *dp = dccp_sk(sk); 383 struct dccp_sock *dp = dccp_sk(sk);
328 const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? 384 const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
329 "CLIENT rx ack: " : "server rx ack: "; 385 "CLIENT rx ack: " : "server rx ack: ";
330#endif 386#endif
331 dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, " 387 dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, "
332 "ack_ackno=%llu, ACKED!\n", 388 "ack_ackno=%llu, ACKED!\n",
333 debug_prefix, 1, 389 debug_prefix, 1,
334 (unsigned long long)av->dccpav_ack_seqno, 390 (unsigned long long)avr->dccpavr_ack_seqno,
335 (unsigned long long)av->dccpav_ack_ackno); 391 (unsigned long long)avr->dccpavr_ack_ackno);
336 dccp_ackvec_throw_away_ack_record(av); 392 dccp_ackvec_throw_record(av, avr);
337 av->dccpav_ack_seqno = DCCP_MAX_SEQNO + 1; 393 break;
394 }
338 } 395 }
339} 396}
340 397
@@ -344,28 +401,20 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
344 const unsigned char *vector) 401 const unsigned char *vector)
345{ 402{
346 unsigned char i; 403 unsigned char i;
404 struct dccp_ackvec_record *avr;
347 405
348 /* Check if we actually sent an ACK vector */ 406 /* Check if we actually sent an ACK vector */
349 if (av->dccpav_ack_seqno == DCCP_MAX_SEQNO + 1) 407 if (list_empty(&av->dccpav_records))
350 return;
351 /*
352 * We're in the receiver half connection, so if the received an ACK
353 * vector ackno (e.g. 50) before dccpav_ack_seqno (e.g. 52), we're
354 * not interested.
355 *
356 * Extra explanation with example:
357 *
358 * if we received an ACK vector with ackno 50, it can only be acking
359 * 50, 49, 48, etc, not 52 (the seqno for the ACK vector we sent).
360 */
361 /* dccp_pr_debug("is %llu < %llu? ", ackno, av->dccpav_ack_seqno); */
362 if (before48(ackno, av->dccpav_ack_seqno)) {
363 /* dccp_pr_debug_cat("yes\n"); */
364 return; 408 return;
365 }
366 /* dccp_pr_debug_cat("no\n"); */
367 409
368 i = len; 410 i = len;
411 /*
412 * XXX
413 * I think it might be more efficient to work backwards. See comment on
414 * rcv_ackno. -sorbo.
415 */
416 avr = list_entry(av->dccpav_records.next, struct dccp_ackvec_record,
417 dccpavr_node);
369 while (i--) { 418 while (i--) {
370 const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK; 419 const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK;
371 u64 ackno_end_rl; 420 u64 ackno_end_rl;
@@ -373,14 +422,20 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
373 dccp_set_seqno(&ackno_end_rl, ackno - rl); 422 dccp_set_seqno(&ackno_end_rl, ackno - rl);
374 423
375 /* 424 /*
376 * dccp_pr_debug("is %llu <= %llu <= %llu? ", ackno_end_rl, 425 * If our AVR sequence number is greater than the ack, go
377 * av->dccpav_ack_seqno, ackno); 426 * forward in the AVR list until it is not so.
378 */ 427 */
379 if (between48(av->dccpav_ack_seqno, ackno_end_rl, ackno)) { 428 list_for_each_entry_from(avr, &av->dccpav_records,
429 dccpavr_node) {
430 if (!after48(avr->dccpavr_ack_seqno, ackno))
431 goto found;
432 }
433 /* End of the dccpav_records list, not found, exit */
434 break;
435found:
436 if (between48(avr->dccpavr_ack_seqno, ackno_end_rl, ackno)) {
380 const u8 state = (*vector & 437 const u8 state = (*vector &
381 DCCP_ACKVEC_STATE_MASK) >> 6; 438 DCCP_ACKVEC_STATE_MASK) >> 6;
382 /* dccp_pr_debug_cat("yes\n"); */
383
384 if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) { 439 if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) {
385#ifdef CONFIG_IP_DCCP_DEBUG 440#ifdef CONFIG_IP_DCCP_DEBUG
386 struct dccp_sock *dp = dccp_sk(sk); 441 struct dccp_sock *dp = dccp_sk(sk);
@@ -393,19 +448,16 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
393 "ACKED!\n", 448 "ACKED!\n",
394 debug_prefix, len, 449 debug_prefix, len,
395 (unsigned long long) 450 (unsigned long long)
396 av->dccpav_ack_seqno, 451 avr->dccpavr_ack_seqno,
397 (unsigned long long) 452 (unsigned long long)
398 av->dccpav_ack_ackno); 453 avr->dccpavr_ack_ackno);
399 dccp_ackvec_throw_away_ack_record(av); 454 dccp_ackvec_throw_record(av, avr);
400 } 455 }
401 /* 456 /*
402 * If dccpav_ack_seqno was not received, no problem 457 * If it wasn't received, continue scanning... we might
403 * we'll send another ACK vector. 458 * find another one.
404 */ 459 */
405 av->dccpav_ack_seqno = DCCP_MAX_SEQNO + 1;
406 break;
407 } 460 }
408 /* dccp_pr_debug_cat("no\n"); */
409 461
410 dccp_set_seqno(&ackno, ackno_end_rl - 1); 462 dccp_set_seqno(&ackno, ackno_end_rl - 1);
411 ++vector; 463 ++vector;
@@ -424,3 +476,43 @@ int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
424 len, value); 476 len, value);
425 return 0; 477 return 0;
426} 478}
479
480static char dccp_ackvec_slab_msg[] __initdata =
481 KERN_CRIT "DCCP: Unable to create ack vectors slab caches\n";
482
483int __init dccp_ackvec_init(void)
484{
485 dccp_ackvec_slab = kmem_cache_create("dccp_ackvec",
486 sizeof(struct dccp_ackvec), 0,
487 SLAB_HWCACHE_ALIGN, NULL, NULL);
488 if (dccp_ackvec_slab == NULL)
489 goto out_err;
490
491 dccp_ackvec_record_slab =
492 kmem_cache_create("dccp_ackvec_record",
493 sizeof(struct dccp_ackvec_record),
494 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
495 if (dccp_ackvec_record_slab == NULL)
496 goto out_destroy_slab;
497
498 return 0;
499
500out_destroy_slab:
501 kmem_cache_destroy(dccp_ackvec_slab);
502 dccp_ackvec_slab = NULL;
503out_err:
504 printk(dccp_ackvec_slab_msg);
505 return -ENOBUFS;
506}
507
508void dccp_ackvec_exit(void)
509{
510 if (dccp_ackvec_slab != NULL) {
511 kmem_cache_destroy(dccp_ackvec_slab);
512 dccp_ackvec_slab = NULL;
513 }
514 if (dccp_ackvec_record_slab != NULL) {
515 kmem_cache_destroy(dccp_ackvec_record_slab);
516 dccp_ackvec_record_slab = NULL;
517 }
518}
diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h
index f7dfb5f67b87..ec7a89bb7b39 100644
--- a/net/dccp/ackvec.h
+++ b/net/dccp/ackvec.h
@@ -13,6 +13,7 @@
13 13
14#include <linux/config.h> 14#include <linux/config.h>
15#include <linux/compiler.h> 15#include <linux/compiler.h>
16#include <linux/list.h>
16#include <linux/time.h> 17#include <linux/time.h>
17#include <linux/types.h> 18#include <linux/types.h>
18 19
@@ -42,39 +43,57 @@
42 * Ack Vectors it has recently sent. For each packet sent carrying an 43 * Ack Vectors it has recently sent. For each packet sent carrying an
43 * Ack Vector, it remembers four variables: 44 * Ack Vector, it remembers four variables:
44 * 45 *
45 * @dccpav_ack_seqno - the Sequence Number used for the packet
46 * (HC-Receiver seqno)
47 * @dccpav_ack_ptr - the value of buf_head at the time of acknowledgement. 46 * @dccpav_ack_ptr - the value of buf_head at the time of acknowledgement.
48 * @dccpav_ack_ackno - the Acknowledgement Number used for the packet 47 * @dccpav_records - list of dccp_ackvec_record
49 * (HC-Sender seqno)
50 * @dccpav_ack_nonce - the one-bit sum of the ECN Nonces for all State 0. 48 * @dccpav_ack_nonce - the one-bit sum of the ECN Nonces for all State 0.
51 * 49 *
52 * @dccpav_buf_len - circular buffer length
53 * @dccpav_time - the time in usecs 50 * @dccpav_time - the time in usecs
54 * @dccpav_buf - circular buffer of acknowledgeable packets 51 * @dccpav_buf - circular buffer of acknowledgeable packets
55 */ 52 */
56struct dccp_ackvec { 53struct dccp_ackvec {
57 u64 dccpav_buf_ackno; 54 u64 dccpav_buf_ackno;
58 u64 dccpav_ack_seqno; 55 struct list_head dccpav_records;
59 u64 dccpav_ack_ackno;
60 struct timeval dccpav_time; 56 struct timeval dccpav_time;
61 u8 dccpav_buf_head; 57 u8 dccpav_buf_head;
62 u8 dccpav_buf_tail; 58 u8 dccpav_buf_tail;
63 u8 dccpav_ack_ptr; 59 u8 dccpav_ack_ptr;
64 u8 dccpav_sent_len; 60 u8 dccpav_sent_len;
65 u8 dccpav_vec_len; 61 u8 dccpav_vec_len;
66 u8 dccpav_buf_len;
67 u8 dccpav_buf_nonce; 62 u8 dccpav_buf_nonce;
68 u8 dccpav_ack_nonce; 63 u8 dccpav_ack_nonce;
69 u8 dccpav_buf[0]; 64 u8 dccpav_buf[DCCP_MAX_ACKVEC_LEN];
65};
66
67/** struct dccp_ackvec_record - ack vector record
68 *
69 * ACK vector record as defined in Appendix A of spec.
70 *
71 * The list is sorted by dccpavr_ack_seqno
72 *
73 * @dccpavr_node - node in dccpav_records
74 * @dccpavr_ack_seqno - sequence number of the packet this record was sent on
75 * @dccpavr_ack_ackno - sequence number being acknowledged
76 * @dccpavr_ack_ptr - pointer into dccpav_buf where this record starts
77 * @dccpavr_ack_nonce - dccpav_ack_nonce at the time this record was sent
78 * @dccpavr_sent_len - lenght of the record in dccpav_buf
79 */
80struct dccp_ackvec_record {
81 struct list_head dccpavr_node;
82 u64 dccpavr_ack_seqno;
83 u64 dccpavr_ack_ackno;
84 u8 dccpavr_ack_ptr;
85 u8 dccpavr_ack_nonce;
86 u8 dccpavr_sent_len;
70}; 87};
71 88
72struct sock; 89struct sock;
73struct sk_buff; 90struct sk_buff;
74 91
75#ifdef CONFIG_IP_DCCP_ACKVEC 92#ifdef CONFIG_IP_DCCP_ACKVEC
76extern struct dccp_ackvec *dccp_ackvec_alloc(unsigned int len, 93extern int dccp_ackvec_init(void);
77 const gfp_t priority); 94extern void dccp_ackvec_exit(void);
95
96extern struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority);
78extern void dccp_ackvec_free(struct dccp_ackvec *av); 97extern void dccp_ackvec_free(struct dccp_ackvec *av);
79 98
80extern int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, 99extern int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
@@ -92,8 +111,16 @@ static inline int dccp_ackvec_pending(const struct dccp_ackvec *av)
92 return av->dccpav_sent_len != av->dccpav_vec_len; 111 return av->dccpav_sent_len != av->dccpav_vec_len;
93} 112}
94#else /* CONFIG_IP_DCCP_ACKVEC */ 113#else /* CONFIG_IP_DCCP_ACKVEC */
95static inline struct dccp_ackvec *dccp_ackvec_alloc(unsigned int len, 114static inline int dccp_ackvec_init(void)
96 const gfp_t priority) 115{
116 return 0;
117}
118
119static inline void dccp_ackvec_exit(void)
120{
121}
122
123static inline struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority)
97{ 124{
98 return NULL; 125 return NULL;
99} 126}
diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c
index 9d8fc0e289ea..ff05e59043cd 100644
--- a/net/dccp/ccid.c
+++ b/net/dccp/ccid.c
@@ -13,7 +13,7 @@
13 13
14#include "ccid.h" 14#include "ccid.h"
15 15
16static struct ccid *ccids[CCID_MAX]; 16static struct ccid_operations *ccids[CCID_MAX];
17#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) 17#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
18static atomic_t ccids_lockct = ATOMIC_INIT(0); 18static atomic_t ccids_lockct = ATOMIC_INIT(0);
19static DEFINE_SPINLOCK(ccids_lock); 19static DEFINE_SPINLOCK(ccids_lock);
@@ -55,85 +55,202 @@ static inline void ccids_read_unlock(void)
55#define ccids_read_unlock() do { } while(0) 55#define ccids_read_unlock() do { } while(0)
56#endif 56#endif
57 57
58int ccid_register(struct ccid *ccid) 58static kmem_cache_t *ccid_kmem_cache_create(int obj_size, const char *fmt,...)
59{ 59{
60 int err; 60 kmem_cache_t *slab;
61 char slab_name_fmt[32], *slab_name;
62 va_list args;
61 63
62 if (ccid->ccid_init == NULL) 64 va_start(args, fmt);
63 return -1; 65 vsnprintf(slab_name_fmt, sizeof(slab_name_fmt), fmt, args);
66 va_end(args);
67
68 slab_name = kstrdup(slab_name_fmt, GFP_KERNEL);
69 if (slab_name == NULL)
70 return NULL;
71 slab = kmem_cache_create(slab_name, sizeof(struct ccid) + obj_size, 0,
72 SLAB_HWCACHE_ALIGN, NULL, NULL);
73 if (slab == NULL)
74 kfree(slab_name);
75 return slab;
76}
77
78static void ccid_kmem_cache_destroy(kmem_cache_t *slab)
79{
80 if (slab != NULL) {
81 const char *name = kmem_cache_name(slab);
82
83 kmem_cache_destroy(slab);
84 kfree(name);
85 }
86}
87
88int ccid_register(struct ccid_operations *ccid_ops)
89{
90 int err = -ENOBUFS;
91
92 ccid_ops->ccid_hc_rx_slab =
93 ccid_kmem_cache_create(ccid_ops->ccid_hc_rx_obj_size,
94 "%s_hc_rx_sock",
95 ccid_ops->ccid_name);
96 if (ccid_ops->ccid_hc_rx_slab == NULL)
97 goto out;
98
99 ccid_ops->ccid_hc_tx_slab =
100 ccid_kmem_cache_create(ccid_ops->ccid_hc_tx_obj_size,
101 "%s_hc_tx_sock",
102 ccid_ops->ccid_name);
103 if (ccid_ops->ccid_hc_tx_slab == NULL)
104 goto out_free_rx_slab;
64 105
65 ccids_write_lock(); 106 ccids_write_lock();
66 err = -EEXIST; 107 err = -EEXIST;
67 if (ccids[ccid->ccid_id] == NULL) { 108 if (ccids[ccid_ops->ccid_id] == NULL) {
68 ccids[ccid->ccid_id] = ccid; 109 ccids[ccid_ops->ccid_id] = ccid_ops;
69 err = 0; 110 err = 0;
70 } 111 }
71 ccids_write_unlock(); 112 ccids_write_unlock();
72 if (err == 0) 113 if (err != 0)
73 pr_info("CCID: Registered CCID %d (%s)\n", 114 goto out_free_tx_slab;
74 ccid->ccid_id, ccid->ccid_name); 115
116 pr_info("CCID: Registered CCID %d (%s)\n",
117 ccid_ops->ccid_id, ccid_ops->ccid_name);
118out:
75 return err; 119 return err;
120out_free_tx_slab:
121 ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab);
122 ccid_ops->ccid_hc_tx_slab = NULL;
123 goto out;
124out_free_rx_slab:
125 ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab);
126 ccid_ops->ccid_hc_rx_slab = NULL;
127 goto out;
76} 128}
77 129
78EXPORT_SYMBOL_GPL(ccid_register); 130EXPORT_SYMBOL_GPL(ccid_register);
79 131
80int ccid_unregister(struct ccid *ccid) 132int ccid_unregister(struct ccid_operations *ccid_ops)
81{ 133{
82 ccids_write_lock(); 134 ccids_write_lock();
83 ccids[ccid->ccid_id] = NULL; 135 ccids[ccid_ops->ccid_id] = NULL;
84 ccids_write_unlock(); 136 ccids_write_unlock();
137
138 ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab);
139 ccid_ops->ccid_hc_tx_slab = NULL;
140 ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab);
141 ccid_ops->ccid_hc_rx_slab = NULL;
142
85 pr_info("CCID: Unregistered CCID %d (%s)\n", 143 pr_info("CCID: Unregistered CCID %d (%s)\n",
86 ccid->ccid_id, ccid->ccid_name); 144 ccid_ops->ccid_id, ccid_ops->ccid_name);
87 return 0; 145 return 0;
88} 146}
89 147
90EXPORT_SYMBOL_GPL(ccid_unregister); 148EXPORT_SYMBOL_GPL(ccid_unregister);
91 149
92struct ccid *ccid_init(unsigned char id, struct sock *sk) 150struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, gfp_t gfp)
93{ 151{
94 struct ccid *ccid; 152 struct ccid_operations *ccid_ops;
153 struct ccid *ccid = NULL;
95 154
155 ccids_read_lock();
96#ifdef CONFIG_KMOD 156#ifdef CONFIG_KMOD
97 if (ccids[id] == NULL) 157 if (ccids[id] == NULL) {
158 /* We only try to load if in process context */
159 ccids_read_unlock();
160 if (gfp & GFP_ATOMIC)
161 goto out;
98 request_module("net-dccp-ccid-%d", id); 162 request_module("net-dccp-ccid-%d", id);
163 ccids_read_lock();
164 }
99#endif 165#endif
100 ccids_read_lock(); 166 ccid_ops = ccids[id];
167 if (ccid_ops == NULL)
168 goto out_unlock;
101 169
102 ccid = ccids[id]; 170 if (!try_module_get(ccid_ops->ccid_owner))
103 if (ccid == NULL) 171 goto out_unlock;
104 goto out;
105 172
106 if (!try_module_get(ccid->ccid_owner)) 173 ccids_read_unlock();
107 goto out_err;
108 174
109 if (ccid->ccid_init(sk) != 0) 175 ccid = kmem_cache_alloc(rx ? ccid_ops->ccid_hc_rx_slab :
176 ccid_ops->ccid_hc_tx_slab, gfp);
177 if (ccid == NULL)
110 goto out_module_put; 178 goto out_module_put;
179 ccid->ccid_ops = ccid_ops;
180 if (rx) {
181 memset(ccid + 1, 0, ccid_ops->ccid_hc_rx_obj_size);
182 if (ccid->ccid_ops->ccid_hc_rx_init != NULL &&
183 ccid->ccid_ops->ccid_hc_rx_init(ccid, sk) != 0)
184 goto out_free_ccid;
185 } else {
186 memset(ccid + 1, 0, ccid_ops->ccid_hc_tx_obj_size);
187 if (ccid->ccid_ops->ccid_hc_tx_init != NULL &&
188 ccid->ccid_ops->ccid_hc_tx_init(ccid, sk) != 0)
189 goto out_free_ccid;
190 }
111out: 191out:
112 ccids_read_unlock();
113 return ccid; 192 return ccid;
114out_module_put: 193out_unlock:
115 module_put(ccid->ccid_owner); 194 ccids_read_unlock();
116out_err: 195 goto out;
196out_free_ccid:
197 kmem_cache_free(rx ? ccid_ops->ccid_hc_rx_slab :
198 ccid_ops->ccid_hc_tx_slab, ccid);
117 ccid = NULL; 199 ccid = NULL;
200out_module_put:
201 module_put(ccid_ops->ccid_owner);
118 goto out; 202 goto out;
119} 203}
120 204
121EXPORT_SYMBOL_GPL(ccid_init); 205EXPORT_SYMBOL_GPL(ccid_new);
206
207struct ccid *ccid_hc_rx_new(unsigned char id, struct sock *sk, gfp_t gfp)
208{
209 return ccid_new(id, sk, 1, gfp);
210}
211
212EXPORT_SYMBOL_GPL(ccid_hc_rx_new);
213
214struct ccid *ccid_hc_tx_new(unsigned char id,struct sock *sk, gfp_t gfp)
215{
216 return ccid_new(id, sk, 0, gfp);
217}
218
219EXPORT_SYMBOL_GPL(ccid_hc_tx_new);
122 220
123void ccid_exit(struct ccid *ccid, struct sock *sk) 221static void ccid_delete(struct ccid *ccid, struct sock *sk, int rx)
124{ 222{
223 struct ccid_operations *ccid_ops;
224
125 if (ccid == NULL) 225 if (ccid == NULL)
126 return; 226 return;
127 227
228 ccid_ops = ccid->ccid_ops;
229 if (rx) {
230 if (ccid_ops->ccid_hc_rx_exit != NULL)
231 ccid_ops->ccid_hc_rx_exit(sk);
232 kmem_cache_free(ccid_ops->ccid_hc_rx_slab, ccid);
233 } else {
234 if (ccid_ops->ccid_hc_tx_exit != NULL)
235 ccid_ops->ccid_hc_tx_exit(sk);
236 kmem_cache_free(ccid_ops->ccid_hc_tx_slab, ccid);
237 }
128 ccids_read_lock(); 238 ccids_read_lock();
239 if (ccids[ccid_ops->ccid_id] != NULL)
240 module_put(ccid_ops->ccid_owner);
241 ccids_read_unlock();
242}
129 243
130 if (ccids[ccid->ccid_id] != NULL) { 244void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk)
131 if (ccid->ccid_exit != NULL) 245{
132 ccid->ccid_exit(sk); 246 ccid_delete(ccid, sk, 1);
133 module_put(ccid->ccid_owner); 247}
134 }
135 248
136 ccids_read_unlock(); 249EXPORT_SYMBOL_GPL(ccid_hc_rx_delete);
250
251void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk)
252{
253 ccid_delete(ccid, sk, 0);
137} 254}
138 255
139EXPORT_SYMBOL_GPL(ccid_exit); 256EXPORT_SYMBOL_GPL(ccid_hc_tx_delete);
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
index de681c6ad081..f7eb6c613414 100644
--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -23,14 +23,16 @@
23 23
24struct tcp_info; 24struct tcp_info;
25 25
26struct ccid { 26struct ccid_operations {
27 unsigned char ccid_id; 27 unsigned char ccid_id;
28 const char *ccid_name; 28 const char *ccid_name;
29 struct module *ccid_owner; 29 struct module *ccid_owner;
30 int (*ccid_init)(struct sock *sk); 30 kmem_cache_t *ccid_hc_rx_slab;
31 void (*ccid_exit)(struct sock *sk); 31 __u32 ccid_hc_rx_obj_size;
32 int (*ccid_hc_rx_init)(struct sock *sk); 32 kmem_cache_t *ccid_hc_tx_slab;
33 int (*ccid_hc_tx_init)(struct sock *sk); 33 __u32 ccid_hc_tx_obj_size;
34 int (*ccid_hc_rx_init)(struct ccid *ccid, struct sock *sk);
35 int (*ccid_hc_tx_init)(struct ccid *ccid, struct sock *sk);
34 void (*ccid_hc_rx_exit)(struct sock *sk); 36 void (*ccid_hc_rx_exit)(struct sock *sk);
35 void (*ccid_hc_tx_exit)(struct sock *sk); 37 void (*ccid_hc_tx_exit)(struct sock *sk);
36 void (*ccid_hc_rx_packet_recv)(struct sock *sk, 38 void (*ccid_hc_rx_packet_recv)(struct sock *sk,
@@ -39,9 +41,9 @@ struct ccid {
39 unsigned char option, 41 unsigned char option,
40 unsigned char len, u16 idx, 42 unsigned char len, u16 idx,
41 unsigned char* value); 43 unsigned char* value);
42 void (*ccid_hc_rx_insert_options)(struct sock *sk, 44 int (*ccid_hc_rx_insert_options)(struct sock *sk,
43 struct sk_buff *skb); 45 struct sk_buff *skb);
44 void (*ccid_hc_tx_insert_options)(struct sock *sk, 46 int (*ccid_hc_tx_insert_options)(struct sock *sk,
45 struct sk_buff *skb); 47 struct sk_buff *skb);
46 void (*ccid_hc_tx_packet_recv)(struct sock *sk, 48 void (*ccid_hc_tx_packet_recv)(struct sock *sk,
47 struct sk_buff *skb); 49 struct sk_buff *skb);
@@ -67,75 +69,58 @@ struct ccid {
67 int __user *optlen); 69 int __user *optlen);
68}; 70};
69 71
70extern int ccid_register(struct ccid *ccid); 72extern int ccid_register(struct ccid_operations *ccid_ops);
71extern int ccid_unregister(struct ccid *ccid); 73extern int ccid_unregister(struct ccid_operations *ccid_ops);
72 74
73extern struct ccid *ccid_init(unsigned char id, struct sock *sk); 75struct ccid {
74extern void ccid_exit(struct ccid *ccid, struct sock *sk); 76 struct ccid_operations *ccid_ops;
77 char ccid_priv[0];
78};
75 79
76static inline void __ccid_get(struct ccid *ccid) 80static inline void *ccid_priv(const struct ccid *ccid)
77{ 81{
78 __module_get(ccid->ccid_owner); 82 return (void *)ccid->ccid_priv;
79} 83}
80 84
85extern struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx,
86 gfp_t gfp);
87
88extern struct ccid *ccid_hc_rx_new(unsigned char id, struct sock *sk,
89 gfp_t gfp);
90extern struct ccid *ccid_hc_tx_new(unsigned char id, struct sock *sk,
91 gfp_t gfp);
92
93extern void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk);
94extern void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk);
95
81static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk, 96static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk,
82 struct sk_buff *skb, int len) 97 struct sk_buff *skb, int len)
83{ 98{
84 int rc = 0; 99 int rc = 0;
85 if (ccid->ccid_hc_tx_send_packet != NULL) 100 if (ccid->ccid_ops->ccid_hc_tx_send_packet != NULL)
86 rc = ccid->ccid_hc_tx_send_packet(sk, skb, len); 101 rc = ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb, len);
87 return rc; 102 return rc;
88} 103}
89 104
90static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk, 105static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk,
91 int more, int len) 106 int more, int len)
92{ 107{
93 if (ccid->ccid_hc_tx_packet_sent != NULL) 108 if (ccid->ccid_ops->ccid_hc_tx_packet_sent != NULL)
94 ccid->ccid_hc_tx_packet_sent(sk, more, len); 109 ccid->ccid_ops->ccid_hc_tx_packet_sent(sk, more, len);
95}
96
97static inline int ccid_hc_rx_init(struct ccid *ccid, struct sock *sk)
98{
99 int rc = 0;
100 if (ccid->ccid_hc_rx_init != NULL)
101 rc = ccid->ccid_hc_rx_init(sk);
102 return rc;
103}
104
105static inline int ccid_hc_tx_init(struct ccid *ccid, struct sock *sk)
106{
107 int rc = 0;
108 if (ccid->ccid_hc_tx_init != NULL)
109 rc = ccid->ccid_hc_tx_init(sk);
110 return rc;
111}
112
113static inline void ccid_hc_rx_exit(struct ccid *ccid, struct sock *sk)
114{
115 if (ccid != NULL && ccid->ccid_hc_rx_exit != NULL &&
116 dccp_sk(sk)->dccps_hc_rx_ccid_private != NULL)
117 ccid->ccid_hc_rx_exit(sk);
118}
119
120static inline void ccid_hc_tx_exit(struct ccid *ccid, struct sock *sk)
121{
122 if (ccid != NULL && ccid->ccid_hc_tx_exit != NULL &&
123 dccp_sk(sk)->dccps_hc_tx_ccid_private != NULL)
124 ccid->ccid_hc_tx_exit(sk);
125} 110}
126 111
127static inline void ccid_hc_rx_packet_recv(struct ccid *ccid, struct sock *sk, 112static inline void ccid_hc_rx_packet_recv(struct ccid *ccid, struct sock *sk,
128 struct sk_buff *skb) 113 struct sk_buff *skb)
129{ 114{
130 if (ccid->ccid_hc_rx_packet_recv != NULL) 115 if (ccid->ccid_ops->ccid_hc_rx_packet_recv != NULL)
131 ccid->ccid_hc_rx_packet_recv(sk, skb); 116 ccid->ccid_ops->ccid_hc_rx_packet_recv(sk, skb);
132} 117}
133 118
134static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk, 119static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
135 struct sk_buff *skb) 120 struct sk_buff *skb)
136{ 121{
137 if (ccid->ccid_hc_tx_packet_recv != NULL) 122 if (ccid->ccid_ops->ccid_hc_tx_packet_recv != NULL)
138 ccid->ccid_hc_tx_packet_recv(sk, skb); 123 ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb);
139} 124}
140 125
141static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk, 126static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
@@ -144,8 +129,8 @@ static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
144 unsigned char* value) 129 unsigned char* value)
145{ 130{
146 int rc = 0; 131 int rc = 0;
147 if (ccid->ccid_hc_tx_parse_options != NULL) 132 if (ccid->ccid_ops->ccid_hc_tx_parse_options != NULL)
148 rc = ccid->ccid_hc_tx_parse_options(sk, option, len, idx, 133 rc = ccid->ccid_ops->ccid_hc_tx_parse_options(sk, option, len, idx,
149 value); 134 value);
150 return rc; 135 return rc;
151} 136}
@@ -156,37 +141,39 @@ static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
156 unsigned char* value) 141 unsigned char* value)
157{ 142{
158 int rc = 0; 143 int rc = 0;
159 if (ccid->ccid_hc_rx_parse_options != NULL) 144 if (ccid->ccid_ops->ccid_hc_rx_parse_options != NULL)
160 rc = ccid->ccid_hc_rx_parse_options(sk, option, len, idx, value); 145 rc = ccid->ccid_ops->ccid_hc_rx_parse_options(sk, option, len, idx, value);
161 return rc; 146 return rc;
162} 147}
163 148
164static inline void ccid_hc_tx_insert_options(struct ccid *ccid, struct sock *sk, 149static inline int ccid_hc_tx_insert_options(struct ccid *ccid, struct sock *sk,
165 struct sk_buff *skb) 150 struct sk_buff *skb)
166{ 151{
167 if (ccid->ccid_hc_tx_insert_options != NULL) 152 if (ccid->ccid_ops->ccid_hc_tx_insert_options != NULL)
168 ccid->ccid_hc_tx_insert_options(sk, skb); 153 return ccid->ccid_ops->ccid_hc_tx_insert_options(sk, skb);
154 return 0;
169} 155}
170 156
171static inline void ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk, 157static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
172 struct sk_buff *skb) 158 struct sk_buff *skb)
173{ 159{
174 if (ccid->ccid_hc_rx_insert_options != NULL) 160 if (ccid->ccid_ops->ccid_hc_rx_insert_options != NULL)
175 ccid->ccid_hc_rx_insert_options(sk, skb); 161 return ccid->ccid_ops->ccid_hc_rx_insert_options(sk, skb);
162 return 0;
176} 163}
177 164
178static inline void ccid_hc_rx_get_info(struct ccid *ccid, struct sock *sk, 165static inline void ccid_hc_rx_get_info(struct ccid *ccid, struct sock *sk,
179 struct tcp_info *info) 166 struct tcp_info *info)
180{ 167{
181 if (ccid->ccid_hc_rx_get_info != NULL) 168 if (ccid->ccid_ops->ccid_hc_rx_get_info != NULL)
182 ccid->ccid_hc_rx_get_info(sk, info); 169 ccid->ccid_ops->ccid_hc_rx_get_info(sk, info);
183} 170}
184 171
185static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk, 172static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk,
186 struct tcp_info *info) 173 struct tcp_info *info)
187{ 174{
188 if (ccid->ccid_hc_tx_get_info != NULL) 175 if (ccid->ccid_ops->ccid_hc_tx_get_info != NULL)
189 ccid->ccid_hc_tx_get_info(sk, info); 176 ccid->ccid_ops->ccid_hc_tx_get_info(sk, info);
190} 177}
191 178
192static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk, 179static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk,
@@ -194,8 +181,8 @@ static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk,
194 u32 __user *optval, int __user *optlen) 181 u32 __user *optval, int __user *optlen)
195{ 182{
196 int rc = -ENOPROTOOPT; 183 int rc = -ENOPROTOOPT;
197 if (ccid->ccid_hc_rx_getsockopt != NULL) 184 if (ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL)
198 rc = ccid->ccid_hc_rx_getsockopt(sk, optname, len, 185 rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len,
199 optval, optlen); 186 optval, optlen);
200 return rc; 187 return rc;
201} 188}
@@ -205,8 +192,8 @@ static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk,
205 u32 __user *optval, int __user *optlen) 192 u32 __user *optval, int __user *optlen)
206{ 193{
207 int rc = -ENOPROTOOPT; 194 int rc = -ENOPROTOOPT;
208 if (ccid->ccid_hc_tx_getsockopt != NULL) 195 if (ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL)
209 rc = ccid->ccid_hc_tx_getsockopt(sk, optname, len, 196 rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len,
210 optval, optlen); 197 optval, optlen);
211 return rc; 198 return rc;
212} 199}
diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig
index 7684d83946a4..ca00191628f7 100644
--- a/net/dccp/ccids/Kconfig
+++ b/net/dccp/ccids/Kconfig
@@ -1,9 +1,39 @@
1menu "DCCP CCIDs Configuration (EXPERIMENTAL)" 1menu "DCCP CCIDs Configuration (EXPERIMENTAL)"
2 depends on IP_DCCP && EXPERIMENTAL 2 depends on IP_DCCP && EXPERIMENTAL
3 3
4config IP_DCCP_CCID2
5 tristate "CCID2 (TCP-Like) (EXPERIMENTAL)"
6 depends on IP_DCCP
7 def_tristate IP_DCCP
8 select IP_DCCP_ACKVEC
9 ---help---
10 CCID 2, TCP-like Congestion Control, denotes Additive Increase,
11 Multiplicative Decrease (AIMD) congestion control with behavior
12 modelled directly on TCP, including congestion window, slow start,
13 timeouts, and so forth [RFC 2581]. CCID 2 achieves maximum
14 bandwidth over the long term, consistent with the use of end-to-end
15 congestion control, but halves its congestion window in response to
16 each congestion event. This leads to the abrupt rate changes
17 typical of TCP. Applications should use CCID 2 if they prefer
18 maximum bandwidth utilization to steadiness of rate. This is often
19 the case for applications that are not playing their data directly
20 to the user. For example, a hypothetical application that
21 transferred files over DCCP, using application-level retransmissions
22 for lost packets, would prefer CCID 2 to CCID 3. On-line games may
23 also prefer CCID 2.
24
25 CCID 2 is further described in:
26 http://www.icir.org/kohler/dccp/draft-ietf-dccp-ccid2-10.txt
27
28 This text was extracted from:
29 http://www.icir.org/kohler/dccp/draft-ietf-dccp-spec-13.txt
30
31 If in doubt, say M.
32
4config IP_DCCP_CCID3 33config IP_DCCP_CCID3
5 tristate "CCID3 (TFRC) (EXPERIMENTAL)" 34 tristate "CCID3 (TCP-Friendly) (EXPERIMENTAL)"
6 depends on IP_DCCP 35 depends on IP_DCCP
36 def_tristate IP_DCCP
7 ---help--- 37 ---help---
8 CCID 3 denotes TCP-Friendly Rate Control (TFRC), an equation-based 38 CCID 3 denotes TCP-Friendly Rate Control (TFRC), an equation-based
9 rate-controlled congestion control mechanism. TFRC is designed to 39 rate-controlled congestion control mechanism. TFRC is designed to
@@ -15,10 +45,15 @@ config IP_DCCP_CCID3
15 suitable than CCID 2 for applications such streaming media where a 45 suitable than CCID 2 for applications such streaming media where a
16 relatively smooth sending rate is of importance. 46 relatively smooth sending rate is of importance.
17 47
18 CCID 3 is further described in [CCID 3 PROFILE]. The TFRC 48 CCID 3 is further described in:
19 congestion control algorithms were initially described in RFC 3448. 49
50 http://www.icir.org/kohler/dccp/draft-ietf-dccp-ccid3-11.txt.
51
52 The TFRC congestion control algorithms were initially described in
53 RFC 3448.
20 54
21 This text was extracted from draft-ietf-dccp-spec-11.txt. 55 This text was extracted from:
56 http://www.icir.org/kohler/dccp/draft-ietf-dccp-spec-13.txt
22 57
23 If in doubt, say M. 58 If in doubt, say M.
24 59
diff --git a/net/dccp/ccids/Makefile b/net/dccp/ccids/Makefile
index 956f79f50743..438f20bccff7 100644
--- a/net/dccp/ccids/Makefile
+++ b/net/dccp/ccids/Makefile
@@ -2,4 +2,8 @@ obj-$(CONFIG_IP_DCCP_CCID3) += dccp_ccid3.o
2 2
3dccp_ccid3-y := ccid3.o 3dccp_ccid3-y := ccid3.o
4 4
5obj-$(CONFIG_IP_DCCP_CCID2) += dccp_ccid2.o
6
7dccp_ccid2-y := ccid2.o
8
5obj-y += lib/ 9obj-y += lib/
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
new file mode 100644
index 000000000000..d4f9e2d33453
--- /dev/null
+++ b/net/dccp/ccids/ccid2.c
@@ -0,0 +1,779 @@
1/*
2 * net/dccp/ccids/ccid2.c
3 *
4 * Copyright (c) 2005, 2006 Andrea Bittau <a.bittau@cs.ucl.ac.uk>
5 *
6 * Changes to meet Linux coding standards, and DCCP infrastructure fixes.
7 *
8 * Copyright (c) 2006 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25/*
26 * This implementation should follow: draft-ietf-dccp-ccid2-10.txt
27 *
28 * BUGS:
29 * - sequence number wrapping
30 * - jiffies wrapping
31 */
32
33#include <linux/config.h>
34#include "../ccid.h"
35#include "../dccp.h"
36#include "ccid2.h"
37
38static int ccid2_debug;
39
40#undef CCID2_DEBUG
41#ifdef CCID2_DEBUG
42#define ccid2_pr_debug(format, a...) \
43 do { if (ccid2_debug) \
44 printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \
45 } while (0)
46#else
47#define ccid2_pr_debug(format, a...)
48#endif
49
50static const int ccid2_seq_len = 128;
51
52#ifdef CCID2_DEBUG
53static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx)
54{
55 int len = 0;
56 int pipe = 0;
57 struct ccid2_seq *seqp = hctx->ccid2hctx_seqh;
58
59 /* there is data in the chain */
60 if (seqp != hctx->ccid2hctx_seqt) {
61 seqp = seqp->ccid2s_prev;
62 len++;
63 if (!seqp->ccid2s_acked)
64 pipe++;
65
66 while (seqp != hctx->ccid2hctx_seqt) {
67 struct ccid2_seq *prev = seqp->ccid2s_prev;
68
69 len++;
70 if (!prev->ccid2s_acked)
71 pipe++;
72
73 /* packets are sent sequentially */
74 BUG_ON(seqp->ccid2s_seq <= prev->ccid2s_seq);
75 BUG_ON(seqp->ccid2s_sent < prev->ccid2s_sent);
76 BUG_ON(len > ccid2_seq_len);
77
78 seqp = prev;
79 }
80 }
81
82 BUG_ON(pipe != hctx->ccid2hctx_pipe);
83 ccid2_pr_debug("len of chain=%d\n", len);
84
85 do {
86 seqp = seqp->ccid2s_prev;
87 len++;
88 BUG_ON(len > ccid2_seq_len);
89 } while (seqp != hctx->ccid2hctx_seqh);
90
91 BUG_ON(len != ccid2_seq_len);
92 ccid2_pr_debug("total len=%d\n", len);
93}
94#else
95#define ccid2_hc_tx_check_sanity(hctx) do {} while (0)
96#endif
97
98static int ccid2_hc_tx_send_packet(struct sock *sk,
99 struct sk_buff *skb, int len)
100{
101 struct ccid2_hc_tx_sock *hctx;
102
103 switch (DCCP_SKB_CB(skb)->dccpd_type) {
104 case 0: /* XXX data packets from userland come through like this */
105 case DCCP_PKT_DATA:
106 case DCCP_PKT_DATAACK:
107 break;
108 /* No congestion control on other packets */
109 default:
110 return 0;
111 }
112
113 hctx = ccid2_hc_tx_sk(sk);
114
115 ccid2_pr_debug("pipe=%d cwnd=%d\n", hctx->ccid2hctx_pipe,
116 hctx->ccid2hctx_cwnd);
117
118 if (hctx->ccid2hctx_pipe < hctx->ccid2hctx_cwnd) {
119 /* OK we can send... make sure previous packet was sent off */
120 if (!hctx->ccid2hctx_sendwait) {
121 hctx->ccid2hctx_sendwait = 1;
122 return 0;
123 }
124 }
125
126 return 100; /* XXX */
127}
128
129static void ccid2_change_l_ack_ratio(struct sock *sk, int val)
130{
131 struct dccp_sock *dp = dccp_sk(sk);
132 /*
133 * XXX I don't really agree with val != 2. If cwnd is 1, ack ratio
134 * should be 1... it shouldn't be allowed to become 2.
135 * -sorbo.
136 */
137 if (val != 2) {
138 const struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
139 int max = hctx->ccid2hctx_cwnd / 2;
140
141 /* round up */
142 if (hctx->ccid2hctx_cwnd & 1)
143 max++;
144
145 if (val > max)
146 val = max;
147 }
148
149 ccid2_pr_debug("changing local ack ratio to %d\n", val);
150 WARN_ON(val <= 0);
151 dp->dccps_l_ack_ratio = val;
152}
153
154static void ccid2_change_cwnd(struct sock *sk, int val)
155{
156 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
157
158 if (val == 0)
159 val = 1;
160
161 /* XXX do we need to change ack ratio? */
162 ccid2_pr_debug("change cwnd to %d\n", val);
163
164 BUG_ON(val < 1);
165 hctx->ccid2hctx_cwnd = val;
166}
167
168static void ccid2_start_rto_timer(struct sock *sk);
169
170static void ccid2_hc_tx_rto_expire(unsigned long data)
171{
172 struct sock *sk = (struct sock *)data;
173 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
174 long s;
175
176 bh_lock_sock(sk);
177 if (sock_owned_by_user(sk)) {
178 sk_reset_timer(sk, &hctx->ccid2hctx_rtotimer,
179 jiffies + HZ / 5);
180 goto out;
181 }
182
183 ccid2_pr_debug("RTO_EXPIRE\n");
184
185 ccid2_hc_tx_check_sanity(hctx);
186
187 /* back-off timer */
188 hctx->ccid2hctx_rto <<= 1;
189
190 s = hctx->ccid2hctx_rto / HZ;
191 if (s > 60)
192 hctx->ccid2hctx_rto = 60 * HZ;
193
194 ccid2_start_rto_timer(sk);
195
196 /* adjust pipe, cwnd etc */
197 hctx->ccid2hctx_pipe = 0;
198 hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd >> 1;
199 if (hctx->ccid2hctx_ssthresh < 2)
200 hctx->ccid2hctx_ssthresh = 2;
201 ccid2_change_cwnd(sk, 1);
202
203 /* clear state about stuff we sent */
204 hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqh;
205 hctx->ccid2hctx_ssacks = 0;
206 hctx->ccid2hctx_acks = 0;
207 hctx->ccid2hctx_sent = 0;
208
209 /* clear ack ratio state. */
210 hctx->ccid2hctx_arsent = 0;
211 hctx->ccid2hctx_ackloss = 0;
212 hctx->ccid2hctx_rpseq = 0;
213 hctx->ccid2hctx_rpdupack = -1;
214 ccid2_change_l_ack_ratio(sk, 1);
215 ccid2_hc_tx_check_sanity(hctx);
216out:
217 bh_unlock_sock(sk);
218 sock_put(sk);
219}
220
221static void ccid2_start_rto_timer(struct sock *sk)
222{
223 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
224
225 ccid2_pr_debug("setting RTO timeout=%ld\n", hctx->ccid2hctx_rto);
226
227 BUG_ON(timer_pending(&hctx->ccid2hctx_rtotimer));
228 sk_reset_timer(sk, &hctx->ccid2hctx_rtotimer,
229 jiffies + hctx->ccid2hctx_rto);
230}
231
232static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len)
233{
234 struct dccp_sock *dp = dccp_sk(sk);
235 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
236 u64 seq;
237
238 ccid2_hc_tx_check_sanity(hctx);
239
240 BUG_ON(!hctx->ccid2hctx_sendwait);
241 hctx->ccid2hctx_sendwait = 0;
242 hctx->ccid2hctx_pipe++;
243 BUG_ON(hctx->ccid2hctx_pipe < 0);
244
245 /* There is an issue. What if another packet is sent between
246 * packet_send() and packet_sent(). Then the sequence number would be
247 * wrong.
248 * -sorbo.
249 */
250 seq = dp->dccps_gss;
251
252 hctx->ccid2hctx_seqh->ccid2s_seq = seq;
253 hctx->ccid2hctx_seqh->ccid2s_acked = 0;
254 hctx->ccid2hctx_seqh->ccid2s_sent = jiffies;
255 hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqh->ccid2s_next;
256
257 ccid2_pr_debug("cwnd=%d pipe=%d\n", hctx->ccid2hctx_cwnd,
258 hctx->ccid2hctx_pipe);
259
260 if (hctx->ccid2hctx_seqh == hctx->ccid2hctx_seqt) {
261 /* XXX allocate more space */
262 WARN_ON(1);
263 }
264
265 hctx->ccid2hctx_sent++;
266
267 /* Ack Ratio. Need to maintain a concept of how many windows we sent */
268 hctx->ccid2hctx_arsent++;
269 /* We had an ack loss in this window... */
270 if (hctx->ccid2hctx_ackloss) {
271 if (hctx->ccid2hctx_arsent >= hctx->ccid2hctx_cwnd) {
272 hctx->ccid2hctx_arsent = 0;
273 hctx->ccid2hctx_ackloss = 0;
274 }
275 } else {
276 /* No acks lost up to now... */
277 /* decrease ack ratio if enough packets were sent */
278 if (dp->dccps_l_ack_ratio > 1) {
279 /* XXX don't calculate denominator each time */
280 int denom = dp->dccps_l_ack_ratio * dp->dccps_l_ack_ratio -
281 dp->dccps_l_ack_ratio;
282
283 denom = hctx->ccid2hctx_cwnd * hctx->ccid2hctx_cwnd / denom;
284
285 if (hctx->ccid2hctx_arsent >= denom) {
286 ccid2_change_l_ack_ratio(sk, dp->dccps_l_ack_ratio - 1);
287 hctx->ccid2hctx_arsent = 0;
288 }
289 } else {
290 /* we can't increase ack ratio further [1] */
291 hctx->ccid2hctx_arsent = 0; /* or maybe set it to cwnd*/
292 }
293 }
294
295 /* setup RTO timer */
296 if (!timer_pending(&hctx->ccid2hctx_rtotimer))
297 ccid2_start_rto_timer(sk);
298
299#ifdef CCID2_DEBUG
300 ccid2_pr_debug("pipe=%d\n", hctx->ccid2hctx_pipe);
301 ccid2_pr_debug("Sent: seq=%llu\n", seq);
302 do {
303 struct ccid2_seq *seqp = hctx->ccid2hctx_seqt;
304
305 while (seqp != hctx->ccid2hctx_seqh) {
306 ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n",
307 seqp->ccid2s_seq, seqp->ccid2s_acked,
308 seqp->ccid2s_sent);
309 seqp = seqp->ccid2s_next;
310 }
311 } while (0);
312 ccid2_pr_debug("=========\n");
313 ccid2_hc_tx_check_sanity(hctx);
314#endif
315}
316
317/* XXX Lame code duplication!
318 * returns -1 if none was found.
319 * else returns the next offset to use in the function call.
320 */
321static int ccid2_ackvector(struct sock *sk, struct sk_buff *skb, int offset,
322 unsigned char **vec, unsigned char *veclen)
323{
324 const struct dccp_hdr *dh = dccp_hdr(skb);
325 unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb);
326 unsigned char *opt_ptr;
327 const unsigned char *opt_end = (unsigned char *)dh +
328 (dh->dccph_doff * 4);
329 unsigned char opt, len;
330 unsigned char *value;
331
332 BUG_ON(offset < 0);
333 options += offset;
334 opt_ptr = options;
335 if (opt_ptr >= opt_end)
336 return -1;
337
338 while (opt_ptr != opt_end) {
339 opt = *opt_ptr++;
340 len = 0;
341 value = NULL;
342
343 /* Check if this isn't a single byte option */
344 if (opt > DCCPO_MAX_RESERVED) {
345 if (opt_ptr == opt_end)
346 goto out_invalid_option;
347
348 len = *opt_ptr++;
349 if (len < 3)
350 goto out_invalid_option;
351 /*
352 * Remove the type and len fields, leaving
353 * just the value size
354 */
355 len -= 2;
356 value = opt_ptr;
357 opt_ptr += len;
358
359 if (opt_ptr > opt_end)
360 goto out_invalid_option;
361 }
362
363 switch (opt) {
364 case DCCPO_ACK_VECTOR_0:
365 case DCCPO_ACK_VECTOR_1:
366 *vec = value;
367 *veclen = len;
368 return offset + (opt_ptr - options);
369 }
370 }
371
372 return -1;
373
374out_invalid_option:
375 BUG_ON(1); /* should never happen... options were previously parsed ! */
376 return -1;
377}
378
379static void ccid2_hc_tx_kill_rto_timer(struct sock *sk)
380{
381 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
382
383 sk_stop_timer(sk, &hctx->ccid2hctx_rtotimer);
384 ccid2_pr_debug("deleted RTO timer\n");
385}
386
387static inline void ccid2_new_ack(struct sock *sk,
388 struct ccid2_seq *seqp,
389 unsigned int *maxincr)
390{
391 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
392
393 /* slow start */
394 if (hctx->ccid2hctx_cwnd < hctx->ccid2hctx_ssthresh) {
395 hctx->ccid2hctx_acks = 0;
396
397 /* We can increase cwnd at most maxincr [ack_ratio/2] */
398 if (*maxincr) {
399 /* increase every 2 acks */
400 hctx->ccid2hctx_ssacks++;
401 if (hctx->ccid2hctx_ssacks == 2) {
402 ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd + 1);
403 hctx->ccid2hctx_ssacks = 0;
404 *maxincr = *maxincr - 1;
405 }
406 } else {
407 /* increased cwnd enough for this single ack */
408 hctx->ccid2hctx_ssacks = 0;
409 }
410 } else {
411 hctx->ccid2hctx_ssacks = 0;
412 hctx->ccid2hctx_acks++;
413
414 if (hctx->ccid2hctx_acks >= hctx->ccid2hctx_cwnd) {
415 ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd + 1);
416 hctx->ccid2hctx_acks = 0;
417 }
418 }
419
420 /* update RTO */
421 if (hctx->ccid2hctx_srtt == -1 ||
422 (jiffies - hctx->ccid2hctx_lastrtt) >= hctx->ccid2hctx_srtt) {
423 unsigned long r = jiffies - seqp->ccid2s_sent;
424 int s;
425
426 /* first measurement */
427 if (hctx->ccid2hctx_srtt == -1) {
428 ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n",
429 r, jiffies, seqp->ccid2s_seq);
430 hctx->ccid2hctx_srtt = r;
431 hctx->ccid2hctx_rttvar = r >> 1;
432 } else {
433 /* RTTVAR */
434 long tmp = hctx->ccid2hctx_srtt - r;
435 if (tmp < 0)
436 tmp *= -1;
437
438 tmp >>= 2;
439 hctx->ccid2hctx_rttvar *= 3;
440 hctx->ccid2hctx_rttvar >>= 2;
441 hctx->ccid2hctx_rttvar += tmp;
442
443 /* SRTT */
444 hctx->ccid2hctx_srtt *= 7;
445 hctx->ccid2hctx_srtt >>= 3;
446 tmp = r >> 3;
447 hctx->ccid2hctx_srtt += tmp;
448 }
449 s = hctx->ccid2hctx_rttvar << 2;
450 /* clock granularity is 1 when based on jiffies */
451 if (!s)
452 s = 1;
453 hctx->ccid2hctx_rto = hctx->ccid2hctx_srtt + s;
454
455 /* must be at least a second */
456 s = hctx->ccid2hctx_rto / HZ;
457 /* DCCP doesn't require this [but I like it cuz my code sux] */
458#if 1
459 if (s < 1)
460 hctx->ccid2hctx_rto = HZ;
461#endif
462 /* max 60 seconds */
463 if (s > 60)
464 hctx->ccid2hctx_rto = HZ * 60;
465
466 hctx->ccid2hctx_lastrtt = jiffies;
467
468 ccid2_pr_debug("srtt: %ld rttvar: %ld rto: %ld (HZ=%d) R=%lu\n",
469 hctx->ccid2hctx_srtt, hctx->ccid2hctx_rttvar,
470 hctx->ccid2hctx_rto, HZ, r);
471 hctx->ccid2hctx_sent = 0;
472 }
473
474 /* we got a new ack, so re-start RTO timer */
475 ccid2_hc_tx_kill_rto_timer(sk);
476 ccid2_start_rto_timer(sk);
477}
478
479static void ccid2_hc_tx_dec_pipe(struct sock *sk)
480{
481 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
482
483 hctx->ccid2hctx_pipe--;
484 BUG_ON(hctx->ccid2hctx_pipe < 0);
485
486 if (hctx->ccid2hctx_pipe == 0)
487 ccid2_hc_tx_kill_rto_timer(sk);
488}
489
490static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
491{
492 struct dccp_sock *dp = dccp_sk(sk);
493 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
494 u64 ackno, seqno;
495 struct ccid2_seq *seqp;
496 unsigned char *vector;
497 unsigned char veclen;
498 int offset = 0;
499 int done = 0;
500 int loss = 0;
501 unsigned int maxincr = 0;
502
503 ccid2_hc_tx_check_sanity(hctx);
504 /* check reverse path congestion */
505 seqno = DCCP_SKB_CB(skb)->dccpd_seq;
506
507 /* XXX this whole "algorithm" is broken. Need to fix it to keep track
508 * of the seqnos of the dupacks so that rpseq and rpdupack are correct
509 * -sorbo.
510 */
511 /* need to bootstrap */
512 if (hctx->ccid2hctx_rpdupack == -1) {
513 hctx->ccid2hctx_rpdupack = 0;
514 hctx->ccid2hctx_rpseq = seqno;
515 } else {
516 /* check if packet is consecutive */
517 if ((hctx->ccid2hctx_rpseq + 1) == seqno)
518 hctx->ccid2hctx_rpseq++;
519 /* it's a later packet */
520 else if (after48(seqno, hctx->ccid2hctx_rpseq)) {
521 hctx->ccid2hctx_rpdupack++;
522
523 /* check if we got enough dupacks */
524 if (hctx->ccid2hctx_rpdupack >=
525 hctx->ccid2hctx_numdupack) {
526 hctx->ccid2hctx_rpdupack = -1; /* XXX lame */
527 hctx->ccid2hctx_rpseq = 0;
528
529 ccid2_change_l_ack_ratio(sk, dp->dccps_l_ack_ratio << 1);
530 }
531 }
532 }
533
534 /* check forward path congestion */
535 /* still didn't send out new data packets */
536 if (hctx->ccid2hctx_seqh == hctx->ccid2hctx_seqt)
537 return;
538
539 switch (DCCP_SKB_CB(skb)->dccpd_type) {
540 case DCCP_PKT_ACK:
541 case DCCP_PKT_DATAACK:
542 break;
543 default:
544 return;
545 }
546
547 ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq;
548 seqp = hctx->ccid2hctx_seqh->ccid2s_prev;
549
550 /* If in slow-start, cwnd can increase at most Ack Ratio / 2 packets for
551 * this single ack. I round up.
552 * -sorbo.
553 */
554 maxincr = dp->dccps_l_ack_ratio >> 1;
555 maxincr++;
556
557 /* go through all ack vectors */
558 while ((offset = ccid2_ackvector(sk, skb, offset,
559 &vector, &veclen)) != -1) {
560 /* go through this ack vector */
561 while (veclen--) {
562 const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK;
563 u64 ackno_end_rl;
564
565 dccp_set_seqno(&ackno_end_rl, ackno - rl);
566 ccid2_pr_debug("ackvec start:%llu end:%llu\n", ackno,
567 ackno_end_rl);
568 /* if the seqno we are analyzing is larger than the
569 * current ackno, then move towards the tail of our
570 * seqnos.
571 */
572 while (after48(seqp->ccid2s_seq, ackno)) {
573 if (seqp == hctx->ccid2hctx_seqt) {
574 done = 1;
575 break;
576 }
577 seqp = seqp->ccid2s_prev;
578 }
579 if (done)
580 break;
581
582 /* check all seqnos in the range of the vector
583 * run length
584 */
585 while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) {
586 const u8 state = (*vector &
587 DCCP_ACKVEC_STATE_MASK) >> 6;
588
589 /* new packet received or marked */
590 if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED &&
591 !seqp->ccid2s_acked) {
592 if (state ==
593 DCCP_ACKVEC_STATE_ECN_MARKED) {
594 loss = 1;
595 } else
596 ccid2_new_ack(sk, seqp,
597 &maxincr);
598
599 seqp->ccid2s_acked = 1;
600 ccid2_pr_debug("Got ack for %llu\n",
601 seqp->ccid2s_seq);
602 ccid2_hc_tx_dec_pipe(sk);
603 }
604 if (seqp == hctx->ccid2hctx_seqt) {
605 done = 1;
606 break;
607 }
608 seqp = seqp->ccid2s_next;
609 }
610 if (done)
611 break;
612
613
614 dccp_set_seqno(&ackno, ackno_end_rl - 1);
615 vector++;
616 }
617 if (done)
618 break;
619 }
620
621 /* The state about what is acked should be correct now
622 * Check for NUMDUPACK
623 */
624 seqp = hctx->ccid2hctx_seqh->ccid2s_prev;
625 done = 0;
626 while (1) {
627 if (seqp->ccid2s_acked) {
628 done++;
629 if (done == hctx->ccid2hctx_numdupack)
630 break;
631 }
632 if (seqp == hctx->ccid2hctx_seqt)
633 break;
634 seqp = seqp->ccid2s_prev;
635 }
636
637 /* If there are at least 3 acknowledgements, anything unacknowledged
638 * below the last sequence number is considered lost
639 */
640 if (done == hctx->ccid2hctx_numdupack) {
641 struct ccid2_seq *last_acked = seqp;
642
643 /* check for lost packets */
644 while (1) {
645 if (!seqp->ccid2s_acked) {
646 loss = 1;
647 ccid2_hc_tx_dec_pipe(sk);
648 }
649 if (seqp == hctx->ccid2hctx_seqt)
650 break;
651 seqp = seqp->ccid2s_prev;
652 }
653
654 hctx->ccid2hctx_seqt = last_acked;
655 }
656
657 /* trim acked packets in tail */
658 while (hctx->ccid2hctx_seqt != hctx->ccid2hctx_seqh) {
659 if (!hctx->ccid2hctx_seqt->ccid2s_acked)
660 break;
661
662 hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqt->ccid2s_next;
663 }
664
665 if (loss) {
666 /* XXX do bit shifts guarantee a 0 as the new bit? */
667 ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd >> 1);
668 hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd;
669 if (hctx->ccid2hctx_ssthresh < 2)
670 hctx->ccid2hctx_ssthresh = 2;
671 }
672
673 ccid2_hc_tx_check_sanity(hctx);
674}
675
676static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
677{
678 struct ccid2_hc_tx_sock *hctx = ccid_priv(ccid);
679 int seqcount = ccid2_seq_len;
680 int i;
681
682 /* XXX init variables with proper values */
683 hctx->ccid2hctx_cwnd = 1;
684 hctx->ccid2hctx_ssthresh = 10;
685 hctx->ccid2hctx_numdupack = 3;
686
687 /* XXX init ~ to window size... */
688 hctx->ccid2hctx_seqbuf = kmalloc(sizeof(*hctx->ccid2hctx_seqbuf) *
689 seqcount, gfp_any());
690 if (hctx->ccid2hctx_seqbuf == NULL)
691 return -ENOMEM;
692
693 for (i = 0; i < (seqcount - 1); i++) {
694 hctx->ccid2hctx_seqbuf[i].ccid2s_next =
695 &hctx->ccid2hctx_seqbuf[i + 1];
696 hctx->ccid2hctx_seqbuf[i + 1].ccid2s_prev =
697 &hctx->ccid2hctx_seqbuf[i];
698 }
699 hctx->ccid2hctx_seqbuf[seqcount - 1].ccid2s_next =
700 hctx->ccid2hctx_seqbuf;
701 hctx->ccid2hctx_seqbuf->ccid2s_prev =
702 &hctx->ccid2hctx_seqbuf[seqcount - 1];
703
704 hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqbuf;
705 hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqh;
706 hctx->ccid2hctx_sent = 0;
707 hctx->ccid2hctx_rto = 3 * HZ;
708 hctx->ccid2hctx_srtt = -1;
709 hctx->ccid2hctx_rttvar = -1;
710 hctx->ccid2hctx_lastrtt = 0;
711 hctx->ccid2hctx_rpdupack = -1;
712
713 hctx->ccid2hctx_rtotimer.function = &ccid2_hc_tx_rto_expire;
714 hctx->ccid2hctx_rtotimer.data = (unsigned long)sk;
715 init_timer(&hctx->ccid2hctx_rtotimer);
716
717 ccid2_hc_tx_check_sanity(hctx);
718 return 0;
719}
720
721static void ccid2_hc_tx_exit(struct sock *sk)
722{
723 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
724
725 ccid2_hc_tx_kill_rto_timer(sk);
726 kfree(hctx->ccid2hctx_seqbuf);
727 hctx->ccid2hctx_seqbuf = NULL;
728}
729
730static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
731{
732 const struct dccp_sock *dp = dccp_sk(sk);
733 struct ccid2_hc_rx_sock *hcrx = ccid2_hc_rx_sk(sk);
734
735 switch (DCCP_SKB_CB(skb)->dccpd_type) {
736 case DCCP_PKT_DATA:
737 case DCCP_PKT_DATAACK:
738 hcrx->ccid2hcrx_data++;
739 if (hcrx->ccid2hcrx_data >= dp->dccps_r_ack_ratio) {
740 dccp_send_ack(sk);
741 hcrx->ccid2hcrx_data = 0;
742 }
743 break;
744 }
745}
746
747static struct ccid_operations ccid2 = {
748 .ccid_id = 2,
749 .ccid_name = "ccid2",
750 .ccid_owner = THIS_MODULE,
751 .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock),
752 .ccid_hc_tx_init = ccid2_hc_tx_init,
753 .ccid_hc_tx_exit = ccid2_hc_tx_exit,
754 .ccid_hc_tx_send_packet = ccid2_hc_tx_send_packet,
755 .ccid_hc_tx_packet_sent = ccid2_hc_tx_packet_sent,
756 .ccid_hc_tx_packet_recv = ccid2_hc_tx_packet_recv,
757 .ccid_hc_rx_obj_size = sizeof(struct ccid2_hc_rx_sock),
758 .ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv,
759};
760
761module_param(ccid2_debug, int, 0444);
762MODULE_PARM_DESC(ccid2_debug, "Enable debug messages");
763
764static __init int ccid2_module_init(void)
765{
766 return ccid_register(&ccid2);
767}
768module_init(ccid2_module_init);
769
770static __exit void ccid2_module_exit(void)
771{
772 ccid_unregister(&ccid2);
773}
774module_exit(ccid2_module_exit);
775
776MODULE_AUTHOR("Andrea Bittau <a.bittau@cs.ucl.ac.uk>");
777MODULE_DESCRIPTION("DCCP TCP-Like (CCID2) CCID");
778MODULE_LICENSE("GPL");
779MODULE_ALIAS("net-dccp-ccid-2");
diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h
new file mode 100644
index 000000000000..451a87464fa5
--- /dev/null
+++ b/net/dccp/ccids/ccid2.h
@@ -0,0 +1,85 @@
1/*
2 * net/dccp/ccids/ccid2.h
3 *
4 * Copyright (c) 2005 Andrea Bittau <a.bittau@cs.ucl.ac.uk>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20#ifndef _DCCP_CCID2_H_
21#define _DCCP_CCID2_H_
22
23#include <linux/dccp.h>
24#include <linux/timer.h>
25#include <linux/types.h>
26#include "../ccid.h"
27
28struct sock;
29
30struct ccid2_seq {
31 u64 ccid2s_seq;
32 unsigned long ccid2s_sent;
33 int ccid2s_acked;
34 struct ccid2_seq *ccid2s_prev;
35 struct ccid2_seq *ccid2s_next;
36};
37
38/** struct ccid2_hc_tx_sock - CCID2 TX half connection
39 *
40 * @ccid2hctx_ssacks - ACKs recv in slow start
41 * @ccid2hctx_acks - ACKS recv in AI phase
42 * @ccid2hctx_sent - packets sent in this window
43 * @ccid2hctx_lastrtt -time RTT was last measured
44 * @ccid2hctx_arsent - packets sent [ack ratio]
45 * @ccid2hctx_ackloss - ack was lost in this win
46 * @ccid2hctx_rpseq - last consecutive seqno
47 * @ccid2hctx_rpdupack - dupacks since rpseq
48*/
49struct ccid2_hc_tx_sock {
50 int ccid2hctx_cwnd;
51 int ccid2hctx_ssacks;
52 int ccid2hctx_acks;
53 int ccid2hctx_ssthresh;
54 int ccid2hctx_pipe;
55 int ccid2hctx_numdupack;
56 struct ccid2_seq *ccid2hctx_seqbuf;
57 struct ccid2_seq *ccid2hctx_seqh;
58 struct ccid2_seq *ccid2hctx_seqt;
59 long ccid2hctx_rto;
60 long ccid2hctx_srtt;
61 long ccid2hctx_rttvar;
62 int ccid2hctx_sent;
63 unsigned long ccid2hctx_lastrtt;
64 struct timer_list ccid2hctx_rtotimer;
65 unsigned long ccid2hctx_arsent;
66 int ccid2hctx_ackloss;
67 u64 ccid2hctx_rpseq;
68 int ccid2hctx_rpdupack;
69 int ccid2hctx_sendwait;
70};
71
72struct ccid2_hc_rx_sock {
73 int ccid2hcrx_data;
74};
75
76static inline struct ccid2_hc_tx_sock *ccid2_hc_tx_sk(const struct sock *sk)
77{
78 return ccid_priv(dccp_sk(sk)->dccps_hc_tx_ccid);
79}
80
81static inline struct ccid2_hc_rx_sock *ccid2_hc_rx_sk(const struct sock *sk)
82{
83 return ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid);
84}
85#endif /* _DCCP_CCID2_H_ */
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 35d1d347541c..b4a51d0355a5 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -46,7 +46,7 @@
46 * Reason for maths here is to avoid 32 bit overflow when a is big. 46 * Reason for maths here is to avoid 32 bit overflow when a is big.
47 * With this we get close to the limit. 47 * With this we get close to the limit.
48 */ 48 */
49static inline u32 usecs_div(const u32 a, const u32 b) 49static u32 usecs_div(const u32 a, const u32 b)
50{ 50{
51 const u32 div = a < (UINT_MAX / (USEC_PER_SEC / 10)) ? 10 : 51 const u32 div = a < (UINT_MAX / (USEC_PER_SEC / 10)) ? 10 :
52 a < (UINT_MAX / (USEC_PER_SEC / 50)) ? 50 : 52 a < (UINT_MAX / (USEC_PER_SEC / 50)) ? 50 :
@@ -76,15 +76,6 @@ static struct dccp_tx_hist *ccid3_tx_hist;
76static struct dccp_rx_hist *ccid3_rx_hist; 76static struct dccp_rx_hist *ccid3_rx_hist;
77static struct dccp_li_hist *ccid3_li_hist; 77static struct dccp_li_hist *ccid3_li_hist;
78 78
79static int ccid3_init(struct sock *sk)
80{
81 return 0;
82}
83
84static void ccid3_exit(struct sock *sk)
85{
86}
87
88/* TFRC sender states */ 79/* TFRC sender states */
89enum ccid3_hc_tx_states { 80enum ccid3_hc_tx_states {
90 TFRC_SSTATE_NO_SENT = 1, 81 TFRC_SSTATE_NO_SENT = 1,
@@ -107,8 +98,8 @@ static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state)
107} 98}
108#endif 99#endif
109 100
110static inline void ccid3_hc_tx_set_state(struct sock *sk, 101static void ccid3_hc_tx_set_state(struct sock *sk,
111 enum ccid3_hc_tx_states state) 102 enum ccid3_hc_tx_states state)
112{ 103{
113 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); 104 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
114 enum ccid3_hc_tx_states oldstate = hctx->ccid3hctx_state; 105 enum ccid3_hc_tx_states oldstate = hctx->ccid3hctx_state;
@@ -316,8 +307,6 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
316 307
317 switch (hctx->ccid3hctx_state) { 308 switch (hctx->ccid3hctx_state) {
318 case TFRC_SSTATE_NO_SENT: 309 case TFRC_SSTATE_NO_SENT:
319 hctx->ccid3hctx_no_feedback_timer.function = ccid3_hc_tx_no_feedback_timer;
320 hctx->ccid3hctx_no_feedback_timer.data = (unsigned long)sk;
321 sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, 310 sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
322 jiffies + usecs_to_jiffies(TFRC_INITIAL_TIMEOUT)); 311 jiffies + usecs_to_jiffies(TFRC_INITIAL_TIMEOUT));
323 hctx->ccid3hctx_last_win_count = 0; 312 hctx->ccid3hctx_last_win_count = 0;
@@ -585,16 +574,15 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
585 } 574 }
586} 575}
587 576
588static void ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb) 577static int ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb)
589{ 578{
590 const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); 579 const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
591 580
592 BUG_ON(hctx == NULL); 581 BUG_ON(hctx == NULL);
593 582
594 if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)) 583 if (sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)
595 return; 584 DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;
596 585 return 0;
597 DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;
598} 586}
599 587
600static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, 588static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
@@ -626,7 +614,7 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
626 __FUNCTION__, dccp_role(sk), sk); 614 __FUNCTION__, dccp_role(sk), sk);
627 rc = -EINVAL; 615 rc = -EINVAL;
628 } else { 616 } else {
629 opt_recv->ccid3or_loss_event_rate = ntohl(*(u32 *)value); 617 opt_recv->ccid3or_loss_event_rate = ntohl(*(__be32 *)value);
630 ccid3_pr_debug("%s, sk=%p, LOSS_EVENT_RATE=%u\n", 618 ccid3_pr_debug("%s, sk=%p, LOSS_EVENT_RATE=%u\n",
631 dccp_role(sk), sk, 619 dccp_role(sk), sk,
632 opt_recv->ccid3or_loss_event_rate); 620 opt_recv->ccid3or_loss_event_rate);
@@ -647,7 +635,7 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
647 __FUNCTION__, dccp_role(sk), sk); 635 __FUNCTION__, dccp_role(sk), sk);
648 rc = -EINVAL; 636 rc = -EINVAL;
649 } else { 637 } else {
650 opt_recv->ccid3or_receive_rate = ntohl(*(u32 *)value); 638 opt_recv->ccid3or_receive_rate = ntohl(*(__be32 *)value);
651 ccid3_pr_debug("%s, sk=%p, RECEIVE_RATE=%u\n", 639 ccid3_pr_debug("%s, sk=%p, RECEIVE_RATE=%u\n",
652 dccp_role(sk), sk, 640 dccp_role(sk), sk,
653 opt_recv->ccid3or_receive_rate); 641 opt_recv->ccid3or_receive_rate);
@@ -658,17 +646,10 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
658 return rc; 646 return rc;
659} 647}
660 648
661static int ccid3_hc_tx_init(struct sock *sk) 649static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
662{ 650{
663 struct dccp_sock *dp = dccp_sk(sk); 651 struct dccp_sock *dp = dccp_sk(sk);
664 struct ccid3_hc_tx_sock *hctx; 652 struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid);
665
666 dp->dccps_hc_tx_ccid_private = kmalloc(sizeof(*hctx), gfp_any());
667 if (dp->dccps_hc_tx_ccid_private == NULL)
668 return -ENOMEM;
669
670 hctx = ccid3_hc_tx_sk(sk);
671 memset(hctx, 0, sizeof(*hctx));
672 653
673 if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE && 654 if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
674 dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE) 655 dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)
@@ -681,6 +662,9 @@ static int ccid3_hc_tx_init(struct sock *sk)
681 hctx->ccid3hctx_t_rto = USEC_PER_SEC; 662 hctx->ccid3hctx_t_rto = USEC_PER_SEC;
682 hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT; 663 hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;
683 INIT_LIST_HEAD(&hctx->ccid3hctx_hist); 664 INIT_LIST_HEAD(&hctx->ccid3hctx_hist);
665
666 hctx->ccid3hctx_no_feedback_timer.function = ccid3_hc_tx_no_feedback_timer;
667 hctx->ccid3hctx_no_feedback_timer.data = (unsigned long)sk;
684 init_timer(&hctx->ccid3hctx_no_feedback_timer); 668 init_timer(&hctx->ccid3hctx_no_feedback_timer);
685 669
686 return 0; 670 return 0;
@@ -688,7 +672,6 @@ static int ccid3_hc_tx_init(struct sock *sk)
688 672
689static void ccid3_hc_tx_exit(struct sock *sk) 673static void ccid3_hc_tx_exit(struct sock *sk)
690{ 674{
691 struct dccp_sock *dp = dccp_sk(sk);
692 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); 675 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
693 676
694 BUG_ON(hctx == NULL); 677 BUG_ON(hctx == NULL);
@@ -698,9 +681,6 @@ static void ccid3_hc_tx_exit(struct sock *sk)
698 681
699 /* Empty packet history */ 682 /* Empty packet history */
700 dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist); 683 dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist);
701
702 kfree(dp->dccps_hc_tx_ccid_private);
703 dp->dccps_hc_tx_ccid_private = NULL;
704} 684}
705 685
706/* 686/*
@@ -727,8 +707,8 @@ static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state)
727} 707}
728#endif 708#endif
729 709
730static inline void ccid3_hc_rx_set_state(struct sock *sk, 710static void ccid3_hc_rx_set_state(struct sock *sk,
731 enum ccid3_hc_rx_states state) 711 enum ccid3_hc_rx_states state)
732{ 712{
733 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); 713 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
734 enum ccid3_hc_rx_states oldstate = hcrx->ccid3hcrx_state; 714 enum ccid3_hc_rx_states oldstate = hcrx->ccid3hcrx_state;
@@ -793,31 +773,35 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
793 dccp_send_ack(sk); 773 dccp_send_ack(sk);
794} 774}
795 775
796static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) 776static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
797{ 777{
798 const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); 778 const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
799 u32 x_recv, pinv; 779 __be32 x_recv, pinv;
800 780
801 BUG_ON(hcrx == NULL); 781 BUG_ON(hcrx == NULL);
802 782
803 if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)) 783 if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))
804 return; 784 return 0;
805 785
806 DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_last_counter; 786 DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_last_counter;
807 787
808 if (dccp_packet_without_ack(skb)) 788 if (dccp_packet_without_ack(skb))
809 return; 789 return 0;
810 790
811 if (hcrx->ccid3hcrx_elapsed_time != 0)
812 dccp_insert_option_elapsed_time(sk, skb,
813 hcrx->ccid3hcrx_elapsed_time);
814 dccp_insert_option_timestamp(sk, skb);
815 x_recv = htonl(hcrx->ccid3hcrx_x_recv); 791 x_recv = htonl(hcrx->ccid3hcrx_x_recv);
816 pinv = htonl(hcrx->ccid3hcrx_pinv); 792 pinv = htonl(hcrx->ccid3hcrx_pinv);
817 dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE, 793
818 &pinv, sizeof(pinv)); 794 if ((hcrx->ccid3hcrx_elapsed_time != 0 &&
819 dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE, 795 dccp_insert_option_elapsed_time(sk, skb,
820 &x_recv, sizeof(x_recv)); 796 hcrx->ccid3hcrx_elapsed_time)) ||
797 dccp_insert_option_timestamp(sk, skb) ||
798 dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE,
799 &pinv, sizeof(pinv)) ||
800 dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE,
801 &x_recv, sizeof(x_recv)))
802 return -1;
803
804 return 0;
821} 805}
822 806
823/* calculate first loss interval 807/* calculate first loss interval
@@ -1047,20 +1031,13 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
1047 } 1031 }
1048} 1032}
1049 1033
1050static int ccid3_hc_rx_init(struct sock *sk) 1034static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
1051{ 1035{
1052 struct dccp_sock *dp = dccp_sk(sk); 1036 struct dccp_sock *dp = dccp_sk(sk);
1053 struct ccid3_hc_rx_sock *hcrx; 1037 struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid);
1054 1038
1055 ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); 1039 ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
1056 1040
1057 dp->dccps_hc_rx_ccid_private = kmalloc(sizeof(*hcrx), gfp_any());
1058 if (dp->dccps_hc_rx_ccid_private == NULL)
1059 return -ENOMEM;
1060
1061 hcrx = ccid3_hc_rx_sk(sk);
1062 memset(hcrx, 0, sizeof(*hcrx));
1063
1064 if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE && 1041 if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
1065 dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE) 1042 dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)
1066 hcrx->ccid3hcrx_s = dp->dccps_packet_size; 1043 hcrx->ccid3hcrx_s = dp->dccps_packet_size;
@@ -1079,7 +1056,6 @@ static int ccid3_hc_rx_init(struct sock *sk)
1079static void ccid3_hc_rx_exit(struct sock *sk) 1056static void ccid3_hc_rx_exit(struct sock *sk)
1080{ 1057{
1081 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); 1058 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
1082 struct dccp_sock *dp = dccp_sk(sk);
1083 1059
1084 BUG_ON(hcrx == NULL); 1060 BUG_ON(hcrx == NULL);
1085 1061
@@ -1090,9 +1066,6 @@ static void ccid3_hc_rx_exit(struct sock *sk)
1090 1066
1091 /* Empty loss interval history */ 1067 /* Empty loss interval history */
1092 dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist); 1068 dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist);
1093
1094 kfree(dp->dccps_hc_rx_ccid_private);
1095 dp->dccps_hc_rx_ccid_private = NULL;
1096} 1069}
1097 1070
1098static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info) 1071static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
@@ -1178,12 +1151,11 @@ static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len,
1178 return 0; 1151 return 0;
1179} 1152}
1180 1153
1181static struct ccid ccid3 = { 1154static struct ccid_operations ccid3 = {
1182 .ccid_id = 3, 1155 .ccid_id = 3,
1183 .ccid_name = "ccid3", 1156 .ccid_name = "ccid3",
1184 .ccid_owner = THIS_MODULE, 1157 .ccid_owner = THIS_MODULE,
1185 .ccid_init = ccid3_init, 1158 .ccid_hc_tx_obj_size = sizeof(struct ccid3_hc_tx_sock),
1186 .ccid_exit = ccid3_exit,
1187 .ccid_hc_tx_init = ccid3_hc_tx_init, 1159 .ccid_hc_tx_init = ccid3_hc_tx_init,
1188 .ccid_hc_tx_exit = ccid3_hc_tx_exit, 1160 .ccid_hc_tx_exit = ccid3_hc_tx_exit,
1189 .ccid_hc_tx_send_packet = ccid3_hc_tx_send_packet, 1161 .ccid_hc_tx_send_packet = ccid3_hc_tx_send_packet,
@@ -1191,6 +1163,7 @@ static struct ccid ccid3 = {
1191 .ccid_hc_tx_packet_recv = ccid3_hc_tx_packet_recv, 1163 .ccid_hc_tx_packet_recv = ccid3_hc_tx_packet_recv,
1192 .ccid_hc_tx_insert_options = ccid3_hc_tx_insert_options, 1164 .ccid_hc_tx_insert_options = ccid3_hc_tx_insert_options,
1193 .ccid_hc_tx_parse_options = ccid3_hc_tx_parse_options, 1165 .ccid_hc_tx_parse_options = ccid3_hc_tx_parse_options,
1166 .ccid_hc_rx_obj_size = sizeof(struct ccid3_hc_rx_sock),
1194 .ccid_hc_rx_init = ccid3_hc_rx_init, 1167 .ccid_hc_rx_init = ccid3_hc_rx_init,
1195 .ccid_hc_rx_exit = ccid3_hc_rx_exit, 1168 .ccid_hc_rx_exit = ccid3_hc_rx_exit,
1196 .ccid_hc_rx_insert_options = ccid3_hc_rx_insert_options, 1169 .ccid_hc_rx_insert_options = ccid3_hc_rx_insert_options,
@@ -1241,15 +1214,6 @@ module_init(ccid3_module_init);
1241 1214
1242static __exit void ccid3_module_exit(void) 1215static __exit void ccid3_module_exit(void)
1243{ 1216{
1244#ifdef CONFIG_IP_DCCP_UNLOAD_HACK
1245 /*
1246 * Hack to use while developing, so that we get rid of the control
1247 * sock, that is what keeps a refcount on dccp.ko -acme
1248 */
1249 extern void dccp_ctl_sock_exit(void);
1250
1251 dccp_ctl_sock_exit();
1252#endif
1253 ccid_unregister(&ccid3); 1217 ccid_unregister(&ccid3);
1254 1218
1255 if (ccid3_tx_hist != NULL) { 1219 if (ccid3_tx_hist != NULL) {
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index 0bde4583d091..f18b96d4e5a2 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -41,6 +41,7 @@
41#include <linux/time.h> 41#include <linux/time.h>
42#include <linux/types.h> 42#include <linux/types.h>
43#include <linux/tfrc.h> 43#include <linux/tfrc.h>
44#include "../ccid.h"
44 45
45#define TFRC_MIN_PACKET_SIZE 16 46#define TFRC_MIN_PACKET_SIZE 16
46#define TFRC_STD_PACKET_SIZE 256 47#define TFRC_STD_PACKET_SIZE 256
@@ -135,12 +136,12 @@ struct ccid3_hc_rx_sock {
135 136
136static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk) 137static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
137{ 138{
138 return dccp_sk(sk)->dccps_hc_tx_ccid_private; 139 return ccid_priv(dccp_sk(sk)->dccps_hc_tx_ccid);
139} 140}
140 141
141static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk) 142static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk)
142{ 143{
143 return dccp_sk(sk)->dccps_hc_rx_ccid_private; 144 return ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid);
144} 145}
145 146
146#endif /* _DCCP_CCID3_H_ */ 147#endif /* _DCCP_CCID3_H_ */
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 93f26dd6e6cb..1fe509148689 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -59,8 +59,6 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo);
59 59
60#define DCCP_RTO_MAX ((unsigned)(120 * HZ)) /* FIXME: using TCP value */ 60#define DCCP_RTO_MAX ((unsigned)(120 * HZ)) /* FIXME: using TCP value */
61 61
62extern struct proto dccp_prot;
63
64/* is seq1 < seq2 ? */ 62/* is seq1 < seq2 ? */
65static inline int before48(const u64 seq1, const u64 seq2) 63static inline int before48(const u64 seq1, const u64 seq2)
66{ 64{
@@ -120,7 +118,6 @@ DECLARE_SNMP_STAT(struct dccp_mib, dccp_statistics);
120 118
121extern int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb); 119extern int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb);
122 120
123extern int dccp_send_response(struct sock *sk);
124extern void dccp_send_ack(struct sock *sk); 121extern void dccp_send_ack(struct sock *sk);
125extern void dccp_send_delayed_ack(struct sock *sk); 122extern void dccp_send_delayed_ack(struct sock *sk);
126extern void dccp_send_sync(struct sock *sk, const u64 seq, 123extern void dccp_send_sync(struct sock *sk, const u64 seq,
@@ -140,53 +137,8 @@ extern unsigned int dccp_sync_mss(struct sock *sk, u32 pmtu);
140extern const char *dccp_packet_name(const int type); 137extern const char *dccp_packet_name(const int type);
141extern const char *dccp_state_name(const int state); 138extern const char *dccp_state_name(const int state);
142 139
143static inline void dccp_set_state(struct sock *sk, const int state) 140extern void dccp_set_state(struct sock *sk, const int state);
144{ 141extern void dccp_done(struct sock *sk);
145 const int oldstate = sk->sk_state;
146
147 dccp_pr_debug("%s(%p) %-10.10s -> %s\n",
148 dccp_role(sk), sk,
149 dccp_state_name(oldstate), dccp_state_name(state));
150 WARN_ON(state == oldstate);
151
152 switch (state) {
153 case DCCP_OPEN:
154 if (oldstate != DCCP_OPEN)
155 DCCP_INC_STATS(DCCP_MIB_CURRESTAB);
156 break;
157
158 case DCCP_CLOSED:
159 if (oldstate == DCCP_CLOSING || oldstate == DCCP_OPEN)
160 DCCP_INC_STATS(DCCP_MIB_ESTABRESETS);
161
162 sk->sk_prot->unhash(sk);
163 if (inet_csk(sk)->icsk_bind_hash != NULL &&
164 !(sk->sk_userlocks & SOCK_BINDPORT_LOCK))
165 inet_put_port(&dccp_hashinfo, sk);
166 /* fall through */
167 default:
168 if (oldstate == DCCP_OPEN)
169 DCCP_DEC_STATS(DCCP_MIB_CURRESTAB);
170 }
171
172 /* Change state AFTER socket is unhashed to avoid closed
173 * socket sitting in hash tables.
174 */
175 sk->sk_state = state;
176}
177
178static inline void dccp_done(struct sock *sk)
179{
180 dccp_set_state(sk, DCCP_CLOSED);
181 dccp_clear_xmit_timers(sk);
182
183 sk->sk_shutdown = SHUTDOWN_MASK;
184
185 if (!sock_flag(sk, SOCK_DEAD))
186 sk->sk_state_change(sk);
187 else
188 inet_csk_destroy_sock(sk);
189}
190 142
191static inline void dccp_openreq_init(struct request_sock *req, 143static inline void dccp_openreq_init(struct request_sock *req,
192 struct dccp_sock *dp, 144 struct dccp_sock *dp,
@@ -209,10 +161,6 @@ extern struct sock *dccp_create_openreq_child(struct sock *sk,
209 161
210extern int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb); 162extern int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb);
211 163
212extern void dccp_v4_err(struct sk_buff *skb, u32);
213
214extern int dccp_v4_rcv(struct sk_buff *skb);
215
216extern struct sock *dccp_v4_request_recv_sock(struct sock *sk, 164extern struct sock *dccp_v4_request_recv_sock(struct sock *sk,
217 struct sk_buff *skb, 165 struct sk_buff *skb,
218 struct request_sock *req, 166 struct request_sock *req,
@@ -228,24 +176,30 @@ extern int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
228extern int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, 176extern int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
229 const struct dccp_hdr *dh, const unsigned len); 177 const struct dccp_hdr *dh, const unsigned len);
230 178
231extern int dccp_v4_init_sock(struct sock *sk); 179extern int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized);
232extern int dccp_v4_destroy_sock(struct sock *sk); 180extern int dccp_destroy_sock(struct sock *sk);
233 181
234extern void dccp_close(struct sock *sk, long timeout); 182extern void dccp_close(struct sock *sk, long timeout);
235extern struct sk_buff *dccp_make_response(struct sock *sk, 183extern struct sk_buff *dccp_make_response(struct sock *sk,
236 struct dst_entry *dst, 184 struct dst_entry *dst,
237 struct request_sock *req); 185 struct request_sock *req);
238extern struct sk_buff *dccp_make_reset(struct sock *sk,
239 struct dst_entry *dst,
240 enum dccp_reset_codes code);
241 186
242extern int dccp_connect(struct sock *sk); 187extern int dccp_connect(struct sock *sk);
243extern int dccp_disconnect(struct sock *sk, int flags); 188extern int dccp_disconnect(struct sock *sk, int flags);
189extern void dccp_hash(struct sock *sk);
244extern void dccp_unhash(struct sock *sk); 190extern void dccp_unhash(struct sock *sk);
245extern int dccp_getsockopt(struct sock *sk, int level, int optname, 191extern int dccp_getsockopt(struct sock *sk, int level, int optname,
246 char __user *optval, int __user *optlen); 192 char __user *optval, int __user *optlen);
247extern int dccp_setsockopt(struct sock *sk, int level, int optname, 193extern int dccp_setsockopt(struct sock *sk, int level, int optname,
248 char __user *optval, int optlen); 194 char __user *optval, int optlen);
195#ifdef CONFIG_COMPAT
196extern int compat_dccp_getsockopt(struct sock *sk,
197 int level, int optname,
198 char __user *optval, int __user *optlen);
199extern int compat_dccp_setsockopt(struct sock *sk,
200 int level, int optname,
201 char __user *optval, int optlen);
202#endif
249extern int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg); 203extern int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg);
250extern int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, 204extern int dccp_sendmsg(struct kiocb *iocb, struct sock *sk,
251 struct msghdr *msg, size_t size); 205 struct msghdr *msg, size_t size);
@@ -262,15 +216,14 @@ extern int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
262 int addr_len); 216 int addr_len);
263 217
264extern int dccp_v4_checksum(const struct sk_buff *skb, 218extern int dccp_v4_checksum(const struct sk_buff *skb,
265 const u32 saddr, const u32 daddr); 219 const __be32 saddr, const __be32 daddr);
266 220
267extern int dccp_v4_send_reset(struct sock *sk, 221extern int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code);
268 enum dccp_reset_codes code);
269extern void dccp_send_close(struct sock *sk, const int active); 222extern void dccp_send_close(struct sock *sk, const int active);
270extern int dccp_invalid_packet(struct sk_buff *skb); 223extern int dccp_invalid_packet(struct sk_buff *skb);
271 224
272static inline int dccp_bad_service_code(const struct sock *sk, 225static inline int dccp_bad_service_code(const struct sock *sk,
273 const __u32 service) 226 const __be32 service)
274{ 227{
275 const struct dccp_sock *dp = dccp_sk(sk); 228 const struct dccp_sock *dp = dccp_sk(sk);
276 229
@@ -334,41 +287,29 @@ static inline void dccp_hdr_set_seq(struct dccp_hdr *dh, const u64 gss)
334{ 287{
335 struct dccp_hdr_ext *dhx = (struct dccp_hdr_ext *)((void *)dh + 288 struct dccp_hdr_ext *dhx = (struct dccp_hdr_ext *)((void *)dh +
336 sizeof(*dh)); 289 sizeof(*dh));
337 290 dh->dccph_seq2 = 0;
338#if defined(__LITTLE_ENDIAN_BITFIELD) 291 dh->dccph_seq = htons((gss >> 32) & 0xfffff);
339 dh->dccph_seq = htonl((gss >> 32)) >> 8;
340#elif defined(__BIG_ENDIAN_BITFIELD)
341 dh->dccph_seq = htonl((gss >> 32));
342#else
343#error "Adjust your <asm/byteorder.h> defines"
344#endif
345 dhx->dccph_seq_low = htonl(gss & 0xffffffff); 292 dhx->dccph_seq_low = htonl(gss & 0xffffffff);
346} 293}
347 294
348static inline void dccp_hdr_set_ack(struct dccp_hdr_ack_bits *dhack, 295static inline void dccp_hdr_set_ack(struct dccp_hdr_ack_bits *dhack,
349 const u64 gsr) 296 const u64 gsr)
350{ 297{
351#if defined(__LITTLE_ENDIAN_BITFIELD) 298 dhack->dccph_reserved1 = 0;
352 dhack->dccph_ack_nr_high = htonl((gsr >> 32)) >> 8; 299 dhack->dccph_ack_nr_high = htons(gsr >> 32);
353#elif defined(__BIG_ENDIAN_BITFIELD)
354 dhack->dccph_ack_nr_high = htonl((gsr >> 32));
355#else
356#error "Adjust your <asm/byteorder.h> defines"
357#endif
358 dhack->dccph_ack_nr_low = htonl(gsr & 0xffffffff); 300 dhack->dccph_ack_nr_low = htonl(gsr & 0xffffffff);
359} 301}
360 302
361static inline void dccp_update_gsr(struct sock *sk, u64 seq) 303static inline void dccp_update_gsr(struct sock *sk, u64 seq)
362{ 304{
363 struct dccp_sock *dp = dccp_sk(sk); 305 struct dccp_sock *dp = dccp_sk(sk);
306 const struct dccp_minisock *dmsk = dccp_msk(sk);
364 307
365 dp->dccps_gsr = seq; 308 dp->dccps_gsr = seq;
366 dccp_set_seqno(&dp->dccps_swl, 309 dccp_set_seqno(&dp->dccps_swl,
367 (dp->dccps_gsr + 1 - 310 dp->dccps_gsr + 1 - (dmsk->dccpms_sequence_window / 4));
368 (dp->dccps_options.dccpo_sequence_window / 4)));
369 dccp_set_seqno(&dp->dccps_swh, 311 dccp_set_seqno(&dp->dccps_swh,
370 (dp->dccps_gsr + 312 dp->dccps_gsr + (3 * dmsk->dccpms_sequence_window) / 4);
371 (3 * dp->dccps_options.dccpo_sequence_window) / 4));
372} 313}
373 314
374static inline void dccp_update_gss(struct sock *sk, u64 seq) 315static inline void dccp_update_gss(struct sock *sk, u64 seq)
@@ -378,7 +319,7 @@ static inline void dccp_update_gss(struct sock *sk, u64 seq)
378 dp->dccps_awh = dp->dccps_gss = seq; 319 dp->dccps_awh = dp->dccps_gss = seq;
379 dccp_set_seqno(&dp->dccps_awl, 320 dccp_set_seqno(&dp->dccps_awl,
380 (dp->dccps_gss - 321 (dp->dccps_gss -
381 dp->dccps_options.dccpo_sequence_window + 1)); 322 dccp_msk(sk)->dccpms_sequence_window + 1));
382} 323}
383 324
384static inline int dccp_ack_pending(const struct sock *sk) 325static inline int dccp_ack_pending(const struct sock *sk)
@@ -386,24 +327,22 @@ static inline int dccp_ack_pending(const struct sock *sk)
386 const struct dccp_sock *dp = dccp_sk(sk); 327 const struct dccp_sock *dp = dccp_sk(sk);
387 return dp->dccps_timestamp_echo != 0 || 328 return dp->dccps_timestamp_echo != 0 ||
388#ifdef CONFIG_IP_DCCP_ACKVEC 329#ifdef CONFIG_IP_DCCP_ACKVEC
389 (dp->dccps_options.dccpo_send_ack_vector && 330 (dccp_msk(sk)->dccpms_send_ack_vector &&
390 dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) || 331 dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) ||
391#endif 332#endif
392 inet_csk_ack_scheduled(sk); 333 inet_csk_ack_scheduled(sk);
393} 334}
394 335
395extern void dccp_insert_options(struct sock *sk, struct sk_buff *skb); 336extern int dccp_insert_options(struct sock *sk, struct sk_buff *skb);
396extern void dccp_insert_option_elapsed_time(struct sock *sk, 337extern int dccp_insert_option_elapsed_time(struct sock *sk,
397 struct sk_buff *skb, 338 struct sk_buff *skb,
398 u32 elapsed_time); 339 u32 elapsed_time);
399extern void dccp_insert_option_timestamp(struct sock *sk, 340extern int dccp_insert_option_timestamp(struct sock *sk,
400 struct sk_buff *skb); 341 struct sk_buff *skb);
401extern void dccp_insert_option(struct sock *sk, struct sk_buff *skb, 342extern int dccp_insert_option(struct sock *sk, struct sk_buff *skb,
402 unsigned char option, 343 unsigned char option,
403 const void *value, unsigned char len); 344 const void *value, unsigned char len);
404 345
405extern struct socket *dccp_ctl_socket;
406
407extern void dccp_timestamp(const struct sock *sk, struct timeval *tv); 346extern void dccp_timestamp(const struct sock *sk, struct timeval *tv);
408 347
409static inline suseconds_t timeval_usecs(const struct timeval *tv) 348static inline suseconds_t timeval_usecs(const struct timeval *tv)
@@ -444,4 +383,18 @@ static inline void timeval_sub_usecs(struct timeval *tv,
444 } 383 }
445} 384}
446 385
386#ifdef CONFIG_SYSCTL
387extern int dccp_sysctl_init(void);
388extern void dccp_sysctl_exit(void);
389#else
390static inline int dccp_sysctl_init(void)
391{
392 return 0;
393}
394
395static inline void dccp_sysctl_exit(void)
396{
397}
398#endif
399
447#endif /* _DCCP_H */ 400#endif /* _DCCP_H */
diff --git a/net/dccp/diag.c b/net/dccp/diag.c
index 3f78c00e3822..0f25dc395967 100644
--- a/net/dccp/diag.c
+++ b/net/dccp/diag.c
@@ -30,7 +30,7 @@ static void dccp_get_info(struct sock *sk, struct tcp_info *info)
30 info->tcpi_backoff = icsk->icsk_backoff; 30 info->tcpi_backoff = icsk->icsk_backoff;
31 info->tcpi_pmtu = icsk->icsk_pmtu_cookie; 31 info->tcpi_pmtu = icsk->icsk_pmtu_cookie;
32 32
33 if (dp->dccps_options.dccpo_send_ack_vector) 33 if (dccp_msk(sk)->dccpms_send_ack_vector)
34 info->tcpi_options |= TCPI_OPT_SACK; 34 info->tcpi_options |= TCPI_OPT_SACK;
35 35
36 ccid_hc_rx_get_info(dp->dccps_hc_rx_ccid, sk, info); 36 ccid_hc_rx_get_info(dp->dccps_hc_rx_ccid, sk, info);
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
new file mode 100644
index 000000000000..e3dd30d36c8a
--- /dev/null
+++ b/net/dccp/feat.c
@@ -0,0 +1,586 @@
1/*
2 * net/dccp/feat.c
3 *
4 * An implementation of the DCCP protocol
5 * Andrea Bittau <a.bittau@cs.ucl.ac.uk>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 */
12
13#include <linux/config.h>
14#include <linux/module.h>
15
16#include "dccp.h"
17#include "ccid.h"
18#include "feat.h"
19
20#define DCCP_FEAT_SP_NOAGREE (-123)
21
22int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature,
23 u8 *val, u8 len, gfp_t gfp)
24{
25 struct dccp_opt_pend *opt;
26
27 dccp_pr_debug("feat change type=%d feat=%d\n", type, feature);
28
29 /* XXX sanity check feat change request */
30
31 /* check if that feature is already being negotiated */
32 list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) {
33 /* ok we found a negotiation for this option already */
34 if (opt->dccpop_feat == feature && opt->dccpop_type == type) {
35 dccp_pr_debug("Replacing old\n");
36 /* replace */
37 BUG_ON(opt->dccpop_val == NULL);
38 kfree(opt->dccpop_val);
39 opt->dccpop_val = val;
40 opt->dccpop_len = len;
41 opt->dccpop_conf = 0;
42 return 0;
43 }
44 }
45
46 /* negotiation for a new feature */
47 opt = kmalloc(sizeof(*opt), gfp);
48 if (opt == NULL)
49 return -ENOMEM;
50
51 opt->dccpop_type = type;
52 opt->dccpop_feat = feature;
53 opt->dccpop_len = len;
54 opt->dccpop_val = val;
55 opt->dccpop_conf = 0;
56 opt->dccpop_sc = NULL;
57
58 BUG_ON(opt->dccpop_val == NULL);
59
60 list_add_tail(&opt->dccpop_node, &dmsk->dccpms_pending);
61 return 0;
62}
63
64EXPORT_SYMBOL_GPL(dccp_feat_change);
65
66static int dccp_feat_update_ccid(struct sock *sk, u8 type, u8 new_ccid_nr)
67{
68 struct dccp_sock *dp = dccp_sk(sk);
69 struct dccp_minisock *dmsk = dccp_msk(sk);
70 /* figure out if we are changing our CCID or the peer's */
71 const int rx = type == DCCPO_CHANGE_R;
72 const u8 ccid_nr = rx ? dmsk->dccpms_rx_ccid : dmsk->dccpms_tx_ccid;
73 struct ccid *new_ccid;
74
75 /* Check if nothing is being changed. */
76 if (ccid_nr == new_ccid_nr)
77 return 0;
78
79 new_ccid = ccid_new(new_ccid_nr, sk, rx, GFP_ATOMIC);
80 if (new_ccid == NULL)
81 return -ENOMEM;
82
83 if (rx) {
84 ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
85 dp->dccps_hc_rx_ccid = new_ccid;
86 dmsk->dccpms_rx_ccid = new_ccid_nr;
87 } else {
88 ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
89 dp->dccps_hc_tx_ccid = new_ccid;
90 dmsk->dccpms_tx_ccid = new_ccid_nr;
91 }
92
93 return 0;
94}
95
96/* XXX taking only u8 vals */
97static int dccp_feat_update(struct sock *sk, u8 type, u8 feat, u8 val)
98{
99 dccp_pr_debug("changing [%d] feat %d to %d\n", type, feat, val);
100
101 switch (feat) {
102 case DCCPF_CCID:
103 return dccp_feat_update_ccid(sk, type, val);
104 default:
105 dccp_pr_debug("IMPLEMENT changing [%d] feat %d to %d\n",
106 type, feat, val);
107 break;
108 }
109 return 0;
110}
111
112static int dccp_feat_reconcile(struct sock *sk, struct dccp_opt_pend *opt,
113 u8 *rpref, u8 rlen)
114{
115 struct dccp_sock *dp = dccp_sk(sk);
116 u8 *spref, slen, *res = NULL;
117 int i, j, rc, agree = 1;
118
119 BUG_ON(rpref == NULL);
120
121 /* check if we are the black sheep */
122 if (dp->dccps_role == DCCP_ROLE_CLIENT) {
123 spref = rpref;
124 slen = rlen;
125 rpref = opt->dccpop_val;
126 rlen = opt->dccpop_len;
127 } else {
128 spref = opt->dccpop_val;
129 slen = opt->dccpop_len;
130 }
131 /*
132 * Now we have server preference list in spref and client preference in
133 * rpref
134 */
135 BUG_ON(spref == NULL);
136 BUG_ON(rpref == NULL);
137
138 /* FIXME sanity check vals */
139
140 /* Are values in any order? XXX Lame "algorithm" here */
141 /* XXX assume values are 1 byte */
142 for (i = 0; i < slen; i++) {
143 for (j = 0; j < rlen; j++) {
144 if (spref[i] == rpref[j]) {
145 res = &spref[i];
146 break;
147 }
148 }
149 if (res)
150 break;
151 }
152
153 /* we didn't agree on anything */
154 if (res == NULL) {
155 /* confirm previous value */
156 switch (opt->dccpop_feat) {
157 case DCCPF_CCID:
158 /* XXX did i get this right? =P */
159 if (opt->dccpop_type == DCCPO_CHANGE_L)
160 res = &dccp_msk(sk)->dccpms_tx_ccid;
161 else
162 res = &dccp_msk(sk)->dccpms_rx_ccid;
163 break;
164
165 default:
166 WARN_ON(1); /* XXX implement res */
167 return -EFAULT;
168 }
169
170 dccp_pr_debug("Don't agree... reconfirming %d\n", *res);
171 agree = 0; /* this is used for mandatory options... */
172 }
173
174 /* need to put result and our preference list */
175 /* XXX assume 1 byte vals */
176 rlen = 1 + opt->dccpop_len;
177 rpref = kmalloc(rlen, GFP_ATOMIC);
178 if (rpref == NULL)
179 return -ENOMEM;
180
181 *rpref = *res;
182 memcpy(&rpref[1], opt->dccpop_val, opt->dccpop_len);
183
184 /* put it in the "confirm queue" */
185 if (opt->dccpop_sc == NULL) {
186 opt->dccpop_sc = kmalloc(sizeof(*opt->dccpop_sc), GFP_ATOMIC);
187 if (opt->dccpop_sc == NULL) {
188 kfree(rpref);
189 return -ENOMEM;
190 }
191 } else {
192 /* recycle the confirm slot */
193 BUG_ON(opt->dccpop_sc->dccpoc_val == NULL);
194 kfree(opt->dccpop_sc->dccpoc_val);
195 dccp_pr_debug("recycling confirm slot\n");
196 }
197 memset(opt->dccpop_sc, 0, sizeof(*opt->dccpop_sc));
198
199 opt->dccpop_sc->dccpoc_val = rpref;
200 opt->dccpop_sc->dccpoc_len = rlen;
201
202 /* update the option on our side [we are about to send the confirm] */
203 rc = dccp_feat_update(sk, opt->dccpop_type, opt->dccpop_feat, *res);
204 if (rc) {
205 kfree(opt->dccpop_sc->dccpoc_val);
206 kfree(opt->dccpop_sc);
207 opt->dccpop_sc = 0;
208 return rc;
209 }
210
211 dccp_pr_debug("Will confirm %d\n", *rpref);
212
213 /* say we want to change to X but we just got a confirm X, suppress our
214 * change
215 */
216 if (!opt->dccpop_conf) {
217 if (*opt->dccpop_val == *res)
218 opt->dccpop_conf = 1;
219 dccp_pr_debug("won't ask for change of same feature\n");
220 }
221
222 return agree ? 0 : DCCP_FEAT_SP_NOAGREE; /* used for mandatory opts */
223}
224
225static int dccp_feat_sp(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len)
226{
227 struct dccp_minisock *dmsk = dccp_msk(sk);
228 struct dccp_opt_pend *opt;
229 int rc = 1;
230 u8 t;
231
232 /*
233 * We received a CHANGE. We gotta match it against our own preference
234 * list. If we got a CHANGE_R it means it's a change for us, so we need
235 * to compare our CHANGE_L list.
236 */
237 if (type == DCCPO_CHANGE_L)
238 t = DCCPO_CHANGE_R;
239 else
240 t = DCCPO_CHANGE_L;
241
242 /* find our preference list for this feature */
243 list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) {
244 if (opt->dccpop_type != t || opt->dccpop_feat != feature)
245 continue;
246
247 /* find the winner from the two preference lists */
248 rc = dccp_feat_reconcile(sk, opt, val, len);
249 break;
250 }
251
252 /* We didn't deal with the change. This can happen if we have no
253 * preference list for the feature. In fact, it just shouldn't
254 * happen---if we understand a feature, we should have a preference list
255 * with at least the default value.
256 */
257 BUG_ON(rc == 1);
258
259 return rc;
260}
261
262static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len)
263{
264 struct dccp_opt_pend *opt;
265 struct dccp_minisock *dmsk = dccp_msk(sk);
266 u8 *copy;
267 int rc;
268
269 /* NN features must be change L */
270 if (type == DCCPO_CHANGE_R) {
271 dccp_pr_debug("received CHANGE_R %d for NN feat %d\n",
272 type, feature);
273 return -EFAULT;
274 }
275
276 /* XXX sanity check opt val */
277
278 /* copy option so we can confirm it */
279 opt = kzalloc(sizeof(*opt), GFP_ATOMIC);
280 if (opt == NULL)
281 return -ENOMEM;
282
283 copy = kmalloc(len, GFP_ATOMIC);
284 if (copy == NULL) {
285 kfree(opt);
286 return -ENOMEM;
287 }
288 memcpy(copy, val, len);
289
290 opt->dccpop_type = DCCPO_CONFIRM_R; /* NN can only confirm R */
291 opt->dccpop_feat = feature;
292 opt->dccpop_val = copy;
293 opt->dccpop_len = len;
294
295 /* change feature */
296 rc = dccp_feat_update(sk, type, feature, *val);
297 if (rc) {
298 kfree(opt->dccpop_val);
299 kfree(opt);
300 return rc;
301 }
302
303 dccp_pr_debug("Confirming NN feature %d (val=%d)\n", feature, *copy);
304 list_add_tail(&opt->dccpop_node, &dmsk->dccpms_conf);
305
306 return 0;
307}
308
309static void dccp_feat_empty_confirm(struct dccp_minisock *dmsk,
310 u8 type, u8 feature)
311{
312 /* XXX check if other confirms for that are queued and recycle slot */
313 struct dccp_opt_pend *opt = kzalloc(sizeof(*opt), GFP_ATOMIC);
314
315 if (opt == NULL) {
316 /* XXX what do we do? Ignoring should be fine. It's a change
317 * after all =P
318 */
319 return;
320 }
321
322 opt->dccpop_type = type == DCCPO_CHANGE_L ? DCCPO_CONFIRM_R :
323 DCCPO_CONFIRM_L;
324 opt->dccpop_feat = feature;
325 opt->dccpop_val = 0;
326 opt->dccpop_len = 0;
327
328 /* change feature */
329 dccp_pr_debug("Empty confirm feature %d type %d\n", feature, type);
330 list_add_tail(&opt->dccpop_node, &dmsk->dccpms_conf);
331}
332
333static void dccp_feat_flush_confirm(struct sock *sk)
334{
335 struct dccp_minisock *dmsk = dccp_msk(sk);
336 /* Check if there is anything to confirm in the first place */
337 int yes = !list_empty(&dmsk->dccpms_conf);
338
339 if (!yes) {
340 struct dccp_opt_pend *opt;
341
342 list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) {
343 if (opt->dccpop_conf) {
344 yes = 1;
345 break;
346 }
347 }
348 }
349
350 if (!yes)
351 return;
352
353 /* OK there is something to confirm... */
354 /* XXX check if packet is in flight? Send delayed ack?? */
355 if (sk->sk_state == DCCP_OPEN)
356 dccp_send_ack(sk);
357}
358
359int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len)
360{
361 int rc;
362
363 dccp_pr_debug("got feat change type=%d feat=%d\n", type, feature);
364
365 /* figure out if it's SP or NN feature */
366 switch (feature) {
367 /* deal with SP features */
368 case DCCPF_CCID:
369 rc = dccp_feat_sp(sk, type, feature, val, len);
370 break;
371
372 /* deal with NN features */
373 case DCCPF_ACK_RATIO:
374 rc = dccp_feat_nn(sk, type, feature, val, len);
375 break;
376
377 /* XXX implement other features */
378 default:
379 rc = -EFAULT;
380 break;
381 }
382
383 /* check if there were problems changing features */
384 if (rc) {
385 /* If we don't agree on SP, we sent a confirm for old value.
386 * However we propagate rc to caller in case option was
387 * mandatory
388 */
389 if (rc != DCCP_FEAT_SP_NOAGREE)
390 dccp_feat_empty_confirm(dccp_msk(sk), type, feature);
391 }
392
393 /* generate the confirm [if required] */
394 dccp_feat_flush_confirm(sk);
395
396 return rc;
397}
398
399EXPORT_SYMBOL_GPL(dccp_feat_change_recv);
400
401int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature,
402 u8 *val, u8 len)
403{
404 u8 t;
405 struct dccp_opt_pend *opt;
406 struct dccp_minisock *dmsk = dccp_msk(sk);
407 int rc = 1;
408 int all_confirmed = 1;
409
410 dccp_pr_debug("got feat confirm type=%d feat=%d\n", type, feature);
411
412 /* XXX sanity check type & feat */
413
414 /* locate our change request */
415 t = type == DCCPO_CONFIRM_L ? DCCPO_CHANGE_R : DCCPO_CHANGE_L;
416
417 list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) {
418 if (!opt->dccpop_conf && opt->dccpop_type == t &&
419 opt->dccpop_feat == feature) {
420 /* we found it */
421 /* XXX do sanity check */
422
423 opt->dccpop_conf = 1;
424
425 /* We got a confirmation---change the option */
426 dccp_feat_update(sk, opt->dccpop_type,
427 opt->dccpop_feat, *val);
428
429 dccp_pr_debug("feat %d type %d confirmed %d\n",
430 feature, type, *val);
431 rc = 0;
432 break;
433 }
434
435 if (!opt->dccpop_conf)
436 all_confirmed = 0;
437 }
438
439 /* fix re-transmit timer */
440 /* XXX gotta make sure that no option negotiation occurs during
441 * connection shutdown. Consider that the CLOSEREQ is sent and timer is
442 * on. if all options are confirmed it might kill timer which should
443 * remain alive until close is received.
444 */
445 if (all_confirmed) {
446 dccp_pr_debug("clear feat negotiation timer %p\n", sk);
447 inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS);
448 }
449
450 if (rc)
451 dccp_pr_debug("feat %d type %d never requested\n",
452 feature, type);
453 return 0;
454}
455
456EXPORT_SYMBOL_GPL(dccp_feat_confirm_recv);
457
458void dccp_feat_clean(struct dccp_minisock *dmsk)
459{
460 struct dccp_opt_pend *opt, *next;
461
462 list_for_each_entry_safe(opt, next, &dmsk->dccpms_pending,
463 dccpop_node) {
464 BUG_ON(opt->dccpop_val == NULL);
465 kfree(opt->dccpop_val);
466
467 if (opt->dccpop_sc != NULL) {
468 BUG_ON(opt->dccpop_sc->dccpoc_val == NULL);
469 kfree(opt->dccpop_sc->dccpoc_val);
470 kfree(opt->dccpop_sc);
471 }
472
473 kfree(opt);
474 }
475 INIT_LIST_HEAD(&dmsk->dccpms_pending);
476
477 list_for_each_entry_safe(opt, next, &dmsk->dccpms_conf, dccpop_node) {
478 BUG_ON(opt == NULL);
479 if (opt->dccpop_val != NULL)
480 kfree(opt->dccpop_val);
481 kfree(opt);
482 }
483 INIT_LIST_HEAD(&dmsk->dccpms_conf);
484}
485
486EXPORT_SYMBOL_GPL(dccp_feat_clean);
487
488/* this is to be called only when a listening sock creates its child. It is
489 * assumed by the function---the confirm is not duplicated, but rather it is
490 * "passed on".
491 */
492int dccp_feat_clone(struct sock *oldsk, struct sock *newsk)
493{
494 struct dccp_minisock *olddmsk = dccp_msk(oldsk);
495 struct dccp_minisock *newdmsk = dccp_msk(newsk);
496 struct dccp_opt_pend *opt;
497 int rc = 0;
498
499 INIT_LIST_HEAD(&newdmsk->dccpms_pending);
500 INIT_LIST_HEAD(&newdmsk->dccpms_conf);
501
502 list_for_each_entry(opt, &olddmsk->dccpms_pending, dccpop_node) {
503 struct dccp_opt_pend *newopt;
504 /* copy the value of the option */
505 u8 *val = kmalloc(opt->dccpop_len, GFP_ATOMIC);
506
507 if (val == NULL)
508 goto out_clean;
509 memcpy(val, opt->dccpop_val, opt->dccpop_len);
510
511 newopt = kmalloc(sizeof(*newopt), GFP_ATOMIC);
512 if (newopt == NULL) {
513 kfree(val);
514 goto out_clean;
515 }
516
517 /* insert the option */
518 memcpy(newopt, opt, sizeof(*newopt));
519 newopt->dccpop_val = val;
520 list_add_tail(&newopt->dccpop_node, &newdmsk->dccpms_pending);
521
522 /* XXX what happens with backlogs and multiple connections at
523 * once...
524 */
525 /* the master socket no longer needs to worry about confirms */
526 opt->dccpop_sc = 0; /* it's not a memleak---new socket has it */
527
528 /* reset state for a new socket */
529 opt->dccpop_conf = 0;
530 }
531
532 /* XXX not doing anything about the conf queue */
533
534out:
535 return rc;
536
537out_clean:
538 dccp_feat_clean(newdmsk);
539 rc = -ENOMEM;
540 goto out;
541}
542
543EXPORT_SYMBOL_GPL(dccp_feat_clone);
544
545static int __dccp_feat_init(struct dccp_minisock *dmsk, u8 type, u8 feat,
546 u8 *val, u8 len)
547{
548 int rc = -ENOMEM;
549 u8 *copy = kmalloc(len, GFP_KERNEL);
550
551 if (copy != NULL) {
552 memcpy(copy, val, len);
553 rc = dccp_feat_change(dmsk, type, feat, copy, len, GFP_KERNEL);
554 if (rc)
555 kfree(copy);
556 }
557 return rc;
558}
559
560int dccp_feat_init(struct dccp_minisock *dmsk)
561{
562 int rc;
563
564 INIT_LIST_HEAD(&dmsk->dccpms_pending);
565 INIT_LIST_HEAD(&dmsk->dccpms_conf);
566
567 /* CCID L */
568 rc = __dccp_feat_init(dmsk, DCCPO_CHANGE_L, DCCPF_CCID,
569 &dmsk->dccpms_tx_ccid, 1);
570 if (rc)
571 goto out;
572
573 /* CCID R */
574 rc = __dccp_feat_init(dmsk, DCCPO_CHANGE_R, DCCPF_CCID,
575 &dmsk->dccpms_rx_ccid, 1);
576 if (rc)
577 goto out;
578
579 /* Ack ratio */
580 rc = __dccp_feat_init(dmsk, DCCPO_CHANGE_L, DCCPF_ACK_RATIO,
581 &dmsk->dccpms_ack_ratio, 1);
582out:
583 return rc;
584}
585
586EXPORT_SYMBOL_GPL(dccp_feat_init);
diff --git a/net/dccp/feat.h b/net/dccp/feat.h
new file mode 100644
index 000000000000..6048373c7186
--- /dev/null
+++ b/net/dccp/feat.h
@@ -0,0 +1,29 @@
1#ifndef _DCCP_FEAT_H
2#define _DCCP_FEAT_H
3/*
4 * net/dccp/feat.h
5 *
6 * An implementation of the DCCP protocol
7 * Copyright (c) 2005 Andrea Bittau <a.bittau@cs.ucl.ac.uk>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/types.h>
15
16struct sock;
17struct dccp_minisock;
18
19extern int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature,
20 u8 *val, u8 len, gfp_t gfp);
21extern int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature,
22 u8 *val, u8 len);
23extern int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature,
24 u8 *val, u8 len);
25extern void dccp_feat_clean(struct dccp_minisock *dmsk);
26extern int dccp_feat_clone(struct sock *oldsk, struct sock *newsk);
27extern int dccp_feat_init(struct dccp_minisock *dmsk);
28
29#endif /* _DCCP_FEAT_H */
diff --git a/net/dccp/input.c b/net/dccp/input.c
index b6cba72b44e8..bfc53665516b 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -32,7 +32,7 @@ static void dccp_fin(struct sock *sk, struct sk_buff *skb)
32 32
33static void dccp_rcv_close(struct sock *sk, struct sk_buff *skb) 33static void dccp_rcv_close(struct sock *sk, struct sk_buff *skb)
34{ 34{
35 dccp_v4_send_reset(sk, DCCP_RESET_CODE_CLOSED); 35 dccp_send_reset(sk, DCCP_RESET_CODE_CLOSED);
36 dccp_fin(sk, skb); 36 dccp_fin(sk, skb);
37 dccp_set_state(sk, DCCP_CLOSED); 37 dccp_set_state(sk, DCCP_CLOSED);
38 sk_wake_async(sk, 1, POLL_HUP); 38 sk_wake_async(sk, 1, POLL_HUP);
@@ -56,11 +56,11 @@ static void dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb)
56 dccp_send_close(sk, 0); 56 dccp_send_close(sk, 0);
57} 57}
58 58
59static inline void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb) 59static void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb)
60{ 60{
61 struct dccp_sock *dp = dccp_sk(sk); 61 struct dccp_sock *dp = dccp_sk(sk);
62 62
63 if (dp->dccps_options.dccpo_send_ack_vector) 63 if (dccp_msk(sk)->dccpms_send_ack_vector)
64 dccp_ackvec_check_rcv_ackno(dp->dccps_hc_rx_ackvec, sk, 64 dccp_ackvec_check_rcv_ackno(dp->dccps_hc_rx_ackvec, sk,
65 DCCP_SKB_CB(skb)->dccpd_ack_seq); 65 DCCP_SKB_CB(skb)->dccpd_ack_seq);
66} 66}
@@ -151,9 +151,8 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)
151 return 0; 151 return 0;
152} 152}
153 153
154static inline int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb, 154static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
155 const struct dccp_hdr *dh, 155 const struct dccp_hdr *dh, const unsigned len)
156 const unsigned len)
157{ 156{
158 struct dccp_sock *dp = dccp_sk(sk); 157 struct dccp_sock *dp = dccp_sk(sk);
159 158
@@ -247,7 +246,7 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
247 if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) 246 if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
248 dccp_event_ack_recv(sk, skb); 247 dccp_event_ack_recv(sk, skb);
249 248
250 if (dp->dccps_options.dccpo_send_ack_vector && 249 if (dccp_msk(sk)->dccpms_send_ack_vector &&
251 dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, 250 dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
252 DCCP_SKB_CB(skb)->dccpd_seq, 251 DCCP_SKB_CB(skb)->dccpd_seq,
253 DCCP_ACKVEC_STATE_RECEIVED)) 252 DCCP_ACKVEC_STATE_RECEIVED))
@@ -300,7 +299,10 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
300 goto out_invalid_packet; 299 goto out_invalid_packet;
301 } 300 }
302 301
303 if (dp->dccps_options.dccpo_send_ack_vector && 302 if (dccp_parse_options(sk, skb))
303 goto out_invalid_packet;
304
305 if (dccp_msk(sk)->dccpms_send_ack_vector &&
304 dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, 306 dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
305 DCCP_SKB_CB(skb)->dccpd_seq, 307 DCCP_SKB_CB(skb)->dccpd_seq,
306 DCCP_ACKVEC_STATE_RECEIVED)) 308 DCCP_ACKVEC_STATE_RECEIVED))
@@ -321,14 +323,6 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
321 dccp_set_seqno(&dp->dccps_swl, 323 dccp_set_seqno(&dp->dccps_swl,
322 max48(dp->dccps_swl, dp->dccps_isr)); 324 max48(dp->dccps_swl, dp->dccps_isr));
323 325
324 if (ccid_hc_rx_init(dp->dccps_hc_rx_ccid, sk) != 0 ||
325 ccid_hc_tx_init(dp->dccps_hc_tx_ccid, sk) != 0) {
326 ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
327 ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
328 /* FIXME: send appropriate RESET code */
329 goto out_invalid_packet;
330 }
331
332 dccp_sync_mss(sk, icsk->icsk_pmtu_cookie); 326 dccp_sync_mss(sk, icsk->icsk_pmtu_cookie);
333 327
334 /* 328 /*
@@ -492,7 +486,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
492 if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) 486 if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
493 dccp_event_ack_recv(sk, skb); 487 dccp_event_ack_recv(sk, skb);
494 488
495 if (dp->dccps_options.dccpo_send_ack_vector && 489 if (dccp_msk(sk)->dccpms_send_ack_vector &&
496 dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, 490 dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
497 DCCP_SKB_CB(skb)->dccpd_seq, 491 DCCP_SKB_CB(skb)->dccpd_seq,
498 DCCP_ACKVEC_STATE_RECEIVED)) 492 DCCP_ACKVEC_STATE_RECEIVED))
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index dc0487b5bace..29047995c695 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -18,8 +18,10 @@
18#include <linux/random.h> 18#include <linux/random.h>
19 19
20#include <net/icmp.h> 20#include <net/icmp.h>
21#include <net/inet_common.h>
21#include <net/inet_hashtables.h> 22#include <net/inet_hashtables.h>
22#include <net/inet_sock.h> 23#include <net/inet_sock.h>
24#include <net/protocol.h>
23#include <net/sock.h> 25#include <net/sock.h>
24#include <net/timewait_sock.h> 26#include <net/timewait_sock.h>
25#include <net/tcp_states.h> 27#include <net/tcp_states.h>
@@ -28,14 +30,14 @@
28#include "ackvec.h" 30#include "ackvec.h"
29#include "ccid.h" 31#include "ccid.h"
30#include "dccp.h" 32#include "dccp.h"
33#include "feat.h"
31 34
32struct inet_hashinfo __cacheline_aligned dccp_hashinfo = { 35/*
33 .lhash_lock = RW_LOCK_UNLOCKED, 36 * This is the global socket data structure used for responding to
34 .lhash_users = ATOMIC_INIT(0), 37 * the Out-of-the-blue (OOTB) packets. A control sock will be created
35 .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(dccp_hashinfo.lhash_wait), 38 * for this socket at the initialization time.
36}; 39 */
37 40static struct socket *dccp_v4_ctl_socket;
38EXPORT_SYMBOL_GPL(dccp_hashinfo);
39 41
40static int dccp_v4_get_port(struct sock *sk, const unsigned short snum) 42static int dccp_v4_get_port(struct sock *sk, const unsigned short snum)
41{ 43{
@@ -43,18 +45,6 @@ static int dccp_v4_get_port(struct sock *sk, const unsigned short snum)
43 inet_csk_bind_conflict); 45 inet_csk_bind_conflict);
44} 46}
45 47
46static void dccp_v4_hash(struct sock *sk)
47{
48 inet_hash(&dccp_hashinfo, sk);
49}
50
51void dccp_unhash(struct sock *sk)
52{
53 inet_unhash(&dccp_hashinfo, sk);
54}
55
56EXPORT_SYMBOL_GPL(dccp_unhash);
57
58int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) 48int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
59{ 49{
60 struct inet_sock *inet = inet_sk(sk); 50 struct inet_sock *inet = inet_sk(sk);
@@ -207,11 +197,12 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk,
207 } /* else let the usual retransmit timer handle it */ 197 } /* else let the usual retransmit timer handle it */
208} 198}
209 199
210static void dccp_v4_ctl_send_ack(struct sk_buff *rxskb) 200static void dccp_v4_reqsk_send_ack(struct sk_buff *rxskb,
201 struct request_sock *req)
211{ 202{
212 int err; 203 int err;
213 struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh; 204 struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
214 const int dccp_hdr_ack_len = sizeof(struct dccp_hdr) + 205 const u32 dccp_hdr_ack_len = sizeof(struct dccp_hdr) +
215 sizeof(struct dccp_hdr_ext) + 206 sizeof(struct dccp_hdr_ext) +
216 sizeof(struct dccp_hdr_ack_bits); 207 sizeof(struct dccp_hdr_ack_bits);
217 struct sk_buff *skb; 208 struct sk_buff *skb;
@@ -219,12 +210,12 @@ static void dccp_v4_ctl_send_ack(struct sk_buff *rxskb)
219 if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL) 210 if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL)
220 return; 211 return;
221 212
222 skb = alloc_skb(MAX_DCCP_HEADER + 15, GFP_ATOMIC); 213 skb = alloc_skb(dccp_v4_ctl_socket->sk->sk_prot->max_header, GFP_ATOMIC);
223 if (skb == NULL) 214 if (skb == NULL)
224 return; 215 return;
225 216
226 /* Reserve space for headers. */ 217 /* Reserve space for headers. */
227 skb_reserve(skb, MAX_DCCP_HEADER); 218 skb_reserve(skb, dccp_v4_ctl_socket->sk->sk_prot->max_header);
228 219
229 skb->dst = dst_clone(rxskb->dst); 220 skb->dst = dst_clone(rxskb->dst);
230 221
@@ -243,11 +234,11 @@ static void dccp_v4_ctl_send_ack(struct sk_buff *rxskb)
243 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), 234 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
244 DCCP_SKB_CB(rxskb)->dccpd_seq); 235 DCCP_SKB_CB(rxskb)->dccpd_seq);
245 236
246 bh_lock_sock(dccp_ctl_socket->sk); 237 bh_lock_sock(dccp_v4_ctl_socket->sk);
247 err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk, 238 err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
248 rxskb->nh.iph->daddr, 239 rxskb->nh.iph->daddr,
249 rxskb->nh.iph->saddr, NULL); 240 rxskb->nh.iph->saddr, NULL);
250 bh_unlock_sock(dccp_ctl_socket->sk); 241 bh_unlock_sock(dccp_v4_ctl_socket->sk);
251 242
252 if (err == NET_XMIT_CN || err == 0) { 243 if (err == NET_XMIT_CN || err == 0) {
253 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); 244 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
@@ -255,12 +246,6 @@ static void dccp_v4_ctl_send_ack(struct sk_buff *rxskb)
255 } 246 }
256} 247}
257 248
258static void dccp_v4_reqsk_send_ack(struct sk_buff *skb,
259 struct request_sock *req)
260{
261 dccp_v4_ctl_send_ack(skb);
262}
263
264static int dccp_v4_send_response(struct sock *sk, struct request_sock *req, 249static int dccp_v4_send_response(struct sock *sk, struct request_sock *req,
265 struct dst_entry *dst) 250 struct dst_entry *dst)
266{ 251{
@@ -275,7 +260,10 @@ static int dccp_v4_send_response(struct sock *sk, struct request_sock *req,
275 skb = dccp_make_response(sk, dst, req); 260 skb = dccp_make_response(sk, dst, req);
276 if (skb != NULL) { 261 if (skb != NULL) {
277 const struct inet_request_sock *ireq = inet_rsk(req); 262 const struct inet_request_sock *ireq = inet_rsk(req);
263 struct dccp_hdr *dh = dccp_hdr(skb);
278 264
265 dh->dccph_checksum = dccp_v4_checksum(skb, ireq->loc_addr,
266 ireq->rmt_addr);
279 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); 267 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
280 err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, 268 err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr,
281 ireq->rmt_addr, 269 ireq->rmt_addr,
@@ -301,7 +289,7 @@ out:
301 * check at all. A more general error queue to queue errors for later handling 289 * check at all. A more general error queue to queue errors for later handling
302 * is probably better. 290 * is probably better.
303 */ 291 */
304void dccp_v4_err(struct sk_buff *skb, u32 info) 292static void dccp_v4_err(struct sk_buff *skb, u32 info)
305{ 293{
306 const struct iphdr *iph = (struct iphdr *)skb->data; 294 const struct iphdr *iph = (struct iphdr *)skb->data;
307 const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + 295 const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data +
@@ -456,32 +444,6 @@ void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)
456 444
457EXPORT_SYMBOL_GPL(dccp_v4_send_check); 445EXPORT_SYMBOL_GPL(dccp_v4_send_check);
458 446
459int dccp_v4_send_reset(struct sock *sk, enum dccp_reset_codes code)
460{
461 struct sk_buff *skb;
462 /*
463 * FIXME: what if rebuild_header fails?
464 * Should we be doing a rebuild_header here?
465 */
466 int err = inet_sk_rebuild_header(sk);
467
468 if (err != 0)
469 return err;
470
471 skb = dccp_make_reset(sk, sk->sk_dst_cache, code);
472 if (skb != NULL) {
473 const struct inet_sock *inet = inet_sk(sk);
474
475 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
476 err = ip_build_and_send_pkt(skb, sk,
477 inet->saddr, inet->daddr, NULL);
478 if (err == NET_XMIT_CN)
479 err = 0;
480 }
481
482 return err;
483}
484
485static inline u64 dccp_v4_init_sequence(const struct sock *sk, 447static inline u64 dccp_v4_init_sequence(const struct sock *sk,
486 const struct sk_buff *skb) 448 const struct sk_buff *skb)
487{ 449{
@@ -497,9 +459,9 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
497 struct dccp_sock dp; 459 struct dccp_sock dp;
498 struct request_sock *req; 460 struct request_sock *req;
499 struct dccp_request_sock *dreq; 461 struct dccp_request_sock *dreq;
500 const __u32 saddr = skb->nh.iph->saddr; 462 const __be32 saddr = skb->nh.iph->saddr;
501 const __u32 daddr = skb->nh.iph->daddr; 463 const __be32 daddr = skb->nh.iph->daddr;
502 const __u32 service = dccp_hdr_request(skb)->dccph_req_service; 464 const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
503 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); 465 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
504 __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY; 466 __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
505 467
@@ -535,7 +497,8 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
535 if (req == NULL) 497 if (req == NULL)
536 goto drop; 498 goto drop;
537 499
538 /* FIXME: process options */ 500 if (dccp_parse_options(sk, skb))
501 goto drop;
539 502
540 dccp_openreq_init(req, &dp, skb); 503 dccp_openreq_init(req, &dp, skb);
541 504
@@ -660,8 +623,8 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
660 return sk; 623 return sk;
661} 624}
662 625
663int dccp_v4_checksum(const struct sk_buff *skb, const u32 saddr, 626int dccp_v4_checksum(const struct sk_buff *skb, const __be32 saddr,
664 const u32 daddr) 627 const __be32 daddr)
665{ 628{
666 const struct dccp_hdr* dh = dccp_hdr(skb); 629 const struct dccp_hdr* dh = dccp_hdr(skb);
667 int checksum_len; 630 int checksum_len;
@@ -680,8 +643,10 @@ int dccp_v4_checksum(const struct sk_buff *skb, const u32 saddr,
680 IPPROTO_DCCP, tmp); 643 IPPROTO_DCCP, tmp);
681} 644}
682 645
646EXPORT_SYMBOL_GPL(dccp_v4_checksum);
647
683static int dccp_v4_verify_checksum(struct sk_buff *skb, 648static int dccp_v4_verify_checksum(struct sk_buff *skb,
684 const u32 saddr, const u32 daddr) 649 const __be32 saddr, const __be32 daddr)
685{ 650{
686 struct dccp_hdr *dh = dccp_hdr(skb); 651 struct dccp_hdr *dh = dccp_hdr(skb);
687 int checksum_len; 652 int checksum_len;
@@ -741,16 +706,17 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb)
741 if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL) 706 if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL)
742 return; 707 return;
743 708
744 dst = dccp_v4_route_skb(dccp_ctl_socket->sk, rxskb); 709 dst = dccp_v4_route_skb(dccp_v4_ctl_socket->sk, rxskb);
745 if (dst == NULL) 710 if (dst == NULL)
746 return; 711 return;
747 712
748 skb = alloc_skb(MAX_DCCP_HEADER + 15, GFP_ATOMIC); 713 skb = alloc_skb(dccp_v4_ctl_socket->sk->sk_prot->max_header,
714 GFP_ATOMIC);
749 if (skb == NULL) 715 if (skb == NULL)
750 goto out; 716 goto out;
751 717
752 /* Reserve space for headers. */ 718 /* Reserve space for headers. */
753 skb_reserve(skb, MAX_DCCP_HEADER); 719 skb_reserve(skb, dccp_v4_ctl_socket->sk->sk_prot->max_header);
754 skb->dst = dst_clone(dst); 720 skb->dst = dst_clone(dst);
755 721
756 skb->h.raw = skb_push(skb, dccp_hdr_reset_len); 722 skb->h.raw = skb_push(skb, dccp_hdr_reset_len);
@@ -778,11 +744,11 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb)
778 dh->dccph_checksum = dccp_v4_checksum(skb, rxskb->nh.iph->saddr, 744 dh->dccph_checksum = dccp_v4_checksum(skb, rxskb->nh.iph->saddr,
779 rxskb->nh.iph->daddr); 745 rxskb->nh.iph->daddr);
780 746
781 bh_lock_sock(dccp_ctl_socket->sk); 747 bh_lock_sock(dccp_v4_ctl_socket->sk);
782 err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk, 748 err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
783 rxskb->nh.iph->daddr, 749 rxskb->nh.iph->daddr,
784 rxskb->nh.iph->saddr, NULL); 750 rxskb->nh.iph->saddr, NULL);
785 bh_unlock_sock(dccp_ctl_socket->sk); 751 bh_unlock_sock(dccp_v4_ctl_socket->sk);
786 752
787 if (err == NET_XMIT_CN || err == 0) { 753 if (err == NET_XMIT_CN || err == 0) {
788 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); 754 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
@@ -912,7 +878,7 @@ int dccp_invalid_packet(struct sk_buff *skb)
912EXPORT_SYMBOL_GPL(dccp_invalid_packet); 878EXPORT_SYMBOL_GPL(dccp_invalid_packet);
913 879
914/* this is called when real data arrives */ 880/* this is called when real data arrives */
915int dccp_v4_rcv(struct sk_buff *skb) 881static int dccp_v4_rcv(struct sk_buff *skb)
916{ 882{
917 const struct dccp_hdr *dh; 883 const struct dccp_hdr *dh;
918 struct sock *sk; 884 struct sock *sk;
@@ -1019,111 +985,37 @@ do_time_wait:
1019 goto no_dccp_socket; 985 goto no_dccp_socket;
1020} 986}
1021 987
1022struct inet_connection_sock_af_ops dccp_ipv4_af_ops = { 988static struct inet_connection_sock_af_ops dccp_ipv4_af_ops = {
1023 .queue_xmit = ip_queue_xmit, 989 .queue_xmit = ip_queue_xmit,
1024 .send_check = dccp_v4_send_check, 990 .send_check = dccp_v4_send_check,
1025 .rebuild_header = inet_sk_rebuild_header, 991 .rebuild_header = inet_sk_rebuild_header,
1026 .conn_request = dccp_v4_conn_request, 992 .conn_request = dccp_v4_conn_request,
1027 .syn_recv_sock = dccp_v4_request_recv_sock, 993 .syn_recv_sock = dccp_v4_request_recv_sock,
1028 .net_header_len = sizeof(struct iphdr), 994 .net_header_len = sizeof(struct iphdr),
1029 .setsockopt = ip_setsockopt, 995 .setsockopt = ip_setsockopt,
1030 .getsockopt = ip_getsockopt, 996 .getsockopt = ip_getsockopt,
1031 .addr2sockaddr = inet_csk_addr2sockaddr, 997 .addr2sockaddr = inet_csk_addr2sockaddr,
1032 .sockaddr_len = sizeof(struct sockaddr_in), 998 .sockaddr_len = sizeof(struct sockaddr_in),
999#ifdef CONFIG_COMPAT
1000 .compat_setsockopt = compat_ip_setsockopt,
1001 .compat_getsockopt = compat_ip_getsockopt,
1002#endif
1033}; 1003};
1034 1004
1035int dccp_v4_init_sock(struct sock *sk) 1005static int dccp_v4_init_sock(struct sock *sk)
1036{
1037 struct dccp_sock *dp = dccp_sk(sk);
1038 struct inet_connection_sock *icsk = inet_csk(sk);
1039 static int dccp_ctl_socket_init = 1;
1040
1041 dccp_options_init(&dp->dccps_options);
1042 do_gettimeofday(&dp->dccps_epoch);
1043
1044 if (dp->dccps_options.dccpo_send_ack_vector) {
1045 dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(DCCP_MAX_ACKVEC_LEN,
1046 GFP_KERNEL);
1047 if (dp->dccps_hc_rx_ackvec == NULL)
1048 return -ENOMEM;
1049 }
1050
1051 /*
1052 * FIXME: We're hardcoding the CCID, and doing this at this point makes
1053 * the listening (master) sock get CCID control blocks, which is not
1054 * necessary, but for now, to not mess with the test userspace apps,
1055 * lets leave it here, later the real solution is to do this in a
1056 * setsockopt(CCIDs-I-want/accept). -acme
1057 */
1058 if (likely(!dccp_ctl_socket_init)) {
1059 dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_rx_ccid,
1060 sk);
1061 dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_tx_ccid,
1062 sk);
1063 if (dp->dccps_hc_rx_ccid == NULL ||
1064 dp->dccps_hc_tx_ccid == NULL) {
1065 ccid_exit(dp->dccps_hc_rx_ccid, sk);
1066 ccid_exit(dp->dccps_hc_tx_ccid, sk);
1067 if (dp->dccps_options.dccpo_send_ack_vector) {
1068 dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
1069 dp->dccps_hc_rx_ackvec = NULL;
1070 }
1071 dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
1072 return -ENOMEM;
1073 }
1074 } else
1075 dccp_ctl_socket_init = 0;
1076
1077 dccp_init_xmit_timers(sk);
1078 icsk->icsk_rto = DCCP_TIMEOUT_INIT;
1079 sk->sk_state = DCCP_CLOSED;
1080 sk->sk_write_space = dccp_write_space;
1081 icsk->icsk_af_ops = &dccp_ipv4_af_ops;
1082 icsk->icsk_sync_mss = dccp_sync_mss;
1083 dp->dccps_mss_cache = 536;
1084 dp->dccps_role = DCCP_ROLE_UNDEFINED;
1085 dp->dccps_service = DCCP_SERVICE_INVALID_VALUE;
1086
1087 return 0;
1088}
1089
1090EXPORT_SYMBOL_GPL(dccp_v4_init_sock);
1091
1092int dccp_v4_destroy_sock(struct sock *sk)
1093{ 1006{
1094 struct dccp_sock *dp = dccp_sk(sk); 1007 static __u8 dccp_v4_ctl_sock_initialized;
1008 int err = dccp_init_sock(sk, dccp_v4_ctl_sock_initialized);
1095 1009
1096 /* 1010 if (err == 0) {
1097 * DCCP doesn't use sk_write_queue, just sk_send_head 1011 if (unlikely(!dccp_v4_ctl_sock_initialized))
1098 * for retransmissions 1012 dccp_v4_ctl_sock_initialized = 1;
1099 */ 1013 inet_csk(sk)->icsk_af_ops = &dccp_ipv4_af_ops;
1100 if (sk->sk_send_head != NULL) {
1101 kfree_skb(sk->sk_send_head);
1102 sk->sk_send_head = NULL;
1103 } 1014 }
1104 1015
1105 /* Clean up a referenced DCCP bind bucket. */ 1016 return err;
1106 if (inet_csk(sk)->icsk_bind_hash != NULL)
1107 inet_put_port(&dccp_hashinfo, sk);
1108
1109 kfree(dp->dccps_service_list);
1110 dp->dccps_service_list = NULL;
1111
1112 ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
1113 ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
1114 if (dp->dccps_options.dccpo_send_ack_vector) {
1115 dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
1116 dp->dccps_hc_rx_ackvec = NULL;
1117 }
1118 ccid_exit(dp->dccps_hc_rx_ccid, sk);
1119 ccid_exit(dp->dccps_hc_tx_ccid, sk);
1120 dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
1121
1122 return 0;
1123} 1017}
1124 1018
1125EXPORT_SYMBOL_GPL(dccp_v4_destroy_sock);
1126
1127static void dccp_v4_reqsk_destructor(struct request_sock *req) 1019static void dccp_v4_reqsk_destructor(struct request_sock *req)
1128{ 1020{
1129 kfree(inet_rsk(req)->opt); 1021 kfree(inet_rsk(req)->opt);
@@ -1142,7 +1034,7 @@ static struct timewait_sock_ops dccp_timewait_sock_ops = {
1142 .twsk_obj_size = sizeof(struct inet_timewait_sock), 1034 .twsk_obj_size = sizeof(struct inet_timewait_sock),
1143}; 1035};
1144 1036
1145struct proto dccp_prot = { 1037static struct proto dccp_v4_prot = {
1146 .name = "DCCP", 1038 .name = "DCCP",
1147 .owner = THIS_MODULE, 1039 .owner = THIS_MODULE,
1148 .close = dccp_close, 1040 .close = dccp_close,
@@ -1155,17 +1047,110 @@ struct proto dccp_prot = {
1155 .sendmsg = dccp_sendmsg, 1047 .sendmsg = dccp_sendmsg,
1156 .recvmsg = dccp_recvmsg, 1048 .recvmsg = dccp_recvmsg,
1157 .backlog_rcv = dccp_v4_do_rcv, 1049 .backlog_rcv = dccp_v4_do_rcv,
1158 .hash = dccp_v4_hash, 1050 .hash = dccp_hash,
1159 .unhash = dccp_unhash, 1051 .unhash = dccp_unhash,
1160 .accept = inet_csk_accept, 1052 .accept = inet_csk_accept,
1161 .get_port = dccp_v4_get_port, 1053 .get_port = dccp_v4_get_port,
1162 .shutdown = dccp_shutdown, 1054 .shutdown = dccp_shutdown,
1163 .destroy = dccp_v4_destroy_sock, 1055 .destroy = dccp_destroy_sock,
1164 .orphan_count = &dccp_orphan_count, 1056 .orphan_count = &dccp_orphan_count,
1165 .max_header = MAX_DCCP_HEADER, 1057 .max_header = MAX_DCCP_HEADER,
1166 .obj_size = sizeof(struct dccp_sock), 1058 .obj_size = sizeof(struct dccp_sock),
1167 .rsk_prot = &dccp_request_sock_ops, 1059 .rsk_prot = &dccp_request_sock_ops,
1168 .twsk_prot = &dccp_timewait_sock_ops, 1060 .twsk_prot = &dccp_timewait_sock_ops,
1061#ifdef CONFIG_COMPAT
1062 .compat_setsockopt = compat_dccp_setsockopt,
1063 .compat_getsockopt = compat_dccp_getsockopt,
1064#endif
1065};
1066
1067static struct net_protocol dccp_v4_protocol = {
1068 .handler = dccp_v4_rcv,
1069 .err_handler = dccp_v4_err,
1070 .no_policy = 1,
1071};
1072
1073static const struct proto_ops inet_dccp_ops = {
1074 .family = PF_INET,
1075 .owner = THIS_MODULE,
1076 .release = inet_release,
1077 .bind = inet_bind,
1078 .connect = inet_stream_connect,
1079 .socketpair = sock_no_socketpair,
1080 .accept = inet_accept,
1081 .getname = inet_getname,
1082 /* FIXME: work on tcp_poll to rename it to inet_csk_poll */
1083 .poll = dccp_poll,
1084 .ioctl = inet_ioctl,
1085 /* FIXME: work on inet_listen to rename it to sock_common_listen */
1086 .listen = inet_dccp_listen,
1087 .shutdown = inet_shutdown,
1088 .setsockopt = sock_common_setsockopt,
1089 .getsockopt = sock_common_getsockopt,
1090 .sendmsg = inet_sendmsg,
1091 .recvmsg = sock_common_recvmsg,
1092 .mmap = sock_no_mmap,
1093 .sendpage = sock_no_sendpage,
1094#ifdef CONFIG_COMPAT
1095 .compat_setsockopt = compat_sock_common_setsockopt,
1096 .compat_getsockopt = compat_sock_common_getsockopt,
1097#endif
1169}; 1098};
1170 1099
1171EXPORT_SYMBOL_GPL(dccp_prot); 1100static struct inet_protosw dccp_v4_protosw = {
1101 .type = SOCK_DCCP,
1102 .protocol = IPPROTO_DCCP,
1103 .prot = &dccp_v4_prot,
1104 .ops = &inet_dccp_ops,
1105 .capability = -1,
1106 .no_check = 0,
1107 .flags = INET_PROTOSW_ICSK,
1108};
1109
1110static int __init dccp_v4_init(void)
1111{
1112 int err = proto_register(&dccp_v4_prot, 1);
1113
1114 if (err != 0)
1115 goto out;
1116
1117 err = inet_add_protocol(&dccp_v4_protocol, IPPROTO_DCCP);
1118 if (err != 0)
1119 goto out_proto_unregister;
1120
1121 inet_register_protosw(&dccp_v4_protosw);
1122
1123 err = inet_csk_ctl_sock_create(&dccp_v4_ctl_socket, PF_INET,
1124 SOCK_DCCP, IPPROTO_DCCP);
1125 if (err)
1126 goto out_unregister_protosw;
1127out:
1128 return err;
1129out_unregister_protosw:
1130 inet_unregister_protosw(&dccp_v4_protosw);
1131 inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP);
1132out_proto_unregister:
1133 proto_unregister(&dccp_v4_prot);
1134 goto out;
1135}
1136
1137static void __exit dccp_v4_exit(void)
1138{
1139 inet_unregister_protosw(&dccp_v4_protosw);
1140 inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP);
1141 proto_unregister(&dccp_v4_prot);
1142}
1143
1144module_init(dccp_v4_init);
1145module_exit(dccp_v4_exit);
1146
1147/*
1148 * __stringify doesn't likes enums, so use SOCK_DCCP (6) and IPPROTO_DCCP (33)
1149 * values directly, Also cover the case where the protocol is not specified,
1150 * i.e. net-pf-PF_INET-proto-0-type-SOCK_DCCP
1151 */
1152MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-33-type-6");
1153MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-0-type-6");
1154MODULE_LICENSE("GPL");
1155MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>");
1156MODULE_DESCRIPTION("DCCP - Datagram Congestion Controlled Protocol");
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 80c4d048869e..65e2ab0886e6 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * DCCP over IPv6 2 * DCCP over IPv6
3 * Linux INET6 implementation 3 * Linux INET6 implementation
4 * 4 *
5 * Based on net/dccp6/ipv6.c 5 * Based on net/dccp6/ipv6.c
6 * 6 *
@@ -33,6 +33,9 @@
33#include "dccp.h" 33#include "dccp.h"
34#include "ipv6.h" 34#include "ipv6.h"
35 35
36/* Socket used for sending RSTs and ACKs */
37static struct socket *dccp_v6_ctl_socket;
38
36static void dccp_v6_ctl_send_reset(struct sk_buff *skb); 39static void dccp_v6_ctl_send_reset(struct sk_buff *skb);
37static void dccp_v6_reqsk_send_ack(struct sk_buff *skb, 40static void dccp_v6_reqsk_send_ack(struct sk_buff *skb,
38 struct request_sock *req); 41 struct request_sock *req);
@@ -53,7 +56,7 @@ static void dccp_v6_hash(struct sock *sk)
53{ 56{
54 if (sk->sk_state != DCCP_CLOSED) { 57 if (sk->sk_state != DCCP_CLOSED) {
55 if (inet_csk(sk)->icsk_af_ops == &dccp_ipv6_mapped) { 58 if (inet_csk(sk)->icsk_af_ops == &dccp_ipv6_mapped) {
56 dccp_prot.hash(sk); 59 dccp_hash(sk);
57 return; 60 return;
58 } 61 }
59 local_bh_disable(); 62 local_bh_disable();
@@ -63,8 +66,8 @@ static void dccp_v6_hash(struct sock *sk)
63} 66}
64 67
65static inline u16 dccp_v6_check(struct dccp_hdr *dh, int len, 68static inline u16 dccp_v6_check(struct dccp_hdr *dh, int len,
66 struct in6_addr *saddr, 69 struct in6_addr *saddr,
67 struct in6_addr *daddr, 70 struct in6_addr *daddr,
68 unsigned long base) 71 unsigned long base)
69{ 72{
70 return csum_ipv6_magic(saddr, daddr, len, IPPROTO_DCCP, base); 73 return csum_ipv6_magic(saddr, daddr, len, IPPROTO_DCCP, base);
@@ -79,17 +82,17 @@ static __u32 dccp_v6_init_sequence(struct sock *sk, struct sk_buff *skb)
79 skb->nh.ipv6h->saddr.s6_addr32, 82 skb->nh.ipv6h->saddr.s6_addr32,
80 dh->dccph_dport, 83 dh->dccph_dport,
81 dh->dccph_sport); 84 dh->dccph_sport);
82 else 85
83 return secure_dccp_sequence_number(skb->nh.iph->daddr, 86 return secure_dccp_sequence_number(skb->nh.iph->daddr,
84 skb->nh.iph->saddr, 87 skb->nh.iph->saddr,
85 dh->dccph_dport, 88 dh->dccph_dport,
86 dh->dccph_sport); 89 dh->dccph_sport);
87} 90}
88 91
89static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, 92static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
90 int addr_len) 93 int addr_len)
91{ 94{
92 struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; 95 struct sockaddr_in6 *usin = (struct sockaddr_in6 *)uaddr;
93 struct inet_connection_sock *icsk = inet_csk(sk); 96 struct inet_connection_sock *icsk = inet_csk(sk);
94 struct inet_sock *inet = inet_sk(sk); 97 struct inet_sock *inet = inet_sk(sk);
95 struct ipv6_pinfo *np = inet6_sk(sk); 98 struct ipv6_pinfo *np = inet6_sk(sk);
@@ -102,10 +105,10 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
102 105
103 dp->dccps_role = DCCP_ROLE_CLIENT; 106 dp->dccps_role = DCCP_ROLE_CLIENT;
104 107
105 if (addr_len < SIN6_LEN_RFC2133) 108 if (addr_len < SIN6_LEN_RFC2133)
106 return -EINVAL; 109 return -EINVAL;
107 110
108 if (usin->sin6_family != AF_INET6) 111 if (usin->sin6_family != AF_INET6)
109 return -EAFNOSUPPORT; 112 return -EAFNOSUPPORT;
110 113
111 memset(&fl, 0, sizeof(fl)); 114 memset(&fl, 0, sizeof(fl));
@@ -122,17 +125,15 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
122 fl6_sock_release(flowlabel); 125 fl6_sock_release(flowlabel);
123 } 126 }
124 } 127 }
125
126 /* 128 /*
127 * connect() to INADDR_ANY means loopback (BSD'ism). 129 * connect() to INADDR_ANY means loopback (BSD'ism).
128 */ 130 */
129 131 if (ipv6_addr_any(&usin->sin6_addr))
130 if (ipv6_addr_any(&usin->sin6_addr)) 132 usin->sin6_addr.s6_addr[15] = 1;
131 usin->sin6_addr.s6_addr[15] = 0x1;
132 133
133 addr_type = ipv6_addr_type(&usin->sin6_addr); 134 addr_type = ipv6_addr_type(&usin->sin6_addr);
134 135
135 if(addr_type & IPV6_ADDR_MULTICAST) 136 if (addr_type & IPV6_ADDR_MULTICAST)
136 return -ENETUNREACH; 137 return -ENETUNREACH;
137 138
138 if (addr_type & IPV6_ADDR_LINKLOCAL) { 139 if (addr_type & IPV6_ADDR_LINKLOCAL) {
@@ -157,9 +158,8 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
157 np->flow_label = fl.fl6_flowlabel; 158 np->flow_label = fl.fl6_flowlabel;
158 159
159 /* 160 /*
160 * DCCP over IPv4 161 * DCCP over IPv4
161 */ 162 */
162
163 if (addr_type == IPV6_ADDR_MAPPED) { 163 if (addr_type == IPV6_ADDR_MAPPED) {
164 u32 exthdrlen = icsk->icsk_ext_hdr_len; 164 u32 exthdrlen = icsk->icsk_ext_hdr_len;
165 struct sockaddr_in sin; 165 struct sockaddr_in sin;
@@ -177,7 +177,6 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
177 sk->sk_backlog_rcv = dccp_v4_do_rcv; 177 sk->sk_backlog_rcv = dccp_v4_do_rcv;
178 178
179 err = dccp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin)); 179 err = dccp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
180
181 if (err) { 180 if (err) {
182 icsk->icsk_ext_hdr_len = exthdrlen; 181 icsk->icsk_ext_hdr_len = exthdrlen;
183 icsk->icsk_af_ops = &dccp_ipv6_af_ops; 182 icsk->icsk_af_ops = &dccp_ipv6_af_ops;
@@ -203,8 +202,9 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
203 fl.fl_ip_dport = usin->sin6_port; 202 fl.fl_ip_dport = usin->sin6_port;
204 fl.fl_ip_sport = inet->sport; 203 fl.fl_ip_sport = inet->sport;
205 204
206 if (np->opt && np->opt->srcrt) { 205 if (np->opt != NULL && np->opt->srcrt != NULL) {
207 struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; 206 const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
207
208 ipv6_addr_copy(&final, &fl.fl6_dst); 208 ipv6_addr_copy(&final, &fl.fl6_dst);
209 ipv6_addr_copy(&fl.fl6_dst, rt0->addr); 209 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
210 final_p = &final; 210 final_p = &final;
@@ -213,10 +213,12 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
213 err = ip6_dst_lookup(sk, &dst, &fl); 213 err = ip6_dst_lookup(sk, &dst, &fl);
214 if (err) 214 if (err)
215 goto failure; 215 goto failure;
216
216 if (final_p) 217 if (final_p)
217 ipv6_addr_copy(&fl.fl6_dst, final_p); 218 ipv6_addr_copy(&fl.fl6_dst, final_p);
218 219
219 if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) 220 err = xfrm_lookup(&dst, &fl, sk, 0);
221 if (err < 0)
220 goto failure; 222 goto failure;
221 223
222 if (saddr == NULL) { 224 if (saddr == NULL) {
@@ -231,7 +233,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
231 ip6_dst_store(sk, dst, NULL); 233 ip6_dst_store(sk, dst, NULL);
232 234
233 icsk->icsk_ext_hdr_len = 0; 235 icsk->icsk_ext_hdr_len = 0;
234 if (np->opt) 236 if (np->opt != NULL)
235 icsk->icsk_ext_hdr_len = (np->opt->opt_flen + 237 icsk->icsk_ext_hdr_len = (np->opt->opt_flen +
236 np->opt->opt_nflen); 238 np->opt->opt_nflen);
237 239
@@ -264,7 +266,7 @@ failure:
264} 266}
265 267
266static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 268static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
267 int type, int code, int offset, __u32 info) 269 int type, int code, int offset, __be32 info)
268{ 270{
269 struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data; 271 struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data;
270 const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset); 272 const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
@@ -305,7 +307,6 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
305 307
306 /* icmp should have updated the destination cache entry */ 308 /* icmp should have updated the destination cache entry */
307 dst = __sk_dst_check(sk, np->dst_cookie); 309 dst = __sk_dst_check(sk, np->dst_cookie);
308
309 if (dst == NULL) { 310 if (dst == NULL) {
310 struct inet_sock *inet = inet_sk(sk); 311 struct inet_sock *inet = inet_sk(sk);
311 struct flowi fl; 312 struct flowi fl;
@@ -322,16 +323,17 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
322 fl.fl_ip_dport = inet->dport; 323 fl.fl_ip_dport = inet->dport;
323 fl.fl_ip_sport = inet->sport; 324 fl.fl_ip_sport = inet->sport;
324 325
325 if ((err = ip6_dst_lookup(sk, &dst, &fl))) { 326 err = ip6_dst_lookup(sk, &dst, &fl);
327 if (err) {
326 sk->sk_err_soft = -err; 328 sk->sk_err_soft = -err;
327 goto out; 329 goto out;
328 } 330 }
329 331
330 if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { 332 err = xfrm_lookup(&dst, &fl, sk, 0);
333 if (err < 0) {
331 sk->sk_err_soft = -err; 334 sk->sk_err_soft = -err;
332 goto out; 335 goto out;
333 } 336 }
334
335 } else 337 } else
336 dst_hold(dst); 338 dst_hold(dst);
337 339
@@ -355,11 +357,12 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
355 req = inet6_csk_search_req(sk, &prev, dh->dccph_dport, 357 req = inet6_csk_search_req(sk, &prev, dh->dccph_dport,
356 &hdr->daddr, &hdr->saddr, 358 &hdr->daddr, &hdr->saddr,
357 inet6_iif(skb)); 359 inet6_iif(skb));
358 if (!req) 360 if (req == NULL)
359 goto out; 361 goto out;
360 362
361 /* ICMPs are not backlogged, hence we cannot get 363 /*
362 * an established socket here. 364 * ICMPs are not backlogged, hence we cannot get an established
365 * socket here.
363 */ 366 */
364 BUG_TRAP(req->sk == NULL); 367 BUG_TRAP(req->sk == NULL);
365 368
@@ -373,7 +376,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
373 376
374 case DCCP_REQUESTING: 377 case DCCP_REQUESTING:
375 case DCCP_RESPOND: /* Cannot happen. 378 case DCCP_RESPOND: /* Cannot happen.
376 It can, it SYNs are crossed. --ANK */ 379 It can, it SYNs are crossed. --ANK */
377 if (!sock_owned_by_user(sk)) { 380 if (!sock_owned_by_user(sk)) {
378 DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS); 381 DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
379 sk->sk_err = err; 382 sk->sk_err = err;
@@ -382,7 +385,6 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
382 * (see connect in sock.c) 385 * (see connect in sock.c)
383 */ 386 */
384 sk->sk_error_report(sk); 387 sk->sk_error_report(sk);
385
386 dccp_done(sk); 388 dccp_done(sk);
387 } else 389 } else
388 sk->sk_err_soft = err; 390 sk->sk_err_soft = err;
@@ -428,14 +430,16 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
428 ireq6->pktopts) { 430 ireq6->pktopts) {
429 struct sk_buff *pktopts = ireq6->pktopts; 431 struct sk_buff *pktopts = ireq6->pktopts;
430 struct inet6_skb_parm *rxopt = IP6CB(pktopts); 432 struct inet6_skb_parm *rxopt = IP6CB(pktopts);
433
431 if (rxopt->srcrt) 434 if (rxopt->srcrt)
432 opt = ipv6_invert_rthdr(sk, 435 opt = ipv6_invert_rthdr(sk,
433 (struct ipv6_rt_hdr *)(pktopts->nh.raw + 436 (struct ipv6_rt_hdr *)(pktopts->nh.raw +
434 rxopt->srcrt)); 437 rxopt->srcrt));
435 } 438 }
436 439
437 if (opt && opt->srcrt) { 440 if (opt != NULL && opt->srcrt != NULL) {
438 struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; 441 const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
442
439 ipv6_addr_copy(&final, &fl.fl6_dst); 443 ipv6_addr_copy(&final, &fl.fl6_dst);
440 ipv6_addr_copy(&fl.fl6_dst, rt0->addr); 444 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
441 final_p = &final; 445 final_p = &final;
@@ -444,15 +448,19 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
444 err = ip6_dst_lookup(sk, &dst, &fl); 448 err = ip6_dst_lookup(sk, &dst, &fl);
445 if (err) 449 if (err)
446 goto done; 450 goto done;
451
447 if (final_p) 452 if (final_p)
448 ipv6_addr_copy(&fl.fl6_dst, final_p); 453 ipv6_addr_copy(&fl.fl6_dst, final_p);
449 if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) 454
455 err = xfrm_lookup(&dst, &fl, sk, 0);
456 if (err < 0)
450 goto done; 457 goto done;
451 } 458 }
452 459
453 skb = dccp_make_response(sk, dst, req); 460 skb = dccp_make_response(sk, dst, req);
454 if (skb != NULL) { 461 if (skb != NULL) {
455 struct dccp_hdr *dh = dccp_hdr(skb); 462 struct dccp_hdr *dh = dccp_hdr(skb);
463
456 dh->dccph_checksum = dccp_v6_check(dh, skb->len, 464 dh->dccph_checksum = dccp_v6_check(dh, skb->len,
457 &ireq6->loc_addr, 465 &ireq6->loc_addr,
458 &ireq6->rmt_addr, 466 &ireq6->rmt_addr,
@@ -466,7 +474,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
466 } 474 }
467 475
468done: 476done:
469 if (opt && opt != np->opt) 477 if (opt != NULL && opt != np->opt)
470 sock_kfree_s(sk, opt, opt->tot_len); 478 sock_kfree_s(sk, opt, opt->tot_len);
471 dst_release(dst); 479 dst_release(dst);
472 return err; 480 return err;
@@ -497,7 +505,7 @@ static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb)
497 struct dccp_hdr *dh = dccp_hdr(skb); 505 struct dccp_hdr *dh = dccp_hdr(skb);
498 506
499 dh->dccph_checksum = csum_ipv6_magic(&np->saddr, &np->daddr, 507 dh->dccph_checksum = csum_ipv6_magic(&np->saddr, &np->daddr,
500 len, IPPROTO_DCCP, 508 len, IPPROTO_DCCP,
501 csum_partial((char *)dh, 509 csum_partial((char *)dh,
502 dh->dccph_doff << 2, 510 dh->dccph_doff << 2,
503 skb->csum)); 511 skb->csum));
@@ -505,8 +513,8 @@ static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb)
505 513
506static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb) 514static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
507{ 515{
508 struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh; 516 struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
509 const int dccp_hdr_reset_len = sizeof(struct dccp_hdr) + 517 const u32 dccp_hdr_reset_len = sizeof(struct dccp_hdr) +
510 sizeof(struct dccp_hdr_ext) + 518 sizeof(struct dccp_hdr_ext) +
511 sizeof(struct dccp_hdr_reset); 519 sizeof(struct dccp_hdr_reset);
512 struct sk_buff *skb; 520 struct sk_buff *skb;
@@ -517,20 +525,14 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
517 return; 525 return;
518 526
519 if (!ipv6_unicast_destination(rxskb)) 527 if (!ipv6_unicast_destination(rxskb))
520 return; 528 return;
521
522 /*
523 * We need to grab some memory, and put together an RST,
524 * and then put it into the queue to be sent.
525 */
526 529
527 skb = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + 530 skb = alloc_skb(dccp_v6_ctl_socket->sk->sk_prot->max_header,
528 dccp_hdr_reset_len, GFP_ATOMIC); 531 GFP_ATOMIC);
529 if (skb == NULL) 532 if (skb == NULL)
530 return; 533 return;
531 534
532 skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr) + 535 skb_reserve(skb, dccp_v6_ctl_socket->sk->sk_prot->max_header);
533 dccp_hdr_reset_len);
534 536
535 skb->h.raw = skb_push(skb, dccp_hdr_reset_len); 537 skb->h.raw = skb_push(skb, dccp_hdr_reset_len);
536 dh = dccp_hdr(skb); 538 dh = dccp_hdr(skb);
@@ -568,7 +570,7 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
568 /* sk = NULL, but it is safe for now. RST socket required. */ 570 /* sk = NULL, but it is safe for now. RST socket required. */
569 if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) { 571 if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
570 if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) { 572 if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
571 ip6_xmit(NULL, skb, &fl, NULL, 0); 573 ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0);
572 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); 574 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
573 DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS); 575 DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
574 return; 576 return;
@@ -578,22 +580,22 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
578 kfree_skb(skb); 580 kfree_skb(skb);
579} 581}
580 582
581static void dccp_v6_ctl_send_ack(struct sk_buff *rxskb) 583static void dccp_v6_reqsk_send_ack(struct sk_buff *rxskb,
584 struct request_sock *req)
582{ 585{
583 struct flowi fl; 586 struct flowi fl;
584 struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh; 587 struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
585 const int dccp_hdr_ack_len = sizeof(struct dccp_hdr) + 588 const u32 dccp_hdr_ack_len = sizeof(struct dccp_hdr) +
586 sizeof(struct dccp_hdr_ext) + 589 sizeof(struct dccp_hdr_ext) +
587 sizeof(struct dccp_hdr_ack_bits); 590 sizeof(struct dccp_hdr_ack_bits);
588 struct sk_buff *skb; 591 struct sk_buff *skb;
589 592
590 skb = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + 593 skb = alloc_skb(dccp_v6_ctl_socket->sk->sk_prot->max_header,
591 dccp_hdr_ack_len, GFP_ATOMIC); 594 GFP_ATOMIC);
592 if (skb == NULL) 595 if (skb == NULL)
593 return; 596 return;
594 597
595 skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr) + 598 skb_reserve(skb, dccp_v6_ctl_socket->sk->sk_prot->max_header);
596 dccp_hdr_ack_len);
597 599
598 skb->h.raw = skb_push(skb, dccp_hdr_ack_len); 600 skb->h.raw = skb_push(skb, dccp_hdr_ack_len);
599 dh = dccp_hdr(skb); 601 dh = dccp_hdr(skb);
@@ -605,7 +607,7 @@ static void dccp_v6_ctl_send_ack(struct sk_buff *rxskb)
605 dh->dccph_dport = rxdh->dccph_sport; 607 dh->dccph_dport = rxdh->dccph_sport;
606 dh->dccph_doff = dccp_hdr_ack_len / 4; 608 dh->dccph_doff = dccp_hdr_ack_len / 4;
607 dh->dccph_x = 1; 609 dh->dccph_x = 1;
608 610
609 dccp_hdr_set_seq(dh, DCCP_SKB_CB(rxskb)->dccpd_ack_seq); 611 dccp_hdr_set_seq(dh, DCCP_SKB_CB(rxskb)->dccpd_ack_seq);
610 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), 612 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
611 DCCP_SKB_CB(rxskb)->dccpd_seq); 613 DCCP_SKB_CB(rxskb)->dccpd_seq);
@@ -623,7 +625,7 @@ static void dccp_v6_ctl_send_ack(struct sk_buff *rxskb)
623 625
624 if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) { 626 if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
625 if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) { 627 if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
626 ip6_xmit(NULL, skb, &fl, NULL, 0); 628 ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0);
627 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); 629 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
628 return; 630 return;
629 } 631 }
@@ -632,12 +634,6 @@ static void dccp_v6_ctl_send_ack(struct sk_buff *rxskb)
632 kfree_skb(skb); 634 kfree_skb(skb);
633} 635}
634 636
635static void dccp_v6_reqsk_send_ack(struct sk_buff *skb,
636 struct request_sock *req)
637{
638 dccp_v6_ctl_send_ack(skb);
639}
640
641static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) 637static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
642{ 638{
643 const struct dccp_hdr *dh = dccp_hdr(skb); 639 const struct dccp_hdr *dh = dccp_hdr(skb);
@@ -657,7 +653,6 @@ static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
657 &iph->saddr, dh->dccph_sport, 653 &iph->saddr, dh->dccph_sport,
658 &iph->daddr, ntohs(dh->dccph_dport), 654 &iph->daddr, ntohs(dh->dccph_dport),
659 inet6_iif(skb)); 655 inet6_iif(skb));
660
661 if (nsk != NULL) { 656 if (nsk != NULL) {
662 if (nsk->sk_state != DCCP_TIME_WAIT) { 657 if (nsk->sk_state != DCCP_TIME_WAIT) {
663 bh_lock_sock(nsk); 658 bh_lock_sock(nsk);
@@ -678,7 +673,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
678 struct dccp_request_sock *dreq; 673 struct dccp_request_sock *dreq;
679 struct inet6_request_sock *ireq6; 674 struct inet6_request_sock *ireq6;
680 struct ipv6_pinfo *np = inet6_sk(sk); 675 struct ipv6_pinfo *np = inet6_sk(sk);
681 const __u32 service = dccp_hdr_request(skb)->dccph_req_service; 676 const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
682 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); 677 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
683 __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY; 678 __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
684 679
@@ -686,17 +681,17 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
686 return dccp_v4_conn_request(sk, skb); 681 return dccp_v4_conn_request(sk, skb);
687 682
688 if (!ipv6_unicast_destination(skb)) 683 if (!ipv6_unicast_destination(skb))
689 goto drop; 684 goto drop;
690 685
691 if (dccp_bad_service_code(sk, service)) { 686 if (dccp_bad_service_code(sk, service)) {
692 reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE; 687 reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
693 goto drop; 688 goto drop;
694 } 689 }
695 /* 690 /*
696 * There are no SYN attacks on IPv6, yet... 691 * There are no SYN attacks on IPv6, yet...
697 */ 692 */
698 if (inet_csk_reqsk_queue_is_full(sk)) 693 if (inet_csk_reqsk_queue_is_full(sk))
699 goto drop; 694 goto drop;
700 695
701 if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) 696 if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
702 goto drop; 697 goto drop;
@@ -730,7 +725,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
730 ipv6_addr_type(&ireq6->rmt_addr) & IPV6_ADDR_LINKLOCAL) 725 ipv6_addr_type(&ireq6->rmt_addr) & IPV6_ADDR_LINKLOCAL)
731 ireq6->iif = inet6_iif(skb); 726 ireq6->iif = inet6_iif(skb);
732 727
733 /* 728 /*
734 * Step 3: Process LISTEN state 729 * Step 3: Process LISTEN state
735 * 730 *
736 * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie 731 * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
@@ -774,9 +769,8 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
774 /* 769 /*
775 * v6 mapped 770 * v6 mapped
776 */ 771 */
777
778 newsk = dccp_v4_request_recv_sock(sk, skb, req, dst); 772 newsk = dccp_v4_request_recv_sock(sk, skb, req, dst);
779 if (newsk == NULL) 773 if (newsk == NULL)
780 return NULL; 774 return NULL;
781 775
782 newdp6 = (struct dccp6_sock *)newsk; 776 newdp6 = (struct dccp6_sock *)newsk;
@@ -822,9 +816,9 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
822 if (sk_acceptq_is_full(sk)) 816 if (sk_acceptq_is_full(sk))
823 goto out_overflow; 817 goto out_overflow;
824 818
825 if (np->rxopt.bits.osrcrt == 2 && 819 if (np->rxopt.bits.osrcrt == 2 && opt == NULL && ireq6->pktopts) {
826 opt == NULL && ireq6->pktopts) { 820 const struct inet6_skb_parm *rxopt = IP6CB(ireq6->pktopts);
827 struct inet6_skb_parm *rxopt = IP6CB(ireq6->pktopts); 821
828 if (rxopt->srcrt) 822 if (rxopt->srcrt)
829 opt = ipv6_invert_rthdr(sk, 823 opt = ipv6_invert_rthdr(sk,
830 (struct ipv6_rt_hdr *)(ireq6->pktopts->nh.raw + 824 (struct ipv6_rt_hdr *)(ireq6->pktopts->nh.raw +
@@ -838,8 +832,9 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
838 memset(&fl, 0, sizeof(fl)); 832 memset(&fl, 0, sizeof(fl));
839 fl.proto = IPPROTO_DCCP; 833 fl.proto = IPPROTO_DCCP;
840 ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); 834 ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
841 if (opt && opt->srcrt) { 835 if (opt != NULL && opt->srcrt != NULL) {
842 struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; 836 const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
837
843 ipv6_addr_copy(&final, &fl.fl6_dst); 838 ipv6_addr_copy(&final, &fl.fl6_dst);
844 ipv6_addr_copy(&fl.fl6_dst, rt0->addr); 839 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
845 final_p = &final; 840 final_p = &final;
@@ -857,7 +852,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
857 852
858 if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0) 853 if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0)
859 goto out; 854 goto out;
860 } 855 }
861 856
862 newsk = dccp_create_openreq_child(sk, req, skb); 857 newsk = dccp_create_openreq_child(sk, req, skb);
863 if (newsk == NULL) 858 if (newsk == NULL)
@@ -870,9 +865,8 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
870 */ 865 */
871 866
872 ip6_dst_store(newsk, dst, NULL); 867 ip6_dst_store(newsk, dst, NULL);
873 newsk->sk_route_caps = dst->dev->features & 868 newsk->sk_route_caps = dst->dev->features & ~(NETIF_F_IP_CSUM |
874 ~(NETIF_F_IP_CSUM | NETIF_F_TSO); 869 NETIF_F_TSO);
875
876 newdp6 = (struct dccp6_sock *)newsk; 870 newdp6 = (struct dccp6_sock *)newsk;
877 newinet = inet_sk(newsk); 871 newinet = inet_sk(newsk);
878 newinet->pinet6 = &newdp6->inet6; 872 newinet->pinet6 = &newdp6->inet6;
@@ -886,7 +880,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
886 ipv6_addr_copy(&newnp->rcv_saddr, &ireq6->loc_addr); 880 ipv6_addr_copy(&newnp->rcv_saddr, &ireq6->loc_addr);
887 newsk->sk_bound_dev_if = ireq6->iif; 881 newsk->sk_bound_dev_if = ireq6->iif;
888 882
889 /* Now IPv6 options... 883 /* Now IPv6 options...
890 884
891 First: no IPv4 options. 885 First: no IPv4 options.
892 */ 886 */
@@ -908,20 +902,20 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
908 newnp->mcast_oif = inet6_iif(skb); 902 newnp->mcast_oif = inet6_iif(skb);
909 newnp->mcast_hops = skb->nh.ipv6h->hop_limit; 903 newnp->mcast_hops = skb->nh.ipv6h->hop_limit;
910 904
911 /* Clone native IPv6 options from listening socket (if any) 905 /*
912 906 * Clone native IPv6 options from listening socket (if any)
913 Yes, keeping reference count would be much more clever, 907 *
914 but we make one more one thing there: reattach optmem 908 * Yes, keeping reference count would be much more clever, but we make
915 to newsk. 909 * one more one thing there: reattach optmem to newsk.
916 */ 910 */
917 if (opt) { 911 if (opt != NULL) {
918 newnp->opt = ipv6_dup_options(newsk, opt); 912 newnp->opt = ipv6_dup_options(newsk, opt);
919 if (opt != np->opt) 913 if (opt != np->opt)
920 sock_kfree_s(sk, opt, opt->tot_len); 914 sock_kfree_s(sk, opt, opt->tot_len);
921 } 915 }
922 916
923 inet_csk(newsk)->icsk_ext_hdr_len = 0; 917 inet_csk(newsk)->icsk_ext_hdr_len = 0;
924 if (newnp->opt) 918 if (newnp->opt != NULL)
925 inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen + 919 inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen +
926 newnp->opt->opt_flen); 920 newnp->opt->opt_flen);
927 921
@@ -938,7 +932,7 @@ out_overflow:
938 NET_INC_STATS_BH(LINUX_MIB_LISTENOVERFLOWS); 932 NET_INC_STATS_BH(LINUX_MIB_LISTENOVERFLOWS);
939out: 933out:
940 NET_INC_STATS_BH(LINUX_MIB_LISTENDROPS); 934 NET_INC_STATS_BH(LINUX_MIB_LISTENDROPS);
941 if (opt && opt != np->opt) 935 if (opt != NULL && opt != np->opt)
942 sock_kfree_s(sk, opt, opt->tot_len); 936 sock_kfree_s(sk, opt, opt->tot_len);
943 dst_release(dst); 937 dst_release(dst);
944 return NULL; 938 return NULL;
@@ -972,8 +966,8 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
972 goto discard; 966 goto discard;
973 967
974 /* 968 /*
975 * socket locking is here for SMP purposes as backlog rcv 969 * socket locking is here for SMP purposes as backlog rcv is currently
976 * is currently called with bh processing disabled. 970 * called with bh processing disabled.
977 */ 971 */
978 972
979 /* Do Stevens' IPV6_PKTOPTIONS. 973 /* Do Stevens' IPV6_PKTOPTIONS.
@@ -998,20 +992,20 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
998 return 0; 992 return 0;
999 } 993 }
1000 994
1001 if (sk->sk_state == DCCP_LISTEN) { 995 if (sk->sk_state == DCCP_LISTEN) {
1002 struct sock *nsk = dccp_v6_hnd_req(sk, skb); 996 struct sock *nsk = dccp_v6_hnd_req(sk, skb);
1003 if (!nsk)
1004 goto discard;
1005 997
998 if (nsk == NULL)
999 goto discard;
1006 /* 1000 /*
1007 * Queue it on the new socket if the new socket is active, 1001 * Queue it on the new socket if the new socket is active,
1008 * otherwise we just shortcircuit this and continue with 1002 * otherwise we just shortcircuit this and continue with
1009 * the new socket.. 1003 * the new socket..
1010 */ 1004 */
1011 if(nsk != sk) { 1005 if (nsk != sk) {
1012 if (dccp_child_process(sk, nsk, skb)) 1006 if (dccp_child_process(sk, nsk, skb))
1013 goto reset; 1007 goto reset;
1014 if (opt_skb) 1008 if (opt_skb != NULL)
1015 __kfree_skb(opt_skb); 1009 __kfree_skb(opt_skb);
1016 return 0; 1010 return 0;
1017 } 1011 }
@@ -1024,7 +1018,7 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
1024reset: 1018reset:
1025 dccp_v6_ctl_send_reset(skb); 1019 dccp_v6_ctl_send_reset(skb);
1026discard: 1020discard:
1027 if (opt_skb) 1021 if (opt_skb != NULL)
1028 __kfree_skb(opt_skb); 1022 __kfree_skb(opt_skb);
1029 kfree_skb(skb); 1023 kfree_skb(skb);
1030 return 0; 1024 return 0;
@@ -1057,7 +1051,7 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
1057 dh->dccph_sport, 1051 dh->dccph_sport,
1058 &skb->nh.ipv6h->daddr, ntohs(dh->dccph_dport), 1052 &skb->nh.ipv6h->daddr, ntohs(dh->dccph_dport),
1059 inet6_iif(skb)); 1053 inet6_iif(skb));
1060 /* 1054 /*
1061 * Step 2: 1055 * Step 2:
1062 * If no socket ... 1056 * If no socket ...
1063 * Generate Reset(No Connection) unless P.type == Reset 1057 * Generate Reset(No Connection) unless P.type == Reset
@@ -1066,15 +1060,14 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
1066 if (sk == NULL) 1060 if (sk == NULL)
1067 goto no_dccp_socket; 1061 goto no_dccp_socket;
1068 1062
1069 /* 1063 /*
1070 * Step 2: 1064 * Step 2:
1071 * ... or S.state == TIMEWAIT, 1065 * ... or S.state == TIMEWAIT,
1072 * Generate Reset(No Connection) unless P.type == Reset 1066 * Generate Reset(No Connection) unless P.type == Reset
1073 * Drop packet and return 1067 * Drop packet and return
1074 */ 1068 */
1075
1076 if (sk->sk_state == DCCP_TIME_WAIT) 1069 if (sk->sk_state == DCCP_TIME_WAIT)
1077 goto do_time_wait; 1070 goto do_time_wait;
1078 1071
1079 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) 1072 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
1080 goto discard_and_relse; 1073 goto discard_and_relse;
@@ -1113,32 +1106,40 @@ do_time_wait:
1113} 1106}
1114 1107
1115static struct inet_connection_sock_af_ops dccp_ipv6_af_ops = { 1108static struct inet_connection_sock_af_ops dccp_ipv6_af_ops = {
1116 .queue_xmit = inet6_csk_xmit, 1109 .queue_xmit = inet6_csk_xmit,
1117 .send_check = dccp_v6_send_check, 1110 .send_check = dccp_v6_send_check,
1118 .rebuild_header = inet6_sk_rebuild_header, 1111 .rebuild_header = inet6_sk_rebuild_header,
1119 .conn_request = dccp_v6_conn_request, 1112 .conn_request = dccp_v6_conn_request,
1120 .syn_recv_sock = dccp_v6_request_recv_sock, 1113 .syn_recv_sock = dccp_v6_request_recv_sock,
1121 .net_header_len = sizeof(struct ipv6hdr), 1114 .net_header_len = sizeof(struct ipv6hdr),
1122 .setsockopt = ipv6_setsockopt, 1115 .setsockopt = ipv6_setsockopt,
1123 .getsockopt = ipv6_getsockopt, 1116 .getsockopt = ipv6_getsockopt,
1124 .addr2sockaddr = inet6_csk_addr2sockaddr, 1117 .addr2sockaddr = inet6_csk_addr2sockaddr,
1125 .sockaddr_len = sizeof(struct sockaddr_in6) 1118 .sockaddr_len = sizeof(struct sockaddr_in6),
1119#ifdef CONFIG_COMPAT
1120 .compat_setsockopt = compat_ipv6_setsockopt,
1121 .compat_getsockopt = compat_ipv6_getsockopt,
1122#endif
1126}; 1123};
1127 1124
1128/* 1125/*
1129 * DCCP over IPv4 via INET6 API 1126 * DCCP over IPv4 via INET6 API
1130 */ 1127 */
1131static struct inet_connection_sock_af_ops dccp_ipv6_mapped = { 1128static struct inet_connection_sock_af_ops dccp_ipv6_mapped = {
1132 .queue_xmit = ip_queue_xmit, 1129 .queue_xmit = ip_queue_xmit,
1133 .send_check = dccp_v4_send_check, 1130 .send_check = dccp_v4_send_check,
1134 .rebuild_header = inet_sk_rebuild_header, 1131 .rebuild_header = inet_sk_rebuild_header,
1135 .conn_request = dccp_v6_conn_request, 1132 .conn_request = dccp_v6_conn_request,
1136 .syn_recv_sock = dccp_v6_request_recv_sock, 1133 .syn_recv_sock = dccp_v6_request_recv_sock,
1137 .net_header_len = sizeof(struct iphdr), 1134 .net_header_len = sizeof(struct iphdr),
1138 .setsockopt = ipv6_setsockopt, 1135 .setsockopt = ipv6_setsockopt,
1139 .getsockopt = ipv6_getsockopt, 1136 .getsockopt = ipv6_getsockopt,
1140 .addr2sockaddr = inet6_csk_addr2sockaddr, 1137 .addr2sockaddr = inet6_csk_addr2sockaddr,
1141 .sockaddr_len = sizeof(struct sockaddr_in6) 1138 .sockaddr_len = sizeof(struct sockaddr_in6),
1139#ifdef CONFIG_COMPAT
1140 .compat_setsockopt = compat_ipv6_setsockopt,
1141 .compat_getsockopt = compat_ipv6_getsockopt,
1142#endif
1142}; 1143};
1143 1144
1144/* NOTE: A lot of things set to zero explicitly by call to 1145/* NOTE: A lot of things set to zero explicitly by call to
@@ -1146,71 +1147,83 @@ static struct inet_connection_sock_af_ops dccp_ipv6_mapped = {
1146 */ 1147 */
1147static int dccp_v6_init_sock(struct sock *sk) 1148static int dccp_v6_init_sock(struct sock *sk)
1148{ 1149{
1149 int err = dccp_v4_init_sock(sk); 1150 static __u8 dccp_v6_ctl_sock_initialized;
1151 int err = dccp_init_sock(sk, dccp_v6_ctl_sock_initialized);
1150 1152
1151 if (err == 0) 1153 if (err == 0) {
1154 if (unlikely(!dccp_v6_ctl_sock_initialized))
1155 dccp_v6_ctl_sock_initialized = 1;
1152 inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops; 1156 inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops;
1157 }
1153 1158
1154 return err; 1159 return err;
1155} 1160}
1156 1161
1157static int dccp_v6_destroy_sock(struct sock *sk) 1162static int dccp_v6_destroy_sock(struct sock *sk)
1158{ 1163{
1159 dccp_v4_destroy_sock(sk); 1164 dccp_destroy_sock(sk);
1160 return inet6_destroy_sock(sk); 1165 return inet6_destroy_sock(sk);
1161} 1166}
1162 1167
1163static struct proto dccp_v6_prot = { 1168static struct proto dccp_v6_prot = {
1164 .name = "DCCPv6", 1169 .name = "DCCPv6",
1165 .owner = THIS_MODULE, 1170 .owner = THIS_MODULE,
1166 .close = dccp_close, 1171 .close = dccp_close,
1167 .connect = dccp_v6_connect, 1172 .connect = dccp_v6_connect,
1168 .disconnect = dccp_disconnect, 1173 .disconnect = dccp_disconnect,
1169 .ioctl = dccp_ioctl, 1174 .ioctl = dccp_ioctl,
1170 .init = dccp_v6_init_sock, 1175 .init = dccp_v6_init_sock,
1171 .setsockopt = dccp_setsockopt, 1176 .setsockopt = dccp_setsockopt,
1172 .getsockopt = dccp_getsockopt, 1177 .getsockopt = dccp_getsockopt,
1173 .sendmsg = dccp_sendmsg, 1178 .sendmsg = dccp_sendmsg,
1174 .recvmsg = dccp_recvmsg, 1179 .recvmsg = dccp_recvmsg,
1175 .backlog_rcv = dccp_v6_do_rcv, 1180 .backlog_rcv = dccp_v6_do_rcv,
1176 .hash = dccp_v6_hash, 1181 .hash = dccp_v6_hash,
1177 .unhash = dccp_unhash, 1182 .unhash = dccp_unhash,
1178 .accept = inet_csk_accept, 1183 .accept = inet_csk_accept,
1179 .get_port = dccp_v6_get_port, 1184 .get_port = dccp_v6_get_port,
1180 .shutdown = dccp_shutdown, 1185 .shutdown = dccp_shutdown,
1181 .destroy = dccp_v6_destroy_sock, 1186 .destroy = dccp_v6_destroy_sock,
1182 .orphan_count = &dccp_orphan_count, 1187 .orphan_count = &dccp_orphan_count,
1183 .max_header = MAX_DCCP_HEADER, 1188 .max_header = MAX_DCCP_HEADER,
1184 .obj_size = sizeof(struct dccp6_sock), 1189 .obj_size = sizeof(struct dccp6_sock),
1185 .rsk_prot = &dccp6_request_sock_ops, 1190 .rsk_prot = &dccp6_request_sock_ops,
1186 .twsk_prot = &dccp6_timewait_sock_ops, 1191 .twsk_prot = &dccp6_timewait_sock_ops,
1192#ifdef CONFIG_COMPAT
1193 .compat_setsockopt = compat_dccp_setsockopt,
1194 .compat_getsockopt = compat_dccp_getsockopt,
1195#endif
1187}; 1196};
1188 1197
1189static struct inet6_protocol dccp_v6_protocol = { 1198static struct inet6_protocol dccp_v6_protocol = {
1190 .handler = dccp_v6_rcv, 1199 .handler = dccp_v6_rcv,
1191 .err_handler = dccp_v6_err, 1200 .err_handler = dccp_v6_err,
1192 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL, 1201 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL,
1193}; 1202};
1194 1203
1195static struct proto_ops inet6_dccp_ops = { 1204static struct proto_ops inet6_dccp_ops = {
1196 .family = PF_INET6, 1205 .family = PF_INET6,
1197 .owner = THIS_MODULE, 1206 .owner = THIS_MODULE,
1198 .release = inet6_release, 1207 .release = inet6_release,
1199 .bind = inet6_bind, 1208 .bind = inet6_bind,
1200 .connect = inet_stream_connect, 1209 .connect = inet_stream_connect,
1201 .socketpair = sock_no_socketpair, 1210 .socketpair = sock_no_socketpair,
1202 .accept = inet_accept, 1211 .accept = inet_accept,
1203 .getname = inet6_getname, 1212 .getname = inet6_getname,
1204 .poll = dccp_poll, 1213 .poll = dccp_poll,
1205 .ioctl = inet6_ioctl, 1214 .ioctl = inet6_ioctl,
1206 .listen = inet_dccp_listen, 1215 .listen = inet_dccp_listen,
1207 .shutdown = inet_shutdown, 1216 .shutdown = inet_shutdown,
1208 .setsockopt = sock_common_setsockopt, 1217 .setsockopt = sock_common_setsockopt,
1209 .getsockopt = sock_common_getsockopt, 1218 .getsockopt = sock_common_getsockopt,
1210 .sendmsg = inet_sendmsg, 1219 .sendmsg = inet_sendmsg,
1211 .recvmsg = sock_common_recvmsg, 1220 .recvmsg = sock_common_recvmsg,
1212 .mmap = sock_no_mmap, 1221 .mmap = sock_no_mmap,
1213 .sendpage = sock_no_sendpage, 1222 .sendpage = sock_no_sendpage,
1223#ifdef CONFIG_COMPAT
1224 .compat_setsockopt = compat_sock_common_setsockopt,
1225 .compat_getsockopt = compat_sock_common_getsockopt,
1226#endif
1214}; 1227};
1215 1228
1216static struct inet_protosw dccp_v6_protosw = { 1229static struct inet_protosw dccp_v6_protosw = {
@@ -1234,8 +1247,16 @@ static int __init dccp_v6_init(void)
1234 goto out_unregister_proto; 1247 goto out_unregister_proto;
1235 1248
1236 inet6_register_protosw(&dccp_v6_protosw); 1249 inet6_register_protosw(&dccp_v6_protosw);
1250
1251 err = inet_csk_ctl_sock_create(&dccp_v6_ctl_socket, PF_INET6,
1252 SOCK_DCCP, IPPROTO_DCCP);
1253 if (err != 0)
1254 goto out_unregister_protosw;
1237out: 1255out:
1238 return err; 1256 return err;
1257out_unregister_protosw:
1258 inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
1259 inet6_unregister_protosw(&dccp_v6_protosw);
1239out_unregister_proto: 1260out_unregister_proto:
1240 proto_unregister(&dccp_v6_prot); 1261 proto_unregister(&dccp_v6_prot);
1241 goto out; 1262 goto out;
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index 29261fc198e7..c0349e5b0551 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -22,6 +22,7 @@
22#include "ackvec.h" 22#include "ackvec.h"
23#include "ccid.h" 23#include "ccid.h"
24#include "dccp.h" 24#include "dccp.h"
25#include "feat.h"
25 26
26struct inet_timewait_death_row dccp_death_row = { 27struct inet_timewait_death_row dccp_death_row = {
27 .sysctl_max_tw_buckets = NR_FILE * 2, 28 .sysctl_max_tw_buckets = NR_FILE * 2,
@@ -106,6 +107,7 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
106 const struct dccp_request_sock *dreq = dccp_rsk(req); 107 const struct dccp_request_sock *dreq = dccp_rsk(req);
107 struct inet_connection_sock *newicsk = inet_csk(sk); 108 struct inet_connection_sock *newicsk = inet_csk(sk);
108 struct dccp_sock *newdp = dccp_sk(newsk); 109 struct dccp_sock *newdp = dccp_sk(newsk);
110 struct dccp_minisock *newdmsk = dccp_msk(newsk);
109 111
110 newdp->dccps_role = DCCP_ROLE_SERVER; 112 newdp->dccps_role = DCCP_ROLE_SERVER;
111 newdp->dccps_hc_rx_ackvec = NULL; 113 newdp->dccps_hc_rx_ackvec = NULL;
@@ -114,27 +116,27 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
114 newicsk->icsk_rto = DCCP_TIMEOUT_INIT; 116 newicsk->icsk_rto = DCCP_TIMEOUT_INIT;
115 do_gettimeofday(&newdp->dccps_epoch); 117 do_gettimeofday(&newdp->dccps_epoch);
116 118
117 if (newdp->dccps_options.dccpo_send_ack_vector) { 119 if (dccp_feat_clone(sk, newsk))
120 goto out_free;
121
122 if (newdmsk->dccpms_send_ack_vector) {
118 newdp->dccps_hc_rx_ackvec = 123 newdp->dccps_hc_rx_ackvec =
119 dccp_ackvec_alloc(DCCP_MAX_ACKVEC_LEN, 124 dccp_ackvec_alloc(GFP_ATOMIC);
120 GFP_ATOMIC);
121 /*
122 * XXX: We're using the same CCIDs set on the parent,
123 * i.e. sk_clone copied the master sock and left the
124 * CCID pointers for this child, that is why we do the
125 * __ccid_get calls.
126 */
127 if (unlikely(newdp->dccps_hc_rx_ackvec == NULL)) 125 if (unlikely(newdp->dccps_hc_rx_ackvec == NULL))
128 goto out_free; 126 goto out_free;
129 } 127 }
130 128
131 if (unlikely(ccid_hc_rx_init(newdp->dccps_hc_rx_ccid, 129 newdp->dccps_hc_rx_ccid =
132 newsk) != 0 || 130 ccid_hc_rx_new(newdmsk->dccpms_rx_ccid,
133 ccid_hc_tx_init(newdp->dccps_hc_tx_ccid, 131 newsk, GFP_ATOMIC);
134 newsk) != 0)) { 132 newdp->dccps_hc_tx_ccid =
133 ccid_hc_tx_new(newdmsk->dccpms_tx_ccid,
134 newsk, GFP_ATOMIC);
135 if (unlikely(newdp->dccps_hc_rx_ccid == NULL ||
136 newdp->dccps_hc_tx_ccid == NULL)) {
135 dccp_ackvec_free(newdp->dccps_hc_rx_ackvec); 137 dccp_ackvec_free(newdp->dccps_hc_rx_ackvec);
136 ccid_hc_rx_exit(newdp->dccps_hc_rx_ccid, newsk); 138 ccid_hc_rx_delete(newdp->dccps_hc_rx_ccid, newsk);
137 ccid_hc_tx_exit(newdp->dccps_hc_tx_ccid, newsk); 139 ccid_hc_tx_delete(newdp->dccps_hc_tx_ccid, newsk);
138out_free: 140out_free:
139 /* It is still raw copy of parent, so invalidate 141 /* It is still raw copy of parent, so invalidate
140 * destructor and make plain sk_free() */ 142 * destructor and make plain sk_free() */
@@ -143,9 +145,6 @@ out_free:
143 return NULL; 145 return NULL;
144 } 146 }
145 147
146 __ccid_get(newdp->dccps_hc_rx_ccid);
147 __ccid_get(newdp->dccps_hc_tx_ccid);
148
149 /* 148 /*
150 * Step 3: Process LISTEN state 149 * Step 3: Process LISTEN state
151 * 150 *
@@ -155,7 +154,7 @@ out_free:
155 */ 154 */
156 155
157 /* See dccp_v4_conn_request */ 156 /* See dccp_v4_conn_request */
158 newdp->dccps_options.dccpo_sequence_window = req->rcv_wnd; 157 newdmsk->dccpms_sequence_window = req->rcv_wnd;
159 158
160 newdp->dccps_gar = newdp->dccps_isr = dreq->dreq_isr; 159 newdp->dccps_gar = newdp->dccps_isr = dreq->dreq_isr;
161 dccp_update_gsr(newsk, dreq->dreq_isr); 160 dccp_update_gsr(newsk, dreq->dreq_isr);
diff --git a/net/dccp/options.c b/net/dccp/options.c
index 0a76426c9aea..e9feb2a0c770 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -21,19 +21,23 @@
21#include "ackvec.h" 21#include "ackvec.h"
22#include "ccid.h" 22#include "ccid.h"
23#include "dccp.h" 23#include "dccp.h"
24#include "feat.h"
24 25
25/* stores the default values for new connection. may be changed with sysctl */ 26int dccp_feat_default_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW;
26static const struct dccp_options dccpo_default_values = { 27int dccp_feat_default_rx_ccid = DCCPF_INITIAL_CCID;
27 .dccpo_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW, 28int dccp_feat_default_tx_ccid = DCCPF_INITIAL_CCID;
28 .dccpo_rx_ccid = DCCPF_INITIAL_CCID, 29int dccp_feat_default_ack_ratio = DCCPF_INITIAL_ACK_RATIO;
29 .dccpo_tx_ccid = DCCPF_INITIAL_CCID, 30int dccp_feat_default_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR;
30 .dccpo_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR, 31int dccp_feat_default_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT;
31 .dccpo_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT,
32};
33 32
34void dccp_options_init(struct dccp_options *dccpo) 33void dccp_minisock_init(struct dccp_minisock *dmsk)
35{ 34{
36 memcpy(dccpo, &dccpo_default_values, sizeof(*dccpo)); 35 dmsk->dccpms_sequence_window = dccp_feat_default_sequence_window;
36 dmsk->dccpms_rx_ccid = dccp_feat_default_rx_ccid;
37 dmsk->dccpms_tx_ccid = dccp_feat_default_tx_ccid;
38 dmsk->dccpms_ack_ratio = dccp_feat_default_ack_ratio;
39 dmsk->dccpms_send_ack_vector = dccp_feat_default_send_ack_vector;
40 dmsk->dccpms_send_ndp_count = dccp_feat_default_send_ndp_count;
37} 41}
38 42
39static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len) 43static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len)
@@ -69,9 +73,12 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
69 unsigned char opt, len; 73 unsigned char opt, len;
70 unsigned char *value; 74 unsigned char *value;
71 u32 elapsed_time; 75 u32 elapsed_time;
76 int rc;
77 int mandatory = 0;
72 78
73 memset(opt_recv, 0, sizeof(*opt_recv)); 79 memset(opt_recv, 0, sizeof(*opt_recv));
74 80
81 opt = len = 0;
75 while (opt_ptr != opt_end) { 82 while (opt_ptr != opt_end) {
76 opt = *opt_ptr++; 83 opt = *opt_ptr++;
77 len = 0; 84 len = 0;
@@ -100,6 +107,12 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
100 switch (opt) { 107 switch (opt) {
101 case DCCPO_PADDING: 108 case DCCPO_PADDING:
102 break; 109 break;
110 case DCCPO_MANDATORY:
111 if (mandatory)
112 goto out_invalid_option;
113 if (pkt_type != DCCP_PKT_DATA)
114 mandatory = 1;
115 break;
103 case DCCPO_NDP_COUNT: 116 case DCCPO_NDP_COUNT:
104 if (len > 3) 117 if (len > 3)
105 goto out_invalid_option; 118 goto out_invalid_option;
@@ -108,12 +121,37 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
108 dccp_pr_debug("%sNDP count=%d\n", debug_prefix, 121 dccp_pr_debug("%sNDP count=%d\n", debug_prefix,
109 opt_recv->dccpor_ndp); 122 opt_recv->dccpor_ndp);
110 break; 123 break;
124 case DCCPO_CHANGE_L:
125 /* fall through */
126 case DCCPO_CHANGE_R:
127 if (len < 2)
128 goto out_invalid_option;
129 rc = dccp_feat_change_recv(sk, opt, *value, value + 1,
130 len - 1);
131 /*
132 * When there is a change error, change_recv is
133 * responsible for dealing with it. i.e. reply with an
134 * empty confirm.
135 * If the change was mandatory, then we need to die.
136 */
137 if (rc && mandatory)
138 goto out_invalid_option;
139 break;
140 case DCCPO_CONFIRM_L:
141 /* fall through */
142 case DCCPO_CONFIRM_R:
143 if (len < 2)
144 goto out_invalid_option;
145 if (dccp_feat_confirm_recv(sk, opt, *value,
146 value + 1, len - 1))
147 goto out_invalid_option;
148 break;
111 case DCCPO_ACK_VECTOR_0: 149 case DCCPO_ACK_VECTOR_0:
112 case DCCPO_ACK_VECTOR_1: 150 case DCCPO_ACK_VECTOR_1:
113 if (pkt_type == DCCP_PKT_DATA) 151 if (pkt_type == DCCP_PKT_DATA)
114 continue; 152 break;
115 153
116 if (dp->dccps_options.dccpo_send_ack_vector && 154 if (dccp_msk(sk)->dccpms_send_ack_vector &&
117 dccp_ackvec_parse(sk, skb, opt, value, len)) 155 dccp_ackvec_parse(sk, skb, opt, value, len))
118 goto out_invalid_option; 156 goto out_invalid_option;
119 break; 157 break;
@@ -121,7 +159,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
121 if (len != 4) 159 if (len != 4)
122 goto out_invalid_option; 160 goto out_invalid_option;
123 161
124 opt_recv->dccpor_timestamp = ntohl(*(u32 *)value); 162 opt_recv->dccpor_timestamp = ntohl(*(__be32 *)value);
125 163
126 dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp; 164 dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp;
127 dccp_timestamp(sk, &dp->dccps_timestamp_time); 165 dccp_timestamp(sk, &dp->dccps_timestamp_time);
@@ -135,7 +173,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
135 if (len != 4 && len != 6 && len != 8) 173 if (len != 4 && len != 6 && len != 8)
136 goto out_invalid_option; 174 goto out_invalid_option;
137 175
138 opt_recv->dccpor_timestamp_echo = ntohl(*(u32 *)value); 176 opt_recv->dccpor_timestamp_echo = ntohl(*(__be32 *)value);
139 177
140 dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, ackno=%llu, ", 178 dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, ackno=%llu, ",
141 debug_prefix, 179 debug_prefix,
@@ -149,9 +187,9 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
149 break; 187 break;
150 188
151 if (len == 6) 189 if (len == 6)
152 elapsed_time = ntohs(*(u16 *)(value + 4)); 190 elapsed_time = ntohs(*(__be16 *)(value + 4));
153 else 191 else
154 elapsed_time = ntohl(*(u32 *)(value + 4)); 192 elapsed_time = ntohl(*(__be32 *)(value + 4));
155 193
156 /* Give precedence to the biggest ELAPSED_TIME */ 194 /* Give precedence to the biggest ELAPSED_TIME */
157 if (elapsed_time > opt_recv->dccpor_elapsed_time) 195 if (elapsed_time > opt_recv->dccpor_elapsed_time)
@@ -165,9 +203,9 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
165 continue; 203 continue;
166 204
167 if (len == 2) 205 if (len == 2)
168 elapsed_time = ntohs(*(u16 *)value); 206 elapsed_time = ntohs(*(__be16 *)value);
169 else 207 else
170 elapsed_time = ntohl(*(u32 *)value); 208 elapsed_time = ntohl(*(__be32 *)value);
171 209
172 if (elapsed_time > opt_recv->dccpor_elapsed_time) 210 if (elapsed_time > opt_recv->dccpor_elapsed_time)
173 opt_recv->dccpor_elapsed_time = elapsed_time; 211 opt_recv->dccpor_elapsed_time = elapsed_time;
@@ -208,8 +246,15 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
208 sk, opt, len); 246 sk, opt, len);
209 break; 247 break;
210 } 248 }
249
250 if (opt != DCCPO_MANDATORY)
251 mandatory = 0;
211 } 252 }
212 253
254 /* mandatory was the last byte in option list -> reset connection */
255 if (mandatory)
256 goto out_invalid_option;
257
213 return 0; 258 return 0;
214 259
215out_invalid_option: 260out_invalid_option:
@@ -219,6 +264,8 @@ out_invalid_option:
219 return -1; 264 return -1;
220} 265}
221 266
267EXPORT_SYMBOL_GPL(dccp_parse_options);
268
222static void dccp_encode_value_var(const u32 value, unsigned char *to, 269static void dccp_encode_value_var(const u32 value, unsigned char *to,
223 const unsigned int len) 270 const unsigned int len)
224{ 271{
@@ -237,17 +284,14 @@ static inline int dccp_ndp_len(const int ndp)
237 return likely(ndp <= 0xFF) ? 1 : ndp <= 0xFFFF ? 2 : 3; 284 return likely(ndp <= 0xFF) ? 1 : ndp <= 0xFFFF ? 2 : 3;
238} 285}
239 286
240void dccp_insert_option(struct sock *sk, struct sk_buff *skb, 287int dccp_insert_option(struct sock *sk, struct sk_buff *skb,
241 const unsigned char option, 288 const unsigned char option,
242 const void *value, const unsigned char len) 289 const void *value, const unsigned char len)
243{ 290{
244 unsigned char *to; 291 unsigned char *to;
245 292
246 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 2 > DCCP_MAX_OPT_LEN) { 293 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 2 > DCCP_MAX_OPT_LEN)
247 LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert " 294 return -1;
248 "%d option!\n", option);
249 return;
250 }
251 295
252 DCCP_SKB_CB(skb)->dccpd_opt_len += len + 2; 296 DCCP_SKB_CB(skb)->dccpd_opt_len += len + 2;
253 297
@@ -256,11 +300,12 @@ void dccp_insert_option(struct sock *sk, struct sk_buff *skb,
256 *to++ = len + 2; 300 *to++ = len + 2;
257 301
258 memcpy(to, value, len); 302 memcpy(to, value, len);
303 return 0;
259} 304}
260 305
261EXPORT_SYMBOL_GPL(dccp_insert_option); 306EXPORT_SYMBOL_GPL(dccp_insert_option);
262 307
263static void dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb) 308static int dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
264{ 309{
265 struct dccp_sock *dp = dccp_sk(sk); 310 struct dccp_sock *dp = dccp_sk(sk);
266 int ndp = dp->dccps_ndp_count; 311 int ndp = dp->dccps_ndp_count;
@@ -276,7 +321,7 @@ static void dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
276 const int len = ndp_len + 2; 321 const int len = ndp_len + 2;
277 322
278 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) 323 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
279 return; 324 return -1;
280 325
281 DCCP_SKB_CB(skb)->dccpd_opt_len += len; 326 DCCP_SKB_CB(skb)->dccpd_opt_len += len;
282 327
@@ -285,6 +330,8 @@ static void dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
285 *ptr++ = len; 330 *ptr++ = len;
286 dccp_encode_value_var(ndp, ptr, ndp_len); 331 dccp_encode_value_var(ndp, ptr, ndp_len);
287 } 332 }
333
334 return 0;
288} 335}
289 336
290static inline int dccp_elapsed_time_len(const u32 elapsed_time) 337static inline int dccp_elapsed_time_len(const u32 elapsed_time)
@@ -292,27 +339,18 @@ static inline int dccp_elapsed_time_len(const u32 elapsed_time)
292 return elapsed_time == 0 ? 0 : elapsed_time <= 0xFFFF ? 2 : 4; 339 return elapsed_time == 0 ? 0 : elapsed_time <= 0xFFFF ? 2 : 4;
293} 340}
294 341
295void dccp_insert_option_elapsed_time(struct sock *sk, 342int dccp_insert_option_elapsed_time(struct sock *sk, struct sk_buff *skb,
296 struct sk_buff *skb, 343 u32 elapsed_time)
297 u32 elapsed_time)
298{ 344{
299#ifdef CONFIG_IP_DCCP_DEBUG
300 struct dccp_sock *dp = dccp_sk(sk);
301 const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
302 "CLIENT TX opt: " : "server TX opt: ";
303#endif
304 const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time); 345 const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
305 const int len = 2 + elapsed_time_len; 346 const int len = 2 + elapsed_time_len;
306 unsigned char *to; 347 unsigned char *to;
307 348
308 if (elapsed_time_len == 0) 349 if (elapsed_time_len == 0)
309 return; 350 return 0;
310 351
311 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { 352 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
312 LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to " 353 return -1;
313 "insert elapsed time!\n");
314 return;
315 }
316 354
317 DCCP_SKB_CB(skb)->dccpd_opt_len += len; 355 DCCP_SKB_CB(skb)->dccpd_opt_len += len;
318 356
@@ -321,17 +359,14 @@ void dccp_insert_option_elapsed_time(struct sock *sk,
321 *to++ = len; 359 *to++ = len;
322 360
323 if (elapsed_time_len == 2) { 361 if (elapsed_time_len == 2) {
324 const u16 var16 = htons((u16)elapsed_time); 362 const __be16 var16 = htons((u16)elapsed_time);
325 memcpy(to, &var16, 2); 363 memcpy(to, &var16, 2);
326 } else { 364 } else {
327 const u32 var32 = htonl(elapsed_time); 365 const __be32 var32 = htonl(elapsed_time);
328 memcpy(to, &var32, 4); 366 memcpy(to, &var32, 4);
329 } 367 }
330 368
331 dccp_pr_debug("%sELAPSED_TIME=%u, len=%d, seqno=%llu\n", 369 return 0;
332 debug_prefix, elapsed_time,
333 len,
334 (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq);
335} 370}
336 371
337EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time); 372EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time);
@@ -352,32 +387,27 @@ void dccp_timestamp(const struct sock *sk, struct timeval *tv)
352 387
353EXPORT_SYMBOL_GPL(dccp_timestamp); 388EXPORT_SYMBOL_GPL(dccp_timestamp);
354 389
355void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb) 390int dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb)
356{ 391{
357 struct timeval tv; 392 struct timeval tv;
358 u32 now; 393 __be32 now;
359 394
360 dccp_timestamp(sk, &tv); 395 dccp_timestamp(sk, &tv);
361 now = timeval_usecs(&tv) / 10; 396 now = htonl(timeval_usecs(&tv) / 10);
362 /* yes this will overflow but that is the point as we want a 397 /* yes this will overflow but that is the point as we want a
363 * 10 usec 32 bit timer which mean it wraps every 11.9 hours */ 398 * 10 usec 32 bit timer which mean it wraps every 11.9 hours */
364 399
365 now = htonl(now); 400 return dccp_insert_option(sk, skb, DCCPO_TIMESTAMP, &now, sizeof(now));
366 dccp_insert_option(sk, skb, DCCPO_TIMESTAMP, &now, sizeof(now));
367} 401}
368 402
369EXPORT_SYMBOL_GPL(dccp_insert_option_timestamp); 403EXPORT_SYMBOL_GPL(dccp_insert_option_timestamp);
370 404
371static void dccp_insert_option_timestamp_echo(struct sock *sk, 405static int dccp_insert_option_timestamp_echo(struct sock *sk,
372 struct sk_buff *skb) 406 struct sk_buff *skb)
373{ 407{
374 struct dccp_sock *dp = dccp_sk(sk); 408 struct dccp_sock *dp = dccp_sk(sk);
375#ifdef CONFIG_IP_DCCP_DEBUG
376 const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
377 "CLIENT TX opt: " : "server TX opt: ";
378#endif
379 struct timeval now; 409 struct timeval now;
380 u32 tstamp_echo; 410 __be32 tstamp_echo;
381 u32 elapsed_time; 411 u32 elapsed_time;
382 int len, elapsed_time_len; 412 int len, elapsed_time_len;
383 unsigned char *to; 413 unsigned char *to;
@@ -387,11 +417,8 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk,
387 elapsed_time_len = dccp_elapsed_time_len(elapsed_time); 417 elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
388 len = 6 + elapsed_time_len; 418 len = 6 + elapsed_time_len;
389 419
390 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { 420 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
391 LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert " 421 return -1;
392 "timestamp echo!\n");
393 return;
394 }
395 422
396 DCCP_SKB_CB(skb)->dccpd_opt_len += len; 423 DCCP_SKB_CB(skb)->dccpd_opt_len += len;
397 424
@@ -402,51 +429,149 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk,
402 tstamp_echo = htonl(dp->dccps_timestamp_echo); 429 tstamp_echo = htonl(dp->dccps_timestamp_echo);
403 memcpy(to, &tstamp_echo, 4); 430 memcpy(to, &tstamp_echo, 4);
404 to += 4; 431 to += 4;
405 432
406 if (elapsed_time_len == 2) { 433 if (elapsed_time_len == 2) {
407 const u16 var16 = htons((u16)elapsed_time); 434 const __be16 var16 = htons((u16)elapsed_time);
408 memcpy(to, &var16, 2); 435 memcpy(to, &var16, 2);
409 } else if (elapsed_time_len == 4) { 436 } else if (elapsed_time_len == 4) {
410 const u32 var32 = htonl(elapsed_time); 437 const __be32 var32 = htonl(elapsed_time);
411 memcpy(to, &var32, 4); 438 memcpy(to, &var32, 4);
412 } 439 }
413 440
414 dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, seqno=%llu\n",
415 debug_prefix, dp->dccps_timestamp_echo,
416 len,
417 (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq);
418
419 dp->dccps_timestamp_echo = 0; 441 dp->dccps_timestamp_echo = 0;
420 dp->dccps_timestamp_time.tv_sec = 0; 442 dp->dccps_timestamp_time.tv_sec = 0;
421 dp->dccps_timestamp_time.tv_usec = 0; 443 dp->dccps_timestamp_time.tv_usec = 0;
444 return 0;
422} 445}
423 446
424void dccp_insert_options(struct sock *sk, struct sk_buff *skb) 447static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat,
448 u8 *val, u8 len)
449{
450 u8 *to;
451
452 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 3 > DCCP_MAX_OPT_LEN) {
453 LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small"
454 " to insert feature %d option!\n", feat);
455 return -1;
456 }
457
458 DCCP_SKB_CB(skb)->dccpd_opt_len += len + 3;
459
460 to = skb_push(skb, len + 3);
461 *to++ = type;
462 *to++ = len + 3;
463 *to++ = feat;
464
465 if (len)
466 memcpy(to, val, len);
467 dccp_pr_debug("option %d feat %d len %d\n", type, feat, len);
468
469 return 0;
470}
471
472static int dccp_insert_options_feat(struct sock *sk, struct sk_buff *skb)
425{ 473{
426 struct dccp_sock *dp = dccp_sk(sk); 474 struct dccp_sock *dp = dccp_sk(sk);
475 struct dccp_minisock *dmsk = dccp_msk(sk);
476 struct dccp_opt_pend *opt, *next;
477 int change = 0;
478
479 /* confirm any options [NN opts] */
480 list_for_each_entry_safe(opt, next, &dmsk->dccpms_conf, dccpop_node) {
481 dccp_insert_feat_opt(skb, opt->dccpop_type,
482 opt->dccpop_feat, opt->dccpop_val,
483 opt->dccpop_len);
484 /* fear empty confirms */
485 if (opt->dccpop_val)
486 kfree(opt->dccpop_val);
487 kfree(opt);
488 }
489 INIT_LIST_HEAD(&dmsk->dccpms_conf);
490
491 /* see which features we need to send */
492 list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) {
493 /* see if we need to send any confirm */
494 if (opt->dccpop_sc) {
495 dccp_insert_feat_opt(skb, opt->dccpop_type + 1,
496 opt->dccpop_feat,
497 opt->dccpop_sc->dccpoc_val,
498 opt->dccpop_sc->dccpoc_len);
499
500 BUG_ON(!opt->dccpop_sc->dccpoc_val);
501 kfree(opt->dccpop_sc->dccpoc_val);
502 kfree(opt->dccpop_sc);
503 opt->dccpop_sc = NULL;
504 }
505
506 /* any option not confirmed, re-send it */
507 if (!opt->dccpop_conf) {
508 dccp_insert_feat_opt(skb, opt->dccpop_type,
509 opt->dccpop_feat, opt->dccpop_val,
510 opt->dccpop_len);
511 change++;
512 }
513 }
514
515 /* Retransmit timer.
516 * If this is the master listening sock, we don't set a timer on it. It
517 * should be fine because if the dude doesn't receive our RESPONSE
518 * [which will contain the CHANGE] he will send another REQUEST which
519 * will "retrnasmit" the change.
520 */
521 if (change && dp->dccps_role != DCCP_ROLE_LISTEN) {
522 dccp_pr_debug("reset feat negotiation timer %p\n", sk);
523
524 /* XXX don't reset the timer on re-transmissions. I.e. reset it
525 * only when sending new stuff i guess. Currently the timer
526 * never backs off because on re-transmission it just resets it!
527 */
528 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
529 inet_csk(sk)->icsk_rto, DCCP_RTO_MAX);
530 }
531
532 return 0;
533}
534
535int dccp_insert_options(struct sock *sk, struct sk_buff *skb)
536{
537 struct dccp_sock *dp = dccp_sk(sk);
538 struct dccp_minisock *dmsk = dccp_msk(sk);
427 539
428 DCCP_SKB_CB(skb)->dccpd_opt_len = 0; 540 DCCP_SKB_CB(skb)->dccpd_opt_len = 0;
429 541
430 if (dp->dccps_options.dccpo_send_ndp_count) 542 if (dmsk->dccpms_send_ndp_count &&
431 dccp_insert_option_ndp(sk, skb); 543 dccp_insert_option_ndp(sk, skb))
544 return -1;
432 545
433 if (!dccp_packet_without_ack(skb)) { 546 if (!dccp_packet_without_ack(skb)) {
434 if (dp->dccps_options.dccpo_send_ack_vector && 547 if (dmsk->dccpms_send_ack_vector &&
435 dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) 548 dccp_ackvec_pending(dp->dccps_hc_rx_ackvec) &&
436 dccp_insert_option_ackvec(sk, skb); 549 dccp_insert_option_ackvec(sk, skb))
437 if (dp->dccps_timestamp_echo != 0) 550 return -1;
438 dccp_insert_option_timestamp_echo(sk, skb); 551
552 if (dp->dccps_timestamp_echo != 0 &&
553 dccp_insert_option_timestamp_echo(sk, skb))
554 return -1;
439 } 555 }
440 556
441 if (dp->dccps_hc_rx_insert_options) { 557 if (dp->dccps_hc_rx_insert_options) {
442 ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb); 558 if (ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb))
559 return -1;
443 dp->dccps_hc_rx_insert_options = 0; 560 dp->dccps_hc_rx_insert_options = 0;
444 } 561 }
445 if (dp->dccps_hc_tx_insert_options) { 562 if (dp->dccps_hc_tx_insert_options) {
446 ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb); 563 if (ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb))
564 return -1;
447 dp->dccps_hc_tx_insert_options = 0; 565 dp->dccps_hc_tx_insert_options = 0;
448 } 566 }
449 567
568 /* Feature negotiation */
569 /* Data packets can't do feat negotiation */
570 if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA &&
571 DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATAACK &&
572 dccp_insert_options_feat(sk, skb))
573 return -1;
574
450 /* XXX: insert other options when appropriate */ 575 /* XXX: insert other options when appropriate */
451 576
452 if (DCCP_SKB_CB(skb)->dccpd_opt_len != 0) { 577 if (DCCP_SKB_CB(skb)->dccpd_opt_len != 0) {
@@ -459,4 +584,6 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb)
459 DCCP_SKB_CB(skb)->dccpd_opt_len += padding; 584 DCCP_SKB_CB(skb)->dccpd_opt_len += padding;
460 } 585 }
461 } 586 }
587
588 return 0;
462} 589}
diff --git a/net/dccp/output.c b/net/dccp/output.c
index efd7ffb903a1..7409e4a3abdf 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -27,7 +27,7 @@ static inline void dccp_event_ack_sent(struct sock *sk)
27 inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); 27 inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
28} 28}
29 29
30static inline void dccp_skb_entail(struct sock *sk, struct sk_buff *skb) 30static void dccp_skb_entail(struct sock *sk, struct sk_buff *skb)
31{ 31{
32 skb_set_owner_w(skb, sk); 32 skb_set_owner_w(skb, sk);
33 WARN_ON(sk->sk_send_head); 33 WARN_ON(sk->sk_send_head);
@@ -49,7 +49,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
49 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); 49 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
50 struct dccp_hdr *dh; 50 struct dccp_hdr *dh;
51 /* XXX For now we're using only 48 bits sequence numbers */ 51 /* XXX For now we're using only 48 bits sequence numbers */
52 const int dccp_header_size = sizeof(*dh) + 52 const u32 dccp_header_size = sizeof(*dh) +
53 sizeof(struct dccp_hdr_ext) + 53 sizeof(struct dccp_hdr_ext) +
54 dccp_packet_hdr_len(dcb->dccpd_type); 54 dccp_packet_hdr_len(dcb->dccpd_type);
55 int err, set_ack = 1; 55 int err, set_ack = 1;
@@ -64,6 +64,10 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
64 case DCCP_PKT_DATAACK: 64 case DCCP_PKT_DATAACK:
65 break; 65 break;
66 66
67 case DCCP_PKT_REQUEST:
68 set_ack = 0;
69 /* fall through */
70
67 case DCCP_PKT_SYNC: 71 case DCCP_PKT_SYNC:
68 case DCCP_PKT_SYNCACK: 72 case DCCP_PKT_SYNCACK:
69 ackno = dcb->dccpd_seq; 73 ackno = dcb->dccpd_seq;
@@ -79,7 +83,11 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
79 } 83 }
80 84
81 dcb->dccpd_seq = dp->dccps_gss; 85 dcb->dccpd_seq = dp->dccps_gss;
82 dccp_insert_options(sk, skb); 86
87 if (dccp_insert_options(sk, skb)) {
88 kfree_skb(skb);
89 return -EPROTO;
90 }
83 91
84 skb->h.raw = skb_push(skb, dccp_header_size); 92 skb->h.raw = skb_push(skb, dccp_header_size);
85 dh = dccp_hdr(skb); 93 dh = dccp_hdr(skb);
@@ -275,17 +283,16 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
275{ 283{
276 struct dccp_hdr *dh; 284 struct dccp_hdr *dh;
277 struct dccp_request_sock *dreq; 285 struct dccp_request_sock *dreq;
278 const int dccp_header_size = sizeof(struct dccp_hdr) + 286 const u32 dccp_header_size = sizeof(struct dccp_hdr) +
279 sizeof(struct dccp_hdr_ext) + 287 sizeof(struct dccp_hdr_ext) +
280 sizeof(struct dccp_hdr_response); 288 sizeof(struct dccp_hdr_response);
281 struct sk_buff *skb = sock_wmalloc(sk, MAX_HEADER + DCCP_MAX_OPT_LEN + 289 struct sk_buff *skb = sock_wmalloc(sk, sk->sk_prot->max_header, 1,
282 dccp_header_size, 1,
283 GFP_ATOMIC); 290 GFP_ATOMIC);
284 if (skb == NULL) 291 if (skb == NULL)
285 return NULL; 292 return NULL;
286 293
287 /* Reserve space for headers. */ 294 /* Reserve space for headers. */
288 skb_reserve(skb, MAX_HEADER + DCCP_MAX_OPT_LEN + dccp_header_size); 295 skb_reserve(skb, sk->sk_prot->max_header);
289 296
290 skb->dst = dst_clone(dst); 297 skb->dst = dst_clone(dst);
291 skb->csum = 0; 298 skb->csum = 0;
@@ -293,7 +300,11 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
293 dreq = dccp_rsk(req); 300 dreq = dccp_rsk(req);
294 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE; 301 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE;
295 DCCP_SKB_CB(skb)->dccpd_seq = dreq->dreq_iss; 302 DCCP_SKB_CB(skb)->dccpd_seq = dreq->dreq_iss;
296 dccp_insert_options(sk, skb); 303
304 if (dccp_insert_options(sk, skb)) {
305 kfree_skb(skb);
306 return NULL;
307 }
297 308
298 skb->h.raw = skb_push(skb, dccp_header_size); 309 skb->h.raw = skb_push(skb, dccp_header_size);
299 310
@@ -310,32 +321,28 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
310 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dreq->dreq_isr); 321 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dreq->dreq_isr);
311 dccp_hdr_response(skb)->dccph_resp_service = dreq->dreq_service; 322 dccp_hdr_response(skb)->dccph_resp_service = dreq->dreq_service;
312 323
313 dh->dccph_checksum = dccp_v4_checksum(skb, inet_rsk(req)->loc_addr,
314 inet_rsk(req)->rmt_addr);
315
316 DCCP_INC_STATS(DCCP_MIB_OUTSEGS); 324 DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
317 return skb; 325 return skb;
318} 326}
319 327
320EXPORT_SYMBOL_GPL(dccp_make_response); 328EXPORT_SYMBOL_GPL(dccp_make_response);
321 329
322struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst, 330static struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst,
323 const enum dccp_reset_codes code) 331 const enum dccp_reset_codes code)
324 332
325{ 333{
326 struct dccp_hdr *dh; 334 struct dccp_hdr *dh;
327 struct dccp_sock *dp = dccp_sk(sk); 335 struct dccp_sock *dp = dccp_sk(sk);
328 const int dccp_header_size = sizeof(struct dccp_hdr) + 336 const u32 dccp_header_size = sizeof(struct dccp_hdr) +
329 sizeof(struct dccp_hdr_ext) + 337 sizeof(struct dccp_hdr_ext) +
330 sizeof(struct dccp_hdr_reset); 338 sizeof(struct dccp_hdr_reset);
331 struct sk_buff *skb = sock_wmalloc(sk, MAX_HEADER + DCCP_MAX_OPT_LEN + 339 struct sk_buff *skb = sock_wmalloc(sk, sk->sk_prot->max_header, 1,
332 dccp_header_size, 1,
333 GFP_ATOMIC); 340 GFP_ATOMIC);
334 if (skb == NULL) 341 if (skb == NULL)
335 return NULL; 342 return NULL;
336 343
337 /* Reserve space for headers. */ 344 /* Reserve space for headers. */
338 skb_reserve(skb, MAX_HEADER + DCCP_MAX_OPT_LEN + dccp_header_size); 345 skb_reserve(skb, sk->sk_prot->max_header);
339 346
340 skb->dst = dst_clone(dst); 347 skb->dst = dst_clone(dst);
341 skb->csum = 0; 348 skb->csum = 0;
@@ -345,7 +352,11 @@ struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst,
345 DCCP_SKB_CB(skb)->dccpd_reset_code = code; 352 DCCP_SKB_CB(skb)->dccpd_reset_code = code;
346 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESET; 353 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESET;
347 DCCP_SKB_CB(skb)->dccpd_seq = dp->dccps_gss; 354 DCCP_SKB_CB(skb)->dccpd_seq = dp->dccps_gss;
348 dccp_insert_options(sk, skb); 355
356 if (dccp_insert_options(sk, skb)) {
357 kfree_skb(skb);
358 return NULL;
359 }
349 360
350 skb->h.raw = skb_push(skb, dccp_header_size); 361 skb->h.raw = skb_push(skb, dccp_header_size);
351 362
@@ -362,14 +373,34 @@ struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst,
362 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dp->dccps_gsr); 373 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dp->dccps_gsr);
363 374
364 dccp_hdr_reset(skb)->dccph_reset_code = code; 375 dccp_hdr_reset(skb)->dccph_reset_code = code;
365 376 inet_csk(sk)->icsk_af_ops->send_check(sk, skb->len, skb);
366 dh->dccph_checksum = dccp_v4_checksum(skb, inet_sk(sk)->saddr,
367 inet_sk(sk)->daddr);
368 377
369 DCCP_INC_STATS(DCCP_MIB_OUTSEGS); 378 DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
370 return skb; 379 return skb;
371} 380}
372 381
382int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code)
383{
384 /*
385 * FIXME: what if rebuild_header fails?
386 * Should we be doing a rebuild_header here?
387 */
388 int err = inet_sk_rebuild_header(sk);
389
390 if (err == 0) {
391 struct sk_buff *skb = dccp_make_reset(sk, sk->sk_dst_cache,
392 code);
393 if (skb != NULL) {
394 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
395 err = inet_csk(sk)->icsk_af_ops->queue_xmit(skb, 0);
396 if (err == NET_XMIT_CN)
397 err = 0;
398 }
399 }
400
401 return err;
402}
403
373/* 404/*
374 * Do all connect socket setups that can be done AF independent. 405 * Do all connect socket setups that can be done AF independent.
375 */ 406 */
@@ -405,12 +436,12 @@ int dccp_connect(struct sock *sk)
405 436
406 dccp_connect_init(sk); 437 dccp_connect_init(sk);
407 438
408 skb = alloc_skb(MAX_DCCP_HEADER + 15, sk->sk_allocation); 439 skb = alloc_skb(sk->sk_prot->max_header, sk->sk_allocation);
409 if (unlikely(skb == NULL)) 440 if (unlikely(skb == NULL))
410 return -ENOBUFS; 441 return -ENOBUFS;
411 442
412 /* Reserve space for headers. */ 443 /* Reserve space for headers. */
413 skb_reserve(skb, MAX_DCCP_HEADER); 444 skb_reserve(skb, sk->sk_prot->max_header);
414 445
415 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST; 446 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST;
416 skb->csum = 0; 447 skb->csum = 0;
@@ -431,7 +462,8 @@ void dccp_send_ack(struct sock *sk)
431{ 462{
432 /* If we have been reset, we may not send again. */ 463 /* If we have been reset, we may not send again. */
433 if (sk->sk_state != DCCP_CLOSED) { 464 if (sk->sk_state != DCCP_CLOSED) {
434 struct sk_buff *skb = alloc_skb(MAX_DCCP_HEADER, GFP_ATOMIC); 465 struct sk_buff *skb = alloc_skb(sk->sk_prot->max_header,
466 GFP_ATOMIC);
435 467
436 if (skb == NULL) { 468 if (skb == NULL) {
437 inet_csk_schedule_ack(sk); 469 inet_csk_schedule_ack(sk);
@@ -443,7 +475,7 @@ void dccp_send_ack(struct sock *sk)
443 } 475 }
444 476
445 /* Reserve space for headers */ 477 /* Reserve space for headers */
446 skb_reserve(skb, MAX_DCCP_HEADER); 478 skb_reserve(skb, sk->sk_prot->max_header);
447 skb->csum = 0; 479 skb->csum = 0;
448 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_ACK; 480 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_ACK;
449 dccp_transmit_skb(sk, skb); 481 dccp_transmit_skb(sk, skb);
@@ -490,14 +522,14 @@ void dccp_send_sync(struct sock *sk, const u64 seq,
490 * dccp_transmit_skb() will set the ownership to this 522 * dccp_transmit_skb() will set the ownership to this
491 * sock. 523 * sock.
492 */ 524 */
493 struct sk_buff *skb = alloc_skb(MAX_DCCP_HEADER, GFP_ATOMIC); 525 struct sk_buff *skb = alloc_skb(sk->sk_prot->max_header, GFP_ATOMIC);
494 526
495 if (skb == NULL) 527 if (skb == NULL)
496 /* FIXME: how to make sure the sync is sent? */ 528 /* FIXME: how to make sure the sync is sent? */
497 return; 529 return;
498 530
499 /* Reserve space for headers and prepare control bits. */ 531 /* Reserve space for headers and prepare control bits. */
500 skb_reserve(skb, MAX_DCCP_HEADER); 532 skb_reserve(skb, sk->sk_prot->max_header);
501 skb->csum = 0; 533 skb->csum = 0;
502 DCCP_SKB_CB(skb)->dccpd_type = pkt_type; 534 DCCP_SKB_CB(skb)->dccpd_type = pkt_type;
503 DCCP_SKB_CB(skb)->dccpd_seq = seq; 535 DCCP_SKB_CB(skb)->dccpd_seq = seq;
@@ -505,6 +537,8 @@ void dccp_send_sync(struct sock *sk, const u64 seq,
505 dccp_transmit_skb(sk, skb); 537 dccp_transmit_skb(sk, skb);
506} 538}
507 539
540EXPORT_SYMBOL_GPL(dccp_send_sync);
541
508/* 542/*
509 * Send a DCCP_PKT_CLOSE/CLOSEREQ. The caller locks the socket for us. This 543 * Send a DCCP_PKT_CLOSE/CLOSEREQ. The caller locks the socket for us. This
510 * cannot be allowed to fail queueing a DCCP_PKT_CLOSE/CLOSEREQ frame under 544 * cannot be allowed to fail queueing a DCCP_PKT_CLOSE/CLOSEREQ frame under
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 65b11ea90d85..d4b293e16283 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -23,9 +23,7 @@
23#include <linux/random.h> 23#include <linux/random.h>
24#include <net/checksum.h> 24#include <net/checksum.h>
25 25
26#include <net/inet_common.h>
27#include <net/inet_sock.h> 26#include <net/inet_sock.h>
28#include <net/protocol.h>
29#include <net/sock.h> 27#include <net/sock.h>
30#include <net/xfrm.h> 28#include <net/xfrm.h>
31 29
@@ -37,6 +35,7 @@
37 35
38#include "ccid.h" 36#include "ccid.h"
39#include "dccp.h" 37#include "dccp.h"
38#include "feat.h"
40 39
41DEFINE_SNMP_STAT(struct dccp_mib, dccp_statistics) __read_mostly; 40DEFINE_SNMP_STAT(struct dccp_mib, dccp_statistics) __read_mostly;
42 41
@@ -46,12 +45,66 @@ atomic_t dccp_orphan_count = ATOMIC_INIT(0);
46 45
47EXPORT_SYMBOL_GPL(dccp_orphan_count); 46EXPORT_SYMBOL_GPL(dccp_orphan_count);
48 47
49static struct net_protocol dccp_protocol = { 48struct inet_hashinfo __cacheline_aligned dccp_hashinfo = {
50 .handler = dccp_v4_rcv, 49 .lhash_lock = RW_LOCK_UNLOCKED,
51 .err_handler = dccp_v4_err, 50 .lhash_users = ATOMIC_INIT(0),
52 .no_policy = 1, 51 .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(dccp_hashinfo.lhash_wait),
53}; 52};
54 53
54EXPORT_SYMBOL_GPL(dccp_hashinfo);
55
56void dccp_set_state(struct sock *sk, const int state)
57{
58 const int oldstate = sk->sk_state;
59
60 dccp_pr_debug("%s(%p) %-10.10s -> %s\n",
61 dccp_role(sk), sk,
62 dccp_state_name(oldstate), dccp_state_name(state));
63 WARN_ON(state == oldstate);
64
65 switch (state) {
66 case DCCP_OPEN:
67 if (oldstate != DCCP_OPEN)
68 DCCP_INC_STATS(DCCP_MIB_CURRESTAB);
69 break;
70
71 case DCCP_CLOSED:
72 if (oldstate == DCCP_CLOSING || oldstate == DCCP_OPEN)
73 DCCP_INC_STATS(DCCP_MIB_ESTABRESETS);
74
75 sk->sk_prot->unhash(sk);
76 if (inet_csk(sk)->icsk_bind_hash != NULL &&
77 !(sk->sk_userlocks & SOCK_BINDPORT_LOCK))
78 inet_put_port(&dccp_hashinfo, sk);
79 /* fall through */
80 default:
81 if (oldstate == DCCP_OPEN)
82 DCCP_DEC_STATS(DCCP_MIB_CURRESTAB);
83 }
84
85 /* Change state AFTER socket is unhashed to avoid closed
86 * socket sitting in hash tables.
87 */
88 sk->sk_state = state;
89}
90
91EXPORT_SYMBOL_GPL(dccp_set_state);
92
93void dccp_done(struct sock *sk)
94{
95 dccp_set_state(sk, DCCP_CLOSED);
96 dccp_clear_xmit_timers(sk);
97
98 sk->sk_shutdown = SHUTDOWN_MASK;
99
100 if (!sock_flag(sk, SOCK_DEAD))
101 sk->sk_state_change(sk);
102 else
103 inet_csk_destroy_sock(sk);
104}
105
106EXPORT_SYMBOL_GPL(dccp_done);
107
55const char *dccp_packet_name(const int type) 108const char *dccp_packet_name(const int type)
56{ 109{
57 static const char *dccp_packet_names[] = { 110 static const char *dccp_packet_names[] = {
@@ -96,6 +149,120 @@ const char *dccp_state_name(const int state)
96 149
97EXPORT_SYMBOL_GPL(dccp_state_name); 150EXPORT_SYMBOL_GPL(dccp_state_name);
98 151
152void dccp_hash(struct sock *sk)
153{
154 inet_hash(&dccp_hashinfo, sk);
155}
156
157EXPORT_SYMBOL_GPL(dccp_hash);
158
159void dccp_unhash(struct sock *sk)
160{
161 inet_unhash(&dccp_hashinfo, sk);
162}
163
164EXPORT_SYMBOL_GPL(dccp_unhash);
165
166int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
167{
168 struct dccp_sock *dp = dccp_sk(sk);
169 struct dccp_minisock *dmsk = dccp_msk(sk);
170 struct inet_connection_sock *icsk = inet_csk(sk);
171
172 dccp_minisock_init(&dp->dccps_minisock);
173 do_gettimeofday(&dp->dccps_epoch);
174
175 /*
176 * FIXME: We're hardcoding the CCID, and doing this at this point makes
177 * the listening (master) sock get CCID control blocks, which is not
178 * necessary, but for now, to not mess with the test userspace apps,
179 * lets leave it here, later the real solution is to do this in a
180 * setsockopt(CCIDs-I-want/accept). -acme
181 */
182 if (likely(ctl_sock_initialized)) {
183 int rc = dccp_feat_init(dmsk);
184
185 if (rc)
186 return rc;
187
188 if (dmsk->dccpms_send_ack_vector) {
189 dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_KERNEL);
190 if (dp->dccps_hc_rx_ackvec == NULL)
191 return -ENOMEM;
192 }
193 dp->dccps_hc_rx_ccid = ccid_hc_rx_new(dmsk->dccpms_rx_ccid,
194 sk, GFP_KERNEL);
195 dp->dccps_hc_tx_ccid = ccid_hc_tx_new(dmsk->dccpms_tx_ccid,
196 sk, GFP_KERNEL);
197 if (unlikely(dp->dccps_hc_rx_ccid == NULL ||
198 dp->dccps_hc_tx_ccid == NULL)) {
199 ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
200 ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
201 if (dmsk->dccpms_send_ack_vector) {
202 dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
203 dp->dccps_hc_rx_ackvec = NULL;
204 }
205 dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
206 return -ENOMEM;
207 }
208 } else {
209 /* control socket doesn't need feat nego */
210 INIT_LIST_HEAD(&dmsk->dccpms_pending);
211 INIT_LIST_HEAD(&dmsk->dccpms_conf);
212 }
213
214 dccp_init_xmit_timers(sk);
215 icsk->icsk_rto = DCCP_TIMEOUT_INIT;
216 sk->sk_state = DCCP_CLOSED;
217 sk->sk_write_space = dccp_write_space;
218 icsk->icsk_sync_mss = dccp_sync_mss;
219 dp->dccps_mss_cache = 536;
220 dp->dccps_role = DCCP_ROLE_UNDEFINED;
221 dp->dccps_service = DCCP_SERVICE_INVALID_VALUE;
222 dp->dccps_l_ack_ratio = dp->dccps_r_ack_ratio = 1;
223
224 return 0;
225}
226
227EXPORT_SYMBOL_GPL(dccp_init_sock);
228
229int dccp_destroy_sock(struct sock *sk)
230{
231 struct dccp_sock *dp = dccp_sk(sk);
232 struct dccp_minisock *dmsk = dccp_msk(sk);
233
234 /*
235 * DCCP doesn't use sk_write_queue, just sk_send_head
236 * for retransmissions
237 */
238 if (sk->sk_send_head != NULL) {
239 kfree_skb(sk->sk_send_head);
240 sk->sk_send_head = NULL;
241 }
242
243 /* Clean up a referenced DCCP bind bucket. */
244 if (inet_csk(sk)->icsk_bind_hash != NULL)
245 inet_put_port(&dccp_hashinfo, sk);
246
247 kfree(dp->dccps_service_list);
248 dp->dccps_service_list = NULL;
249
250 if (dmsk->dccpms_send_ack_vector) {
251 dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
252 dp->dccps_hc_rx_ackvec = NULL;
253 }
254 ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
255 ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
256 dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
257
258 /* clean up feature negotiation state */
259 dccp_feat_clean(dmsk);
260
261 return 0;
262}
263
264EXPORT_SYMBOL_GPL(dccp_destroy_sock);
265
99static inline int dccp_listen_start(struct sock *sk) 266static inline int dccp_listen_start(struct sock *sk)
100{ 267{
101 struct dccp_sock *dp = dccp_sk(sk); 268 struct dccp_sock *dp = dccp_sk(sk);
@@ -220,7 +387,7 @@ int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg)
220 387
221EXPORT_SYMBOL_GPL(dccp_ioctl); 388EXPORT_SYMBOL_GPL(dccp_ioctl);
222 389
223static int dccp_setsockopt_service(struct sock *sk, const u32 service, 390static int dccp_setsockopt_service(struct sock *sk, const __be32 service,
224 char __user *optval, int optlen) 391 char __user *optval, int optlen)
225{ 392{
226 struct dccp_sock *dp = dccp_sk(sk); 393 struct dccp_sock *dp = dccp_sk(sk);
@@ -255,18 +422,46 @@ static int dccp_setsockopt_service(struct sock *sk, const u32 service,
255 return 0; 422 return 0;
256} 423}
257 424
258int dccp_setsockopt(struct sock *sk, int level, int optname, 425/* byte 1 is feature. the rest is the preference list */
259 char __user *optval, int optlen) 426static int dccp_setsockopt_change(struct sock *sk, int type,
427 struct dccp_so_feat __user *optval)
428{
429 struct dccp_so_feat opt;
430 u8 *val;
431 int rc;
432
433 if (copy_from_user(&opt, optval, sizeof(opt)))
434 return -EFAULT;
435
436 val = kmalloc(opt.dccpsf_len, GFP_KERNEL);
437 if (!val)
438 return -ENOMEM;
439
440 if (copy_from_user(val, opt.dccpsf_val, opt.dccpsf_len)) {
441 rc = -EFAULT;
442 goto out_free_val;
443 }
444
445 rc = dccp_feat_change(dccp_msk(sk), type, opt.dccpsf_feat,
446 val, opt.dccpsf_len, GFP_KERNEL);
447 if (rc)
448 goto out_free_val;
449
450out:
451 return rc;
452
453out_free_val:
454 kfree(val);
455 goto out;
456}
457
458static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
459 char __user *optval, int optlen)
260{ 460{
261 struct dccp_sock *dp; 461 struct dccp_sock *dp;
262 int err; 462 int err;
263 int val; 463 int val;
264 464
265 if (level != SOL_DCCP)
266 return inet_csk(sk)->icsk_af_ops->setsockopt(sk, level,
267 optname, optval,
268 optlen);
269
270 if (optlen < sizeof(int)) 465 if (optlen < sizeof(int))
271 return -EINVAL; 466 return -EINVAL;
272 467
@@ -284,6 +479,25 @@ int dccp_setsockopt(struct sock *sk, int level, int optname,
284 case DCCP_SOCKOPT_PACKET_SIZE: 479 case DCCP_SOCKOPT_PACKET_SIZE:
285 dp->dccps_packet_size = val; 480 dp->dccps_packet_size = val;
286 break; 481 break;
482
483 case DCCP_SOCKOPT_CHANGE_L:
484 if (optlen != sizeof(struct dccp_so_feat))
485 err = -EINVAL;
486 else
487 err = dccp_setsockopt_change(sk, DCCPO_CHANGE_L,
488 (struct dccp_so_feat *)
489 optval);
490 break;
491
492 case DCCP_SOCKOPT_CHANGE_R:
493 if (optlen != sizeof(struct dccp_so_feat))
494 err = -EINVAL;
495 else
496 err = dccp_setsockopt_change(sk, DCCPO_CHANGE_R,
497 (struct dccp_so_feat *)
498 optval);
499 break;
500
287 default: 501 default:
288 err = -ENOPROTOOPT; 502 err = -ENOPROTOOPT;
289 break; 503 break;
@@ -293,10 +507,33 @@ int dccp_setsockopt(struct sock *sk, int level, int optname,
293 return err; 507 return err;
294} 508}
295 509
510int dccp_setsockopt(struct sock *sk, int level, int optname,
511 char __user *optval, int optlen)
512{
513 if (level != SOL_DCCP)
514 return inet_csk(sk)->icsk_af_ops->setsockopt(sk, level,
515 optname, optval,
516 optlen);
517 return do_dccp_setsockopt(sk, level, optname, optval, optlen);
518}
519
296EXPORT_SYMBOL_GPL(dccp_setsockopt); 520EXPORT_SYMBOL_GPL(dccp_setsockopt);
297 521
522#ifdef CONFIG_COMPAT
523int compat_dccp_setsockopt(struct sock *sk, int level, int optname,
524 char __user *optval, int optlen)
525{
526 if (level != SOL_DCCP)
527 return inet_csk_compat_setsockopt(sk, level, optname,
528 optval, optlen);
529 return do_dccp_setsockopt(sk, level, optname, optval, optlen);
530}
531
532EXPORT_SYMBOL_GPL(compat_dccp_setsockopt);
533#endif
534
298static int dccp_getsockopt_service(struct sock *sk, int len, 535static int dccp_getsockopt_service(struct sock *sk, int len,
299 u32 __user *optval, 536 __be32 __user *optval,
300 int __user *optlen) 537 int __user *optlen)
301{ 538{
302 const struct dccp_sock *dp = dccp_sk(sk); 539 const struct dccp_sock *dp = dccp_sk(sk);
@@ -326,16 +563,12 @@ out:
326 return err; 563 return err;
327} 564}
328 565
329int dccp_getsockopt(struct sock *sk, int level, int optname, 566static int do_dccp_getsockopt(struct sock *sk, int level, int optname,
330 char __user *optval, int __user *optlen) 567 char __user *optval, int __user *optlen)
331{ 568{
332 struct dccp_sock *dp; 569 struct dccp_sock *dp;
333 int val, len; 570 int val, len;
334 571
335 if (level != SOL_DCCP)
336 return inet_csk(sk)->icsk_af_ops->getsockopt(sk, level,
337 optname, optval,
338 optlen);
339 if (get_user(len, optlen)) 572 if (get_user(len, optlen))
340 return -EFAULT; 573 return -EFAULT;
341 574
@@ -351,7 +584,7 @@ int dccp_getsockopt(struct sock *sk, int level, int optname,
351 break; 584 break;
352 case DCCP_SOCKOPT_SERVICE: 585 case DCCP_SOCKOPT_SERVICE:
353 return dccp_getsockopt_service(sk, len, 586 return dccp_getsockopt_service(sk, len,
354 (u32 __user *)optval, optlen); 587 (__be32 __user *)optval, optlen);
355 case 128 ... 191: 588 case 128 ... 191:
356 return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname, 589 return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname,
357 len, (u32 __user *)optval, optlen); 590 len, (u32 __user *)optval, optlen);
@@ -368,8 +601,31 @@ int dccp_getsockopt(struct sock *sk, int level, int optname,
368 return 0; 601 return 0;
369} 602}
370 603
604int dccp_getsockopt(struct sock *sk, int level, int optname,
605 char __user *optval, int __user *optlen)
606{
607 if (level != SOL_DCCP)
608 return inet_csk(sk)->icsk_af_ops->getsockopt(sk, level,
609 optname, optval,
610 optlen);
611 return do_dccp_getsockopt(sk, level, optname, optval, optlen);
612}
613
371EXPORT_SYMBOL_GPL(dccp_getsockopt); 614EXPORT_SYMBOL_GPL(dccp_getsockopt);
372 615
616#ifdef CONFIG_COMPAT
617int compat_dccp_getsockopt(struct sock *sk, int level, int optname,
618 char __user *optval, int __user *optlen)
619{
620 if (level != SOL_DCCP)
621 return inet_csk_compat_getsockopt(sk, level, optname,
622 optval, optlen);
623 return do_dccp_getsockopt(sk, level, optname, optval, optlen);
624}
625
626EXPORT_SYMBOL_GPL(compat_dccp_getsockopt);
627#endif
628
373int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, 629int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
374 size_t len) 630 size_t len)
375{ 631{
@@ -679,84 +935,7 @@ void dccp_shutdown(struct sock *sk, int how)
679 935
680EXPORT_SYMBOL_GPL(dccp_shutdown); 936EXPORT_SYMBOL_GPL(dccp_shutdown);
681 937
682static const struct proto_ops inet_dccp_ops = { 938static int __init dccp_mib_init(void)
683 .family = PF_INET,
684 .owner = THIS_MODULE,
685 .release = inet_release,
686 .bind = inet_bind,
687 .connect = inet_stream_connect,
688 .socketpair = sock_no_socketpair,
689 .accept = inet_accept,
690 .getname = inet_getname,
691 /* FIXME: work on tcp_poll to rename it to inet_csk_poll */
692 .poll = dccp_poll,
693 .ioctl = inet_ioctl,
694 /* FIXME: work on inet_listen to rename it to sock_common_listen */
695 .listen = inet_dccp_listen,
696 .shutdown = inet_shutdown,
697 .setsockopt = sock_common_setsockopt,
698 .getsockopt = sock_common_getsockopt,
699 .sendmsg = inet_sendmsg,
700 .recvmsg = sock_common_recvmsg,
701 .mmap = sock_no_mmap,
702 .sendpage = sock_no_sendpage,
703};
704
705extern struct net_proto_family inet_family_ops;
706
707static struct inet_protosw dccp_v4_protosw = {
708 .type = SOCK_DCCP,
709 .protocol = IPPROTO_DCCP,
710 .prot = &dccp_prot,
711 .ops = &inet_dccp_ops,
712 .capability = -1,
713 .no_check = 0,
714 .flags = INET_PROTOSW_ICSK,
715};
716
717/*
718 * This is the global socket data structure used for responding to
719 * the Out-of-the-blue (OOTB) packets. A control sock will be created
720 * for this socket at the initialization time.
721 */
722struct socket *dccp_ctl_socket;
723
724static char dccp_ctl_socket_err_msg[] __initdata =
725 KERN_ERR "DCCP: Failed to create the control socket.\n";
726
727static int __init dccp_ctl_sock_init(void)
728{
729 int rc = sock_create_kern(PF_INET, SOCK_DCCP, IPPROTO_DCCP,
730 &dccp_ctl_socket);
731 if (rc < 0)
732 printk(dccp_ctl_socket_err_msg);
733 else {
734 dccp_ctl_socket->sk->sk_allocation = GFP_ATOMIC;
735 inet_sk(dccp_ctl_socket->sk)->uc_ttl = -1;
736
737 /* Unhash it so that IP input processing does not even
738 * see it, we do not wish this socket to see incoming
739 * packets.
740 */
741 dccp_ctl_socket->sk->sk_prot->unhash(dccp_ctl_socket->sk);
742 }
743
744 return rc;
745}
746
747#ifdef CONFIG_IP_DCCP_UNLOAD_HACK
748void dccp_ctl_sock_exit(void)
749{
750 if (dccp_ctl_socket != NULL) {
751 sock_release(dccp_ctl_socket);
752 dccp_ctl_socket = NULL;
753 }
754}
755
756EXPORT_SYMBOL_GPL(dccp_ctl_sock_exit);
757#endif
758
759static int __init init_dccp_v4_mibs(void)
760{ 939{
761 int rc = -ENOMEM; 940 int rc = -ENOMEM;
762 941
@@ -778,6 +957,13 @@ out_free_one:
778 957
779} 958}
780 959
960static void dccp_mib_exit(void)
961{
962 free_percpu(dccp_statistics[0]);
963 free_percpu(dccp_statistics[1]);
964 dccp_statistics[0] = dccp_statistics[1] = NULL;
965}
966
781static int thash_entries; 967static int thash_entries;
782module_param(thash_entries, int, 0444); 968module_param(thash_entries, int, 0444);
783MODULE_PARM_DESC(thash_entries, "Number of ehash buckets"); 969MODULE_PARM_DESC(thash_entries, "Number of ehash buckets");
@@ -794,17 +980,14 @@ static int __init dccp_init(void)
794{ 980{
795 unsigned long goal; 981 unsigned long goal;
796 int ehash_order, bhash_order, i; 982 int ehash_order, bhash_order, i;
797 int rc = proto_register(&dccp_prot, 1); 983 int rc = -ENOBUFS;
798
799 if (rc)
800 goto out;
801 984
802 dccp_hashinfo.bind_bucket_cachep = 985 dccp_hashinfo.bind_bucket_cachep =
803 kmem_cache_create("dccp_bind_bucket", 986 kmem_cache_create("dccp_bind_bucket",
804 sizeof(struct inet_bind_bucket), 0, 987 sizeof(struct inet_bind_bucket), 0,
805 SLAB_HWCACHE_ALIGN, NULL, NULL); 988 SLAB_HWCACHE_ALIGN, NULL, NULL);
806 if (!dccp_hashinfo.bind_bucket_cachep) 989 if (!dccp_hashinfo.bind_bucket_cachep)
807 goto out_proto_unregister; 990 goto out;
808 991
809 /* 992 /*
810 * Size and allocate the main established and bind bucket 993 * Size and allocate the main established and bind bucket
@@ -866,27 +1049,23 @@ static int __init dccp_init(void)
866 INIT_HLIST_HEAD(&dccp_hashinfo.bhash[i].chain); 1049 INIT_HLIST_HEAD(&dccp_hashinfo.bhash[i].chain);
867 } 1050 }
868 1051
869 if (init_dccp_v4_mibs()) 1052 rc = dccp_mib_init();
1053 if (rc)
870 goto out_free_dccp_bhash; 1054 goto out_free_dccp_bhash;
871 1055
872 rc = -EAGAIN; 1056 rc = dccp_ackvec_init();
873 if (inet_add_protocol(&dccp_protocol, IPPROTO_DCCP)) 1057 if (rc)
874 goto out_free_dccp_v4_mibs; 1058 goto out_free_dccp_mib;
875
876 inet_register_protosw(&dccp_v4_protosw);
877 1059
878 rc = dccp_ctl_sock_init(); 1060 rc = dccp_sysctl_init();
879 if (rc) 1061 if (rc)
880 goto out_unregister_protosw; 1062 goto out_ackvec_exit;
881out: 1063out:
882 return rc; 1064 return rc;
883out_unregister_protosw: 1065out_ackvec_exit:
884 inet_unregister_protosw(&dccp_v4_protosw); 1066 dccp_ackvec_exit();
885 inet_del_protocol(&dccp_protocol, IPPROTO_DCCP); 1067out_free_dccp_mib:
886out_free_dccp_v4_mibs: 1068 dccp_mib_exit();
887 free_percpu(dccp_statistics[0]);
888 free_percpu(dccp_statistics[1]);
889 dccp_statistics[0] = dccp_statistics[1] = NULL;
890out_free_dccp_bhash: 1069out_free_dccp_bhash:
891 free_pages((unsigned long)dccp_hashinfo.bhash, bhash_order); 1070 free_pages((unsigned long)dccp_hashinfo.bhash, bhash_order);
892 dccp_hashinfo.bhash = NULL; 1071 dccp_hashinfo.bhash = NULL;
@@ -896,23 +1075,12 @@ out_free_dccp_ehash:
896out_free_bind_bucket_cachep: 1075out_free_bind_bucket_cachep:
897 kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep); 1076 kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep);
898 dccp_hashinfo.bind_bucket_cachep = NULL; 1077 dccp_hashinfo.bind_bucket_cachep = NULL;
899out_proto_unregister:
900 proto_unregister(&dccp_prot);
901 goto out; 1078 goto out;
902} 1079}
903 1080
904static const char dccp_del_proto_err_msg[] __exitdata =
905 KERN_ERR "can't remove dccp net_protocol\n";
906
907static void __exit dccp_fini(void) 1081static void __exit dccp_fini(void)
908{ 1082{
909 inet_unregister_protosw(&dccp_v4_protosw); 1083 dccp_mib_exit();
910
911 if (inet_del_protocol(&dccp_protocol, IPPROTO_DCCP) < 0)
912 printk(dccp_del_proto_err_msg);
913
914 free_percpu(dccp_statistics[0]);
915 free_percpu(dccp_statistics[1]);
916 free_pages((unsigned long)dccp_hashinfo.bhash, 1084 free_pages((unsigned long)dccp_hashinfo.bhash,
917 get_order(dccp_hashinfo.bhash_size * 1085 get_order(dccp_hashinfo.bhash_size *
918 sizeof(struct inet_bind_hashbucket))); 1086 sizeof(struct inet_bind_hashbucket)));
@@ -920,19 +1088,13 @@ static void __exit dccp_fini(void)
920 get_order(dccp_hashinfo.ehash_size * 1088 get_order(dccp_hashinfo.ehash_size *
921 sizeof(struct inet_ehash_bucket))); 1089 sizeof(struct inet_ehash_bucket)));
922 kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep); 1090 kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep);
923 proto_unregister(&dccp_prot); 1091 dccp_ackvec_exit();
1092 dccp_sysctl_exit();
924} 1093}
925 1094
926module_init(dccp_init); 1095module_init(dccp_init);
927module_exit(dccp_fini); 1096module_exit(dccp_fini);
928 1097
929/*
930 * __stringify doesn't likes enums, so use SOCK_DCCP (6) and IPPROTO_DCCP (33)
931 * values directly, Also cover the case where the protocol is not specified,
932 * i.e. net-pf-PF_INET-proto-0-type-SOCK_DCCP
933 */
934MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-33-type-6");
935MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-0-type-6");
936MODULE_LICENSE("GPL"); 1098MODULE_LICENSE("GPL");
937MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@conectiva.com.br>"); 1099MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@conectiva.com.br>");
938MODULE_DESCRIPTION("DCCP - Datagram Congestion Controlled Protocol"); 1100MODULE_DESCRIPTION("DCCP - Datagram Congestion Controlled Protocol");
diff --git a/net/dccp/sysctl.c b/net/dccp/sysctl.c
new file mode 100644
index 000000000000..64c89e9c229e
--- /dev/null
+++ b/net/dccp/sysctl.c
@@ -0,0 +1,124 @@
1/*
2 * net/dccp/sysctl.c
3 *
4 * An implementation of the DCCP protocol
5 * Arnaldo Carvalho de Melo <acme@mandriva.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License v2
9 * as published by the Free Software Foundation.
10 */
11
12#include <linux/config.h>
13#include <linux/mm.h>
14#include <linux/sysctl.h>
15
16#ifndef CONFIG_SYSCTL
17#error This file should not be compiled without CONFIG_SYSCTL defined
18#endif
19
20extern int dccp_feat_default_sequence_window;
21extern int dccp_feat_default_rx_ccid;
22extern int dccp_feat_default_tx_ccid;
23extern int dccp_feat_default_ack_ratio;
24extern int dccp_feat_default_send_ack_vector;
25extern int dccp_feat_default_send_ndp_count;
26
27static struct ctl_table dccp_default_table[] = {
28 {
29 .ctl_name = NET_DCCP_DEFAULT_SEQ_WINDOW,
30 .procname = "seq_window",
31 .data = &dccp_feat_default_sequence_window,
32 .maxlen = sizeof(dccp_feat_default_sequence_window),
33 .mode = 0644,
34 .proc_handler = proc_dointvec,
35 },
36 {
37 .ctl_name = NET_DCCP_DEFAULT_RX_CCID,
38 .procname = "rx_ccid",
39 .data = &dccp_feat_default_rx_ccid,
40 .maxlen = sizeof(dccp_feat_default_rx_ccid),
41 .mode = 0644,
42 .proc_handler = proc_dointvec,
43 },
44 {
45 .ctl_name = NET_DCCP_DEFAULT_TX_CCID,
46 .procname = "tx_ccid",
47 .data = &dccp_feat_default_tx_ccid,
48 .maxlen = sizeof(dccp_feat_default_tx_ccid),
49 .mode = 0644,
50 .proc_handler = proc_dointvec,
51 },
52 {
53 .ctl_name = NET_DCCP_DEFAULT_ACK_RATIO,
54 .procname = "ack_ratio",
55 .data = &dccp_feat_default_ack_ratio,
56 .maxlen = sizeof(dccp_feat_default_ack_ratio),
57 .mode = 0644,
58 .proc_handler = proc_dointvec,
59 },
60 {
61 .ctl_name = NET_DCCP_DEFAULT_SEND_ACKVEC,
62 .procname = "send_ackvec",
63 .data = &dccp_feat_default_send_ack_vector,
64 .maxlen = sizeof(dccp_feat_default_send_ack_vector),
65 .mode = 0644,
66 .proc_handler = proc_dointvec,
67 },
68 {
69 .ctl_name = NET_DCCP_DEFAULT_SEND_NDP,
70 .procname = "send_ndp",
71 .data = &dccp_feat_default_send_ndp_count,
72 .maxlen = sizeof(dccp_feat_default_send_ndp_count),
73 .mode = 0644,
74 .proc_handler = proc_dointvec,
75 },
76 { .ctl_name = 0, }
77};
78
79static struct ctl_table dccp_table[] = {
80 {
81 .ctl_name = NET_DCCP_DEFAULT,
82 .procname = "default",
83 .mode = 0555,
84 .child = dccp_default_table,
85 },
86 { .ctl_name = 0, },
87};
88
89static struct ctl_table dccp_dir_table[] = {
90 {
91 .ctl_name = NET_DCCP,
92 .procname = "dccp",
93 .mode = 0555,
94 .child = dccp_table,
95 },
96 { .ctl_name = 0, },
97};
98
99static struct ctl_table dccp_root_table[] = {
100 {
101 .ctl_name = CTL_NET,
102 .procname = "net",
103 .mode = 0555,
104 .child = dccp_dir_table,
105 },
106 { .ctl_name = 0, },
107};
108
109static struct ctl_table_header *dccp_table_header;
110
111int __init dccp_sysctl_init(void)
112{
113 dccp_table_header = register_sysctl_table(dccp_root_table, 1);
114
115 return dccp_table_header != NULL ? 0 : -ENOMEM;
116}
117
118void dccp_sysctl_exit(void)
119{
120 if (dccp_table_header != NULL) {
121 unregister_sysctl_table(dccp_table_header);
122 dccp_table_header = NULL;
123 }
124}
diff --git a/net/dccp/timer.c b/net/dccp/timer.c
index aa34b576e228..5244415e5f18 100644
--- a/net/dccp/timer.c
+++ b/net/dccp/timer.c
@@ -31,7 +31,7 @@ static void dccp_write_err(struct sock *sk)
31 sk->sk_err = sk->sk_err_soft ? : ETIMEDOUT; 31 sk->sk_err = sk->sk_err_soft ? : ETIMEDOUT;
32 sk->sk_error_report(sk); 32 sk->sk_error_report(sk);
33 33
34 dccp_v4_send_reset(sk, DCCP_RESET_CODE_ABORTED); 34 dccp_send_reset(sk, DCCP_RESET_CODE_ABORTED);
35 dccp_done(sk); 35 dccp_done(sk);
36 DCCP_INC_STATS_BH(DCCP_MIB_ABORTONTIMEOUT); 36 DCCP_INC_STATS_BH(DCCP_MIB_ABORTONTIMEOUT);
37} 37}
@@ -141,6 +141,17 @@ static void dccp_retransmit_timer(struct sock *sk)
141{ 141{
142 struct inet_connection_sock *icsk = inet_csk(sk); 142 struct inet_connection_sock *icsk = inet_csk(sk);
143 143
144 /* retransmit timer is used for feature negotiation throughout
145 * connection. In this case, no packet is re-transmitted, but rather an
146 * ack is generated and pending changes are splaced into its options.
147 */
148 if (sk->sk_send_head == NULL) {
149 dccp_pr_debug("feat negotiation retransmit timeout %p\n", sk);
150 if (sk->sk_state == DCCP_OPEN)
151 dccp_send_ack(sk);
152 goto backoff;
153 }
154
144 /* 155 /*
145 * sk->sk_send_head has to have one skb with 156 * sk->sk_send_head has to have one skb with
146 * DCCP_SKB_CB(skb)->dccpd_type set to one of the retransmittable DCCP 157 * DCCP_SKB_CB(skb)->dccpd_type set to one of the retransmittable DCCP
@@ -177,6 +188,7 @@ static void dccp_retransmit_timer(struct sock *sk)
177 goto out; 188 goto out;
178 } 189 }
179 190
191backoff:
180 icsk->icsk_backoff++; 192 icsk->icsk_backoff++;
181 icsk->icsk_retransmits++; 193 icsk->icsk_retransmits++;
182 194
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index ce4aaf94860d..2b289ef20ab3 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -172,7 +172,7 @@ static struct hlist_head *dn_find_list(struct sock *sk)
172/* 172/*
173 * Valid ports are those greater than zero and not already in use. 173 * Valid ports are those greater than zero and not already in use.
174 */ 174 */
175static int check_port(unsigned short port) 175static int check_port(__le16 port)
176{ 176{
177 struct sock *sk; 177 struct sock *sk;
178 struct hlist_node *node; 178 struct hlist_node *node;
@@ -661,7 +661,7 @@ disc_reject:
661 } 661 }
662} 662}
663 663
664char *dn_addr2asc(dn_address addr, char *buf) 664char *dn_addr2asc(__u16 addr, char *buf)
665{ 665{
666 unsigned short node, area; 666 unsigned short node, area;
667 667
@@ -801,7 +801,7 @@ static int dn_auto_bind(struct socket *sock)
801 /* End of compatibility stuff */ 801 /* End of compatibility stuff */
802 802
803 scp->addr.sdn_add.a_len = dn_htons(2); 803 scp->addr.sdn_add.a_len = dn_htons(2);
804 rv = dn_dev_bind_default((dn_address *)scp->addr.sdn_add.a_addr); 804 rv = dn_dev_bind_default((__le16 *)scp->addr.sdn_add.a_addr);
805 if (rv == 0) { 805 if (rv == 0) {
806 rv = dn_hash_sock(sk); 806 rv = dn_hash_sock(sk);
807 if (rv) 807 if (rv)
@@ -1021,7 +1021,7 @@ static void dn_user_copy(struct sk_buff *skb, struct optdata_dn *opt)
1021 opt->opt_optl = *ptr++; 1021 opt->opt_optl = *ptr++;
1022 opt->opt_status = 0; 1022 opt->opt_status = 0;
1023 memcpy(opt->opt_data, ptr, opt->opt_optl); 1023 memcpy(opt->opt_data, ptr, opt->opt_optl);
1024 skb_pull(skb, opt->opt_optl + 1); 1024 skb_pull(skb, dn_ntohs(opt->opt_optl) + 1);
1025 1025
1026} 1026}
1027 1027
@@ -1121,8 +1121,8 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags)
1121 1121
1122 skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &(DN_SK(newsk)->addr), &type)); 1122 skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &(DN_SK(newsk)->addr), &type));
1123 skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &(DN_SK(newsk)->peer), &type)); 1123 skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &(DN_SK(newsk)->peer), &type));
1124 *(dn_address *)(DN_SK(newsk)->peer.sdn_add.a_addr) = cb->src; 1124 *(__le16 *)(DN_SK(newsk)->peer.sdn_add.a_addr) = cb->src;
1125 *(dn_address *)(DN_SK(newsk)->addr.sdn_add.a_addr) = cb->dst; 1125 *(__le16 *)(DN_SK(newsk)->addr.sdn_add.a_addr) = cb->dst;
1126 1126
1127 menuver = *skb->data; 1127 menuver = *skb->data;
1128 skb_pull(skb, 1); 1128 skb_pull(skb, 1);
@@ -1365,7 +1365,7 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char __us
1365 if (optlen != sizeof(struct optdata_dn)) 1365 if (optlen != sizeof(struct optdata_dn))
1366 return -EINVAL; 1366 return -EINVAL;
1367 1367
1368 if (u.opt.opt_optl > 16) 1368 if (dn_ntohs(u.opt.opt_optl) > 16)
1369 return -EINVAL; 1369 return -EINVAL;
1370 1370
1371 memcpy(&scp->conndata_out, &u.opt, optlen); 1371 memcpy(&scp->conndata_out, &u.opt, optlen);
@@ -1378,7 +1378,7 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char __us
1378 if (optlen != sizeof(struct optdata_dn)) 1378 if (optlen != sizeof(struct optdata_dn))
1379 return -EINVAL; 1379 return -EINVAL;
1380 1380
1381 if (u.opt.opt_optl > 16) 1381 if (dn_ntohs(u.opt.opt_optl) > 16)
1382 return -EINVAL; 1382 return -EINVAL;
1383 1383
1384 memcpy(&scp->discdata_out, &u.opt, optlen); 1384 memcpy(&scp->discdata_out, &u.opt, optlen);
@@ -1693,7 +1693,7 @@ static int dn_recvmsg(struct kiocb *iocb, struct socket *sock,
1693 if (rv) 1693 if (rv)
1694 goto out; 1694 goto out;
1695 1695
1696 if (flags & ~(MSG_PEEK|MSG_OOB|MSG_WAITALL|MSG_DONTWAIT|MSG_NOSIGNAL)) { 1696 if (flags & ~(MSG_CMSG_COMPAT|MSG_PEEK|MSG_OOB|MSG_WAITALL|MSG_DONTWAIT|MSG_NOSIGNAL)) {
1697 rv = -EOPNOTSUPP; 1697 rv = -EOPNOTSUPP;
1698 goto out; 1698 goto out;
1699 } 1699 }
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index efbead83ba7f..cc7b9d9255ef 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -64,7 +64,7 @@ extern struct neigh_table dn_neigh_table;
64/* 64/*
65 * decnet_address is kept in network order. 65 * decnet_address is kept in network order.
66 */ 66 */
67dn_address decnet_address = 0; 67__le16 decnet_address = 0;
68 68
69static DEFINE_RWLOCK(dndev_lock); 69static DEFINE_RWLOCK(dndev_lock);
70static struct net_device *decnet_default_device; 70static struct net_device *decnet_default_device;
@@ -439,7 +439,7 @@ static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int de
439 *ifap = ifa1->ifa_next; 439 *ifap = ifa1->ifa_next;
440 440
441 if (dn_db->dev->type == ARPHRD_ETHER) { 441 if (dn_db->dev->type == ARPHRD_ETHER) {
442 if (ifa1->ifa_local != dn_htons(dn_eth2dn(dev->dev_addr))) { 442 if (ifa1->ifa_local != dn_eth2dn(dev->dev_addr)) {
443 dn_dn2eth(mac_addr, ifa1->ifa_local); 443 dn_dn2eth(mac_addr, ifa1->ifa_local);
444 dev_mc_delete(dev, mac_addr, ETH_ALEN, 0); 444 dev_mc_delete(dev, mac_addr, ETH_ALEN, 0);
445 } 445 }
@@ -470,7 +470,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa)
470 } 470 }
471 471
472 if (dev->type == ARPHRD_ETHER) { 472 if (dev->type == ARPHRD_ETHER) {
473 if (ifa->ifa_local != dn_htons(dn_eth2dn(dev->dev_addr))) { 473 if (ifa->ifa_local != dn_eth2dn(dev->dev_addr)) {
474 dn_dn2eth(mac_addr, ifa->ifa_local); 474 dn_dn2eth(mac_addr, ifa->ifa_local);
475 dev_mc_add(dev, mac_addr, ETH_ALEN, 0); 475 dev_mc_add(dev, mac_addr, ETH_ALEN, 0);
476 dev_mc_upload(dev); 476 dev_mc_upload(dev);
@@ -561,7 +561,7 @@ int dn_dev_ioctl(unsigned int cmd, void __user *arg)
561 561
562 switch(cmd) { 562 switch(cmd) {
563 case SIOCGIFADDR: 563 case SIOCGIFADDR:
564 *((dn_address *)sdn->sdn_nodeaddr) = ifa->ifa_local; 564 *((__le16 *)sdn->sdn_nodeaddr) = ifa->ifa_local;
565 goto rarok; 565 goto rarok;
566 566
567 case SIOCSIFADDR: 567 case SIOCSIFADDR:
@@ -804,7 +804,7 @@ done:
804 return skb->len; 804 return skb->len;
805} 805}
806 806
807static int dn_dev_get_first(struct net_device *dev, dn_address *addr) 807static int dn_dev_get_first(struct net_device *dev, __le16 *addr)
808{ 808{
809 struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr; 809 struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
810 struct dn_ifaddr *ifa; 810 struct dn_ifaddr *ifa;
@@ -830,7 +830,7 @@ out:
830 * a sensible default. Eventually the routing code will take care of all the 830 * a sensible default. Eventually the routing code will take care of all the
831 * nasties for us I hope. 831 * nasties for us I hope.
832 */ 832 */
833int dn_dev_bind_default(dn_address *addr) 833int dn_dev_bind_default(__le16 *addr)
834{ 834{
835 struct net_device *dev; 835 struct net_device *dev;
836 int rv; 836 int rv;
@@ -853,7 +853,7 @@ static void dn_send_endnode_hello(struct net_device *dev, struct dn_ifaddr *ifa)
853{ 853{
854 struct endnode_hello_message *msg; 854 struct endnode_hello_message *msg;
855 struct sk_buff *skb = NULL; 855 struct sk_buff *skb = NULL;
856 unsigned short int *pktlen; 856 __le16 *pktlen;
857 struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr; 857 struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
858 858
859 if ((skb = dn_alloc_skb(NULL, sizeof(*msg), GFP_ATOMIC)) == NULL) 859 if ((skb = dn_alloc_skb(NULL, sizeof(*msg), GFP_ATOMIC)) == NULL)
@@ -882,7 +882,7 @@ static void dn_send_endnode_hello(struct net_device *dev, struct dn_ifaddr *ifa)
882 msg->datalen = 0x02; 882 msg->datalen = 0x02;
883 memset(msg->data, 0xAA, 2); 883 memset(msg->data, 0xAA, 2);
884 884
885 pktlen = (unsigned short *)skb_push(skb,2); 885 pktlen = (__le16 *)skb_push(skb,2);
886 *pktlen = dn_htons(skb->len - 2); 886 *pktlen = dn_htons(skb->len - 2);
887 887
888 skb->nh.raw = skb->data; 888 skb->nh.raw = skb->data;
@@ -926,7 +926,7 @@ static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa)
926 size_t size; 926 size_t size;
927 unsigned char *ptr; 927 unsigned char *ptr;
928 unsigned char *i1, *i2; 928 unsigned char *i1, *i2;
929 unsigned short *pktlen; 929 __le16 *pktlen;
930 char *src; 930 char *src;
931 931
932 if (mtu2blksize(dev) < (26 + 7)) 932 if (mtu2blksize(dev) < (26 + 7))
@@ -955,11 +955,11 @@ static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa)
955 ptr += ETH_ALEN; 955 ptr += ETH_ALEN;
956 *ptr++ = dn_db->parms.forwarding == 1 ? 956 *ptr++ = dn_db->parms.forwarding == 1 ?
957 DN_RT_INFO_L1RT : DN_RT_INFO_L2RT; 957 DN_RT_INFO_L1RT : DN_RT_INFO_L2RT;
958 *((unsigned short *)ptr) = dn_htons(mtu2blksize(dev)); 958 *((__le16 *)ptr) = dn_htons(mtu2blksize(dev));
959 ptr += 2; 959 ptr += 2;
960 *ptr++ = dn_db->parms.priority; /* Priority */ 960 *ptr++ = dn_db->parms.priority; /* Priority */
961 *ptr++ = 0; /* Area: Reserved */ 961 *ptr++ = 0; /* Area: Reserved */
962 *((unsigned short *)ptr) = dn_htons((unsigned short)dn_db->parms.t3); 962 *((__le16 *)ptr) = dn_htons((unsigned short)dn_db->parms.t3);
963 ptr += 2; 963 ptr += 2;
964 *ptr++ = 0; /* MPD: Reserved */ 964 *ptr++ = 0; /* MPD: Reserved */
965 i1 = ptr++; 965 i1 = ptr++;
@@ -974,7 +974,7 @@ static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa)
974 974
975 skb_trim(skb, (27 + *i2)); 975 skb_trim(skb, (27 + *i2));
976 976
977 pktlen = (unsigned short *)skb_push(skb, 2); 977 pktlen = (__le16 *)skb_push(skb, 2);
978 *pktlen = dn_htons(skb->len - 2); 978 *pktlen = dn_htons(skb->len - 2);
979 979
980 skb->nh.raw = skb->data; 980 skb->nh.raw = skb->data;
@@ -1016,7 +1016,7 @@ static void dn_send_ptp_hello(struct net_device *dev, struct dn_ifaddr *ifa)
1016 ptr = skb_put(skb, 2 + 4 + tdlen); 1016 ptr = skb_put(skb, 2 + 4 + tdlen);
1017 1017
1018 *ptr++ = DN_RT_PKT_HELO; 1018 *ptr++ = DN_RT_PKT_HELO;
1019 *((dn_address *)ptr) = ifa->ifa_local; 1019 *((__le16 *)ptr) = ifa->ifa_local;
1020 ptr += 2; 1020 ptr += 2;
1021 *ptr++ = tdlen; 1021 *ptr++ = tdlen;
1022 1022
@@ -1150,7 +1150,7 @@ struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
1150void dn_dev_up(struct net_device *dev) 1150void dn_dev_up(struct net_device *dev)
1151{ 1151{
1152 struct dn_ifaddr *ifa; 1152 struct dn_ifaddr *ifa;
1153 dn_address addr = decnet_address; 1153 __le16 addr = decnet_address;
1154 int maybe_default = 0; 1154 int maybe_default = 0;
1155 struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr; 1155 struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
1156 1156
@@ -1173,7 +1173,7 @@ void dn_dev_up(struct net_device *dev)
1173 if (dev->type == ARPHRD_ETHER) { 1173 if (dev->type == ARPHRD_ETHER) {
1174 if (memcmp(dev->dev_addr, dn_hiord, 4) != 0) 1174 if (memcmp(dev->dev_addr, dn_hiord, 4) != 0)
1175 return; 1175 return;
1176 addr = dn_htons(dn_eth2dn(dev->dev_addr)); 1176 addr = dn_eth2dn(dev->dev_addr);
1177 maybe_default = 1; 1177 maybe_default = 1;
1178 } 1178 }
1179 1179
@@ -1385,8 +1385,8 @@ static int dn_dev_seq_show(struct seq_file *seq, void *v)
1385 mtu2blksize(dev), 1385 mtu2blksize(dev),
1386 dn_db->parms.priority, 1386 dn_db->parms.priority,
1387 dn_db->parms.state, dn_db->parms.name, 1387 dn_db->parms.state, dn_db->parms.name,
1388 dn_db->router ? dn_addr2asc(dn_ntohs(*(dn_address *)dn_db->router->primary_key), router_buf) : "", 1388 dn_db->router ? dn_addr2asc(dn_ntohs(*(__le16 *)dn_db->router->primary_key), router_buf) : "",
1389 dn_db->peer ? dn_addr2asc(dn_ntohs(*(dn_address *)dn_db->peer->primary_key), peer_buf) : ""); 1389 dn_db->peer ? dn_addr2asc(dn_ntohs(*(__le16 *)dn_db->peer->primary_key), peer_buf) : "");
1390 } 1390 }
1391 return 0; 1391 return 0;
1392} 1392}
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index 99bc061759c3..bd4ce8681a12 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -143,11 +143,11 @@ static inline struct dn_fib_info *dn_fib_find_info(const struct dn_fib_info *nfi
143 return NULL; 143 return NULL;
144} 144}
145 145
146u16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type) 146__le16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type)
147{ 147{
148 while(RTA_OK(attr,attrlen)) { 148 while(RTA_OK(attr,attrlen)) {
149 if (attr->rta_type == type) 149 if (attr->rta_type == type)
150 return *(u16*)RTA_DATA(attr); 150 return *(__le16*)RTA_DATA(attr);
151 attr = RTA_NEXT(attr, attrlen); 151 attr = RTA_NEXT(attr, attrlen);
152 } 152 }
153 153
@@ -565,7 +565,7 @@ int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
565 return skb->len; 565 return skb->len;
566} 566}
567 567
568static void fib_magic(int cmd, int type, __u16 dst, int dst_len, struct dn_ifaddr *ifa) 568static void fib_magic(int cmd, int type, __le16 dst, int dst_len, struct dn_ifaddr *ifa)
569{ 569{
570 struct dn_fib_table *tb; 570 struct dn_fib_table *tb;
571 struct { 571 struct {
@@ -684,7 +684,7 @@ static int dn_fib_dnaddr_event(struct notifier_block *this, unsigned long event,
684 return NOTIFY_DONE; 684 return NOTIFY_DONE;
685} 685}
686 686
687int dn_fib_sync_down(dn_address local, struct net_device *dev, int force) 687int dn_fib_sync_down(__le16 local, struct net_device *dev, int force)
688{ 688{
689 int ret = 0; 689 int ret = 0;
690 int scope = RT_SCOPE_NOWHERE; 690 int scope = RT_SCOPE_NOWHERE;
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 33ab256cfd4a..7c8692c26bfe 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -95,7 +95,7 @@ static struct neigh_ops dn_phase3_ops = {
95struct neigh_table dn_neigh_table = { 95struct neigh_table dn_neigh_table = {
96 .family = PF_DECnet, 96 .family = PF_DECnet,
97 .entry_size = sizeof(struct dn_neigh), 97 .entry_size = sizeof(struct dn_neigh),
98 .key_len = sizeof(dn_address), 98 .key_len = sizeof(__le16),
99 .hash = dn_neigh_hash, 99 .hash = dn_neigh_hash,
100 .constructor = dn_neigh_construct, 100 .constructor = dn_neigh_construct,
101 .id = "dn_neigh_cache", 101 .id = "dn_neigh_cache",
@@ -123,7 +123,7 @@ struct neigh_table dn_neigh_table = {
123 123
124static u32 dn_neigh_hash(const void *pkey, const struct net_device *dev) 124static u32 dn_neigh_hash(const void *pkey, const struct net_device *dev)
125{ 125{
126 return jhash_2words(*(dn_address *)pkey, 0, dn_neigh_table.hash_rnd); 126 return jhash_2words(*(__u16 *)pkey, 0, dn_neigh_table.hash_rnd);
127} 127}
128 128
129static int dn_neigh_construct(struct neighbour *neigh) 129static int dn_neigh_construct(struct neighbour *neigh)
@@ -249,14 +249,14 @@ static int dn_long_output(struct sk_buff *skb)
249 data = skb_push(skb, sizeof(struct dn_long_packet) + 3); 249 data = skb_push(skb, sizeof(struct dn_long_packet) + 3);
250 lp = (struct dn_long_packet *)(data+3); 250 lp = (struct dn_long_packet *)(data+3);
251 251
252 *((unsigned short *)data) = dn_htons(skb->len - 2); 252 *((__le16 *)data) = dn_htons(skb->len - 2);
253 *(data + 2) = 1 | DN_RT_F_PF; /* Padding */ 253 *(data + 2) = 1 | DN_RT_F_PF; /* Padding */
254 254
255 lp->msgflg = DN_RT_PKT_LONG|(cb->rt_flags&(DN_RT_F_IE|DN_RT_F_RQR|DN_RT_F_RTS)); 255 lp->msgflg = DN_RT_PKT_LONG|(cb->rt_flags&(DN_RT_F_IE|DN_RT_F_RQR|DN_RT_F_RTS));
256 lp->d_area = lp->d_subarea = 0; 256 lp->d_area = lp->d_subarea = 0;
257 dn_dn2eth(lp->d_id, dn_ntohs(cb->dst)); 257 dn_dn2eth(lp->d_id, cb->dst);
258 lp->s_area = lp->s_subarea = 0; 258 lp->s_area = lp->s_subarea = 0;
259 dn_dn2eth(lp->s_id, dn_ntohs(cb->src)); 259 dn_dn2eth(lp->s_id, cb->src);
260 lp->nl2 = 0; 260 lp->nl2 = 0;
261 lp->visit_ct = cb->hops & 0x3f; 261 lp->visit_ct = cb->hops & 0x3f;
262 lp->s_class = 0; 262 lp->s_class = 0;
@@ -293,7 +293,7 @@ static int dn_short_output(struct sk_buff *skb)
293 } 293 }
294 294
295 data = skb_push(skb, sizeof(struct dn_short_packet) + 2); 295 data = skb_push(skb, sizeof(struct dn_short_packet) + 2);
296 *((unsigned short *)data) = dn_htons(skb->len - 2); 296 *((__le16 *)data) = dn_htons(skb->len - 2);
297 sp = (struct dn_short_packet *)(data+2); 297 sp = (struct dn_short_packet *)(data+2);
298 298
299 sp->msgflg = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS)); 299 sp->msgflg = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS));
@@ -335,7 +335,7 @@ static int dn_phase3_output(struct sk_buff *skb)
335 } 335 }
336 336
337 data = skb_push(skb, sizeof(struct dn_short_packet) + 2); 337 data = skb_push(skb, sizeof(struct dn_short_packet) + 2);
338 *((unsigned short *)data) = dn_htons(skb->len - 2); 338 *((__le16 *)data) = dn_htons(skb->len - 2);
339 sp = (struct dn_short_packet *)(data + 2); 339 sp = (struct dn_short_packet *)(data + 2);
340 340
341 sp->msgflg = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS)); 341 sp->msgflg = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS));
@@ -373,9 +373,9 @@ int dn_neigh_router_hello(struct sk_buff *skb)
373 struct neighbour *neigh; 373 struct neighbour *neigh;
374 struct dn_neigh *dn; 374 struct dn_neigh *dn;
375 struct dn_dev *dn_db; 375 struct dn_dev *dn_db;
376 dn_address src; 376 __le16 src;
377 377
378 src = dn_htons(dn_eth2dn(msg->id)); 378 src = dn_eth2dn(msg->id);
379 379
380 neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1); 380 neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1);
381 381
@@ -409,7 +409,7 @@ int dn_neigh_router_hello(struct sk_buff *skb)
409 } 409 }
410 410
411 /* Only use routers in our area */ 411 /* Only use routers in our area */
412 if ((dn_ntohs(src)>>10) == dn_ntohs((decnet_address)>>10)) { 412 if ((dn_ntohs(src)>>10) == (dn_ntohs((decnet_address))>>10)) {
413 if (!dn_db->router) { 413 if (!dn_db->router) {
414 dn_db->router = neigh_clone(neigh); 414 dn_db->router = neigh_clone(neigh);
415 } else { 415 } else {
@@ -433,9 +433,9 @@ int dn_neigh_endnode_hello(struct sk_buff *skb)
433 struct endnode_hello_message *msg = (struct endnode_hello_message *)skb->data; 433 struct endnode_hello_message *msg = (struct endnode_hello_message *)skb->data;
434 struct neighbour *neigh; 434 struct neighbour *neigh;
435 struct dn_neigh *dn; 435 struct dn_neigh *dn;
436 dn_address src; 436 __le16 src;
437 437
438 src = dn_htons(dn_eth2dn(msg->id)); 438 src = dn_eth2dn(msg->id);
439 439
440 neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1); 440 neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1);
441 441
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
index 44bda85e678f..547523b41c81 100644
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -85,7 +85,7 @@ static void dn_log_martian(struct sk_buff *skb, const char *msg)
85 if (decnet_log_martians && net_ratelimit()) { 85 if (decnet_log_martians && net_ratelimit()) {
86 char *devname = skb->dev ? skb->dev->name : "???"; 86 char *devname = skb->dev ? skb->dev->name : "???";
87 struct dn_skb_cb *cb = DN_SKB_CB(skb); 87 struct dn_skb_cb *cb = DN_SKB_CB(skb);
88 printk(KERN_INFO "DECnet: Martian packet (%s) dev=%s src=0x%04hx dst=0x%04hx srcport=0x%04hx dstport=0x%04hx\n", msg, devname, cb->src, cb->dst, cb->src_port, cb->dst_port); 88 printk(KERN_INFO "DECnet: Martian packet (%s) dev=%s src=0x%04hx dst=0x%04hx srcport=0x%04hx dstport=0x%04hx\n", msg, devname, dn_ntohs(cb->src), dn_ntohs(cb->dst), dn_ntohs(cb->src_port), dn_ntohs(cb->dst_port));
89 } 89 }
90} 90}
91 91
@@ -128,7 +128,7 @@ static void dn_ack(struct sock *sk, struct sk_buff *skb, unsigned short ack)
128 */ 128 */
129static int dn_process_ack(struct sock *sk, struct sk_buff *skb, int oth) 129static int dn_process_ack(struct sock *sk, struct sk_buff *skb, int oth)
130{ 130{
131 unsigned short *ptr = (unsigned short *)skb->data; 131 __le16 *ptr = (__le16 *)skb->data;
132 int len = 0; 132 int len = 0;
133 unsigned short ack; 133 unsigned short ack;
134 134
@@ -346,7 +346,7 @@ static void dn_nsp_conn_conf(struct sock *sk, struct sk_buff *skb)
346 ptr = skb->data; 346 ptr = skb->data;
347 cb->services = *ptr++; 347 cb->services = *ptr++;
348 cb->info = *ptr++; 348 cb->info = *ptr++;
349 cb->segsize = dn_ntohs(*(__u16 *)ptr); 349 cb->segsize = dn_ntohs(*(__le16 *)ptr);
350 350
351 if ((scp->state == DN_CI) || (scp->state == DN_CD)) { 351 if ((scp->state == DN_CI) || (scp->state == DN_CD)) {
352 scp->persist = 0; 352 scp->persist = 0;
@@ -363,7 +363,7 @@ static void dn_nsp_conn_conf(struct sock *sk, struct sk_buff *skb)
363 if (skb->len > 0) { 363 if (skb->len > 0) {
364 unsigned char dlen = *skb->data; 364 unsigned char dlen = *skb->data;
365 if ((dlen <= 16) && (dlen <= skb->len)) { 365 if ((dlen <= 16) && (dlen <= skb->len)) {
366 scp->conndata_in.opt_optl = dlen; 366 scp->conndata_in.opt_optl = dn_htons((__u16)dlen);
367 memcpy(scp->conndata_in.opt_data, skb->data + 1, dlen); 367 memcpy(scp->conndata_in.opt_data, skb->data + 1, dlen);
368 } 368 }
369 } 369 }
@@ -397,17 +397,17 @@ static void dn_nsp_disc_init(struct sock *sk, struct sk_buff *skb)
397 if (skb->len < 2) 397 if (skb->len < 2)
398 goto out; 398 goto out;
399 399
400 reason = dn_ntohs(*(__u16 *)skb->data); 400 reason = dn_ntohs(*(__le16 *)skb->data);
401 skb_pull(skb, 2); 401 skb_pull(skb, 2);
402 402
403 scp->discdata_in.opt_status = reason; 403 scp->discdata_in.opt_status = dn_htons(reason);
404 scp->discdata_in.opt_optl = 0; 404 scp->discdata_in.opt_optl = 0;
405 memset(scp->discdata_in.opt_data, 0, 16); 405 memset(scp->discdata_in.opt_data, 0, 16);
406 406
407 if (skb->len > 0) { 407 if (skb->len > 0) {
408 unsigned char dlen = *skb->data; 408 unsigned char dlen = *skb->data;
409 if ((dlen <= 16) && (dlen <= skb->len)) { 409 if ((dlen <= 16) && (dlen <= skb->len)) {
410 scp->discdata_in.opt_optl = dlen; 410 scp->discdata_in.opt_optl = dn_htons((__u16)dlen);
411 memcpy(scp->discdata_in.opt_data, skb->data + 1, dlen); 411 memcpy(scp->discdata_in.opt_data, skb->data + 1, dlen);
412 } 412 }
413 } 413 }
@@ -464,7 +464,7 @@ static void dn_nsp_disc_conf(struct sock *sk, struct sk_buff *skb)
464 if (skb->len != 2) 464 if (skb->len != 2)
465 goto out; 465 goto out;
466 466
467 reason = dn_ntohs(*(__u16 *)skb->data); 467 reason = dn_ntohs(*(__le16 *)skb->data);
468 468
469 sk->sk_state = TCP_CLOSE; 469 sk->sk_state = TCP_CLOSE;
470 470
@@ -513,7 +513,7 @@ static void dn_nsp_linkservice(struct sock *sk, struct sk_buff *skb)
513 if (skb->len != 4) 513 if (skb->len != 4)
514 goto out; 514 goto out;
515 515
516 segnum = dn_ntohs(*(__u16 *)ptr); 516 segnum = dn_ntohs(*(__le16 *)ptr);
517 ptr += 2; 517 ptr += 2;
518 lsflags = *(unsigned char *)ptr++; 518 lsflags = *(unsigned char *)ptr++;
519 fcval = *ptr; 519 fcval = *ptr;
@@ -621,7 +621,7 @@ static void dn_nsp_otherdata(struct sock *sk, struct sk_buff *skb)
621 if (skb->len < 2) 621 if (skb->len < 2)
622 goto out; 622 goto out;
623 623
624 cb->segnum = segnum = dn_ntohs(*(__u16 *)skb->data); 624 cb->segnum = segnum = dn_ntohs(*(__le16 *)skb->data);
625 skb_pull(skb, 2); 625 skb_pull(skb, 2);
626 626
627 if (seq_next(scp->numoth_rcv, segnum)) { 627 if (seq_next(scp->numoth_rcv, segnum)) {
@@ -649,7 +649,7 @@ static void dn_nsp_data(struct sock *sk, struct sk_buff *skb)
649 if (skb->len < 2) 649 if (skb->len < 2)
650 goto out; 650 goto out;
651 651
652 cb->segnum = segnum = dn_ntohs(*(__u16 *)skb->data); 652 cb->segnum = segnum = dn_ntohs(*(__le16 *)skb->data);
653 skb_pull(skb, 2); 653 skb_pull(skb, 2);
654 654
655 if (seq_next(scp->numdat_rcv, segnum)) { 655 if (seq_next(scp->numdat_rcv, segnum)) {
@@ -760,7 +760,7 @@ static int dn_nsp_rx_packet(struct sk_buff *skb)
760 /* 760 /*
761 * Grab the destination address. 761 * Grab the destination address.
762 */ 762 */
763 cb->dst_port = *(unsigned short *)ptr; 763 cb->dst_port = *(__le16 *)ptr;
764 cb->src_port = 0; 764 cb->src_port = 0;
765 ptr += 2; 765 ptr += 2;
766 766
@@ -768,7 +768,7 @@ static int dn_nsp_rx_packet(struct sk_buff *skb)
768 * If not a connack, grab the source address too. 768 * If not a connack, grab the source address too.
769 */ 769 */
770 if (pskb_may_pull(skb, 5)) { 770 if (pskb_may_pull(skb, 5)) {
771 cb->src_port = *(unsigned short *)ptr; 771 cb->src_port = *(__le16 *)ptr;
772 ptr += 2; 772 ptr += 2;
773 skb_pull(skb, 5); 773 skb_pull(skb, 5);
774 } 774 }
@@ -778,7 +778,7 @@ static int dn_nsp_rx_packet(struct sk_buff *skb)
778 * Swap src & dst and look up in the normal way. 778 * Swap src & dst and look up in the normal way.
779 */ 779 */
780 if (unlikely(cb->rt_flags & DN_RT_F_RTS)) { 780 if (unlikely(cb->rt_flags & DN_RT_F_RTS)) {
781 unsigned short tmp = cb->dst_port; 781 __le16 tmp = cb->dst_port;
782 cb->dst_port = cb->src_port; 782 cb->dst_port = cb->src_port;
783 cb->src_port = tmp; 783 cb->src_port = tmp;
784 tmp = cb->dst; 784 tmp = cb->dst;
diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c
index c96c767b1f74..c2e21cd89b3c 100644
--- a/net/decnet/dn_nsp_out.c
+++ b/net/decnet/dn_nsp_out.c
@@ -287,26 +287,26 @@ int dn_nsp_xmit_timeout(struct sock *sk)
287 return 0; 287 return 0;
288} 288}
289 289
290static inline unsigned char *dn_mk_common_header(struct dn_scp *scp, struct sk_buff *skb, unsigned char msgflag, int len) 290static inline __le16 *dn_mk_common_header(struct dn_scp *scp, struct sk_buff *skb, unsigned char msgflag, int len)
291{ 291{
292 unsigned char *ptr = skb_push(skb, len); 292 unsigned char *ptr = skb_push(skb, len);
293 293
294 BUG_ON(len < 5); 294 BUG_ON(len < 5);
295 295
296 *ptr++ = msgflag; 296 *ptr++ = msgflag;
297 *((unsigned short *)ptr) = scp->addrrem; 297 *((__le16 *)ptr) = scp->addrrem;
298 ptr += 2; 298 ptr += 2;
299 *((unsigned short *)ptr) = scp->addrloc; 299 *((__le16 *)ptr) = scp->addrloc;
300 ptr += 2; 300 ptr += 2;
301 return ptr; 301 return (__le16 __force *)ptr;
302} 302}
303 303
304static unsigned short *dn_mk_ack_header(struct sock *sk, struct sk_buff *skb, unsigned char msgflag, int hlen, int other) 304static __le16 *dn_mk_ack_header(struct sock *sk, struct sk_buff *skb, unsigned char msgflag, int hlen, int other)
305{ 305{
306 struct dn_scp *scp = DN_SK(sk); 306 struct dn_scp *scp = DN_SK(sk);
307 unsigned short acknum = scp->numdat_rcv & 0x0FFF; 307 unsigned short acknum = scp->numdat_rcv & 0x0FFF;
308 unsigned short ackcrs = scp->numoth_rcv & 0x0FFF; 308 unsigned short ackcrs = scp->numoth_rcv & 0x0FFF;
309 unsigned short *ptr; 309 __le16 *ptr;
310 310
311 BUG_ON(hlen < 9); 311 BUG_ON(hlen < 9);
312 312
@@ -325,7 +325,7 @@ static unsigned short *dn_mk_ack_header(struct sock *sk, struct sk_buff *skb, un
325 /* Set "cross subchannel" bit in ackcrs */ 325 /* Set "cross subchannel" bit in ackcrs */
326 ackcrs |= 0x2000; 326 ackcrs |= 0x2000;
327 327
328 ptr = (unsigned short *)dn_mk_common_header(scp, skb, msgflag, hlen); 328 ptr = (__le16 *)dn_mk_common_header(scp, skb, msgflag, hlen);
329 329
330 *ptr++ = dn_htons(acknum); 330 *ptr++ = dn_htons(acknum);
331 *ptr++ = dn_htons(ackcrs); 331 *ptr++ = dn_htons(ackcrs);
@@ -333,11 +333,11 @@ static unsigned short *dn_mk_ack_header(struct sock *sk, struct sk_buff *skb, un
333 return ptr; 333 return ptr;
334} 334}
335 335
336static unsigned short *dn_nsp_mk_data_header(struct sock *sk, struct sk_buff *skb, int oth) 336static __le16 *dn_nsp_mk_data_header(struct sock *sk, struct sk_buff *skb, int oth)
337{ 337{
338 struct dn_scp *scp = DN_SK(sk); 338 struct dn_scp *scp = DN_SK(sk);
339 struct dn_skb_cb *cb = DN_SKB_CB(skb); 339 struct dn_skb_cb *cb = DN_SKB_CB(skb);
340 unsigned short *ptr = dn_mk_ack_header(sk, skb, cb->nsp_flags, 11, oth); 340 __le16 *ptr = dn_mk_ack_header(sk, skb, cb->nsp_flags, 11, oth);
341 341
342 if (unlikely(oth)) { 342 if (unlikely(oth)) {
343 cb->segnum = scp->numoth; 343 cb->segnum = scp->numoth;
@@ -524,9 +524,9 @@ void dn_send_conn_conf(struct sock *sk, gfp_t gfp)
524 struct dn_scp *scp = DN_SK(sk); 524 struct dn_scp *scp = DN_SK(sk);
525 struct sk_buff *skb = NULL; 525 struct sk_buff *skb = NULL;
526 struct nsp_conn_init_msg *msg; 526 struct nsp_conn_init_msg *msg;
527 unsigned char len = scp->conndata_out.opt_optl; 527 __u8 len = (__u8)dn_ntohs(scp->conndata_out.opt_optl);
528 528
529 if ((skb = dn_alloc_skb(sk, 50 + scp->conndata_out.opt_optl, gfp)) == NULL) 529 if ((skb = dn_alloc_skb(sk, 50 + dn_ntohs(scp->conndata_out.opt_optl), gfp)) == NULL)
530 return; 530 return;
531 531
532 msg = (struct nsp_conn_init_msg *)skb_put(skb, sizeof(*msg)); 532 msg = (struct nsp_conn_init_msg *)skb_put(skb, sizeof(*msg));
@@ -553,7 +553,7 @@ void dn_send_conn_conf(struct sock *sk, gfp_t gfp)
553static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg, 553static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg,
554 unsigned short reason, gfp_t gfp, 554 unsigned short reason, gfp_t gfp,
555 struct dst_entry *dst, 555 struct dst_entry *dst,
556 int ddl, unsigned char *dd, __u16 rem, __u16 loc) 556 int ddl, unsigned char *dd, __le16 rem, __le16 loc)
557{ 557{
558 struct sk_buff *skb = NULL; 558 struct sk_buff *skb = NULL;
559 int size = 7 + ddl + ((msgflg == NSP_DISCINIT) ? 1 : 0); 559 int size = 7 + ddl + ((msgflg == NSP_DISCINIT) ? 1 : 0);
@@ -561,7 +561,7 @@ static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg,
561 561
562 if ((dst == NULL) || (rem == 0)) { 562 if ((dst == NULL) || (rem == 0)) {
563 if (net_ratelimit()) 563 if (net_ratelimit())
564 printk(KERN_DEBUG "DECnet: dn_nsp_do_disc: BUG! Please report this to SteveW@ACM.org rem=%u dst=%p\n", (unsigned)rem, dst); 564 printk(KERN_DEBUG "DECnet: dn_nsp_do_disc: BUG! Please report this to SteveW@ACM.org rem=%u dst=%p\n", dn_ntohs(rem), dst);
565 return; 565 return;
566 } 566 }
567 567
@@ -570,11 +570,11 @@ static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg,
570 570
571 msg = skb_put(skb, size); 571 msg = skb_put(skb, size);
572 *msg++ = msgflg; 572 *msg++ = msgflg;
573 *(__u16 *)msg = rem; 573 *(__le16 *)msg = rem;
574 msg += 2; 574 msg += 2;
575 *(__u16 *)msg = loc; 575 *(__le16 *)msg = loc;
576 msg += 2; 576 msg += 2;
577 *(__u16 *)msg = dn_htons(reason); 577 *(__le16 *)msg = dn_htons(reason);
578 msg += 2; 578 msg += 2;
579 if (msgflg == NSP_DISCINIT) 579 if (msgflg == NSP_DISCINIT)
580 *msg++ = ddl; 580 *msg++ = ddl;
@@ -600,10 +600,10 @@ void dn_nsp_send_disc(struct sock *sk, unsigned char msgflg,
600 int ddl = 0; 600 int ddl = 0;
601 601
602 if (msgflg == NSP_DISCINIT) 602 if (msgflg == NSP_DISCINIT)
603 ddl = scp->discdata_out.opt_optl; 603 ddl = dn_ntohs(scp->discdata_out.opt_optl);
604 604
605 if (reason == 0) 605 if (reason == 0)
606 reason = scp->discdata_out.opt_status; 606 reason = dn_ntohs(scp->discdata_out.opt_status);
607 607
608 dn_nsp_do_disc(sk, msgflg, reason, gfp, sk->sk_dst_cache, ddl, 608 dn_nsp_do_disc(sk, msgflg, reason, gfp, sk->sk_dst_cache, ddl,
609 scp->discdata_out.opt_data, scp->addrrem, scp->addrloc); 609 scp->discdata_out.opt_data, scp->addrrem, scp->addrloc);
@@ -708,7 +708,7 @@ void dn_nsp_send_conninit(struct sock *sk, unsigned char msgflg)
708 if (aux > 0) 708 if (aux > 0)
709 memcpy(skb_put(skb, aux), scp->accessdata.acc_acc, aux); 709 memcpy(skb_put(skb, aux), scp->accessdata.acc_acc, aux);
710 710
711 aux = scp->conndata_out.opt_optl; 711 aux = (__u8)dn_ntohs(scp->conndata_out.opt_optl);
712 *skb_put(skb, 1) = aux; 712 *skb_put(skb, 1) = aux;
713 if (aux > 0) 713 if (aux > 0)
714 memcpy(skb_put(skb,aux), scp->conndata_out.opt_data, aux); 714 memcpy(skb_put(skb,aux), scp->conndata_out.opt_data, aux);
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 3407f190afe8..e172cf98d7fc 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -133,9 +133,9 @@ static struct dst_ops dn_dst_ops = {
133 .entries = ATOMIC_INIT(0), 133 .entries = ATOMIC_INIT(0),
134}; 134};
135 135
136static __inline__ unsigned dn_hash(unsigned short src, unsigned short dst) 136static __inline__ unsigned dn_hash(__le16 src, __le16 dst)
137{ 137{
138 unsigned short tmp = src ^ dst; 138 __u16 tmp = (__u16 __force)(src ^ dst);
139 tmp ^= (tmp >> 3); 139 tmp ^= (tmp >> 3);
140 tmp ^= (tmp >> 5); 140 tmp ^= (tmp >> 5);
141 tmp ^= (tmp >> 10); 141 tmp ^= (tmp >> 10);
@@ -149,8 +149,7 @@ static inline void dnrt_free(struct dn_route *rt)
149 149
150static inline void dnrt_drop(struct dn_route *rt) 150static inline void dnrt_drop(struct dn_route *rt)
151{ 151{
152 if (rt) 152 dst_release(&rt->u.dst);
153 dst_release(&rt->u.dst);
154 call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free); 153 call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
155} 154}
156 155
@@ -379,9 +378,9 @@ static int dn_return_short(struct sk_buff *skb)
379{ 378{
380 struct dn_skb_cb *cb; 379 struct dn_skb_cb *cb;
381 unsigned char *ptr; 380 unsigned char *ptr;
382 dn_address *src; 381 __le16 *src;
383 dn_address *dst; 382 __le16 *dst;
384 dn_address tmp; 383 __le16 tmp;
385 384
386 /* Add back headers */ 385 /* Add back headers */
387 skb_push(skb, skb->data - skb->nh.raw); 386 skb_push(skb, skb->data - skb->nh.raw);
@@ -394,9 +393,9 @@ static int dn_return_short(struct sk_buff *skb)
394 ptr = skb->data + 2; 393 ptr = skb->data + 2;
395 *ptr++ = (cb->rt_flags & ~DN_RT_F_RQR) | DN_RT_F_RTS; 394 *ptr++ = (cb->rt_flags & ~DN_RT_F_RQR) | DN_RT_F_RTS;
396 395
397 dst = (dn_address *)ptr; 396 dst = (__le16 *)ptr;
398 ptr += 2; 397 ptr += 2;
399 src = (dn_address *)ptr; 398 src = (__le16 *)ptr;
400 ptr += 2; 399 ptr += 2;
401 *ptr = 0; /* Zero hop count */ 400 *ptr = 0; /* Zero hop count */
402 401
@@ -475,7 +474,8 @@ static int dn_route_rx_packet(struct sk_buff *skb)
475 struct dn_skb_cb *cb = DN_SKB_CB(skb); 474 struct dn_skb_cb *cb = DN_SKB_CB(skb);
476 printk(KERN_DEBUG 475 printk(KERN_DEBUG
477 "DECnet: dn_route_rx_packet: rt_flags=0x%02x dev=%s len=%d src=0x%04hx dst=0x%04hx err=%d type=%d\n", 476 "DECnet: dn_route_rx_packet: rt_flags=0x%02x dev=%s len=%d src=0x%04hx dst=0x%04hx err=%d type=%d\n",
478 (int)cb->rt_flags, devname, skb->len, cb->src, cb->dst, 477 (int)cb->rt_flags, devname, skb->len,
478 dn_ntohs(cb->src), dn_ntohs(cb->dst),
479 err, skb->pkt_type); 479 err, skb->pkt_type);
480 } 480 }
481 481
@@ -505,7 +505,7 @@ static int dn_route_rx_long(struct sk_buff *skb)
505 505
506 /* Destination info */ 506 /* Destination info */
507 ptr += 2; 507 ptr += 2;
508 cb->dst = dn_htons(dn_eth2dn(ptr)); 508 cb->dst = dn_eth2dn(ptr);
509 if (memcmp(ptr, dn_hiord_addr, 4) != 0) 509 if (memcmp(ptr, dn_hiord_addr, 4) != 0)
510 goto drop_it; 510 goto drop_it;
511 ptr += 6; 511 ptr += 6;
@@ -513,7 +513,7 @@ static int dn_route_rx_long(struct sk_buff *skb)
513 513
514 /* Source info */ 514 /* Source info */
515 ptr += 2; 515 ptr += 2;
516 cb->src = dn_htons(dn_eth2dn(ptr)); 516 cb->src = dn_eth2dn(ptr);
517 if (memcmp(ptr, dn_hiord_addr, 4) != 0) 517 if (memcmp(ptr, dn_hiord_addr, 4) != 0)
518 goto drop_it; 518 goto drop_it;
519 ptr += 6; 519 ptr += 6;
@@ -541,9 +541,9 @@ static int dn_route_rx_short(struct sk_buff *skb)
541 skb_pull(skb, 5); 541 skb_pull(skb, 5);
542 skb->h.raw = skb->data; 542 skb->h.raw = skb->data;
543 543
544 cb->dst = *(dn_address *)ptr; 544 cb->dst = *(__le16 *)ptr;
545 ptr += 2; 545 ptr += 2;
546 cb->src = *(dn_address *)ptr; 546 cb->src = *(__le16 *)ptr;
547 ptr += 2; 547 ptr += 2;
548 cb->hops = *ptr & 0x3f; 548 cb->hops = *ptr & 0x3f;
549 549
@@ -575,7 +575,7 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type
575{ 575{
576 struct dn_skb_cb *cb; 576 struct dn_skb_cb *cb;
577 unsigned char flags = 0; 577 unsigned char flags = 0;
578 __u16 len = dn_ntohs(*(__u16 *)skb->data); 578 __u16 len = dn_ntohs(*(__le16 *)skb->data);
579 struct dn_dev *dn = (struct dn_dev *)dev->dn_ptr; 579 struct dn_dev *dn = (struct dn_dev *)dev->dn_ptr;
580 unsigned char padlen = 0; 580 unsigned char padlen = 0;
581 581
@@ -782,7 +782,7 @@ static int dn_rt_bug(struct sk_buff *skb)
782 struct dn_skb_cb *cb = DN_SKB_CB(skb); 782 struct dn_skb_cb *cb = DN_SKB_CB(skb);
783 783
784 printk(KERN_DEBUG "dn_rt_bug: skb from:%04x to:%04x\n", 784 printk(KERN_DEBUG "dn_rt_bug: skb from:%04x to:%04x\n",
785 cb->src, cb->dst); 785 dn_ntohs(cb->src), dn_ntohs(cb->dst));
786 } 786 }
787 787
788 kfree_skb(skb); 788 kfree_skb(skb);
@@ -823,7 +823,7 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
823 return 0; 823 return 0;
824} 824}
825 825
826static inline int dn_match_addr(__u16 addr1, __u16 addr2) 826static inline int dn_match_addr(__le16 addr1, __le16 addr2)
827{ 827{
828 __u16 tmp = dn_ntohs(addr1) ^ dn_ntohs(addr2); 828 __u16 tmp = dn_ntohs(addr1) ^ dn_ntohs(addr2);
829 int match = 16; 829 int match = 16;
@@ -834,9 +834,9 @@ static inline int dn_match_addr(__u16 addr1, __u16 addr2)
834 return match; 834 return match;
835} 835}
836 836
837static __u16 dnet_select_source(const struct net_device *dev, __u16 daddr, int scope) 837static __le16 dnet_select_source(const struct net_device *dev, __le16 daddr, int scope)
838{ 838{
839 __u16 saddr = 0; 839 __le16 saddr = 0;
840 struct dn_dev *dn_db = dev->dn_ptr; 840 struct dn_dev *dn_db = dev->dn_ptr;
841 struct dn_ifaddr *ifa; 841 struct dn_ifaddr *ifa;
842 int best_match = 0; 842 int best_match = 0;
@@ -861,14 +861,14 @@ static __u16 dnet_select_source(const struct net_device *dev, __u16 daddr, int s
861 return saddr; 861 return saddr;
862} 862}
863 863
864static inline __u16 __dn_fib_res_prefsrc(struct dn_fib_res *res) 864static inline __le16 __dn_fib_res_prefsrc(struct dn_fib_res *res)
865{ 865{
866 return dnet_select_source(DN_FIB_RES_DEV(*res), DN_FIB_RES_GW(*res), res->scope); 866 return dnet_select_source(DN_FIB_RES_DEV(*res), DN_FIB_RES_GW(*res), res->scope);
867} 867}
868 868
869static inline __u16 dn_fib_rules_map_destination(__u16 daddr, struct dn_fib_res *res) 869static inline __le16 dn_fib_rules_map_destination(__le16 daddr, struct dn_fib_res *res)
870{ 870{
871 __u16 mask = dnet_make_mask(res->prefixlen); 871 __le16 mask = dnet_make_mask(res->prefixlen);
872 return (daddr&~mask)|res->fi->fib_nh->nh_gw; 872 return (daddr&~mask)|res->fi->fib_nh->nh_gw;
873} 873}
874 874
@@ -892,12 +892,13 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old
892 struct dn_fib_res res = { .fi = NULL, .type = RTN_UNICAST }; 892 struct dn_fib_res res = { .fi = NULL, .type = RTN_UNICAST };
893 int err; 893 int err;
894 int free_res = 0; 894 int free_res = 0;
895 __u16 gateway = 0; 895 __le16 gateway = 0;
896 896
897 if (decnet_debug_level & 16) 897 if (decnet_debug_level & 16)
898 printk(KERN_DEBUG 898 printk(KERN_DEBUG
899 "dn_route_output_slow: dst=%04x src=%04x mark=%d" 899 "dn_route_output_slow: dst=%04x src=%04x mark=%d"
900 " iif=%d oif=%d\n", oldflp->fld_dst, oldflp->fld_src, 900 " iif=%d oif=%d\n", dn_ntohs(oldflp->fld_dst),
901 dn_ntohs(oldflp->fld_src),
901 oldflp->fld_fwmark, loopback_dev.ifindex, oldflp->oif); 902 oldflp->fld_fwmark, loopback_dev.ifindex, oldflp->oif);
902 903
903 /* If we have an output interface, verify its a DECnet device */ 904 /* If we have an output interface, verify its a DECnet device */
@@ -961,8 +962,9 @@ source_ok:
961 if (decnet_debug_level & 16) 962 if (decnet_debug_level & 16)
962 printk(KERN_DEBUG 963 printk(KERN_DEBUG
963 "dn_route_output_slow: initial checks complete." 964 "dn_route_output_slow: initial checks complete."
964 " dst=%o4x src=%04x oif=%d try_hard=%d\n", fl.fld_dst, 965 " dst=%o4x src=%04x oif=%d try_hard=%d\n",
965 fl.fld_src, fl.oif, try_hard); 966 dn_ntohs(fl.fld_dst), dn_ntohs(fl.fld_src),
967 fl.oif, try_hard);
966 968
967 /* 969 /*
968 * N.B. If the kernel is compiled without router support then 970 * N.B. If the kernel is compiled without router support then
@@ -1218,8 +1220,8 @@ static int dn_route_input_slow(struct sk_buff *skb)
1218 struct neighbour *neigh = NULL; 1220 struct neighbour *neigh = NULL;
1219 unsigned hash; 1221 unsigned hash;
1220 int flags = 0; 1222 int flags = 0;
1221 __u16 gateway = 0; 1223 __le16 gateway = 0;
1222 __u16 local_src = 0; 1224 __le16 local_src = 0;
1223 struct flowi fl = { .nl_u = { .dn_u = 1225 struct flowi fl = { .nl_u = { .dn_u =
1224 { .daddr = cb->dst, 1226 { .daddr = cb->dst,
1225 .saddr = cb->src, 1227 .saddr = cb->src,
@@ -1266,7 +1268,7 @@ static int dn_route_input_slow(struct sk_buff *skb)
1266 res.type = RTN_LOCAL; 1268 res.type = RTN_LOCAL;
1267 flags |= RTCF_DIRECTSRC; 1269 flags |= RTCF_DIRECTSRC;
1268 } else { 1270 } else {
1269 __u16 src_map = fl.fld_src; 1271 __le16 src_map = fl.fld_src;
1270 free_res = 1; 1272 free_res = 1;
1271 1273
1272 out_dev = DN_FIB_RES_DEV(res); 1274 out_dev = DN_FIB_RES_DEV(res);
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index 1060de70bc0c..446faafe2065 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -27,6 +27,8 @@
27#include <linux/timer.h> 27#include <linux/timer.h>
28#include <linux/spinlock.h> 28#include <linux/spinlock.h>
29#include <linux/in_route.h> 29#include <linux/in_route.h>
30#include <linux/list.h>
31#include <linux/rcupdate.h>
30#include <asm/atomic.h> 32#include <asm/atomic.h>
31#include <asm/uaccess.h> 33#include <asm/uaccess.h>
32#include <net/neighbour.h> 34#include <net/neighbour.h>
@@ -39,18 +41,18 @@
39 41
40struct dn_fib_rule 42struct dn_fib_rule
41{ 43{
42 struct dn_fib_rule *r_next; 44 struct hlist_node r_hlist;
43 atomic_t r_clntref; 45 atomic_t r_clntref;
44 u32 r_preference; 46 u32 r_preference;
45 unsigned char r_table; 47 unsigned char r_table;
46 unsigned char r_action; 48 unsigned char r_action;
47 unsigned char r_dst_len; 49 unsigned char r_dst_len;
48 unsigned char r_src_len; 50 unsigned char r_src_len;
49 dn_address r_src; 51 __le16 r_src;
50 dn_address r_srcmask; 52 __le16 r_srcmask;
51 dn_address r_dst; 53 __le16 r_dst;
52 dn_address r_dstmask; 54 __le16 r_dstmask;
53 dn_address r_srcmap; 55 __le16 r_srcmap;
54 u8 r_flags; 56 u8 r_flags;
55#ifdef CONFIG_DECNET_ROUTE_FWMARK 57#ifdef CONFIG_DECNET_ROUTE_FWMARK
56 u32 r_fwmark; 58 u32 r_fwmark;
@@ -58,6 +60,7 @@ struct dn_fib_rule
58 int r_ifindex; 60 int r_ifindex;
59 char r_ifname[IFNAMSIZ]; 61 char r_ifname[IFNAMSIZ];
60 int r_dead; 62 int r_dead;
63 struct rcu_head rcu;
61}; 64};
62 65
63static struct dn_fib_rule default_rule = { 66static struct dn_fib_rule default_rule = {
@@ -67,18 +70,17 @@ static struct dn_fib_rule default_rule = {
67 .r_action = RTN_UNICAST 70 .r_action = RTN_UNICAST
68}; 71};
69 72
70static struct dn_fib_rule *dn_fib_rules = &default_rule; 73static struct hlist_head dn_fib_rules;
71static DEFINE_RWLOCK(dn_fib_rules_lock);
72
73 74
74int dn_fib_rtm_delrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 75int dn_fib_rtm_delrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
75{ 76{
76 struct rtattr **rta = arg; 77 struct rtattr **rta = arg;
77 struct rtmsg *rtm = NLMSG_DATA(nlh); 78 struct rtmsg *rtm = NLMSG_DATA(nlh);
78 struct dn_fib_rule *r, **rp; 79 struct dn_fib_rule *r;
80 struct hlist_node *node;
79 int err = -ESRCH; 81 int err = -ESRCH;
80 82
81 for(rp=&dn_fib_rules; (r=*rp) != NULL; rp = &r->r_next) { 83 hlist_for_each_entry(r, node, &dn_fib_rules, r_hlist) {
82 if ((!rta[RTA_SRC-1] || memcmp(RTA_DATA(rta[RTA_SRC-1]), &r->r_src, 2) == 0) && 84 if ((!rta[RTA_SRC-1] || memcmp(RTA_DATA(rta[RTA_SRC-1]), &r->r_src, 2) == 0) &&
83 rtm->rtm_src_len == r->r_src_len && 85 rtm->rtm_src_len == r->r_src_len &&
84 rtm->rtm_dst_len == r->r_dst_len && 86 rtm->rtm_dst_len == r->r_dst_len &&
@@ -95,10 +97,8 @@ int dn_fib_rtm_delrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
95 if (r == &default_rule) 97 if (r == &default_rule)
96 break; 98 break;
97 99
98 write_lock_bh(&dn_fib_rules_lock); 100 hlist_del_rcu(&r->r_hlist);
99 *rp = r->r_next;
100 r->r_dead = 1; 101 r->r_dead = 1;
101 write_unlock_bh(&dn_fib_rules_lock);
102 dn_fib_rule_put(r); 102 dn_fib_rule_put(r);
103 err = 0; 103 err = 0;
104 break; 104 break;
@@ -108,11 +108,17 @@ int dn_fib_rtm_delrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
108 return err; 108 return err;
109} 109}
110 110
111static inline void dn_fib_rule_put_rcu(struct rcu_head *head)
112{
113 struct dn_fib_rule *r = container_of(head, struct dn_fib_rule, rcu);
114 kfree(r);
115}
116
111void dn_fib_rule_put(struct dn_fib_rule *r) 117void dn_fib_rule_put(struct dn_fib_rule *r)
112{ 118{
113 if (atomic_dec_and_test(&r->r_clntref)) { 119 if (atomic_dec_and_test(&r->r_clntref)) {
114 if (r->r_dead) 120 if (r->r_dead)
115 kfree(r); 121 call_rcu(&r->rcu, dn_fib_rule_put_rcu);
116 else 122 else
117 printk(KERN_DEBUG "Attempt to free alive dn_fib_rule\n"); 123 printk(KERN_DEBUG "Attempt to free alive dn_fib_rule\n");
118 } 124 }
@@ -123,7 +129,8 @@ int dn_fib_rtm_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
123{ 129{
124 struct rtattr **rta = arg; 130 struct rtattr **rta = arg;
125 struct rtmsg *rtm = NLMSG_DATA(nlh); 131 struct rtmsg *rtm = NLMSG_DATA(nlh);
126 struct dn_fib_rule *r, *new_r, **rp; 132 struct dn_fib_rule *r, *new_r, *last = NULL;
133 struct hlist_node *node = NULL;
127 unsigned char table_id; 134 unsigned char table_id;
128 135
129 if (rtm->rtm_src_len > 16 || rtm->rtm_dst_len > 16) 136 if (rtm->rtm_src_len > 16 || rtm->rtm_dst_len > 16)
@@ -149,6 +156,7 @@ int dn_fib_rtm_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
149 if (!new_r) 156 if (!new_r)
150 return -ENOMEM; 157 return -ENOMEM;
151 memset(new_r, 0, sizeof(*new_r)); 158 memset(new_r, 0, sizeof(*new_r));
159
152 if (rta[RTA_SRC-1]) 160 if (rta[RTA_SRC-1])
153 memcpy(&new_r->r_src, RTA_DATA(rta[RTA_SRC-1]), 2); 161 memcpy(&new_r->r_src, RTA_DATA(rta[RTA_SRC-1]), 2);
154 if (rta[RTA_DST-1]) 162 if (rta[RTA_DST-1])
@@ -179,27 +187,26 @@ int dn_fib_rtm_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
179 } 187 }
180 } 188 }
181 189
182 rp = &dn_fib_rules; 190 r = container_of(dn_fib_rules.first, struct dn_fib_rule, r_hlist);
183 if (!new_r->r_preference) { 191 if (!new_r->r_preference) {
184 r = dn_fib_rules; 192 if (r && r->r_hlist.next != NULL) {
185 if (r && (r = r->r_next) != NULL) { 193 r = container_of(r->r_hlist.next, struct dn_fib_rule, r_hlist);
186 rp = &dn_fib_rules->r_next;
187 if (r->r_preference) 194 if (r->r_preference)
188 new_r->r_preference = r->r_preference - 1; 195 new_r->r_preference = r->r_preference - 1;
189 } 196 }
190 } 197 }
191 198
192 while((r=*rp) != NULL) { 199 hlist_for_each_entry(r, node, &dn_fib_rules, r_hlist) {
193 if (r->r_preference > new_r->r_preference) 200 if (r->r_preference > new_r->r_preference)
194 break; 201 break;
195 rp = &r->r_next; 202 last = r;
196 } 203 }
197
198 new_r->r_next = r;
199 atomic_inc(&new_r->r_clntref); 204 atomic_inc(&new_r->r_clntref);
200 write_lock_bh(&dn_fib_rules_lock); 205
201 *rp = new_r; 206 if (last)
202 write_unlock_bh(&dn_fib_rules_lock); 207 hlist_add_after_rcu(&last->r_hlist, &new_r->r_hlist);
208 else
209 hlist_add_before_rcu(&new_r->r_hlist, &r->r_hlist);
203 return 0; 210 return 0;
204} 211}
205 212
@@ -208,12 +215,14 @@ int dn_fib_lookup(const struct flowi *flp, struct dn_fib_res *res)
208{ 215{
209 struct dn_fib_rule *r, *policy; 216 struct dn_fib_rule *r, *policy;
210 struct dn_fib_table *tb; 217 struct dn_fib_table *tb;
211 dn_address saddr = flp->fld_src; 218 __le16 saddr = flp->fld_src;
212 dn_address daddr = flp->fld_dst; 219 __le16 daddr = flp->fld_dst;
220 struct hlist_node *node;
213 int err; 221 int err;
214 222
215 read_lock(&dn_fib_rules_lock); 223 rcu_read_lock();
216 for(r = dn_fib_rules; r; r = r->r_next) { 224
225 hlist_for_each_entry_rcu(r, node, &dn_fib_rules, r_hlist) {
217 if (((saddr^r->r_src) & r->r_srcmask) || 226 if (((saddr^r->r_src) & r->r_srcmask) ||
218 ((daddr^r->r_dst) & r->r_dstmask) || 227 ((daddr^r->r_dst) & r->r_dstmask) ||
219#ifdef CONFIG_DECNET_ROUTE_FWMARK 228#ifdef CONFIG_DECNET_ROUTE_FWMARK
@@ -228,14 +237,14 @@ int dn_fib_lookup(const struct flowi *flp, struct dn_fib_res *res)
228 policy = r; 237 policy = r;
229 break; 238 break;
230 case RTN_UNREACHABLE: 239 case RTN_UNREACHABLE:
231 read_unlock(&dn_fib_rules_lock); 240 rcu_read_unlock();
232 return -ENETUNREACH; 241 return -ENETUNREACH;
233 default: 242 default:
234 case RTN_BLACKHOLE: 243 case RTN_BLACKHOLE:
235 read_unlock(&dn_fib_rules_lock); 244 rcu_read_unlock();
236 return -EINVAL; 245 return -EINVAL;
237 case RTN_PROHIBIT: 246 case RTN_PROHIBIT:
238 read_unlock(&dn_fib_rules_lock); 247 rcu_read_unlock();
239 return -EACCES; 248 return -EACCES;
240 } 249 }
241 250
@@ -246,20 +255,20 @@ int dn_fib_lookup(const struct flowi *flp, struct dn_fib_res *res)
246 res->r = policy; 255 res->r = policy;
247 if (policy) 256 if (policy)
248 atomic_inc(&policy->r_clntref); 257 atomic_inc(&policy->r_clntref);
249 read_unlock(&dn_fib_rules_lock); 258 rcu_read_unlock();
250 return 0; 259 return 0;
251 } 260 }
252 if (err < 0 && err != -EAGAIN) { 261 if (err < 0 && err != -EAGAIN) {
253 read_unlock(&dn_fib_rules_lock); 262 rcu_read_unlock();
254 return err; 263 return err;
255 } 264 }
256 } 265 }
257 266
258 read_unlock(&dn_fib_rules_lock); 267 rcu_read_unlock();
259 return -ESRCH; 268 return -ESRCH;
260} 269}
261 270
262unsigned dnet_addr_type(__u16 addr) 271unsigned dnet_addr_type(__le16 addr)
263{ 272{
264 struct flowi fl = { .nl_u = { .dn_u = { .daddr = addr } } }; 273 struct flowi fl = { .nl_u = { .dn_u = { .daddr = addr } } };
265 struct dn_fib_res res; 274 struct dn_fib_res res;
@@ -277,7 +286,7 @@ unsigned dnet_addr_type(__u16 addr)
277 return ret; 286 return ret;
278} 287}
279 288
280__u16 dn_fib_rules_policy(__u16 saddr, struct dn_fib_res *res, unsigned *flags) 289__le16 dn_fib_rules_policy(__le16 saddr, struct dn_fib_res *res, unsigned *flags)
281{ 290{
282 struct dn_fib_rule *r = res->r; 291 struct dn_fib_rule *r = res->r;
283 292
@@ -297,27 +306,23 @@ __u16 dn_fib_rules_policy(__u16 saddr, struct dn_fib_res *res, unsigned *flags)
297 306
298static void dn_fib_rules_detach(struct net_device *dev) 307static void dn_fib_rules_detach(struct net_device *dev)
299{ 308{
309 struct hlist_node *node;
300 struct dn_fib_rule *r; 310 struct dn_fib_rule *r;
301 311
302 for(r = dn_fib_rules; r; r = r->r_next) { 312 hlist_for_each_entry(r, node, &dn_fib_rules, r_hlist) {
303 if (r->r_ifindex == dev->ifindex) { 313 if (r->r_ifindex == dev->ifindex)
304 write_lock_bh(&dn_fib_rules_lock);
305 r->r_ifindex = -1; 314 r->r_ifindex = -1;
306 write_unlock_bh(&dn_fib_rules_lock);
307 }
308 } 315 }
309} 316}
310 317
311static void dn_fib_rules_attach(struct net_device *dev) 318static void dn_fib_rules_attach(struct net_device *dev)
312{ 319{
320 struct hlist_node *node;
313 struct dn_fib_rule *r; 321 struct dn_fib_rule *r;
314 322
315 for(r = dn_fib_rules; r; r = r->r_next) { 323 hlist_for_each_entry(r, node, &dn_fib_rules, r_hlist) {
316 if (r->r_ifindex == -1 && strcmp(dev->name, r->r_ifname) == 0) { 324 if (r->r_ifindex == -1 && strcmp(dev->name, r->r_ifname) == 0)
317 write_lock_bh(&dn_fib_rules_lock);
318 r->r_ifindex = dev->ifindex; 325 r->r_ifindex = dev->ifindex;
319 write_unlock_bh(&dn_fib_rules_lock);
320 }
321 } 326 }
322} 327}
323 328
@@ -387,18 +392,20 @@ rtattr_failure:
387 392
388int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) 393int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
389{ 394{
390 int idx; 395 int idx = 0;
391 int s_idx = cb->args[0]; 396 int s_idx = cb->args[0];
392 struct dn_fib_rule *r; 397 struct dn_fib_rule *r;
398 struct hlist_node *node;
393 399
394 read_lock(&dn_fib_rules_lock); 400 rcu_read_lock();
395 for(r = dn_fib_rules, idx = 0; r; r = r->r_next, idx++) { 401 hlist_for_each_entry(r, node, &dn_fib_rules, r_hlist) {
396 if (idx < s_idx) 402 if (idx < s_idx)
397 continue; 403 continue;
398 if (dn_fib_fill_rule(skb, r, cb, NLM_F_MULTI) < 0) 404 if (dn_fib_fill_rule(skb, r, cb, NLM_F_MULTI) < 0)
399 break; 405 break;
406 idx++;
400 } 407 }
401 read_unlock(&dn_fib_rules_lock); 408 rcu_read_unlock();
402 cb->args[0] = idx; 409 cb->args[0] = idx;
403 410
404 return skb->len; 411 return skb->len;
@@ -406,6 +413,8 @@ int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
406 413
407void __init dn_fib_rules_init(void) 414void __init dn_fib_rules_init(void)
408{ 415{
416 INIT_HLIST_HEAD(&dn_fib_rules);
417 hlist_add_head(&default_rule.r_hlist, &dn_fib_rules);
409 register_netdevice_notifier(&dn_fib_rules_notifier); 418 register_netdevice_notifier(&dn_fib_rules_notifier);
410} 419}
411 420
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
index 6f8b5658cb4e..0ebc46af1bdd 100644
--- a/net/decnet/dn_table.c
+++ b/net/decnet/dn_table.c
@@ -46,7 +46,7 @@ struct dn_zone
46 u32 dz_hashmask; 46 u32 dz_hashmask;
47#define DZ_HASHMASK(dz) ((dz)->dz_hashmask) 47#define DZ_HASHMASK(dz) ((dz)->dz_hashmask)
48 int dz_order; 48 int dz_order;
49 u16 dz_mask; 49 __le16 dz_mask;
50#define DZ_MASK(dz) ((dz)->dz_mask) 50#define DZ_MASK(dz) ((dz)->dz_mask)
51}; 51};
52 52
@@ -84,14 +84,14 @@ static int dn_fib_hash_zombies;
84 84
85static inline dn_fib_idx_t dn_hash(dn_fib_key_t key, struct dn_zone *dz) 85static inline dn_fib_idx_t dn_hash(dn_fib_key_t key, struct dn_zone *dz)
86{ 86{
87 u16 h = ntohs(key.datum)>>(16 - dz->dz_order); 87 u16 h = dn_ntohs(key.datum)>>(16 - dz->dz_order);
88 h ^= (h >> 10); 88 h ^= (h >> 10);
89 h ^= (h >> 6); 89 h ^= (h >> 6);
90 h &= DZ_HASHMASK(dz); 90 h &= DZ_HASHMASK(dz);
91 return *(dn_fib_idx_t *)&h; 91 return *(dn_fib_idx_t *)&h;
92} 92}
93 93
94static inline dn_fib_key_t dz_key(u16 dst, struct dn_zone *dz) 94static inline dn_fib_key_t dz_key(__le16 dst, struct dn_zone *dz)
95{ 95{
96 dn_fib_key_t k; 96 dn_fib_key_t k;
97 k.datum = dst & DZ_MASK(dz); 97 k.datum = dst & DZ_MASK(dz);
@@ -250,7 +250,7 @@ static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct dn_kern
250 250
251 for_nexthops(fi) { 251 for_nexthops(fi) {
252 int attrlen = nhlen - sizeof(struct rtnexthop); 252 int attrlen = nhlen - sizeof(struct rtnexthop);
253 dn_address gw; 253 __le16 gw;
254 254
255 if (attrlen < 0 || (nhlen -= nhp->rtnh_len) < 0) 255 if (attrlen < 0 || (nhlen -= nhp->rtnh_len) < 0)
256 return -EINVAL; 256 return -EINVAL;
@@ -457,7 +457,7 @@ static int dn_fib_table_insert(struct dn_fib_table *tb, struct rtmsg *r, struct
457 457
458 dz_key_0(key); 458 dz_key_0(key);
459 if (rta->rta_dst) { 459 if (rta->rta_dst) {
460 dn_address dst; 460 __le16 dst;
461 memcpy(&dst, rta->rta_dst, 2); 461 memcpy(&dst, rta->rta_dst, 2);
462 if (dst & ~DZ_MASK(dz)) 462 if (dst & ~DZ_MASK(dz))
463 return -EINVAL; 463 return -EINVAL;
@@ -593,7 +593,7 @@ static int dn_fib_table_delete(struct dn_fib_table *tb, struct rtmsg *r, struct
593 593
594 dz_key_0(key); 594 dz_key_0(key);
595 if (rta->rta_dst) { 595 if (rta->rta_dst) {
596 dn_address dst; 596 __le16 dst;
597 memcpy(&dst, rta->rta_dst, 2); 597 memcpy(&dst, rta->rta_dst, 2);
598 if (dst & ~DZ_MASK(dz)) 598 if (dst & ~DZ_MASK(dz))
599 return -EINVAL; 599 return -EINVAL;
diff --git a/net/decnet/sysctl_net_decnet.c b/net/decnet/sysctl_net_decnet.c
index 0e9d2c571165..bda5920215fd 100644
--- a/net/decnet/sysctl_net_decnet.c
+++ b/net/decnet/sysctl_net_decnet.c
@@ -86,9 +86,9 @@ static void strip_it(char *str)
86 * Simple routine to parse an ascii DECnet address 86 * Simple routine to parse an ascii DECnet address
87 * into a network order address. 87 * into a network order address.
88 */ 88 */
89static int parse_addr(dn_address *addr, char *str) 89static int parse_addr(__le16 *addr, char *str)
90{ 90{
91 dn_address area, node; 91 __u16 area, node;
92 92
93 while(*str && !ISNUM(*str)) str++; 93 while(*str && !ISNUM(*str)) str++;
94 94
@@ -139,7 +139,7 @@ static int dn_node_address_strategy(ctl_table *table, int __user *name, int nlen
139 void **context) 139 void **context)
140{ 140{
141 size_t len; 141 size_t len;
142 dn_address addr; 142 __le16 addr;
143 143
144 if (oldval && oldlenp) { 144 if (oldval && oldlenp) {
145 if (get_user(len, oldlenp)) 145 if (get_user(len, oldlenp))
@@ -147,14 +147,14 @@ static int dn_node_address_strategy(ctl_table *table, int __user *name, int nlen
147 if (len) { 147 if (len) {
148 if (len != sizeof(unsigned short)) 148 if (len != sizeof(unsigned short))
149 return -EINVAL; 149 return -EINVAL;
150 if (put_user(decnet_address, (unsigned short __user *)oldval)) 150 if (put_user(decnet_address, (__le16 __user *)oldval))
151 return -EFAULT; 151 return -EFAULT;
152 } 152 }
153 } 153 }
154 if (newval && newlen) { 154 if (newval && newlen) {
155 if (newlen != sizeof(unsigned short)) 155 if (newlen != sizeof(unsigned short))
156 return -EINVAL; 156 return -EINVAL;
157 if (get_user(addr, (unsigned short __user *)newval)) 157 if (get_user(addr, (__le16 __user *)newval))
158 return -EFAULT; 158 return -EFAULT;
159 159
160 dn_dev_devices_off(); 160 dn_dev_devices_off();
@@ -173,7 +173,7 @@ static int dn_node_address_handler(ctl_table *table, int write,
173{ 173{
174 char addr[DN_ASCBUF_LEN]; 174 char addr[DN_ASCBUF_LEN];
175 size_t len; 175 size_t len;
176 dn_address dnaddr; 176 __le16 dnaddr;
177 177
178 if (!*lenp || (*ppos && !write)) { 178 if (!*lenp || (*ppos && !write)) {
179 *lenp = 0; 179 *lenp = 0;
diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig
index d18ccba3ea9e..dbb08528ddf5 100644
--- a/net/ieee80211/Kconfig
+++ b/net/ieee80211/Kconfig
@@ -66,3 +66,4 @@ config IEEE80211_CRYPT_TKIP
66 This can be compiled as a modules and it will be called 66 This can be compiled as a modules and it will be called
67 "ieee80211_crypt_tkip". 67 "ieee80211_crypt_tkip".
68 68
69source "net/ieee80211/softmac/Kconfig"
diff --git a/net/ieee80211/Makefile b/net/ieee80211/Makefile
index f988417121da..796a7c76ee48 100644
--- a/net/ieee80211/Makefile
+++ b/net/ieee80211/Makefile
@@ -10,3 +10,4 @@ ieee80211-objs := \
10 ieee80211_wx.o \ 10 ieee80211_wx.o \
11 ieee80211_geo.o 11 ieee80211_geo.o
12 12
13obj-$(CONFIG_IEEE80211_SOFTMAC) += softmac/
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index a7f2a642a512..604b7b0097bc 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -780,6 +780,80 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
780 return 0; 780 return 0;
781} 781}
782 782
783/* Filter out unrelated packets, call ieee80211_rx[_mgt] */
784int ieee80211_rx_any(struct ieee80211_device *ieee,
785 struct sk_buff *skb, struct ieee80211_rx_stats *stats)
786{
787 struct ieee80211_hdr_4addr *hdr;
788 int is_packet_for_us;
789 u16 fc;
790
791 if (ieee->iw_mode == IW_MODE_MONITOR)
792 return ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL;
793
794 hdr = (struct ieee80211_hdr_4addr *)skb->data;
795 fc = le16_to_cpu(hdr->frame_ctl);
796
797 if ((fc & IEEE80211_FCTL_VERS) != 0)
798 return -EINVAL;
799
800 switch (fc & IEEE80211_FCTL_FTYPE) {
801 case IEEE80211_FTYPE_MGMT:
802 ieee80211_rx_mgt(ieee, hdr, stats);
803 return 0;
804 case IEEE80211_FTYPE_DATA:
805 break;
806 case IEEE80211_FTYPE_CTL:
807 return 0;
808 default:
809 return -EINVAL;
810 }
811
812 is_packet_for_us = 0;
813 switch (ieee->iw_mode) {
814 case IW_MODE_ADHOC:
815 /* our BSS and not from/to DS */
816 if (memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) == 0)
817 if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == 0) {
818 /* promisc: get all */
819 if (ieee->dev->flags & IFF_PROMISC)
820 is_packet_for_us = 1;
821 /* to us */
822 else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0)
823 is_packet_for_us = 1;
824 /* mcast */
825 else if (is_multicast_ether_addr(hdr->addr1))
826 is_packet_for_us = 1;
827 }
828 break;
829 case IW_MODE_INFRA:
830 /* our BSS (== from our AP) and from DS */
831 if (memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) == 0)
832 if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS) {
833 /* promisc: get all */
834 if (ieee->dev->flags & IFF_PROMISC)
835 is_packet_for_us = 1;
836 /* to us */
837 else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0)
838 is_packet_for_us = 1;
839 /* mcast */
840 else if (is_multicast_ether_addr(hdr->addr1)) {
841 /* not our own packet bcasted from AP */
842 if (memcmp(hdr->addr3, ieee->dev->dev_addr, ETH_ALEN))
843 is_packet_for_us = 1;
844 }
845 }
846 break;
847 default:
848 /* ? */
849 break;
850 }
851
852 if (is_packet_for_us)
853 return (ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL);
854 return 0;
855}
856
783#define MGMT_FRAME_FIXED_PART_LENGTH 0x24 857#define MGMT_FRAME_FIXED_PART_LENGTH 0x24
784 858
785static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 }; 859static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
diff --git a/net/ieee80211/softmac/Kconfig b/net/ieee80211/softmac/Kconfig
new file mode 100644
index 000000000000..6cd9f3427be6
--- /dev/null
+++ b/net/ieee80211/softmac/Kconfig
@@ -0,0 +1,10 @@
1config IEEE80211_SOFTMAC
2 tristate "Software MAC add-on to the IEEE 802.11 networking stack"
3 depends on IEEE80211 && EXPERIMENTAL
4 ---help---
5 This option enables the hardware independent software MAC addon
6 for the IEEE 802.11 networking stack.
7
8config IEEE80211_SOFTMAC_DEBUG
9 bool "Enable full debugging output"
10 depends on IEEE80211_SOFTMAC
diff --git a/net/ieee80211/softmac/Makefile b/net/ieee80211/softmac/Makefile
new file mode 100644
index 000000000000..bfcb391bb2c7
--- /dev/null
+++ b/net/ieee80211/softmac/Makefile
@@ -0,0 +1,9 @@
1obj-$(CONFIG_IEEE80211_SOFTMAC) += ieee80211softmac.o
2ieee80211softmac-objs := \
3 ieee80211softmac_io.o \
4 ieee80211softmac_auth.o \
5 ieee80211softmac_module.o \
6 ieee80211softmac_scan.o \
7 ieee80211softmac_wx.o \
8 ieee80211softmac_assoc.o \
9 ieee80211softmac_event.o
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
new file mode 100644
index 000000000000..be61de78dfa4
--- /dev/null
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -0,0 +1,396 @@
1/*
2 * This file contains the softmac's association logic.
3 *
4 * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
5 * Joseph Jezak <josejx@gentoo.org>
6 * Larry Finger <Larry.Finger@lwfinger.net>
7 * Danny van Dyk <kugelfang@gentoo.org>
8 * Michael Buesch <mbuesch@freenet.de>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 * The full GNU General Public License is included in this distribution in the
24 * file called COPYING.
25 */
26
27#include "ieee80211softmac_priv.h"
28
29/*
30 * Overview
31 *
32 * Before you can associate, you have to authenticate.
33 *
34 */
35
36/* Sends out an association request to the desired AP */
37static void
38ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net)
39{
40 unsigned long flags;
41
42 /* Switch to correct channel for this network */
43 mac->set_channel(mac->dev, net->channel);
44
45 /* Send association request */
46 ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_ASSOC_REQ, 0);
47
48 dprintk(KERN_INFO PFX "sent association request!\n");
49
50 /* Change the state to associating */
51 spin_lock_irqsave(&mac->lock, flags);
52 mac->associnfo.associating = 1;
53 mac->associated = 0; /* just to make sure */
54 spin_unlock_irqrestore(&mac->lock, flags);
55
56 /* Set a timer for timeout */
57 /* FIXME: make timeout configurable */
58 schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ);
59}
60
61void
62ieee80211softmac_assoc_timeout(void *d)
63{
64 struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d;
65 unsigned long flags;
66
67 spin_lock_irqsave(&mac->lock, flags);
68 /* we might race against ieee80211softmac_handle_assoc_response,
69 * so make sure only one of us does something */
70 if (!mac->associnfo.associating) {
71 spin_unlock_irqrestore(&mac->lock, flags);
72 return;
73 }
74 mac->associnfo.associating = 0;
75 mac->associnfo.bssvalid = 0;
76 mac->associated = 0;
77 spin_unlock_irqrestore(&mac->lock, flags);
78
79 dprintk(KERN_INFO PFX "assoc request timed out!\n");
80 /* FIXME: we need to know the network here. that requires a bit of restructuring */
81 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, NULL);
82}
83
84/* Sends out a disassociation request to the desired AP */
85static void
86ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason)
87{
88 unsigned long flags;
89 struct ieee80211softmac_network *found;
90
91 if (mac->associnfo.bssvalid && mac->associated) {
92 found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
93 if (found)
94 ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason);
95 } else if (mac->associnfo.associating) {
96 cancel_delayed_work(&mac->associnfo.timeout);
97 }
98
99 /* Change our state */
100 spin_lock_irqsave(&mac->lock, flags);
101 /* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */
102 mac->associated = 0;
103 mac->associnfo.associating = 0;
104 spin_unlock_irqrestore(&mac->lock, flags);
105}
106
107static inline int
108we_support_all_basic_rates(struct ieee80211softmac_device *mac, u8 *from, u8 from_len)
109{
110 int idx, search, found;
111 u8 rate, search_rate;
112
113 for (idx = 0; idx < (from_len); idx++) {
114 rate = (from)[idx];
115 if (!(rate & IEEE80211_BASIC_RATE_MASK))
116 continue;
117 found = 0;
118 rate &= ~IEEE80211_BASIC_RATE_MASK;
119 for (search = 0; search < mac->ratesinfo.count; search++) {
120 search_rate = mac->ratesinfo.rates[search];
121 search_rate &= ~IEEE80211_BASIC_RATE_MASK;
122 if (rate == search_rate) {
123 found = 1;
124 break;
125 }
126 }
127 if (!found)
128 return 0;
129 }
130 return 1;
131}
132
133static int
134network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_network *net)
135{
136 /* we cannot associate to networks whose name we don't know */
137 if (ieee80211_is_empty_essid(net->ssid, net->ssid_len))
138 return 0;
139 /* do not associate to a network whose BSSBasicRateSet we cannot support */
140 if (!we_support_all_basic_rates(mac, net->rates, net->rates_len))
141 return 0;
142 /* do we really need to check the ex rates? */
143 if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len))
144 return 0;
145
146 /* if 'ANY' network requested, take any that doesn't have privacy enabled */
147 if (mac->associnfo.req_essid.len == 0
148 && !(net->capability & WLAN_CAPABILITY_PRIVACY))
149 return 1;
150 if (net->ssid_len != mac->associnfo.req_essid.len)
151 return 0;
152 if (!memcmp(net->ssid, mac->associnfo.req_essid.data, mac->associnfo.req_essid.len))
153 return 1;
154 return 0;
155}
156
157static void
158ieee80211softmac_assoc_notify(struct net_device *dev, void *context)
159{
160 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
161 ieee80211softmac_assoc_work((void*)mac);
162}
163
164/* This function is called to handle userspace requests (asynchronously) */
165void
166ieee80211softmac_assoc_work(void *d)
167{
168 struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d;
169 struct ieee80211softmac_network *found = NULL;
170 struct ieee80211_network *net = NULL, *best = NULL;
171 unsigned long flags;
172
173 /* meh */
174 if (mac->associated)
175 ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
176
177 /* try to find the requested network in our list, if we found one already */
178 if (mac->associnfo.bssvalid)
179 found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
180
181 /* Search the ieee80211 networks for this network if we didn't find it by bssid,
182 * but only if we've scanned at least once (to get a better list of networks to
183 * select from). If we have not scanned before, the !found logic below will be
184 * invoked and will scan. */
185 if (!found && (mac->associnfo.scan_retry < IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT))
186 {
187 s8 rssi = -128; /* if I don't initialise, gcc emits an invalid warning
188 because it cannot follow the best pointer logic. */
189 spin_lock_irqsave(&mac->ieee->lock, flags);
190 list_for_each_entry(net, &mac->ieee->network_list, list) {
191 /* we're supposed to find the network with
192 * the best signal here, as we're asked to join
193 * any network with a specific ESSID, and many
194 * different ones could have that.
195 *
196 * I'll for now just go with the reported rssi.
197 *
198 * We also should take into account the rateset
199 * here to find the best BSSID to try.
200 */
201 if (network_matches_request(mac, net)) {
202 if (!best) {
203 best = net;
204 rssi = best->stats.rssi;
205 continue;
206 }
207 /* we already had a matching network, so
208 * compare their properties to get the
209 * better of the two ... (see above)
210 */
211 if (rssi < net->stats.rssi) {
212 best = net;
213 rssi = best->stats.rssi;
214 }
215 }
216 }
217 /* if we unlock here, we might get interrupted and the `best'
218 * pointer could go stale */
219 if (best) {
220 found = ieee80211softmac_create_network(mac, best);
221 /* if found is still NULL, then we got -ENOMEM somewhere */
222 if (found)
223 ieee80211softmac_add_network(mac, found);
224 }
225 spin_unlock_irqrestore(&mac->ieee->lock, flags);
226 }
227
228 if (!found) {
229 if (mac->associnfo.scan_retry > 0) {
230 spin_lock_irqsave(&mac->lock, flags);
231 mac->associnfo.scan_retry--;
232 spin_unlock_irqrestore(&mac->lock, flags);
233
234 /* We know of no such network. Let's scan.
235 * NB: this also happens if we had no memory to copy the network info...
236 * Maybe we can hope to have more memory after scanning finishes ;)
237 */
238 dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n");
239 ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify, NULL);
240 if (ieee80211softmac_start_scan(mac))
241 dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
242 return;
243 }
244 else {
245 spin_lock_irqsave(&mac->lock, flags);
246 mac->associnfo.associating = 0;
247 mac->associated = 0;
248 spin_unlock_irqrestore(&mac->lock, flags);
249
250 dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n");
251 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL);
252 return;
253 }
254 }
255
256 mac->associnfo.bssvalid = 1;
257 memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN);
258 /* copy the ESSID for displaying it */
259 mac->associnfo.associate_essid.len = found->essid.len;
260 memcpy(mac->associnfo.associate_essid.data, found->essid.data, IW_ESSID_MAX_SIZE + 1);
261
262 /* we found a network! authenticate (if necessary) and associate to it. */
263 if (!found->authenticated) {
264 /* This relies on the fact that _auth_req only queues the work,
265 * otherwise adding the notification would be racy. */
266 if (!ieee80211softmac_auth_req(mac, found)) {
267 dprintk(KERN_INFO PFX "cannot associate without being authenticated, requested authentication\n");
268 ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify, NULL, GFP_KERNEL);
269 } else {
270 printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n");
271 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);
272 }
273 return;
274 }
275 /* finally! now we can start associating */
276 ieee80211softmac_assoc(mac, found);
277}
278
279/* call this to do whatever is necessary when we're associated */
280static void
281ieee80211softmac_associated(struct ieee80211softmac_device *mac,
282 struct ieee80211_assoc_response * resp,
283 struct ieee80211softmac_network *net)
284{
285 mac->associnfo.associating = 0;
286 mac->associated = 1;
287 if (mac->set_bssid_filter)
288 mac->set_bssid_filter(mac->dev, net->bssid);
289 memcpy(mac->ieee->bssid, net->bssid, ETH_ALEN);
290 netif_carrier_on(mac->dev);
291
292 mac->association_id = le16_to_cpup(&resp->aid);
293}
294
295/* received frame handling functions */
296int
297ieee80211softmac_handle_assoc_response(struct net_device * dev,
298 struct ieee80211_assoc_response * resp,
299 struct ieee80211_network * _ieee80211_network_do_not_use)
300{
301 /* NOTE: the network parameter has to be ignored by
302 * this code because it is the ieee80211's pointer
303 * to the struct, not ours (we made a copy)
304 */
305 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
306 u16 status = le16_to_cpup(&resp->status);
307 struct ieee80211softmac_network *network = NULL;
308 unsigned long flags;
309
310 spin_lock_irqsave(&mac->lock, flags);
311
312 if (!mac->associnfo.associating) {
313 /* we race against the timeout function, so make sure
314 * only one of us can do work */
315 spin_unlock_irqrestore(&mac->lock, flags);
316 return 0;
317 }
318 network = ieee80211softmac_get_network_by_bssid_locked(mac, resp->header.addr3);
319
320 /* someone sending us things without us knowing him? Ignore. */
321 if (!network) {
322 dprintk(KERN_INFO PFX "Received unrequested assocation response from " MAC_FMT "\n", MAC_ARG(resp->header.addr3));
323 spin_unlock_irqrestore(&mac->lock, flags);
324 return 0;
325 }
326
327 /* now that we know it was for us, we can cancel the timeout */
328 cancel_delayed_work(&mac->associnfo.timeout);
329
330 switch (status) {
331 case 0:
332 dprintk(KERN_INFO PFX "associated!\n");
333 ieee80211softmac_associated(mac, resp, network);
334 ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATED, network);
335 break;
336 case WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH:
337 if (!network->auth_desynced_once) {
338 /* there seem to be a few rare cases where our view of
339 * the world is obscured, or buggy APs that don't DEAUTH
340 * us properly. So we handle that, but allow it only once.
341 */
342 printkl(KERN_INFO PFX "We were not authenticated during association, retrying...\n");
343 network->authenticated = 0;
344 /* we don't want to do this more than once ... */
345 network->auth_desynced_once = 1;
346 schedule_work(&mac->associnfo.work);
347 break;
348 }
349 default:
350 dprintk(KERN_INFO PFX "associating failed (reason: 0x%x)!\n", status);
351 mac->associnfo.associating = 0;
352 mac->associnfo.bssvalid = 0;
353 mac->associated = 0;
354 ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, network);
355 }
356
357 spin_unlock_irqrestore(&mac->lock, flags);
358 return 0;
359}
360
361int
362ieee80211softmac_handle_disassoc(struct net_device * dev,
363 struct ieee80211_disassoc *disassoc)
364{
365 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
366 unsigned long flags;
367 if (memcmp(disassoc->header.addr2, mac->associnfo.bssid, ETH_ALEN))
368 return 0;
369 if (memcmp(disassoc->header.addr1, mac->dev->dev_addr, ETH_ALEN))
370 return 0;
371 dprintk(KERN_INFO PFX "got disassoc frame\n");
372 netif_carrier_off(dev);
373 spin_lock_irqsave(&mac->lock, flags);
374 mac->associnfo.bssvalid = 0;
375 mac->associated = 0;
376 schedule_work(&mac->associnfo.work);
377 spin_unlock_irqrestore(&mac->lock, flags);
378
379 return 0;
380}
381
382int
383ieee80211softmac_handle_reassoc_req(struct net_device * dev,
384 struct ieee80211_reassoc_request * resp)
385{
386 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
387 struct ieee80211softmac_network *network;
388
389 network = ieee80211softmac_get_network_by_bssid(mac, resp->header.addr3);
390 if (!network) {
391 dprintkl(KERN_INFO PFX "reassoc request from unknown network\n");
392 return 0;
393 }
394 ieee80211softmac_assoc(mac, network);
395 return 0;
396}
diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c
new file mode 100644
index 000000000000..9a0eac6c61eb
--- /dev/null
+++ b/net/ieee80211/softmac/ieee80211softmac_auth.c
@@ -0,0 +1,364 @@
1/*
2 * This file contains the softmac's authentication logic.
3 *
4 * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
5 * Joseph Jezak <josejx@gentoo.org>
6 * Larry Finger <Larry.Finger@lwfinger.net>
7 * Danny van Dyk <kugelfang@gentoo.org>
8 * Michael Buesch <mbuesch@freenet.de>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 * The full GNU General Public License is included in this distribution in the
24 * file called COPYING.
25 */
26
27#include "ieee80211softmac_priv.h"
28
29static void ieee80211softmac_auth_queue(void *data);
30
31/* Queues an auth request to the desired AP */
32int
33ieee80211softmac_auth_req(struct ieee80211softmac_device *mac,
34 struct ieee80211softmac_network *net)
35{
36 struct ieee80211softmac_auth_queue_item *auth;
37 unsigned long flags;
38
39 if (net->authenticating)
40 return 0;
41
42 /* Add the network if it's not already added */
43 ieee80211softmac_add_network(mac, net);
44
45 dprintk(KERN_NOTICE PFX "Queueing Authentication Request to "MAC_FMT"\n", MAC_ARG(net->bssid));
46 /* Queue the auth request */
47 auth = (struct ieee80211softmac_auth_queue_item *)
48 kmalloc(sizeof(struct ieee80211softmac_auth_queue_item), GFP_KERNEL);
49 if(auth == NULL)
50 return -ENOMEM;
51
52 auth->net = net;
53 auth->mac = mac;
54 auth->retry = IEEE80211SOFTMAC_AUTH_RETRY_LIMIT;
55 auth->state = IEEE80211SOFTMAC_AUTH_OPEN_REQUEST;
56 INIT_WORK(&auth->work, &ieee80211softmac_auth_queue, (void *)auth);
57
58 /* Lock (for list) */
59 spin_lock_irqsave(&mac->lock, flags);
60
61 /* add to list */
62 list_add_tail(&auth->list, &mac->auth_queue);
63 schedule_work(&auth->work);
64 spin_unlock_irqrestore(&mac->lock, flags);
65
66 return 0;
67}
68
69
70/* Sends an auth request to the desired AP and handles timeouts */
71static void
72ieee80211softmac_auth_queue(void *data)
73{
74 struct ieee80211softmac_device *mac;
75 struct ieee80211softmac_auth_queue_item *auth;
76 struct ieee80211softmac_network *net;
77 unsigned long flags;
78
79 auth = (struct ieee80211softmac_auth_queue_item *)data;
80 net = auth->net;
81 mac = auth->mac;
82
83 if(auth->retry > 0) {
84 /* Switch to correct channel for this network */
85 mac->set_channel(mac->dev, net->channel);
86
87 /* Lock and set flags */
88 spin_lock_irqsave(&mac->lock, flags);
89 net->authenticated = 0;
90 net->authenticating = 1;
91 /* add a timeout call so we eventually give up waiting for an auth reply */
92 schedule_delayed_work(&auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT);
93 auth->retry--;
94 spin_unlock_irqrestore(&mac->lock, flags);
95 if (ieee80211softmac_send_mgt_frame(mac, auth->net, IEEE80211_STYPE_AUTH, auth->state))
96 dprintk(KERN_NOTICE PFX "Sending Authentication Request to "MAC_FMT" failed (this shouldn't happen, wait for the timeout).\n", MAC_ARG(net->bssid));
97 else
98 dprintk(KERN_NOTICE PFX "Sent Authentication Request to "MAC_FMT".\n", MAC_ARG(net->bssid));
99 return;
100 }
101
102 printkl(KERN_WARNING PFX "Authentication timed out with "MAC_FMT"\n", MAC_ARG(net->bssid));
103 /* Remove this item from the queue */
104 spin_lock_irqsave(&mac->lock, flags);
105 ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net);
106 cancel_delayed_work(&auth->work); /* just to make sure... */
107 list_del(&auth->list);
108 spin_unlock_irqrestore(&mac->lock, flags);
109 /* Free it */
110 kfree(auth);
111}
112
113/* Handle the auth response from the AP
114 * This should be registered with ieee80211 as handle_auth
115 */
116int
117ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
118{
119
120 struct list_head *list_ptr;
121 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
122 struct ieee80211softmac_auth_queue_item *aq = NULL;
123 struct ieee80211softmac_network *net = NULL;
124 unsigned long flags;
125 u8 * data;
126
127 /* Find correct auth queue item */
128 spin_lock_irqsave(&mac->lock, flags);
129 list_for_each(list_ptr, &mac->auth_queue) {
130 aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list);
131 net = aq->net;
132 if (!memcmp(net->bssid, auth->header.addr2, ETH_ALEN))
133 break;
134 else
135 aq = NULL;
136 }
137 spin_unlock_irqrestore(&mac->lock, flags);
138
139 /* Make sure that we've got an auth queue item for this request */
140 if(aq == NULL)
141 {
142 printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but no queue item exists.\n", MAC_ARG(auth->header.addr2));
143 /* Error #? */
144 return -1;
145 }
146
147 /* Check for out of order authentication */
148 if(!net->authenticating)
149 {
150 printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but did not request authentication.\n",MAC_ARG(auth->header.addr2));
151 return -1;
152 }
153
154 /* Parse the auth packet */
155 switch(auth->algorithm) {
156 case WLAN_AUTH_OPEN:
157 /* Check the status code of the response */
158
159 switch(auth->status) {
160 case WLAN_STATUS_SUCCESS:
161 /* Update the status to Authenticated */
162 spin_lock_irqsave(&mac->lock, flags);
163 net->authenticating = 0;
164 net->authenticated = 1;
165 spin_unlock_irqrestore(&mac->lock, flags);
166
167 /* Send event */
168 printkl(KERN_NOTICE PFX "Open Authentication completed with "MAC_FMT"\n", MAC_ARG(net->bssid));
169 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
170 break;
171 default:
172 /* Lock and reset flags */
173 spin_lock_irqsave(&mac->lock, flags);
174 net->authenticated = 0;
175 net->authenticating = 0;
176 spin_unlock_irqrestore(&mac->lock, flags);
177
178 printkl(KERN_NOTICE PFX "Open Authentication with "MAC_FMT" failed, error code: %i\n",
179 MAC_ARG(net->bssid), le16_to_cpup(&auth->status));
180 /* Count the error? */
181 break;
182 }
183 goto free_aq;
184 break;
185 case WLAN_AUTH_SHARED_KEY:
186 /* Figure out where we are in the process */
187 switch(auth->transaction) {
188 case IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE:
189 /* Check to make sure we have a challenge IE */
190 data = (u8 *)auth->info_element;
191 if(*data++ != MFIE_TYPE_CHALLENGE){
192 printkl(KERN_NOTICE PFX "Shared Key Authentication failed due to a missing challenge.\n");
193 break;
194 }
195 /* Save the challenge */
196 spin_lock_irqsave(&mac->lock, flags);
197 net->challenge_len = *data++;
198 if(net->challenge_len > WLAN_AUTH_CHALLENGE_LEN)
199 net->challenge_len = WLAN_AUTH_CHALLENGE_LEN;
200 if(net->challenge != NULL)
201 kfree(net->challenge);
202 net->challenge = kmalloc(net->challenge_len, GFP_ATOMIC);
203 memcpy(net->challenge, data, net->challenge_len);
204 aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE;
205 spin_unlock_irqrestore(&mac->lock, flags);
206
207 /* Switch to correct channel for this network */
208 mac->set_channel(mac->dev, net->channel);
209
210 /* Send our response (How to encrypt?) */
211 ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state);
212 break;
213 case IEEE80211SOFTMAC_AUTH_SHARED_PASS:
214 /* Check the status code of the response */
215 switch(auth->status) {
216 case WLAN_STATUS_SUCCESS:
217 /* Update the status to Authenticated */
218 spin_lock_irqsave(&mac->lock, flags);
219 net->authenticating = 0;
220 net->authenticated = 1;
221 spin_unlock_irqrestore(&mac->lock, flags);
222 printkl(KERN_NOTICE PFX "Shared Key Authentication completed with "MAC_FMT"\n",
223 MAC_ARG(net->bssid));
224 break;
225 default:
226 printkl(KERN_NOTICE PFX "Shared Key Authentication with "MAC_FMT" failed, error code: %i\n",
227 MAC_ARG(net->bssid), le16_to_cpup(&auth->status));
228 /* Lock and reset flags */
229 spin_lock_irqsave(&mac->lock, flags);
230 net->authenticating = 0;
231 net->authenticated = 0;
232 spin_unlock_irqrestore(&mac->lock, flags);
233 /* Count the error? */
234 break;
235 }
236 goto free_aq;
237 break;
238 default:
239 printkl(KERN_WARNING PFX "Unhandled Authentication Step: %i\n", auth->transaction);
240 break;
241 }
242 goto free_aq;
243 break;
244 default:
245 /* ERROR */
246 goto free_aq;
247 break;
248 }
249 return 0;
250free_aq:
251 /* Cancel the timeout */
252 spin_lock_irqsave(&mac->lock, flags);
253 cancel_delayed_work(&aq->work);
254 /* Remove this item from the queue */
255 list_del(&aq->list);
256 spin_unlock_irqrestore(&mac->lock, flags);
257
258 /* Free it */
259 kfree(aq);
260 return 0;
261}
262
263/*
264 * Handle deauthorization
265 */
266static void
267ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
268 struct ieee80211softmac_network *net)
269{
270 struct ieee80211softmac_auth_queue_item *aq = NULL;
271 struct list_head *list_ptr;
272 unsigned long flags;
273
274 /* Lock and reset status flags */
275 spin_lock_irqsave(&mac->lock, flags);
276 net->authenticating = 0;
277 net->authenticated = 0;
278
279 /* Find correct auth queue item, if it exists */
280 list_for_each(list_ptr, &mac->auth_queue) {
281 aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list);
282 if (!memcmp(net->bssid, aq->net->bssid, ETH_ALEN))
283 break;
284 else
285 aq = NULL;
286 }
287
288 /* Cancel pending work */
289 if(aq != NULL)
290 /* Not entirely safe? What about running work? */
291 cancel_delayed_work(&aq->work);
292
293 /* Free our network ref */
294 ieee80211softmac_del_network_locked(mac, net);
295 if(net->challenge != NULL)
296 kfree(net->challenge);
297 kfree(net);
298
299 /* can't transmit data right now... */
300 netif_carrier_off(mac->dev);
301 /* let's try to re-associate */
302 schedule_work(&mac->associnfo.work);
303 spin_unlock_irqrestore(&mac->lock, flags);
304}
305
306/*
307 * Sends a deauth request to the desired AP
308 */
309int
310ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac,
311 struct ieee80211softmac_network *net, int reason)
312{
313 int ret;
314
315 /* Make sure the network is authenticated */
316 if (!net->authenticated)
317 {
318 printkl(KERN_DEBUG PFX "Can't send deauthentication packet, network is not authenticated.\n");
319 /* Error okay? */
320 return -EPERM;
321 }
322
323 /* Send the de-auth packet */
324 if((ret = ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_DEAUTH, reason)))
325 return ret;
326
327 ieee80211softmac_deauth_from_net(mac, net);
328 return 0;
329}
330
331/*
332 * This should be registered with ieee80211 as handle_deauth
333 */
334int
335ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *deauth)
336{
337
338 struct ieee80211softmac_network *net = NULL;
339 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
340
341 if (!deauth) {
342 dprintk("deauth without deauth packet. eek!\n");
343 return 0;
344 }
345
346 net = ieee80211softmac_get_network_by_bssid(mac, deauth->header.addr2);
347
348 if (net == NULL) {
349 printkl(KERN_DEBUG PFX "Received deauthentication packet from "MAC_FMT", but that network is unknown.\n",
350 MAC_ARG(deauth->header.addr2));
351 return 0;
352 }
353
354 /* Make sure the network is authenticated */
355 if(!net->authenticated)
356 {
357 printkl(KERN_DEBUG PFX "Can't perform deauthentication, network is not authenticated.\n");
358 /* Error okay? */
359 return -EPERM;
360 }
361
362 ieee80211softmac_deauth_from_net(mac, net);
363 return 0;
364}
diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c
new file mode 100644
index 000000000000..0a52bbda1e4c
--- /dev/null
+++ b/net/ieee80211/softmac/ieee80211softmac_event.c
@@ -0,0 +1,159 @@
1/*
2 * Event system
3 * Also see comments in public header file and longer explanation below.
4 *
5 * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
6 * Joseph Jezak <josejx@gentoo.org>
7 * Larry Finger <Larry.Finger@lwfinger.net>
8 * Danny van Dyk <kugelfang@gentoo.org>
9 * Michael Buesch <mbuesch@freenet.de>
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of version 2 of the GNU General Public License as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 *
24 * The full GNU General Public License is included in this distribution in the
25 * file called COPYING.
26 */
27
28#include "ieee80211softmac_priv.h"
29
30/*
31 * Each event has associated to it
32 * - an event type (see constants in public header)
33 * - an event context (see below)
34 * - the function to be called
35 * - a context (extra parameter to call the function with)
36 * - and the softmac struct
37 *
38 * The event context is private and can only be used from
39 * within this module. Its meaning varies with the event
40 * type:
41 * SCAN_FINISHED: no special meaning
42 * ASSOCIATED,
43 * ASSOCIATE_FAILED,
44 * ASSOCIATE_TIMEOUT,
45 * AUTHENTICATED,
46 * AUTH_FAILED,
47 * AUTH_TIMEOUT: a pointer to the network struct
48 * ...
49 * Code within this module can use the event context to be only
50 * called when the event is true for that specific context
51 * as per above table.
52 * If the event context is NULL, then the notification is always called,
53 * regardless of the event context. The event context is not passed to
54 * the callback, it is assumed that the context suffices.
55 *
56 * You can also use the event context only by setting the event type
57 * to -1 (private use only), in which case you'll be notified
58 * whenever the event context matches.
59 */
60
61static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = {
62 "scan finished",
63 "associated",
64 "associating failed",
65 "associating timed out",
66 "authenticated",
67 "authenticating failed",
68 "authenticating timed out",
69 "associating failed because no suitable network was found",
70};
71
72
73static void
74ieee80211softmac_notify_callback(void *d)
75{
76 struct ieee80211softmac_event event = *(struct ieee80211softmac_event*) d;
77 kfree(d);
78
79 event.fun(event.mac->dev, event.context);
80}
81
82int
83ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac,
84 int event, void *event_context, notify_function_ptr fun, void *context, gfp_t gfp_mask)
85{
86 struct ieee80211softmac_event *eventptr;
87 unsigned long flags;
88
89 if (event < -1 || event > IEEE80211SOFTMAC_EVENT_LAST)
90 return -ENOSYS;
91
92 if (!fun)
93 return -EINVAL;
94
95 eventptr = kmalloc(sizeof(struct ieee80211softmac_event), gfp_mask);
96 if (!eventptr)
97 return -ENOMEM;
98
99 eventptr->event_type = event;
100 INIT_WORK(&eventptr->work, ieee80211softmac_notify_callback, eventptr);
101 eventptr->fun = fun;
102 eventptr->context = context;
103 eventptr->mac = mac;
104 eventptr->event_context = event_context;
105
106 spin_lock_irqsave(&mac->lock, flags);
107 list_add(&eventptr->list, &mac->events);
108 spin_unlock_irqrestore(&mac->lock, flags);
109
110 return 0;
111}
112
113int
114ieee80211softmac_notify_gfp(struct net_device *dev,
115 int event, notify_function_ptr fun, void *context, gfp_t gfp_mask)
116{
117 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
118
119 if (event < 0 || event > IEEE80211SOFTMAC_EVENT_LAST)
120 return -ENOSYS;
121
122 return ieee80211softmac_notify_internal(mac, event, NULL, fun, context, gfp_mask);
123}
124EXPORT_SYMBOL_GPL(ieee80211softmac_notify_gfp);
125
126/* private -- calling all callbacks that were specified */
127void
128ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx)
129{
130 struct ieee80211softmac_event *eventptr, *tmp;
131 union iwreq_data wrqu;
132 char *msg;
133
134 if (event >= 0) {
135 msg = event_descriptions[event];
136 wrqu.data.length = strlen(msg);
137 wireless_send_event(mac->dev, IWEVCUSTOM, &wrqu, msg);
138 }
139
140 if (!list_empty(&mac->events))
141 list_for_each_entry_safe(eventptr, tmp, &mac->events, list) {
142 if ((eventptr->event_type == event || eventptr->event_type == -1)
143 && (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) {
144 list_del(&eventptr->list);
145 schedule_work(&eventptr->work);
146 }
147 }
148}
149
150void
151ieee80211softmac_call_events(struct ieee80211softmac_device *mac, int event, void *event_ctx)
152{
153 unsigned long flags;
154
155 spin_lock_irqsave(&mac->lock, flags);
156 ieee80211softmac_call_events_locked(mac, event, event_ctx);
157
158 spin_unlock_irqrestore(&mac->lock, flags);
159}
diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
new file mode 100644
index 000000000000..febc51dbb412
--- /dev/null
+++ b/net/ieee80211/softmac/ieee80211softmac_io.c
@@ -0,0 +1,474 @@
1/*
2 * Some parts based on code from net80211
3 * Copyright (c) 2001 Atsushi Onoe
4 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * Alternatively, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") version 2 as published by the Free
20 * Software Foundation.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 */
34
35#include "ieee80211softmac_priv.h"
36
37/* Helper functions for inserting data into the frames */
38
39/*
40 * Adds an ESSID element to the frame
41 *
42 */
43static u8 *
44ieee80211softmac_add_essid(u8 *dst, struct ieee80211softmac_essid *essid)
45{
46 if (essid) {
47 *dst++ = MFIE_TYPE_SSID;
48 *dst++ = essid->len;
49 memcpy(dst, essid->data, essid->len);
50 return dst+essid->len;
51 } else {
52 *dst++ = MFIE_TYPE_SSID;
53 *dst++ = 0;
54 return dst;
55 }
56}
57
58/* Adds Supported Rates and if required Extended Rates Information Element
59 * to the frame, ASSUMES WE HAVE A SORTED LIST OF RATES */
60static u8 *
61ieee80211softmac_frame_add_rates(u8 *dst, const struct ieee80211softmac_ratesinfo *r)
62{
63 int cck_len, ofdm_len;
64 *dst++ = MFIE_TYPE_RATES;
65
66 for(cck_len=0; ieee80211_is_cck_rate(r->rates[cck_len]) && (cck_len < r->count);cck_len++);
67
68 if(cck_len > IEEE80211SOFTMAC_MAX_RATES_LEN)
69 cck_len = IEEE80211SOFTMAC_MAX_RATES_LEN;
70 *dst++ = cck_len;
71 memcpy(dst, r->rates, cck_len);
72 dst += cck_len;
73
74 if(cck_len < r->count){
75 for (ofdm_len=0; ieee80211_is_ofdm_rate(r->rates[ofdm_len + cck_len]) && (ofdm_len + cck_len < r->count); ofdm_len++);
76 if (ofdm_len > 0) {
77 if (ofdm_len > IEEE80211SOFTMAC_MAX_EX_RATES_LEN)
78 ofdm_len = IEEE80211SOFTMAC_MAX_EX_RATES_LEN;
79 *dst++ = MFIE_TYPE_RATES_EX;
80 *dst++ = ofdm_len;
81 memcpy(dst, r->rates + cck_len, ofdm_len);
82 dst += ofdm_len;
83 }
84 }
85 return dst;
86}
87
88/* Allocate a management frame */
89static u8 *
90ieee80211softmac_alloc_mgt(u32 size)
91{
92 u8 * data;
93
94 /* Add the header and FCS to the size */
95 size = size + IEEE80211_3ADDR_LEN;
96 if(size > IEEE80211_DATA_LEN)
97 return NULL;
98 /* Allocate the frame */
99 data = kmalloc(size, GFP_ATOMIC);
100 memset(data, 0, size);
101 return data;
102}
103
104/*
105 * Add a 2 Address Header
106 */
107static void
108ieee80211softmac_hdr_2addr(struct ieee80211softmac_device *mac,
109 struct ieee80211_hdr_2addr *header, u32 type, u8 *dest)
110{
111 /* Fill in the frame control flags */
112 header->frame_ctl = cpu_to_le16(type);
113 /* Control packets always have WEP turned off */
114 if(type > IEEE80211_STYPE_CFENDACK && type < IEEE80211_STYPE_PSPOLL)
115 header->frame_ctl |= mac->ieee->sec.level ? cpu_to_le16(IEEE80211_FCTL_PROTECTED) : 0;
116
117 /* Fill in the duration */
118 header->duration_id = 0;
119 /* FIXME: How do I find this?
120 * calculate. But most drivers just fill in 0 (except if it's a station id of course) */
121
122 /* Fill in the Destination Address */
123 if(dest == NULL)
124 memset(header->addr1, 0xFF, ETH_ALEN);
125 else
126 memcpy(header->addr1, dest, ETH_ALEN);
127 /* Fill in the Source Address */
128 memcpy(header->addr2, mac->ieee->dev->dev_addr, ETH_ALEN);
129
130}
131
132
133/* Add a 3 Address Header */
134static void
135ieee80211softmac_hdr_3addr(struct ieee80211softmac_device *mac,
136 struct ieee80211_hdr_3addr *header, u32 type, u8 *dest, u8 *bssid)
137{
138 /* This is common with 2addr, so use that instead */
139 ieee80211softmac_hdr_2addr(mac, (struct ieee80211_hdr_2addr *)header, type, dest);
140
141 /* Fill in the BSS ID */
142 if(bssid == NULL)
143 memset(header->addr3, 0xFF, ETH_ALEN);
144 else
145 memcpy(header->addr3, bssid, ETH_ALEN);
146
147 /* Fill in the sequence # */
148 /* FIXME: I need to add this to the softmac struct
149 * shouldn't the sequence number be in ieee80211? */
150}
151
152
153/*****************************************************************************
154 * Create Management packets
155 *****************************************************************************/
156
157/* Creates an association request packet */
158static u32
159ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt,
160 struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net)
161{
162 u8 *data;
163 (*pkt) = (struct ieee80211_assoc_request *)ieee80211softmac_alloc_mgt(
164 2 + /* Capability Info */
165 2 + /* Listen Interval */
166 /* SSID IE */
167 1 + 1 + IW_ESSID_MAX_SIZE +
168 /* Rates IE */
169 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN +
170 /* Extended Rates IE */
171 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN +
172 /* WPA IE if present */
173 mac->wpa.IElen
174 /* Other IE's? Optional?
175 * Yeah, probably need an extra IE parameter -- lots of vendors like to
176 * fill in their own IEs */
177 );
178 if (unlikely((*pkt) == NULL))
179 return 0;
180 ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
181
182 /* Fill in capability Info */
183 (*pkt)->capability = (mac->ieee->iw_mode == IW_MODE_MASTER) || (mac->ieee->iw_mode == IW_MODE_INFRA) ?
184 cpu_to_le16(WLAN_CAPABILITY_ESS) :
185 cpu_to_le16(WLAN_CAPABILITY_IBSS);
186 /* Need to add this
187 (*pkt)->capability |= mac->ieee->short_slot ?
188 cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0;
189 */
190 (*pkt)->capability |= mac->ieee->sec.level ? cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
191 /* Fill in Listen Interval (?) */
192 (*pkt)->listen_interval = cpu_to_le16(10);
193
194 data = (u8 *)(*pkt)->info_element;
195 /* Add SSID */
196 data = ieee80211softmac_add_essid(data, &net->essid);
197 /* Add Rates */
198 data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo);
199 /* Add WPA IE */
200 if (mac->wpa.IElen && mac->wpa.IE) {
201 memcpy(data, mac->wpa.IE, mac->wpa.IElen);
202 data += mac->wpa.IElen;
203 }
204 /* Return the number of used bytes */
205 return (data - (u8*)(*pkt));
206}
207
208/* Create a reassociation request packet */
209static u32
210ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt,
211 struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net)
212{
213 u8 *data;
214 (*pkt) = (struct ieee80211_reassoc_request *)ieee80211softmac_alloc_mgt(
215 2 + /* Capability Info */
216 2 + /* Listen Interval */
217 ETH_ALEN + /* AP MAC */
218 /* SSID IE */
219 1 + 1 + IW_ESSID_MAX_SIZE +
220 /* Rates IE */
221 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN +
222 /* Extended Rates IE */
223 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN
224 /* Other IE's? */
225 );
226 if (unlikely((*pkt) == NULL))
227 return 0;
228 ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_REASSOC_REQ, net->bssid, net->bssid);
229
230 /* Fill in capability Info */
231 (*pkt)->capability = mac->ieee->iw_mode == IW_MODE_MASTER ?
232 cpu_to_le16(WLAN_CAPABILITY_ESS) :
233 cpu_to_le16(WLAN_CAPABILITY_IBSS);
234 /*
235 (*pkt)->capability |= mac->ieee->short_slot ?
236 cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0;
237 */
238 (*pkt)->capability |= mac->ieee->sec.level ?
239 cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
240
241 /* Fill in Listen Interval (?) */
242 (*pkt)->listen_interval = cpu_to_le16(10);
243 /* Fill in the current AP MAC */
244 memcpy((*pkt)->current_ap, mac->ieee->bssid, ETH_ALEN);
245
246 data = (u8 *)(*pkt)->info_element;
247 /* Add SSID */
248 data = ieee80211softmac_add_essid(data, &net->essid);
249 /* Add Rates */
250 data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo);
251 /* Return packet size */
252 return (data - (u8 *)(*pkt));
253}
254
255/* Create an authentication packet */
256static u32
257ieee80211softmac_auth(struct ieee80211_auth **pkt,
258 struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net,
259 u16 transaction, u16 status)
260{
261 u8 *data;
262 /* Allocate Packet */
263 (*pkt) = (struct ieee80211_auth *)ieee80211softmac_alloc_mgt(
264 2 + /* Auth Algorithm */
265 2 + /* Auth Transaction Seq */
266 2 + /* Status Code */
267 /* Challenge Text IE */
268 mac->ieee->open_wep ? 0 :
269 1 + 1 + WLAN_AUTH_CHALLENGE_LEN
270 );
271 if (unlikely((*pkt) == NULL))
272 return 0;
273 ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_AUTH, net->bssid, net->bssid);
274
275 /* Algorithm */
276 (*pkt)->algorithm = mac->ieee->open_wep ?
277 cpu_to_le16(WLAN_AUTH_OPEN) :
278 cpu_to_le16(WLAN_AUTH_SHARED_KEY);
279 /* Transaction */
280 (*pkt)->transaction = cpu_to_le16(transaction);
281 /* Status */
282 (*pkt)->status = cpu_to_le16(status);
283
284 data = (u8 *)(*pkt)->info_element;
285 /* Challenge Text */
286 if(!mac->ieee->open_wep){
287 *data = MFIE_TYPE_CHALLENGE;
288 data++;
289
290 /* Copy the challenge in */
291 // *data = challenge length
292 // data += sizeof(u16);
293 // memcpy(data, challenge, challenge length);
294 // data += challenge length;
295
296 /* Add the full size to the packet length */
297 }
298
299 /* Return the packet size */
300 return (data - (u8 *)(*pkt));
301}
302
303/* Create a disassocation or deauthentication packet */
304static u32
305ieee80211softmac_disassoc_deauth(struct ieee80211_disassoc **pkt,
306 struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net,
307 u16 type, u16 reason)
308{
309 /* Allocate Packet */
310 (*pkt) = (struct ieee80211_disassoc *)ieee80211softmac_alloc_mgt(2);
311 if (unlikely((*pkt) == NULL))
312 return 0;
313 ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), type, net->bssid, net->bssid);
314 /* Reason */
315 (*pkt)->reason = cpu_to_le16(reason);
316 /* Return the packet size */
317 return (2 + IEEE80211_3ADDR_LEN);
318}
319
320/* Create a probe request packet */
321static u32
322ieee80211softmac_probe_req(struct ieee80211_probe_request **pkt,
323 struct ieee80211softmac_device *mac, struct ieee80211softmac_essid *essid)
324{
325 u8 *data;
326 /* Allocate Packet */
327 (*pkt) = (struct ieee80211_probe_request *)ieee80211softmac_alloc_mgt(
328 /* SSID of requested network */
329 1 + 1 + IW_ESSID_MAX_SIZE +
330 /* Rates IE */
331 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN +
332 /* Extended Rates IE */
333 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN
334 );
335 if (unlikely((*pkt) == NULL))
336 return 0;
337 ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_PROBE_REQ, NULL, NULL);
338
339 data = (u8 *)(*pkt)->info_element;
340 /* Add ESSID (can be NULL) */
341 data = ieee80211softmac_add_essid(data, essid);
342 /* Add Rates */
343 data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo);
344 /* Return packet size */
345 return (data - (u8 *)(*pkt));
346}
347
348/* Create a probe response packet */
349/* FIXME: Not complete */
350static u32
351ieee80211softmac_probe_resp(struct ieee80211_probe_response **pkt,
352 struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net)
353{
354 u8 *data;
355 /* Allocate Packet */
356 (*pkt) = (struct ieee80211_probe_response *)ieee80211softmac_alloc_mgt(
357 8 + /* Timestamp */
358 2 + /* Beacon Interval */
359 2 + /* Capability Info */
360 /* SSID IE */
361 1 + 1 + IW_ESSID_MAX_SIZE +
362 7 + /* FH Parameter Set */
363 2 + /* DS Parameter Set */
364 8 + /* CF Parameter Set */
365 4 /* IBSS Parameter Set */
366 );
367 if (unlikely((*pkt) == NULL))
368 return 0;
369 ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_PROBE_RESP, net->bssid, net->bssid);
370 data = (u8 *)(*pkt)->info_element;
371
372 /* Return the packet size */
373 return (data - (u8 *)(*pkt));
374}
375
376
377/* Sends a manangement packet
378 * FIXME: document the use of the arg parameter
379 * for _AUTH: (transaction #) | (status << 16)
380 */
381int
382ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
383 void *ptrarg, u32 type, u32 arg)
384{
385 void *pkt = NULL;
386 u32 pkt_size = 0;
387
388 switch(type) {
389 case IEEE80211_STYPE_ASSOC_REQ:
390 pkt_size = ieee80211softmac_assoc_req((struct ieee80211_assoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg);
391 break;
392 case IEEE80211_STYPE_REASSOC_REQ:
393 pkt_size = ieee80211softmac_reassoc_req((struct ieee80211_reassoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg);
394 break;
395 case IEEE80211_STYPE_AUTH:
396 pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16));
397 break;
398 case IEEE80211_STYPE_DISASSOC:
399 case IEEE80211_STYPE_DEAUTH:
400 pkt_size = ieee80211softmac_disassoc_deauth((struct ieee80211_disassoc **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, type, (u16)(arg & 0xFFFF));
401 break;
402 case IEEE80211_STYPE_PROBE_REQ:
403 pkt_size = ieee80211softmac_probe_req((struct ieee80211_probe_request **)(&pkt), mac, (struct ieee80211softmac_essid *)ptrarg);
404 break;
405 case IEEE80211_STYPE_PROBE_RESP:
406 pkt_size = ieee80211softmac_probe_resp((struct ieee80211_probe_response **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg);
407 break;
408 default:
409 printkl(KERN_DEBUG PFX "Unsupported Management Frame type: %i\n", type);
410 return -EINVAL;
411 };
412
413 if(pkt_size == 0 || pkt == NULL) {
414 printkl(KERN_DEBUG PFX "Error, packet is nonexistant or 0 length\n");
415 return -ENOMEM;
416 }
417
418 /* Send the packet to the ieee80211 layer for tx */
419 /* we defined softmac->mgmt_xmit for this. Should we keep it
420 * as it is (that means we'd need to wrap this into a txb),
421 * modify the prototype (so it matches this function),
422 * or get rid of it alltogether?
423 * Does this work for you now?
424 */
425 ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt, pkt_size);
426
427 kfree(pkt);
428 return 0;
429}
430
431
432/* Create an rts/cts frame */
433static u32
434ieee80211softmac_rts_cts(struct ieee80211_hdr_2addr **pkt,
435 struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net,
436 u32 type)
437{
438 /* Allocate Packet */
439 (*pkt) = kmalloc(IEEE80211_2ADDR_LEN, GFP_ATOMIC);
440 memset(*pkt, 0, IEEE80211_2ADDR_LEN);
441 if((*pkt) == NULL)
442 return 0;
443 ieee80211softmac_hdr_2addr(mac, (*pkt), type, net->bssid);
444 return IEEE80211_2ADDR_LEN;
445}
446
447
448/* Sends a control packet */
449static int
450ieee80211softmac_send_ctl_frame(struct ieee80211softmac_device *mac,
451 struct ieee80211softmac_network *net, u32 type, u32 arg)
452{
453 void *pkt = NULL;
454 u32 pkt_size = 0;
455
456 switch(type) {
457 case IEEE80211_STYPE_RTS:
458 case IEEE80211_STYPE_CTS:
459 pkt_size = ieee80211softmac_rts_cts((struct ieee80211_hdr_2addr **)(&pkt), mac, net, type);
460 break;
461 default:
462 printkl(KERN_DEBUG PFX "Unsupported Control Frame type: %i\n", type);
463 return -EINVAL;
464 }
465
466 if(pkt_size == 0)
467 return -ENOMEM;
468
469 /* Send the packet to the ieee80211 layer for tx */
470 ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *) pkt, pkt_size);
471
472 kfree(pkt);
473 return 0;
474}
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
new file mode 100644
index 000000000000..6f99f781bff8
--- /dev/null
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -0,0 +1,457 @@
1/*
2 * Contains some basic softmac functions along with module registration code etc.
3 *
4 * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
5 * Joseph Jezak <josejx@gentoo.org>
6 * Larry Finger <Larry.Finger@lwfinger.net>
7 * Danny van Dyk <kugelfang@gentoo.org>
8 * Michael Buesch <mbuesch@freenet.de>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 * The full GNU General Public License is included in this distribution in the
24 * file called COPYING.
25 */
26
27#include "ieee80211softmac_priv.h"
28#include <linux/sort.h>
29
30struct net_device *alloc_ieee80211softmac(int sizeof_priv)
31{
32 struct ieee80211softmac_device *softmac;
33 struct net_device *dev;
34
35 dev = alloc_ieee80211(sizeof(struct ieee80211softmac_device) + sizeof_priv);
36 softmac = ieee80211_priv(dev);
37 softmac->dev = dev;
38 softmac->ieee = netdev_priv(dev);
39 spin_lock_init(&softmac->lock);
40
41 softmac->ieee->handle_auth = ieee80211softmac_auth_resp;
42 softmac->ieee->handle_deauth = ieee80211softmac_deauth_resp;
43 softmac->ieee->handle_assoc_response = ieee80211softmac_handle_assoc_response;
44 softmac->ieee->handle_reassoc_request = ieee80211softmac_handle_reassoc_req;
45 softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc;
46 softmac->scaninfo = NULL;
47
48 /* TODO: initialise all the other callbacks in the ieee struct
49 * (once they're written)
50 */
51
52 INIT_LIST_HEAD(&softmac->auth_queue);
53 INIT_LIST_HEAD(&softmac->network_list);
54 INIT_LIST_HEAD(&softmac->events);
55
56 INIT_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work, softmac);
57 INIT_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout, softmac);
58 softmac->start_scan = ieee80211softmac_start_scan_implementation;
59 softmac->wait_for_scan = ieee80211softmac_wait_for_scan_implementation;
60 softmac->stop_scan = ieee80211softmac_stop_scan_implementation;
61
62 //TODO: The mcast rate has to be assigned dynamically somewhere (in scanning, association. Not sure...)
63 // It has to be set to the highest rate all stations in the current network can handle.
64 softmac->txrates.mcast_rate = IEEE80211_CCK_RATE_1MB;
65 softmac->txrates.mcast_fallback = IEEE80211_CCK_RATE_1MB;
66 /* This is reassigned in ieee80211softmac_start to sane values. */
67 softmac->txrates.default_rate = IEEE80211_CCK_RATE_1MB;
68 softmac->txrates.default_fallback = IEEE80211_CCK_RATE_1MB;
69
70 /* to start with, we can't send anything ... */
71 netif_carrier_off(dev);
72
73 return dev;
74}
75EXPORT_SYMBOL_GPL(alloc_ieee80211softmac);
76
77/* Clears the pending work queue items, stops all scans, etc. */
78void
79ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm)
80{
81 unsigned long flags;
82 struct ieee80211softmac_event *eventptr, *eventtmp;
83 struct ieee80211softmac_auth_queue_item *authptr, *authtmp;
84 struct ieee80211softmac_network *netptr, *nettmp;
85
86 ieee80211softmac_stop_scan(sm);
87 ieee80211softmac_wait_for_scan(sm);
88
89 spin_lock_irqsave(&sm->lock, flags);
90 /* Free all pending assoc work items */
91 cancel_delayed_work(&sm->associnfo.work);
92
93 /* Free all pending scan work items */
94 if(sm->scaninfo != NULL)
95 cancel_delayed_work(&sm->scaninfo->softmac_scan);
96
97 /* Free all pending auth work items */
98 list_for_each_entry(authptr, &sm->auth_queue, list)
99 cancel_delayed_work(&authptr->work);
100
101 /* delete all pending event calls and work items */
102 list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list)
103 cancel_delayed_work(&eventptr->work);
104
105 spin_unlock_irqrestore(&sm->lock, flags);
106 flush_scheduled_work();
107
108 /* now we should be save and no longer need locking... */
109 spin_lock_irqsave(&sm->lock, flags);
110 /* Free all pending auth work items */
111 list_for_each_entry_safe(authptr, authtmp, &sm->auth_queue, list) {
112 list_del(&authptr->list);
113 kfree(authptr);
114 }
115
116 /* delete all pending event calls and work items */
117 list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list) {
118 list_del(&eventptr->list);
119 kfree(eventptr);
120 }
121
122 /* Free all networks */
123 list_for_each_entry_safe(netptr, nettmp, &sm->network_list, list) {
124 ieee80211softmac_del_network_locked(sm, netptr);
125 if(netptr->challenge != NULL)
126 kfree(netptr->challenge);
127 kfree(netptr);
128 }
129
130 spin_unlock_irqrestore(&sm->lock, flags);
131}
132EXPORT_SYMBOL_GPL(ieee80211softmac_clear_pending_work);
133
134void free_ieee80211softmac(struct net_device *dev)
135{
136 struct ieee80211softmac_device *sm = ieee80211_priv(dev);
137 ieee80211softmac_clear_pending_work(sm);
138 kfree(sm->scaninfo);
139 kfree(sm->wpa.IE);
140 free_ieee80211(dev);
141}
142EXPORT_SYMBOL_GPL(free_ieee80211softmac);
143
144static void ieee80211softmac_start_check_rates(struct ieee80211softmac_device *mac)
145{
146 struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
147 /* I took out the sorting check, we're seperating by modulation now. */
148 if (ri->count)
149 return;
150 /* otherwise assume we hav'em all! */
151 if (mac->ieee->modulation & IEEE80211_CCK_MODULATION) {
152 ri->rates[ri->count++] = IEEE80211_CCK_RATE_1MB;
153 ri->rates[ri->count++] = IEEE80211_CCK_RATE_2MB;
154 ri->rates[ri->count++] = IEEE80211_CCK_RATE_5MB;
155 ri->rates[ri->count++] = IEEE80211_CCK_RATE_11MB;
156 }
157 if (mac->ieee->modulation & IEEE80211_OFDM_MODULATION) {
158 ri->rates[ri->count++] = IEEE80211_OFDM_RATE_6MB;
159 ri->rates[ri->count++] = IEEE80211_OFDM_RATE_9MB;
160 ri->rates[ri->count++] = IEEE80211_OFDM_RATE_12MB;
161 ri->rates[ri->count++] = IEEE80211_OFDM_RATE_18MB;
162 ri->rates[ri->count++] = IEEE80211_OFDM_RATE_24MB;
163 ri->rates[ri->count++] = IEEE80211_OFDM_RATE_36MB;
164 ri->rates[ri->count++] = IEEE80211_OFDM_RATE_48MB;
165 ri->rates[ri->count++] = IEEE80211_OFDM_RATE_54MB;
166 }
167}
168
169void ieee80211softmac_start(struct net_device *dev)
170{
171 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
172 struct ieee80211_device *ieee = mac->ieee;
173 u32 change = 0;
174 struct ieee80211softmac_txrates oldrates;
175
176 ieee80211softmac_start_check_rates(mac);
177
178 /* TODO: We need some kind of state machine to lower the default rates
179 * if we loose too many packets.
180 */
181 /* Change the default txrate to the highest possible value.
182 * The txrate machine will lower it, if it is too high.
183 */
184 if (mac->txrates_change)
185 oldrates = mac->txrates;
186 if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
187 mac->txrates.default_rate = IEEE80211_OFDM_RATE_54MB;
188 change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
189 mac->txrates.default_fallback = IEEE80211_OFDM_RATE_24MB;
190 change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
191 } else if (ieee->modulation & IEEE80211_CCK_MODULATION) {
192 mac->txrates.default_rate = IEEE80211_CCK_RATE_11MB;
193 change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
194 mac->txrates.default_fallback = IEEE80211_CCK_RATE_5MB;
195 change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
196 } else
197 assert(0);
198 if (mac->txrates_change)
199 mac->txrates_change(dev, change, &oldrates);
200}
201EXPORT_SYMBOL_GPL(ieee80211softmac_start);
202
203void ieee80211softmac_stop(struct net_device *dev)
204{
205 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
206
207 ieee80211softmac_clear_pending_work(mac);
208}
209EXPORT_SYMBOL_GPL(ieee80211softmac_stop);
210
211void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates)
212{
213 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
214 unsigned long flags;
215
216 spin_lock_irqsave(&mac->lock, flags);
217 memcpy(mac->ratesinfo.rates, rates, count);
218 mac->ratesinfo.count = count;
219 spin_unlock_irqrestore(&mac->lock, flags);
220}
221EXPORT_SYMBOL_GPL(ieee80211softmac_set_rates);
222
223static u8 raise_rate(struct ieee80211softmac_device *mac, u8 rate)
224{
225 int i;
226 struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
227
228 for (i=0; i<ri->count-1; i++) {
229 if (ri->rates[i] == rate)
230 return ri->rates[i+1];
231 }
232 /* I guess we can't go any higher... */
233 return ri->rates[ri->count];
234}
235
236u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta)
237{
238 int i;
239 struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
240
241 for (i=delta; i<ri->count; i++) {
242 if (ri->rates[i] == rate)
243 return ri->rates[i-delta];
244 }
245 /* I guess we can't go any lower... */
246 return ri->rates[0];
247}
248
249static void ieee80211softmac_add_txrates_badness(struct ieee80211softmac_device *mac,
250 int amount)
251{
252 struct ieee80211softmac_txrates oldrates;
253 u8 default_rate = mac->txrates.default_rate;
254 u8 default_fallback = mac->txrates.default_fallback;
255 u32 changes = 0;
256
257 //TODO: This is highly experimental code.
258 // Maybe the dynamic rate selection does not work
259 // and it has to be removed again.
260
261printk("badness %d\n", mac->txrate_badness);
262 mac->txrate_badness += amount;
263 if (mac->txrate_badness <= -1000) {
264 /* Very small badness. Try a faster bitrate. */
265 if (mac->txrates_change)
266 memcpy(&oldrates, &mac->txrates, sizeof(oldrates));
267 default_rate = raise_rate(mac, default_rate);
268 changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
269 default_fallback = get_fallback_rate(mac, default_rate);
270 changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
271 mac->txrate_badness = 0;
272printk("Bitrate raised to %u\n", default_rate);
273 } else if (mac->txrate_badness >= 10000) {
274 /* Very high badness. Try a slower bitrate. */
275 if (mac->txrates_change)
276 memcpy(&oldrates, &mac->txrates, sizeof(oldrates));
277 default_rate = lower_rate(mac, default_rate);
278 changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
279 default_fallback = get_fallback_rate(mac, default_rate);
280 changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
281 mac->txrate_badness = 0;
282printk("Bitrate lowered to %u\n", default_rate);
283 }
284
285 mac->txrates.default_rate = default_rate;
286 mac->txrates.default_fallback = default_fallback;
287
288 if (changes && mac->txrates_change)
289 mac->txrates_change(mac->dev, changes, &oldrates);
290}
291
292void ieee80211softmac_fragment_lost(struct net_device *dev,
293 u16 wl_seq)
294{
295 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
296 unsigned long flags;
297
298 spin_lock_irqsave(&mac->lock, flags);
299 ieee80211softmac_add_txrates_badness(mac, 1000);
300 //TODO
301
302 spin_unlock_irqrestore(&mac->lock, flags);
303}
304EXPORT_SYMBOL_GPL(ieee80211softmac_fragment_lost);
305
306static int rate_cmp(const void *a_, const void *b_) {
307 u8 *a, *b;
308 a = (u8*)a_;
309 b = (u8*)b_;
310 return ((*a & ~IEEE80211_BASIC_RATE_MASK) - (*b & ~IEEE80211_BASIC_RATE_MASK));
311}
312
313/* Allocate a softmac network struct and fill it from a network */
314struct ieee80211softmac_network *
315ieee80211softmac_create_network(struct ieee80211softmac_device *mac,
316 struct ieee80211_network *net)
317{
318 struct ieee80211softmac_network *softnet;
319 softnet = kzalloc(sizeof(struct ieee80211softmac_network), GFP_ATOMIC);
320 if(softnet == NULL)
321 return NULL;
322 memcpy(softnet->bssid, net->bssid, ETH_ALEN);
323 softnet->channel = net->channel;
324 softnet->essid.len = net->ssid_len;
325 memcpy(softnet->essid.data, net->ssid, softnet->essid.len);
326
327 /* copy rates over */
328 softnet->supported_rates.count = net->rates_len;
329 memcpy(&softnet->supported_rates.rates[0], net->rates, net->rates_len);
330 memcpy(&softnet->supported_rates.rates[softnet->supported_rates.count], net->rates_ex, net->rates_ex_len);
331 softnet->supported_rates.count += net->rates_ex_len;
332 sort(softnet->supported_rates.rates, softnet->supported_rates.count, sizeof(softnet->supported_rates.rates[0]), rate_cmp, NULL);
333
334 softnet->capabilities = net->capability;
335 return softnet;
336}
337
338
339/* Add a network to the list, while locked */
340void
341ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac,
342 struct ieee80211softmac_network *add_net)
343{
344 struct list_head *list_ptr;
345 struct ieee80211softmac_network *softmac_net = NULL;
346
347 list_for_each(list_ptr, &mac->network_list) {
348 softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
349 if(!memcmp(softmac_net->bssid, add_net->bssid, ETH_ALEN))
350 break;
351 else
352 softmac_net = NULL;
353 }
354 if(softmac_net == NULL)
355 list_add(&(add_net->list), &mac->network_list);
356}
357
358/* Add a network to the list, with locking */
359void
360ieee80211softmac_add_network(struct ieee80211softmac_device *mac,
361 struct ieee80211softmac_network *add_net)
362{
363 unsigned long flags;
364 spin_lock_irqsave(&mac->lock, flags);
365 ieee80211softmac_add_network_locked(mac, add_net);
366 spin_unlock_irqrestore(&mac->lock, flags);
367}
368
369
370/* Delete a network from the list, while locked*/
371void
372ieee80211softmac_del_network_locked(struct ieee80211softmac_device *mac,
373 struct ieee80211softmac_network *del_net)
374{
375 list_del(&(del_net->list));
376}
377
378/* Delete a network from the list with locking */
379void
380ieee80211softmac_del_network(struct ieee80211softmac_device *mac,
381 struct ieee80211softmac_network *del_net)
382{
383 unsigned long flags;
384 spin_lock_irqsave(&mac->lock, flags);
385 ieee80211softmac_del_network_locked(mac, del_net);
386 spin_unlock_irqrestore(&mac->lock, flags);
387}
388
389/* Get a network from the list by MAC while locked */
390struct ieee80211softmac_network *
391ieee80211softmac_get_network_by_bssid_locked(struct ieee80211softmac_device *mac,
392 u8 *bssid)
393{
394 struct list_head *list_ptr;
395 struct ieee80211softmac_network *softmac_net = NULL;
396 list_for_each(list_ptr, &mac->network_list) {
397 softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
398 if(!memcmp(softmac_net->bssid, bssid, ETH_ALEN))
399 break;
400 else
401 softmac_net = NULL;
402 }
403 return softmac_net;
404}
405
406/* Get a network from the list by BSSID with locking */
407struct ieee80211softmac_network *
408ieee80211softmac_get_network_by_bssid(struct ieee80211softmac_device *mac,
409 u8 *bssid)
410{
411 unsigned long flags;
412 struct ieee80211softmac_network *softmac_net;
413
414 spin_lock_irqsave(&mac->lock, flags);
415 softmac_net = ieee80211softmac_get_network_by_bssid_locked(mac, bssid);
416 spin_unlock_irqrestore(&mac->lock, flags);
417 return softmac_net;
418}
419
420/* Get a network from the list by ESSID while locked */
421struct ieee80211softmac_network *
422ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac,
423 struct ieee80211softmac_essid *essid)
424{
425 struct list_head *list_ptr;
426 struct ieee80211softmac_network *softmac_net = NULL;
427
428 list_for_each(list_ptr, &mac->network_list) {
429 softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
430 if (softmac_net->essid.len == essid->len &&
431 !memcmp(softmac_net->essid.data, essid->data, essid->len))
432 return softmac_net;
433 }
434 return NULL;
435}
436
437/* Get a network from the list by ESSID with locking */
438struct ieee80211softmac_network *
439ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac,
440 struct ieee80211softmac_essid *essid)
441{
442 unsigned long flags;
443 struct ieee80211softmac_network *softmac_net = NULL;
444
445 spin_lock_irqsave(&mac->lock, flags);
446 softmac_net = ieee80211softmac_get_network_by_essid_locked(mac, essid);
447 spin_unlock_irqrestore(&mac->lock, flags);
448 return softmac_net;
449}
450
451MODULE_LICENSE("GPL");
452MODULE_AUTHOR("Johannes Berg");
453MODULE_AUTHOR("Joseph Jezak");
454MODULE_AUTHOR("Larry Finger");
455MODULE_AUTHOR("Danny van Dyk");
456MODULE_AUTHOR("Michael Buesch");
457MODULE_DESCRIPTION("802.11 software MAC");
diff --git a/net/ieee80211/softmac/ieee80211softmac_priv.h b/net/ieee80211/softmac/ieee80211softmac_priv.h
new file mode 100644
index 000000000000..9ba7dbd161eb
--- /dev/null
+++ b/net/ieee80211/softmac/ieee80211softmac_priv.h
@@ -0,0 +1,230 @@
1/*
2 * Internal softmac API definitions.
3 *
4 * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
5 * Joseph Jezak <josejx@gentoo.org>
6 * Larry Finger <Larry.Finger@lwfinger.net>
7 * Danny van Dyk <kugelfang@gentoo.org>
8 * Michael Buesch <mbuesch@freenet.de>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 * The full GNU General Public License is included in this distribution in the
24 * file called COPYING.
25 */
26
27#ifndef IEEE80211SOFTMAC_PRIV_H_
28#define IEEE80211SOFTMAC_PRIV_H_
29
30#include <net/ieee80211softmac.h>
31#include <net/ieee80211softmac_wx.h>
32#include <linux/kernel.h>
33#include <linux/stringify.h>
34
35
36#define PFX "SoftMAC: "
37
38#ifdef assert
39# undef assert
40#endif
41#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG
42#define assert(expr) \
43 do { \
44 if (unlikely(!(expr))) { \
45 printkl(KERN_ERR PFX "ASSERTION FAILED (%s) at: %s:%d:%s()\n", #expr, \
46 __FILE__, __LINE__, __FUNCTION__); \
47 } \
48 } while (0)
49#else
50#define assert(expr) do {} while (0)
51#endif
52
53/* rate limited printk(). */
54#ifdef printkl
55# undef printkl
56#endif
57#define printkl(f, x...) do { if (printk_ratelimit()) printk(f ,##x); } while (0)
58/* rate limited printk() for debugging */
59#ifdef dprintkl
60# undef dprintkl
61#endif
62#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG
63# define dprintkl printkl
64#else
65# define dprintkl(f, x...) do { /* nothing */ } while (0)
66#endif
67
68/* debugging printk() */
69#ifdef dprintk
70# undef dprintk
71#endif
72#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG
73# define dprintk(f, x...) do { printk(f ,##x); } while (0)
74#else
75# define dprintk(f, x...) do { /* nothing */ } while (0)
76#endif
77
78/* private definitions and prototypes */
79
80/*** prototypes from _scan.c */
81void ieee80211softmac_scan(void *sm);
82/* for internal use if scanning is needed */
83int ieee80211softmac_start_scan(struct ieee80211softmac_device *mac);
84void ieee80211softmac_stop_scan(struct ieee80211softmac_device *mac);
85void ieee80211softmac_wait_for_scan(struct ieee80211softmac_device *mac);
86
87/* for use by _module.c to assign to the callbacks */
88int ieee80211softmac_start_scan_implementation(struct net_device *dev);
89void ieee80211softmac_stop_scan_implementation(struct net_device *dev);
90void ieee80211softmac_wait_for_scan_implementation(struct net_device *dev);
91
92/*** Network prototypes from _module.c */
93struct ieee80211softmac_network * ieee80211softmac_create_network(
94 struct ieee80211softmac_device *mac, struct ieee80211_network *net);
95void ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac,
96 struct ieee80211softmac_network *net);
97void ieee80211softmac_add_network(struct ieee80211softmac_device *mac,
98 struct ieee80211softmac_network *net);
99void ieee80211softmac_del_network_locked(struct ieee80211softmac_device *mac,
100 struct ieee80211softmac_network *net);
101void ieee80211softmac_del_network(struct ieee80211softmac_device *mac,
102 struct ieee80211softmac_network *net);
103struct ieee80211softmac_network * ieee80211softmac_get_network_by_bssid_locked(
104 struct ieee80211softmac_device *mac, u8 *ea);
105struct ieee80211softmac_network * ieee80211softmac_get_network_by_bssid(
106 struct ieee80211softmac_device *mac, u8 *ea);
107struct ieee80211softmac_network * ieee80211softmac_get_network_by_ssid_locked(
108 struct ieee80211softmac_device *mac, u8 *ssid, u8 ssid_len);
109struct ieee80211softmac_network * ieee80211softmac_get_network_by_ssid(
110 struct ieee80211softmac_device *mac, u8 *ssid, u8 ssid_len);
111struct ieee80211softmac_network *
112ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac,
113 struct ieee80211softmac_essid *essid);
114struct ieee80211softmac_network *
115ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac,
116 struct ieee80211softmac_essid *essid);
117
118/* Rates related */
119u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta);
120static inline u8 lower_rate(struct ieee80211softmac_device *mac, u8 rate) {
121 return ieee80211softmac_lower_rate_delta(mac, rate, 1);
122}
123
124static inline u8 get_fallback_rate(struct ieee80211softmac_device *mac, u8 rate)
125{
126 return ieee80211softmac_lower_rate_delta(mac, rate, 2);
127}
128
129
130/*** prototypes from _io.c */
131int ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
132 void* ptrarg, u32 type, u32 arg);
133
134/*** prototypes from _auth.c */
135/* do these have to go into the public header? */
136int ieee80211softmac_auth_req(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net);
137int ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, int reason);
138
139/* for use by _module.c to assign to the callbacks */
140int ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth);
141int ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *deauth);
142
143/*** prototypes from _assoc.c */
144void ieee80211softmac_assoc_work(void *d);
145int ieee80211softmac_handle_assoc_response(struct net_device * dev,
146 struct ieee80211_assoc_response * resp,
147 struct ieee80211_network * network);
148int ieee80211softmac_handle_disassoc(struct net_device * dev,
149 struct ieee80211_disassoc * disassoc);
150int ieee80211softmac_handle_reassoc_req(struct net_device * dev,
151 struct ieee80211_reassoc_request * reassoc);
152void ieee80211softmac_assoc_timeout(void *d);
153
154/* some helper functions */
155static inline int ieee80211softmac_scan_handlers_check_self(struct ieee80211softmac_device *sm)
156{
157 return (sm->start_scan == ieee80211softmac_start_scan_implementation) &&
158 (sm->stop_scan == ieee80211softmac_stop_scan_implementation) &&
159 (sm->wait_for_scan == ieee80211softmac_wait_for_scan_implementation);
160}
161
162static inline int ieee80211softmac_scan_sanity_check(struct ieee80211softmac_device *sm)
163{
164 return ((sm->start_scan != ieee80211softmac_start_scan_implementation) &&
165 (sm->stop_scan != ieee80211softmac_stop_scan_implementation) &&
166 (sm->wait_for_scan != ieee80211softmac_wait_for_scan_implementation)
167 ) || ieee80211softmac_scan_handlers_check_self(sm);
168}
169
170#define IEEE80211SOFTMAC_PROBE_DELAY HZ/2
171#define IEEE80211SOFTMAC_WORKQUEUE_NAME_LEN (17 + IFNAMSIZ)
172
173struct ieee80211softmac_network {
174 struct list_head list; /* List */
175 /* Network information copied from ieee80211_network */
176 u8 bssid[ETH_ALEN];
177 u8 channel;
178 struct ieee80211softmac_essid essid;
179
180 struct ieee80211softmac_ratesinfo supported_rates;
181
182 /* SoftMAC specific */
183 u16 authenticating:1, /* Status Flags */
184 authenticated:1,
185 auth_desynced_once:1;
186
187 u16 capabilities; /* Capabilities bitfield */
188 u8 challenge_len; /* Auth Challenge length */
189 char *challenge; /* Challenge Text */
190};
191
192/* structure used to keep track of networks we're auth'ing to */
193struct ieee80211softmac_auth_queue_item {
194 struct list_head list; /* List head */
195 struct ieee80211softmac_network *net; /* Network to auth */
196 struct ieee80211softmac_device *mac; /* SoftMAC device */
197 u8 retry; /* Retry limit */
198 u8 state; /* Auth State */
199 struct work_struct work; /* Work queue */
200};
201
202/* scanning information */
203struct ieee80211softmac_scaninfo {
204 u8 current_channel_idx,
205 number_channels;
206 struct ieee80211_channel *channels;
207 u8 started:1,
208 stop:1;
209 u8 skip_flags;
210 struct completion finished;
211 struct work_struct softmac_scan;
212};
213
214/* private event struct */
215struct ieee80211softmac_event {
216 struct list_head list;
217 int event_type;
218 void *event_context;
219 struct work_struct work;
220 notify_function_ptr fun;
221 void *context;
222 struct ieee80211softmac_device *mac;
223};
224
225void ieee80211softmac_call_events(struct ieee80211softmac_device *mac, int event, void *event_context);
226void ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_context);
227int ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac,
228 int event, void *event_context, notify_function_ptr fun, void *context, gfp_t gfp_mask);
229
230#endif /* IEEE80211SOFTMAC_PRIV_H_ */
diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c
new file mode 100644
index 000000000000..bb9ab8b45d09
--- /dev/null
+++ b/net/ieee80211/softmac/ieee80211softmac_scan.c
@@ -0,0 +1,244 @@
1/*
2 * Scanning routines.
3 *
4 * These are not exported because they're assigned to the function pointers.
5 *
6 * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
7 * Joseph Jezak <josejx@gentoo.org>
8 * Larry Finger <Larry.Finger@lwfinger.net>
9 * Danny van Dyk <kugelfang@gentoo.org>
10 * Michael Buesch <mbuesch@freenet.de>
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of version 2 of the GNU General Public License as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 * more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 * The full GNU General Public License is included in this distribution in the
26 * file called COPYING.
27 */
28
29#include <linux/completion.h>
30#include "ieee80211softmac_priv.h"
31
32/* internal, use to trigger scanning if needed.
33 * Returns -EBUSY if already scanning,
34 * result of start_scan otherwise */
35int
36ieee80211softmac_start_scan(struct ieee80211softmac_device *sm)
37{
38 unsigned long flags;
39 int ret;
40
41 spin_lock_irqsave(&sm->lock, flags);
42 if (sm->scanning)
43 {
44 spin_unlock_irqrestore(&sm->lock, flags);
45 return -EINPROGRESS;
46 }
47 sm->scanning = 1;
48 spin_unlock_irqrestore(&sm->lock, flags);
49
50 ret = sm->start_scan(sm->dev);
51 if (ret) {
52 spin_lock_irqsave(&sm->lock, flags);
53 sm->scanning = 0;
54 spin_unlock_irqrestore(&sm->lock, flags);
55 }
56 return ret;
57}
58
59void
60ieee80211softmac_stop_scan(struct ieee80211softmac_device *sm)
61{
62 unsigned long flags;
63
64 spin_lock_irqsave(&sm->lock, flags);
65
66 if (!sm->scanning) {
67 spin_unlock_irqrestore(&sm->lock, flags);
68 return;
69 }
70
71 spin_unlock_irqrestore(&sm->lock, flags);
72 sm->stop_scan(sm->dev);
73}
74
75void
76ieee80211softmac_wait_for_scan(struct ieee80211softmac_device *sm)
77{
78 unsigned long flags;
79
80 spin_lock_irqsave(&sm->lock, flags);
81
82 if (!sm->scanning) {
83 spin_unlock_irqrestore(&sm->lock, flags);
84 return;
85 }
86
87 spin_unlock_irqrestore(&sm->lock, flags);
88 sm->wait_for_scan(sm->dev);
89}
90
91
92/* internal scanning implementation follows */
93void ieee80211softmac_scan(void *d)
94{
95 int invalid_channel;
96 u8 current_channel_idx;
97 struct ieee80211softmac_device *sm = (struct ieee80211softmac_device *)d;
98 struct ieee80211softmac_scaninfo *si = sm->scaninfo;
99 unsigned long flags;
100
101 while (!(si->stop) && (si->current_channel_idx < si->number_channels)) {
102 current_channel_idx = si->current_channel_idx;
103 si->current_channel_idx++; /* go to the next channel */
104
105 invalid_channel = (si->skip_flags & si->channels[current_channel_idx].flags);
106
107 if (!invalid_channel) {
108 sm->set_channel(sm->dev, si->channels[current_channel_idx].channel);
109 // FIXME make this user configurable (active/passive)
110 if(ieee80211softmac_send_mgt_frame(sm, NULL, IEEE80211_STYPE_PROBE_REQ, 0))
111 printkl(KERN_DEBUG PFX "Sending Probe Request Failed\n");
112
113 /* also send directed management frame for the network we're looking for */
114 // TODO: is this if correct, or should we do this only if scanning from assoc request?
115 if (sm->associnfo.req_essid.len)
116 ieee80211softmac_send_mgt_frame(sm, &sm->associnfo.req_essid, IEEE80211_STYPE_PROBE_REQ, 0);
117 schedule_delayed_work(&si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY);
118 return;
119 } else {
120 dprintk(PFX "Not probing Channel %d (not allowed here)\n", si->channels[current_channel_idx].channel);
121 }
122 }
123
124 spin_lock_irqsave(&sm->lock, flags);
125 cancel_delayed_work(&si->softmac_scan);
126 si->started = 0;
127 spin_unlock_irqrestore(&sm->lock, flags);
128
129 dprintk(PFX "Scanning finished\n");
130 ieee80211softmac_scan_finished(sm);
131 complete_all(&sm->scaninfo->finished);
132}
133
134static inline struct ieee80211softmac_scaninfo *allocate_scaninfo(struct ieee80211softmac_device *mac)
135{
136 /* ugh. can we call this without having the spinlock held? */
137 struct ieee80211softmac_scaninfo *info = kmalloc(sizeof(struct ieee80211softmac_scaninfo), GFP_ATOMIC);
138 if (unlikely(!info))
139 return NULL;
140 INIT_WORK(&info->softmac_scan, ieee80211softmac_scan, mac);
141 init_completion(&info->finished);
142 return info;
143}
144
145int ieee80211softmac_start_scan_implementation(struct net_device *dev)
146{
147 struct ieee80211softmac_device *sm = ieee80211_priv(dev);
148 unsigned long flags;
149
150 if (!(dev->flags & IFF_UP))
151 return -ENODEV;
152
153 assert(ieee80211softmac_scan_handlers_check_self(sm));
154 if (!ieee80211softmac_scan_handlers_check_self(sm))
155 return -EINVAL;
156
157 spin_lock_irqsave(&sm->lock, flags);
158 /* it looks like we need to hold the lock here
159 * to make sure we don't allocate two of these... */
160 if (unlikely(!sm->scaninfo))
161 sm->scaninfo = allocate_scaninfo(sm);
162 if (unlikely(!sm->scaninfo)) {
163 spin_unlock_irqrestore(&sm->lock, flags);
164 return -ENOMEM;
165 }
166
167 sm->scaninfo->skip_flags = IEEE80211_CH_INVALID;
168 if (0 /* not scanning in IEEE802.11b */)//TODO
169 sm->scaninfo->skip_flags |= IEEE80211_CH_B_ONLY;
170 if (0 /* IEEE802.11a */) {//TODO
171 sm->scaninfo->channels = sm->ieee->geo.a;
172 sm->scaninfo->number_channels = sm->ieee->geo.a_channels;
173 } else {
174 sm->scaninfo->channels = sm->ieee->geo.bg;
175 sm->scaninfo->number_channels = sm->ieee->geo.bg_channels;
176 }
177 dprintk(PFX "Start scanning with channel: %d\n", sm->scaninfo->channels[0].channel);
178 dprintk(PFX "Scanning %d channels\n", sm->scaninfo->number_channels);
179 sm->scaninfo->current_channel_idx = 0;
180 sm->scaninfo->started = 1;
181 sm->scaninfo->stop = 0;
182 INIT_COMPLETION(sm->scaninfo->finished);
183 schedule_work(&sm->scaninfo->softmac_scan);
184 spin_unlock_irqrestore(&sm->lock, flags);
185 return 0;
186}
187
188void ieee80211softmac_stop_scan_implementation(struct net_device *dev)
189{
190 struct ieee80211softmac_device *sm = ieee80211_priv(dev);
191 unsigned long flags;
192
193 assert(ieee80211softmac_scan_handlers_check_self(sm));
194 if (!ieee80211softmac_scan_handlers_check_self(sm))
195 return;
196
197 spin_lock_irqsave(&sm->lock, flags);
198 assert(sm->scaninfo != NULL);
199 if (sm->scaninfo) {
200 if (sm->scaninfo->started)
201 sm->scaninfo->stop = 1;
202 else
203 complete_all(&sm->scaninfo->finished);
204 }
205 spin_unlock_irqrestore(&sm->lock, flags);
206}
207
208void ieee80211softmac_wait_for_scan_implementation(struct net_device *dev)
209{
210 struct ieee80211softmac_device *sm = ieee80211_priv(dev);
211 unsigned long flags;
212
213 assert(ieee80211softmac_scan_handlers_check_self(sm));
214 if (!ieee80211softmac_scan_handlers_check_self(sm))
215 return;
216
217 spin_lock_irqsave(&sm->lock, flags);
218 if (!sm->scaninfo->started) {
219 spin_unlock_irqrestore(&sm->lock, flags);
220 return;
221 }
222 spin_unlock_irqrestore(&sm->lock, flags);
223 wait_for_completion(&sm->scaninfo->finished);
224}
225
226/* this is what drivers (that do scanning) call when they're done */
227void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm)
228{
229 unsigned long flags;
230
231 spin_lock_irqsave(&sm->lock, flags);
232 sm->scanning = 0;
233 spin_unlock_irqrestore(&sm->lock, flags);
234
235 if (sm->associnfo.bssvalid) {
236 struct ieee80211softmac_network *net;
237
238 net = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid);
239 if (net)
240 sm->set_channel(sm->dev, net->channel);
241 }
242 ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL);
243}
244EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished);
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
new file mode 100644
index 000000000000..e1a9bc6d36ff
--- /dev/null
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -0,0 +1,412 @@
1/*
2 * This file contains our _wx handlers. Make sure you EXPORT_SYMBOL_GPL them
3 *
4 * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
5 * Joseph Jezak <josejx@gentoo.org>
6 * Larry Finger <Larry.Finger@lwfinger.net>
7 * Danny van Dyk <kugelfang@gentoo.org>
8 * Michael Buesch <mbuesch@freenet.de>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 * The full GNU General Public License is included in this distribution in the
24 * file called COPYING.
25 */
26
27#include "ieee80211softmac_priv.h"
28
29#include <net/iw_handler.h>
30
31
32int
33ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
34 struct iw_request_info *info,
35 union iwreq_data *data,
36 char *extra)
37{
38 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
39 return ieee80211softmac_start_scan(sm);
40}
41EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan);
42
43
44int
45ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
46 struct iw_request_info *info,
47 union iwreq_data *data,
48 char *extra)
49{
50 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
51 return ieee80211_wx_get_scan(sm->ieee, info, data, extra);
52}
53EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results);
54
55int
56ieee80211softmac_wx_set_essid(struct net_device *net_dev,
57 struct iw_request_info *info,
58 union iwreq_data *data,
59 char *extra)
60{
61 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
62 int length = 0;
63 unsigned long flags;
64
65 spin_lock_irqsave(&sm->lock, flags);
66
67 sm->associnfo.static_essid = 0;
68
69 if (data->essid.flags && data->essid.length && extra /*required?*/) {
70 length = min(data->essid.length - 1, IW_ESSID_MAX_SIZE);
71 if (length) {
72 memcpy(sm->associnfo.req_essid.data, extra, length);
73 sm->associnfo.static_essid = 1;
74 }
75 }
76 sm->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
77
78 /* set our requested ESSID length.
79 * If applicable, we have already copied the data in */
80 sm->associnfo.req_essid.len = length;
81
82 /* queue lower level code to do work (if necessary) */
83 schedule_work(&sm->associnfo.work);
84
85 spin_unlock_irqrestore(&sm->lock, flags);
86 return 0;
87}
88EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid);
89
90int
91ieee80211softmac_wx_get_essid(struct net_device *net_dev,
92 struct iw_request_info *info,
93 union iwreq_data *data,
94 char *extra)
95{
96 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
97 unsigned long flags;
98
99 /* avoid getting inconsistent information */
100 spin_lock_irqsave(&sm->lock, flags);
101 /* If all fails, return ANY (empty) */
102 data->essid.length = 0;
103 data->essid.flags = 0; /* active */
104
105 /* If we have a statically configured ESSID then return it */
106 if (sm->associnfo.static_essid) {
107 data->essid.length = sm->associnfo.req_essid.len;
108 data->essid.flags = 1; /* active */
109 memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len);
110 }
111
112 /* If we're associating/associated, return that */
113 if (sm->associated || sm->associnfo.associating) {
114 data->essid.length = sm->associnfo.associate_essid.len;
115 data->essid.flags = 1; /* active */
116 memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len);
117 }
118 spin_unlock_irqrestore(&sm->lock, flags);
119 return 0;
120}
121EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid);
122
123int
124ieee80211softmac_wx_set_rate(struct net_device *net_dev,
125 struct iw_request_info *info,
126 union iwreq_data *data,
127 char *extra)
128{
129 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
130 struct ieee80211_device *ieee = mac->ieee;
131 unsigned long flags;
132 s32 in_rate = data->bitrate.value;
133 u8 rate;
134 int is_ofdm = 0;
135 int err = -EINVAL;
136
137 if (in_rate == -1) {
138 /* automatic detect */
139 if (ieee->modulation & IEEE80211_OFDM_MODULATION)
140 in_rate = 54000000;
141 else
142 in_rate = 11000000;
143 }
144
145 switch (in_rate) {
146 case 1000000:
147 rate = IEEE80211_CCK_RATE_1MB;
148 break;
149 case 2000000:
150 rate = IEEE80211_CCK_RATE_2MB;
151 break;
152 case 5500000:
153 rate = IEEE80211_CCK_RATE_5MB;
154 break;
155 case 11000000:
156 rate = IEEE80211_CCK_RATE_11MB;
157 break;
158 case 6000000:
159 rate = IEEE80211_OFDM_RATE_6MB;
160 is_ofdm = 1;
161 break;
162 case 9000000:
163 rate = IEEE80211_OFDM_RATE_9MB;
164 is_ofdm = 1;
165 break;
166 case 12000000:
167 rate = IEEE80211_OFDM_RATE_12MB;
168 is_ofdm = 1;
169 break;
170 case 18000000:
171 rate = IEEE80211_OFDM_RATE_18MB;
172 is_ofdm = 1;
173 break;
174 case 24000000:
175 rate = IEEE80211_OFDM_RATE_24MB;
176 is_ofdm = 1;
177 break;
178 case 36000000:
179 rate = IEEE80211_OFDM_RATE_36MB;
180 is_ofdm = 1;
181 break;
182 case 48000000:
183 rate = IEEE80211_OFDM_RATE_48MB;
184 is_ofdm = 1;
185 break;
186 case 54000000:
187 rate = IEEE80211_OFDM_RATE_54MB;
188 is_ofdm = 1;
189 break;
190 default:
191 goto out;
192 }
193
194 spin_lock_irqsave(&mac->lock, flags);
195
196 /* Check if correct modulation for this PHY. */
197 if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION))
198 goto out_unlock;
199
200 mac->txrates.default_rate = rate;
201 mac->txrates.default_fallback = lower_rate(mac, rate);
202 err = 0;
203
204out_unlock:
205 spin_unlock_irqrestore(&mac->lock, flags);
206out:
207 return err;
208}
209EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_rate);
210
211int
212ieee80211softmac_wx_get_rate(struct net_device *net_dev,
213 struct iw_request_info *info,
214 union iwreq_data *data,
215 char *extra)
216{
217 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
218 unsigned long flags;
219 int err = -EINVAL;
220
221 spin_lock_irqsave(&mac->lock, flags);
222 switch (mac->txrates.default_rate) {
223 case IEEE80211_CCK_RATE_1MB:
224 data->bitrate.value = 1000000;
225 break;
226 case IEEE80211_CCK_RATE_2MB:
227 data->bitrate.value = 2000000;
228 break;
229 case IEEE80211_CCK_RATE_5MB:
230 data->bitrate.value = 5500000;
231 break;
232 case IEEE80211_CCK_RATE_11MB:
233 data->bitrate.value = 11000000;
234 break;
235 case IEEE80211_OFDM_RATE_6MB:
236 data->bitrate.value = 6000000;
237 break;
238 case IEEE80211_OFDM_RATE_9MB:
239 data->bitrate.value = 9000000;
240 break;
241 case IEEE80211_OFDM_RATE_12MB:
242 data->bitrate.value = 12000000;
243 break;
244 case IEEE80211_OFDM_RATE_18MB:
245 data->bitrate.value = 18000000;
246 break;
247 case IEEE80211_OFDM_RATE_24MB:
248 data->bitrate.value = 24000000;
249 break;
250 case IEEE80211_OFDM_RATE_36MB:
251 data->bitrate.value = 36000000;
252 break;
253 case IEEE80211_OFDM_RATE_48MB:
254 data->bitrate.value = 48000000;
255 break;
256 case IEEE80211_OFDM_RATE_54MB:
257 data->bitrate.value = 54000000;
258 break;
259 default:
260 assert(0);
261 goto out_unlock;
262 }
263 err = 0;
264out_unlock:
265 spin_unlock_irqrestore(&mac->lock, flags);
266
267 return err;
268}
269EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_rate);
270
271int
272ieee80211softmac_wx_get_wap(struct net_device *net_dev,
273 struct iw_request_info *info,
274 union iwreq_data *data,
275 char *extra)
276{
277 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
278 int err = 0;
279 unsigned long flags;
280
281 spin_lock_irqsave(&mac->lock, flags);
282 if (mac->associnfo.bssvalid)
283 memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN);
284 else
285 memset(data->ap_addr.sa_data, 0xff, ETH_ALEN);
286 data->ap_addr.sa_family = ARPHRD_ETHER;
287 spin_unlock_irqrestore(&mac->lock, flags);
288 return err;
289}
290EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap);
291
292int
293ieee80211softmac_wx_set_wap(struct net_device *net_dev,
294 struct iw_request_info *info,
295 union iwreq_data *data,
296 char *extra)
297{
298 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
299 static const unsigned char any[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
300 static const unsigned char off[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
301 unsigned long flags;
302
303 /* sanity check */
304 if (data->ap_addr.sa_family != ARPHRD_ETHER) {
305 return -EINVAL;
306 }
307
308 spin_lock_irqsave(&mac->lock, flags);
309 if (!memcmp(any, data->ap_addr.sa_data, ETH_ALEN) ||
310 !memcmp(off, data->ap_addr.sa_data, ETH_ALEN)) {
311 schedule_work(&mac->associnfo.work);
312 goto out;
313 } else {
314 if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
315 if (mac->associnfo.associating || mac->associated) {
316 /* bssid unchanged and associated or associating - just return */
317 goto out;
318 }
319 } else {
320 /* copy new value in data->ap_addr.sa_data to bssid */
321 memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
322 }
323 /* queue associate if new bssid or (old one again and not associated) */
324 schedule_work(&mac->associnfo.work);
325 }
326
327out:
328 spin_unlock_irqrestore(&mac->lock, flags);
329 return 0;
330}
331EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap);
332
333int
334ieee80211softmac_wx_set_genie(struct net_device *dev,
335 struct iw_request_info *info,
336 union iwreq_data *wrqu,
337 char *extra)
338{
339 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
340 unsigned long flags;
341 int err = 0;
342 char *buf;
343 int i;
344
345 spin_lock_irqsave(&mac->lock, flags);
346 /* bleh. shouldn't be locked for that kmalloc... */
347
348 if (wrqu->data.length) {
349 if ((wrqu->data.length < 2) || (extra[1]+2 != wrqu->data.length)) {
350 /* this is an IE, so the length must be
351 * correct. Is it possible though that
352 * more than one IE is passed in?
353 */
354 err = -EINVAL;
355 goto out;
356 }
357 if (mac->wpa.IEbuflen <= wrqu->data.length) {
358 buf = kmalloc(wrqu->data.length, GFP_ATOMIC);
359 if (!buf) {
360 err = -ENOMEM;
361 goto out;
362 }
363 kfree(mac->wpa.IE);
364 mac->wpa.IE = buf;
365 mac->wpa.IEbuflen = wrqu->data.length;
366 }
367 memcpy(mac->wpa.IE, extra, wrqu->data.length);
368 dprintk(KERN_INFO PFX "generic IE set to ");
369 for (i=0;i<wrqu->data.length;i++)
370 dprintk("%.2x", mac->wpa.IE[i]);
371 dprintk("\n");
372 mac->wpa.IElen = wrqu->data.length;
373 } else {
374 kfree(mac->wpa.IE);
375 mac->wpa.IE = NULL;
376 mac->wpa.IElen = 0;
377 mac->wpa.IEbuflen = 0;
378 }
379
380 out:
381 spin_unlock_irqrestore(&mac->lock, flags);
382 return err;
383}
384EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie);
385
386int
387ieee80211softmac_wx_get_genie(struct net_device *dev,
388 struct iw_request_info *info,
389 union iwreq_data *wrqu,
390 char *extra)
391{
392 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
393 unsigned long flags;
394 int err = 0;
395 int space = wrqu->data.length;
396
397 spin_lock_irqsave(&mac->lock, flags);
398
399 wrqu->data.length = 0;
400
401 if (mac->wpa.IE && mac->wpa.IElen) {
402 wrqu->data.length = mac->wpa.IElen;
403 if (mac->wpa.IElen <= space)
404 memcpy(extra, mac->wpa.IE, mac->wpa.IElen);
405 else
406 err = -E2BIG;
407 }
408 spin_unlock_irqrestore(&mac->lock, flags);
409 return err;
410}
411EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie);
412
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 97c276f95b35..dc206f1f914f 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -788,45 +788,53 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
788} 788}
789 789
790const struct proto_ops inet_stream_ops = { 790const struct proto_ops inet_stream_ops = {
791 .family = PF_INET, 791 .family = PF_INET,
792 .owner = THIS_MODULE, 792 .owner = THIS_MODULE,
793 .release = inet_release, 793 .release = inet_release,
794 .bind = inet_bind, 794 .bind = inet_bind,
795 .connect = inet_stream_connect, 795 .connect = inet_stream_connect,
796 .socketpair = sock_no_socketpair, 796 .socketpair = sock_no_socketpair,
797 .accept = inet_accept, 797 .accept = inet_accept,
798 .getname = inet_getname, 798 .getname = inet_getname,
799 .poll = tcp_poll, 799 .poll = tcp_poll,
800 .ioctl = inet_ioctl, 800 .ioctl = inet_ioctl,
801 .listen = inet_listen, 801 .listen = inet_listen,
802 .shutdown = inet_shutdown, 802 .shutdown = inet_shutdown,
803 .setsockopt = sock_common_setsockopt, 803 .setsockopt = sock_common_setsockopt,
804 .getsockopt = sock_common_getsockopt, 804 .getsockopt = sock_common_getsockopt,
805 .sendmsg = inet_sendmsg, 805 .sendmsg = inet_sendmsg,
806 .recvmsg = sock_common_recvmsg, 806 .recvmsg = sock_common_recvmsg,
807 .mmap = sock_no_mmap, 807 .mmap = sock_no_mmap,
808 .sendpage = tcp_sendpage 808 .sendpage = tcp_sendpage,
809#ifdef CONFIG_COMPAT
810 .compat_setsockopt = compat_sock_common_setsockopt,
811 .compat_getsockopt = compat_sock_common_getsockopt,
812#endif
809}; 813};
810 814
811const struct proto_ops inet_dgram_ops = { 815const struct proto_ops inet_dgram_ops = {
812 .family = PF_INET, 816 .family = PF_INET,
813 .owner = THIS_MODULE, 817 .owner = THIS_MODULE,
814 .release = inet_release, 818 .release = inet_release,
815 .bind = inet_bind, 819 .bind = inet_bind,
816 .connect = inet_dgram_connect, 820 .connect = inet_dgram_connect,
817 .socketpair = sock_no_socketpair, 821 .socketpair = sock_no_socketpair,
818 .accept = sock_no_accept, 822 .accept = sock_no_accept,
819 .getname = inet_getname, 823 .getname = inet_getname,
820 .poll = udp_poll, 824 .poll = udp_poll,
821 .ioctl = inet_ioctl, 825 .ioctl = inet_ioctl,
822 .listen = sock_no_listen, 826 .listen = sock_no_listen,
823 .shutdown = inet_shutdown, 827 .shutdown = inet_shutdown,
824 .setsockopt = sock_common_setsockopt, 828 .setsockopt = sock_common_setsockopt,
825 .getsockopt = sock_common_getsockopt, 829 .getsockopt = sock_common_getsockopt,
826 .sendmsg = inet_sendmsg, 830 .sendmsg = inet_sendmsg,
827 .recvmsg = sock_common_recvmsg, 831 .recvmsg = sock_common_recvmsg,
828 .mmap = sock_no_mmap, 832 .mmap = sock_no_mmap,
829 .sendpage = inet_sendpage, 833 .sendpage = inet_sendpage,
834#ifdef CONFIG_COMPAT
835 .compat_setsockopt = compat_sock_common_setsockopt,
836 .compat_getsockopt = compat_sock_common_getsockopt,
837#endif
830}; 838};
831 839
832/* 840/*
@@ -834,24 +842,28 @@ const struct proto_ops inet_dgram_ops = {
834 * udp_poll 842 * udp_poll
835 */ 843 */
836static const struct proto_ops inet_sockraw_ops = { 844static const struct proto_ops inet_sockraw_ops = {
837 .family = PF_INET, 845 .family = PF_INET,
838 .owner = THIS_MODULE, 846 .owner = THIS_MODULE,
839 .release = inet_release, 847 .release = inet_release,
840 .bind = inet_bind, 848 .bind = inet_bind,
841 .connect = inet_dgram_connect, 849 .connect = inet_dgram_connect,
842 .socketpair = sock_no_socketpair, 850 .socketpair = sock_no_socketpair,
843 .accept = sock_no_accept, 851 .accept = sock_no_accept,
844 .getname = inet_getname, 852 .getname = inet_getname,
845 .poll = datagram_poll, 853 .poll = datagram_poll,
846 .ioctl = inet_ioctl, 854 .ioctl = inet_ioctl,
847 .listen = sock_no_listen, 855 .listen = sock_no_listen,
848 .shutdown = inet_shutdown, 856 .shutdown = inet_shutdown,
849 .setsockopt = sock_common_setsockopt, 857 .setsockopt = sock_common_setsockopt,
850 .getsockopt = sock_common_getsockopt, 858 .getsockopt = sock_common_getsockopt,
851 .sendmsg = inet_sendmsg, 859 .sendmsg = inet_sendmsg,
852 .recvmsg = sock_common_recvmsg, 860 .recvmsg = sock_common_recvmsg,
853 .mmap = sock_no_mmap, 861 .mmap = sock_no_mmap,
854 .sendpage = inet_sendpage, 862 .sendpage = inet_sendpage,
863#ifdef CONFIG_COMPAT
864 .compat_setsockopt = compat_sock_common_setsockopt,
865 .compat_getsockopt = compat_sock_common_getsockopt,
866#endif
855}; 867};
856 868
857static struct net_proto_family inet_family_ops = { 869static struct net_proto_family inet_family_ops = {
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index aed537fa2c88..e16d8b42b953 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -97,6 +97,7 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
97 ah->reserved = 0; 97 ah->reserved = 0;
98 ah->spi = x->id.spi; 98 ah->spi = x->id.spi;
99 ah->seq_no = htonl(++x->replay.oseq); 99 ah->seq_no = htonl(++x->replay.oseq);
100 xfrm_aevent_doreplay(x);
100 ahp->icv(ahp, skb, ah->auth_data); 101 ahp->icv(ahp, skb, ah->auth_data);
101 102
102 top_iph->tos = iph->tos; 103 top_iph->tos = iph->tos;
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index accdefedfed7..041dadde31af 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -879,16 +879,16 @@ static int arp_process(struct sk_buff *skb)
879 879
880 n = __neigh_lookup(&arp_tbl, &sip, dev, 0); 880 n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
881 881
882#ifdef CONFIG_IP_ACCEPT_UNSOLICITED_ARP 882 if (ipv4_devconf.arp_accept) {
883 /* Unsolicited ARP is not accepted by default. 883 /* Unsolicited ARP is not accepted by default.
884 It is possible, that this option should be enabled for some 884 It is possible, that this option should be enabled for some
885 devices (strip is candidate) 885 devices (strip is candidate)
886 */ 886 */
887 if (n == NULL && 887 if (n == NULL &&
888 arp->ar_op == htons(ARPOP_REPLY) && 888 arp->ar_op == htons(ARPOP_REPLY) &&
889 inet_addr_type(sip) == RTN_UNICAST) 889 inet_addr_type(sip) == RTN_UNICAST)
890 n = __neigh_lookup(&arp_tbl, &sip, dev, -1); 890 n = __neigh_lookup(&arp_tbl, &sip, dev, -1);
891#endif 891 }
892 892
893 if (n) { 893 if (n) {
894 int state = NUD_REACHABLE; 894 int state = NUD_REACHABLE;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 3ffa60dadc0c..44fdf1413e2c 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1394,6 +1394,14 @@ static struct devinet_sysctl_table {
1394 .proc_handler = &proc_dointvec, 1394 .proc_handler = &proc_dointvec,
1395 }, 1395 },
1396 { 1396 {
1397 .ctl_name = NET_IPV4_CONF_ARP_ACCEPT,
1398 .procname = "arp_accept",
1399 .data = &ipv4_devconf.arp_accept,
1400 .maxlen = sizeof(int),
1401 .mode = 0644,
1402 .proc_handler = &proc_dointvec,
1403 },
1404 {
1397 .ctl_name = NET_IPV4_CONF_NOXFRM, 1405 .ctl_name = NET_IPV4_CONF_NOXFRM,
1398 .procname = "disable_xfrm", 1406 .procname = "disable_xfrm",
1399 .data = &ipv4_devconf.no_xfrm, 1407 .data = &ipv4_devconf.no_xfrm,
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 09590f356086..bf88c620a954 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -90,6 +90,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
90 90
91 esph->spi = x->id.spi; 91 esph->spi = x->id.spi;
92 esph->seq_no = htonl(++x->replay.oseq); 92 esph->seq_no = htonl(++x->replay.oseq);
93 xfrm_aevent_doreplay(x);
93 94
94 if (esp->conf.ivlen) 95 if (esp->conf.ivlen)
95 crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); 96 crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 0dd4d06e456d..ec566f3e66c7 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -40,6 +40,8 @@
40#include <linux/skbuff.h> 40#include <linux/skbuff.h>
41#include <linux/netlink.h> 41#include <linux/netlink.h>
42#include <linux/init.h> 42#include <linux/init.h>
43#include <linux/list.h>
44#include <linux/rcupdate.h>
43 45
44#include <net/ip.h> 46#include <net/ip.h>
45#include <net/protocol.h> 47#include <net/protocol.h>
@@ -52,7 +54,7 @@
52 54
53struct fib_rule 55struct fib_rule
54{ 56{
55 struct fib_rule *r_next; 57 struct hlist_node hlist;
56 atomic_t r_clntref; 58 atomic_t r_clntref;
57 u32 r_preference; 59 u32 r_preference;
58 unsigned char r_table; 60 unsigned char r_table;
@@ -75,6 +77,7 @@ struct fib_rule
75#endif 77#endif
76 char r_ifname[IFNAMSIZ]; 78 char r_ifname[IFNAMSIZ];
77 int r_dead; 79 int r_dead;
80 struct rcu_head rcu;
78}; 81};
79 82
80static struct fib_rule default_rule = { 83static struct fib_rule default_rule = {
@@ -85,7 +88,6 @@ static struct fib_rule default_rule = {
85}; 88};
86 89
87static struct fib_rule main_rule = { 90static struct fib_rule main_rule = {
88 .r_next = &default_rule,
89 .r_clntref = ATOMIC_INIT(2), 91 .r_clntref = ATOMIC_INIT(2),
90 .r_preference = 0x7FFE, 92 .r_preference = 0x7FFE,
91 .r_table = RT_TABLE_MAIN, 93 .r_table = RT_TABLE_MAIN,
@@ -93,23 +95,26 @@ static struct fib_rule main_rule = {
93}; 95};
94 96
95static struct fib_rule local_rule = { 97static struct fib_rule local_rule = {
96 .r_next = &main_rule,
97 .r_clntref = ATOMIC_INIT(2), 98 .r_clntref = ATOMIC_INIT(2),
98 .r_table = RT_TABLE_LOCAL, 99 .r_table = RT_TABLE_LOCAL,
99 .r_action = RTN_UNICAST, 100 .r_action = RTN_UNICAST,
100}; 101};
101 102
102static struct fib_rule *fib_rules = &local_rule; 103static struct hlist_head fib_rules;
103static DEFINE_RWLOCK(fib_rules_lock); 104
105/* writer func called from netlink -- rtnl_sem hold*/
106
107static void rtmsg_rule(int, struct fib_rule *);
104 108
105int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) 109int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
106{ 110{
107 struct rtattr **rta = arg; 111 struct rtattr **rta = arg;
108 struct rtmsg *rtm = NLMSG_DATA(nlh); 112 struct rtmsg *rtm = NLMSG_DATA(nlh);
109 struct fib_rule *r, **rp; 113 struct fib_rule *r;
114 struct hlist_node *node;
110 int err = -ESRCH; 115 int err = -ESRCH;
111 116
112 for (rp=&fib_rules; (r=*rp) != NULL; rp=&r->r_next) { 117 hlist_for_each_entry(r, node, &fib_rules, hlist) {
113 if ((!rta[RTA_SRC-1] || memcmp(RTA_DATA(rta[RTA_SRC-1]), &r->r_src, 4) == 0) && 118 if ((!rta[RTA_SRC-1] || memcmp(RTA_DATA(rta[RTA_SRC-1]), &r->r_src, 4) == 0) &&
114 rtm->rtm_src_len == r->r_src_len && 119 rtm->rtm_src_len == r->r_src_len &&
115 rtm->rtm_dst_len == r->r_dst_len && 120 rtm->rtm_dst_len == r->r_dst_len &&
@@ -126,10 +131,9 @@ int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
126 if (r == &local_rule) 131 if (r == &local_rule)
127 break; 132 break;
128 133
129 write_lock_bh(&fib_rules_lock); 134 hlist_del_rcu(&r->hlist);
130 *rp = r->r_next;
131 r->r_dead = 1; 135 r->r_dead = 1;
132 write_unlock_bh(&fib_rules_lock); 136 rtmsg_rule(RTM_DELRULE, r);
133 fib_rule_put(r); 137 fib_rule_put(r);
134 err = 0; 138 err = 0;
135 break; 139 break;
@@ -150,21 +154,30 @@ static struct fib_table *fib_empty_table(void)
150 return NULL; 154 return NULL;
151} 155}
152 156
157static inline void fib_rule_put_rcu(struct rcu_head *head)
158{
159 struct fib_rule *r = container_of(head, struct fib_rule, rcu);
160 kfree(r);
161}
162
153void fib_rule_put(struct fib_rule *r) 163void fib_rule_put(struct fib_rule *r)
154{ 164{
155 if (atomic_dec_and_test(&r->r_clntref)) { 165 if (atomic_dec_and_test(&r->r_clntref)) {
156 if (r->r_dead) 166 if (r->r_dead)
157 kfree(r); 167 call_rcu(&r->rcu, fib_rule_put_rcu);
158 else 168 else
159 printk("Freeing alive rule %p\n", r); 169 printk("Freeing alive rule %p\n", r);
160 } 170 }
161} 171}
162 172
173/* writer func called from netlink -- rtnl_sem hold*/
174
163int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) 175int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
164{ 176{
165 struct rtattr **rta = arg; 177 struct rtattr **rta = arg;
166 struct rtmsg *rtm = NLMSG_DATA(nlh); 178 struct rtmsg *rtm = NLMSG_DATA(nlh);
167 struct fib_rule *r, *new_r, **rp; 179 struct fib_rule *r, *new_r, *last = NULL;
180 struct hlist_node *node = NULL;
168 unsigned char table_id; 181 unsigned char table_id;
169 182
170 if (rtm->rtm_src_len > 32 || rtm->rtm_dst_len > 32 || 183 if (rtm->rtm_src_len > 32 || rtm->rtm_dst_len > 32 ||
@@ -188,6 +201,7 @@ int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
188 if (!new_r) 201 if (!new_r)
189 return -ENOMEM; 202 return -ENOMEM;
190 memset(new_r, 0, sizeof(*new_r)); 203 memset(new_r, 0, sizeof(*new_r));
204
191 if (rta[RTA_SRC-1]) 205 if (rta[RTA_SRC-1])
192 memcpy(&new_r->r_src, RTA_DATA(rta[RTA_SRC-1]), 4); 206 memcpy(&new_r->r_src, RTA_DATA(rta[RTA_SRC-1]), 4);
193 if (rta[RTA_DST-1]) 207 if (rta[RTA_DST-1])
@@ -220,28 +234,29 @@ int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
220 if (rta[RTA_FLOW-1]) 234 if (rta[RTA_FLOW-1])
221 memcpy(&new_r->r_tclassid, RTA_DATA(rta[RTA_FLOW-1]), 4); 235 memcpy(&new_r->r_tclassid, RTA_DATA(rta[RTA_FLOW-1]), 4);
222#endif 236#endif
237 r = container_of(fib_rules.first, struct fib_rule, hlist);
223 238
224 rp = &fib_rules;
225 if (!new_r->r_preference) { 239 if (!new_r->r_preference) {
226 r = fib_rules; 240 if (r && r->hlist.next != NULL) {
227 if (r && (r = r->r_next) != NULL) { 241 r = container_of(r->hlist.next, struct fib_rule, hlist);
228 rp = &fib_rules->r_next;
229 if (r->r_preference) 242 if (r->r_preference)
230 new_r->r_preference = r->r_preference - 1; 243 new_r->r_preference = r->r_preference - 1;
231 } 244 }
232 } 245 }
233 246
234 while ( (r = *rp) != NULL ) { 247 hlist_for_each_entry(r, node, &fib_rules, hlist) {
235 if (r->r_preference > new_r->r_preference) 248 if (r->r_preference > new_r->r_preference)
236 break; 249 break;
237 rp = &r->r_next; 250 last = r;
238 } 251 }
239
240 new_r->r_next = r;
241 atomic_inc(&new_r->r_clntref); 252 atomic_inc(&new_r->r_clntref);
242 write_lock_bh(&fib_rules_lock); 253
243 *rp = new_r; 254 if (last)
244 write_unlock_bh(&fib_rules_lock); 255 hlist_add_after_rcu(&last->hlist, &new_r->hlist);
256 else
257 hlist_add_before_rcu(&new_r->hlist, &r->hlist);
258
259 rtmsg_rule(RTM_NEWRULE, new_r);
245 return 0; 260 return 0;
246} 261}
247 262
@@ -254,30 +269,30 @@ u32 fib_rules_tclass(struct fib_result *res)
254} 269}
255#endif 270#endif
256 271
272/* callers should hold rtnl semaphore */
257 273
258static void fib_rules_detach(struct net_device *dev) 274static void fib_rules_detach(struct net_device *dev)
259{ 275{
276 struct hlist_node *node;
260 struct fib_rule *r; 277 struct fib_rule *r;
261 278
262 for (r=fib_rules; r; r=r->r_next) { 279 hlist_for_each_entry(r, node, &fib_rules, hlist) {
263 if (r->r_ifindex == dev->ifindex) { 280 if (r->r_ifindex == dev->ifindex)
264 write_lock_bh(&fib_rules_lock);
265 r->r_ifindex = -1; 281 r->r_ifindex = -1;
266 write_unlock_bh(&fib_rules_lock); 282
267 }
268 } 283 }
269} 284}
270 285
286/* callers should hold rtnl semaphore */
287
271static void fib_rules_attach(struct net_device *dev) 288static void fib_rules_attach(struct net_device *dev)
272{ 289{
290 struct hlist_node *node;
273 struct fib_rule *r; 291 struct fib_rule *r;
274 292
275 for (r=fib_rules; r; r=r->r_next) { 293 hlist_for_each_entry(r, node, &fib_rules, hlist) {
276 if (r->r_ifindex == -1 && strcmp(dev->name, r->r_ifname) == 0) { 294 if (r->r_ifindex == -1 && strcmp(dev->name, r->r_ifname) == 0)
277 write_lock_bh(&fib_rules_lock);
278 r->r_ifindex = dev->ifindex; 295 r->r_ifindex = dev->ifindex;
279 write_unlock_bh(&fib_rules_lock);
280 }
281 } 296 }
282} 297}
283 298
@@ -286,14 +301,17 @@ int fib_lookup(const struct flowi *flp, struct fib_result *res)
286 int err; 301 int err;
287 struct fib_rule *r, *policy; 302 struct fib_rule *r, *policy;
288 struct fib_table *tb; 303 struct fib_table *tb;
304 struct hlist_node *node;
289 305
290 u32 daddr = flp->fl4_dst; 306 u32 daddr = flp->fl4_dst;
291 u32 saddr = flp->fl4_src; 307 u32 saddr = flp->fl4_src;
292 308
293FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ", 309FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ",
294 NIPQUAD(flp->fl4_dst), NIPQUAD(flp->fl4_src)); 310 NIPQUAD(flp->fl4_dst), NIPQUAD(flp->fl4_src));
295 read_lock(&fib_rules_lock); 311
296 for (r = fib_rules; r; r=r->r_next) { 312 rcu_read_lock();
313
314 hlist_for_each_entry_rcu(r, node, &fib_rules, hlist) {
297 if (((saddr^r->r_src) & r->r_srcmask) || 315 if (((saddr^r->r_src) & r->r_srcmask) ||
298 ((daddr^r->r_dst) & r->r_dstmask) || 316 ((daddr^r->r_dst) & r->r_dstmask) ||
299 (r->r_tos && r->r_tos != flp->fl4_tos) || 317 (r->r_tos && r->r_tos != flp->fl4_tos) ||
@@ -309,14 +327,14 @@ FRprintk("tb %d r %d ", r->r_table, r->r_action);
309 policy = r; 327 policy = r;
310 break; 328 break;
311 case RTN_UNREACHABLE: 329 case RTN_UNREACHABLE:
312 read_unlock(&fib_rules_lock); 330 rcu_read_unlock();
313 return -ENETUNREACH; 331 return -ENETUNREACH;
314 default: 332 default:
315 case RTN_BLACKHOLE: 333 case RTN_BLACKHOLE:
316 read_unlock(&fib_rules_lock); 334 rcu_read_unlock();
317 return -EINVAL; 335 return -EINVAL;
318 case RTN_PROHIBIT: 336 case RTN_PROHIBIT:
319 read_unlock(&fib_rules_lock); 337 rcu_read_unlock();
320 return -EACCES; 338 return -EACCES;
321 } 339 }
322 340
@@ -327,16 +345,16 @@ FRprintk("tb %d r %d ", r->r_table, r->r_action);
327 res->r = policy; 345 res->r = policy;
328 if (policy) 346 if (policy)
329 atomic_inc(&policy->r_clntref); 347 atomic_inc(&policy->r_clntref);
330 read_unlock(&fib_rules_lock); 348 rcu_read_unlock();
331 return 0; 349 return 0;
332 } 350 }
333 if (err < 0 && err != -EAGAIN) { 351 if (err < 0 && err != -EAGAIN) {
334 read_unlock(&fib_rules_lock); 352 rcu_read_unlock();
335 return err; 353 return err;
336 } 354 }
337 } 355 }
338FRprintk("FAILURE\n"); 356FRprintk("FAILURE\n");
339 read_unlock(&fib_rules_lock); 357 rcu_read_unlock();
340 return -ENETUNREACH; 358 return -ENETUNREACH;
341} 359}
342 360
@@ -368,14 +386,14 @@ static struct notifier_block fib_rules_notifier = {
368 386
369static __inline__ int inet_fill_rule(struct sk_buff *skb, 387static __inline__ int inet_fill_rule(struct sk_buff *skb,
370 struct fib_rule *r, 388 struct fib_rule *r,
371 struct netlink_callback *cb, 389 u32 pid, u32 seq, int event,
372 unsigned int flags) 390 unsigned int flags)
373{ 391{
374 struct rtmsg *rtm; 392 struct rtmsg *rtm;
375 struct nlmsghdr *nlh; 393 struct nlmsghdr *nlh;
376 unsigned char *b = skb->tail; 394 unsigned char *b = skb->tail;
377 395
378 nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWRULE, sizeof(*rtm), flags); 396 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags);
379 rtm = NLMSG_DATA(nlh); 397 rtm = NLMSG_DATA(nlh);
380 rtm->rtm_family = AF_INET; 398 rtm->rtm_family = AF_INET;
381 rtm->rtm_dst_len = r->r_dst_len; 399 rtm->rtm_dst_len = r->r_dst_len;
@@ -414,20 +432,42 @@ rtattr_failure:
414 return -1; 432 return -1;
415} 433}
416 434
435/* callers should hold rtnl semaphore */
436
437static void rtmsg_rule(int event, struct fib_rule *r)
438{
439 int size = NLMSG_SPACE(sizeof(struct rtmsg) + 128);
440 struct sk_buff *skb = alloc_skb(size, GFP_KERNEL);
441
442 if (!skb)
443 netlink_set_err(rtnl, 0, RTNLGRP_IPV4_RULE, ENOBUFS);
444 else if (inet_fill_rule(skb, r, 0, 0, event, 0) < 0) {
445 kfree_skb(skb);
446 netlink_set_err(rtnl, 0, RTNLGRP_IPV4_RULE, EINVAL);
447 } else {
448 netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV4_RULE, GFP_KERNEL);
449 }
450}
451
417int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) 452int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
418{ 453{
419 int idx; 454 int idx = 0;
420 int s_idx = cb->args[0]; 455 int s_idx = cb->args[0];
421 struct fib_rule *r; 456 struct fib_rule *r;
457 struct hlist_node *node;
458
459 rcu_read_lock();
460 hlist_for_each_entry(r, node, &fib_rules, hlist) {
422 461
423 read_lock(&fib_rules_lock);
424 for (r=fib_rules, idx=0; r; r = r->r_next, idx++) {
425 if (idx < s_idx) 462 if (idx < s_idx)
426 continue; 463 continue;
427 if (inet_fill_rule(skb, r, cb, NLM_F_MULTI) < 0) 464 if (inet_fill_rule(skb, r, NETLINK_CB(cb->skb).pid,
465 cb->nlh->nlmsg_seq,
466 RTM_NEWRULE, NLM_F_MULTI) < 0)
428 break; 467 break;
468 idx++;
429 } 469 }
430 read_unlock(&fib_rules_lock); 470 rcu_read_unlock();
431 cb->args[0] = idx; 471 cb->args[0] = idx;
432 472
433 return skb->len; 473 return skb->len;
@@ -435,5 +475,9 @@ int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
435 475
436void __init fib_rules_init(void) 476void __init fib_rules_init(void)
437{ 477{
478 INIT_HLIST_HEAD(&fib_rules);
479 hlist_add_head(&local_rule.hlist, &fib_rules);
480 hlist_add_after(&local_rule.hlist, &main_rule.hlist);
481 hlist_add_after(&main_rule.hlist, &default_rule.hlist);
438 register_netdevice_notifier(&fib_rules_notifier); 482 register_netdevice_notifier(&fib_rules_notifier);
439} 483}
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index e320b32373e5..ccd3efc6a173 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -50,7 +50,7 @@
50 * Patrick McHardy <kaber@trash.net> 50 * Patrick McHardy <kaber@trash.net>
51 */ 51 */
52 52
53#define VERSION "0.404" 53#define VERSION "0.406"
54 54
55#include <linux/config.h> 55#include <linux/config.h>
56#include <asm/uaccess.h> 56#include <asm/uaccess.h>
@@ -84,7 +84,7 @@
84#include "fib_lookup.h" 84#include "fib_lookup.h"
85 85
86#undef CONFIG_IP_FIB_TRIE_STATS 86#undef CONFIG_IP_FIB_TRIE_STATS
87#define MAX_CHILDS 16384 87#define MAX_STAT_DEPTH 32
88 88
89#define KEYLENGTH (8*sizeof(t_key)) 89#define KEYLENGTH (8*sizeof(t_key))
90#define MASK_PFX(k, l) (((l)==0)?0:(k >> (KEYLENGTH-l)) << (KEYLENGTH-l)) 90#define MASK_PFX(k, l) (((l)==0)?0:(k >> (KEYLENGTH-l)) << (KEYLENGTH-l))
@@ -154,7 +154,7 @@ struct trie_stat {
154 unsigned int tnodes; 154 unsigned int tnodes;
155 unsigned int leaves; 155 unsigned int leaves;
156 unsigned int nullpointers; 156 unsigned int nullpointers;
157 unsigned int nodesizes[MAX_CHILDS]; 157 unsigned int nodesizes[MAX_STAT_DEPTH];
158}; 158};
159 159
160struct trie { 160struct trie {
@@ -2040,7 +2040,15 @@ rescan:
2040static struct node *fib_trie_get_first(struct fib_trie_iter *iter, 2040static struct node *fib_trie_get_first(struct fib_trie_iter *iter,
2041 struct trie *t) 2041 struct trie *t)
2042{ 2042{
2043 struct node *n = rcu_dereference(t->trie); 2043 struct node *n ;
2044
2045 if(!t)
2046 return NULL;
2047
2048 n = rcu_dereference(t->trie);
2049
2050 if(!iter)
2051 return NULL;
2044 2052
2045 if (n && IS_TNODE(n)) { 2053 if (n && IS_TNODE(n)) {
2046 iter->tnode = (struct tnode *) n; 2054 iter->tnode = (struct tnode *) n;
@@ -2072,7 +2080,9 @@ static void trie_collect_stats(struct trie *t, struct trie_stat *s)
2072 int i; 2080 int i;
2073 2081
2074 s->tnodes++; 2082 s->tnodes++;
2075 s->nodesizes[tn->bits]++; 2083 if(tn->bits < MAX_STAT_DEPTH)
2084 s->nodesizes[tn->bits]++;
2085
2076 for (i = 0; i < (1<<tn->bits); i++) 2086 for (i = 0; i < (1<<tn->bits); i++)
2077 if (!tn->child[i]) 2087 if (!tn->child[i])
2078 s->nullpointers++; 2088 s->nullpointers++;
@@ -2102,8 +2112,8 @@ static void trie_show_stats(struct seq_file *seq, struct trie_stat *stat)
2102 seq_printf(seq, "\tInternal nodes: %d\n\t", stat->tnodes); 2112 seq_printf(seq, "\tInternal nodes: %d\n\t", stat->tnodes);
2103 bytes += sizeof(struct tnode) * stat->tnodes; 2113 bytes += sizeof(struct tnode) * stat->tnodes;
2104 2114
2105 max = MAX_CHILDS-1; 2115 max = MAX_STAT_DEPTH;
2106 while (max >= 0 && stat->nodesizes[max] == 0) 2116 while (max > 0 && stat->nodesizes[max-1] == 0)
2107 max--; 2117 max--;
2108 2118
2109 pointers = 0; 2119 pointers = 0;
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 64ce52bf0485..d512239a1473 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -1382,7 +1382,7 @@ static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr)
1382 dev = ip_dev_find(imr->imr_address.s_addr); 1382 dev = ip_dev_find(imr->imr_address.s_addr);
1383 if (!dev) 1383 if (!dev)
1384 return NULL; 1384 return NULL;
1385 __dev_put(dev); 1385 dev_put(dev);
1386 } 1386 }
1387 1387
1388 if (!dev && !ip_route_output_key(&rt, &fl)) { 1388 if (!dev && !ip_route_output_key(&rt, &fl)) {
@@ -1730,7 +1730,7 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
1730 if (!MULTICAST(addr)) 1730 if (!MULTICAST(addr))
1731 return -EINVAL; 1731 return -EINVAL;
1732 1732
1733 rtnl_shlock(); 1733 rtnl_lock();
1734 1734
1735 in_dev = ip_mc_find_dev(imr); 1735 in_dev = ip_mc_find_dev(imr);
1736 1736
@@ -1763,7 +1763,7 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
1763 ip_mc_inc_group(in_dev, addr); 1763 ip_mc_inc_group(in_dev, addr);
1764 err = 0; 1764 err = 0;
1765done: 1765done:
1766 rtnl_shunlock(); 1766 rtnl_unlock();
1767 return err; 1767 return err;
1768} 1768}
1769 1769
@@ -1837,7 +1837,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
1837 if (!MULTICAST(addr)) 1837 if (!MULTICAST(addr))
1838 return -EINVAL; 1838 return -EINVAL;
1839 1839
1840 rtnl_shlock(); 1840 rtnl_lock();
1841 1841
1842 imr.imr_multiaddr.s_addr = mreqs->imr_multiaddr; 1842 imr.imr_multiaddr.s_addr = mreqs->imr_multiaddr;
1843 imr.imr_address.s_addr = mreqs->imr_interface; 1843 imr.imr_address.s_addr = mreqs->imr_interface;
@@ -1947,7 +1947,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
1947 ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 1, 1947 ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 1,
1948 &mreqs->imr_sourceaddr, 1); 1948 &mreqs->imr_sourceaddr, 1);
1949done: 1949done:
1950 rtnl_shunlock(); 1950 rtnl_unlock();
1951 if (leavegroup) 1951 if (leavegroup)
1952 return ip_mc_leave_group(sk, &imr); 1952 return ip_mc_leave_group(sk, &imr);
1953 return err; 1953 return err;
@@ -1970,7 +1970,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
1970 msf->imsf_fmode != MCAST_EXCLUDE) 1970 msf->imsf_fmode != MCAST_EXCLUDE)
1971 return -EINVAL; 1971 return -EINVAL;
1972 1972
1973 rtnl_shlock(); 1973 rtnl_lock();
1974 1974
1975 imr.imr_multiaddr.s_addr = msf->imsf_multiaddr; 1975 imr.imr_multiaddr.s_addr = msf->imsf_multiaddr;
1976 imr.imr_address.s_addr = msf->imsf_interface; 1976 imr.imr_address.s_addr = msf->imsf_interface;
@@ -2030,7 +2030,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
2030 pmc->sfmode = msf->imsf_fmode; 2030 pmc->sfmode = msf->imsf_fmode;
2031 err = 0; 2031 err = 0;
2032done: 2032done:
2033 rtnl_shunlock(); 2033 rtnl_unlock();
2034 if (leavegroup) 2034 if (leavegroup)
2035 err = ip_mc_leave_group(sk, &imr); 2035 err = ip_mc_leave_group(sk, &imr);
2036 return err; 2036 return err;
@@ -2050,7 +2050,7 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
2050 if (!MULTICAST(addr)) 2050 if (!MULTICAST(addr))
2051 return -EINVAL; 2051 return -EINVAL;
2052 2052
2053 rtnl_shlock(); 2053 rtnl_lock();
2054 2054
2055 imr.imr_multiaddr.s_addr = msf->imsf_multiaddr; 2055 imr.imr_multiaddr.s_addr = msf->imsf_multiaddr;
2056 imr.imr_address.s_addr = msf->imsf_interface; 2056 imr.imr_address.s_addr = msf->imsf_interface;
@@ -2072,7 +2072,7 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
2072 goto done; 2072 goto done;
2073 msf->imsf_fmode = pmc->sfmode; 2073 msf->imsf_fmode = pmc->sfmode;
2074 psl = pmc->sflist; 2074 psl = pmc->sflist;
2075 rtnl_shunlock(); 2075 rtnl_unlock();
2076 if (!psl) { 2076 if (!psl) {
2077 len = 0; 2077 len = 0;
2078 count = 0; 2078 count = 0;
@@ -2091,7 +2091,7 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
2091 return -EFAULT; 2091 return -EFAULT;
2092 return 0; 2092 return 0;
2093done: 2093done:
2094 rtnl_shunlock(); 2094 rtnl_unlock();
2095 return err; 2095 return err;
2096} 2096}
2097 2097
@@ -2112,7 +2112,7 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
2112 if (!MULTICAST(addr)) 2112 if (!MULTICAST(addr))
2113 return -EINVAL; 2113 return -EINVAL;
2114 2114
2115 rtnl_shlock(); 2115 rtnl_lock();
2116 2116
2117 err = -EADDRNOTAVAIL; 2117 err = -EADDRNOTAVAIL;
2118 2118
@@ -2125,7 +2125,7 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
2125 goto done; 2125 goto done;
2126 gsf->gf_fmode = pmc->sfmode; 2126 gsf->gf_fmode = pmc->sfmode;
2127 psl = pmc->sflist; 2127 psl = pmc->sflist;
2128 rtnl_shunlock(); 2128 rtnl_unlock();
2129 count = psl ? psl->sl_count : 0; 2129 count = psl ? psl->sl_count : 0;
2130 copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc; 2130 copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc;
2131 gsf->gf_numsrc = count; 2131 gsf->gf_numsrc = count;
@@ -2146,7 +2146,7 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
2146 } 2146 }
2147 return 0; 2147 return 0;
2148done: 2148done:
2149 rtnl_shunlock(); 2149 rtnl_unlock();
2150 return err; 2150 return err;
2151} 2151}
2152 2152
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index ae20281d8deb..9a01bb81f8bf 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -648,3 +648,52 @@ void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr)
648} 648}
649 649
650EXPORT_SYMBOL_GPL(inet_csk_addr2sockaddr); 650EXPORT_SYMBOL_GPL(inet_csk_addr2sockaddr);
651
652int inet_csk_ctl_sock_create(struct socket **sock, unsigned short family,
653 unsigned short type, unsigned char protocol)
654{
655 int rc = sock_create_kern(family, type, protocol, sock);
656
657 if (rc == 0) {
658 (*sock)->sk->sk_allocation = GFP_ATOMIC;
659 inet_sk((*sock)->sk)->uc_ttl = -1;
660 /*
661 * Unhash it so that IP input processing does not even see it,
662 * we do not wish this socket to see incoming packets.
663 */
664 (*sock)->sk->sk_prot->unhash((*sock)->sk);
665 }
666 return rc;
667}
668
669EXPORT_SYMBOL_GPL(inet_csk_ctl_sock_create);
670
671#ifdef CONFIG_COMPAT
672int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname,
673 char __user *optval, int __user *optlen)
674{
675 const struct inet_connection_sock *icsk = inet_csk(sk);
676
677 if (icsk->icsk_af_ops->compat_getsockopt != NULL)
678 return icsk->icsk_af_ops->compat_getsockopt(sk, level, optname,
679 optval, optlen);
680 return icsk->icsk_af_ops->getsockopt(sk, level, optname,
681 optval, optlen);
682}
683
684EXPORT_SYMBOL_GPL(inet_csk_compat_getsockopt);
685
686int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname,
687 char __user *optval, int optlen)
688{
689 const struct inet_connection_sock *icsk = inet_csk(sk);
690
691 if (icsk->icsk_af_ops->compat_setsockopt != NULL)
692 return icsk->icsk_af_ops->compat_setsockopt(sk, level, optname,
693 optval, optlen);
694 return icsk->icsk_af_ops->setsockopt(sk, level, optname,
695 optval, optlen);
696}
697
698EXPORT_SYMBOL_GPL(inet_csk_compat_setsockopt);
699#endif
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 8ee4d016740d..f75ff1d96551 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1249,11 +1249,7 @@ int ip_push_pending_frames(struct sock *sk)
1249 iph->tos = inet->tos; 1249 iph->tos = inet->tos;
1250 iph->tot_len = htons(skb->len); 1250 iph->tot_len = htons(skb->len);
1251 iph->frag_off = df; 1251 iph->frag_off = df;
1252 if (!df) { 1252 ip_select_ident(iph, &rt->u.dst, sk);
1253 __ip_select_ident(iph, &rt->u.dst, 0);
1254 } else {
1255 iph->id = htons(inet->id++);
1256 }
1257 iph->ttl = ttl; 1253 iph->ttl = ttl;
1258 iph->protocol = sk->sk_protocol; 1254 iph->protocol = sk->sk_protocol;
1259 iph->saddr = rt->rt_src; 1255 iph->saddr = rt->rt_src;
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 2bf8d782f678..12e0bf19f24a 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -50,6 +50,7 @@
50#define IP_CMSG_TOS 4 50#define IP_CMSG_TOS 4
51#define IP_CMSG_RECVOPTS 8 51#define IP_CMSG_RECVOPTS 8
52#define IP_CMSG_RETOPTS 16 52#define IP_CMSG_RETOPTS 16
53#define IP_CMSG_PASSSEC 32
53 54
54/* 55/*
55 * SOL_IP control messages. 56 * SOL_IP control messages.
@@ -109,6 +110,19 @@ static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb)
109 put_cmsg(msg, SOL_IP, IP_RETOPTS, opt->optlen, opt->__data); 110 put_cmsg(msg, SOL_IP, IP_RETOPTS, opt->optlen, opt->__data);
110} 111}
111 112
113static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
114{
115 char *secdata;
116 u32 seclen;
117 int err;
118
119 err = security_socket_getpeersec_dgram(skb, &secdata, &seclen);
120 if (err)
121 return;
122
123 put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata);
124}
125
112 126
113void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) 127void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
114{ 128{
@@ -138,6 +152,11 @@ void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
138 152
139 if (flags & 1) 153 if (flags & 1)
140 ip_cmsg_recv_retopts(msg, skb); 154 ip_cmsg_recv_retopts(msg, skb);
155 if ((flags>>=1) == 0)
156 return;
157
158 if (flags & 1)
159 ip_cmsg_recv_security(msg, skb);
141} 160}
142 161
143int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc) 162int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc)
@@ -380,20 +399,19 @@ out:
380 * an IP socket. 399 * an IP socket.
381 */ 400 */
382 401
383int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) 402static int do_ip_setsockopt(struct sock *sk, int level,
403 int optname, char __user *optval, int optlen)
384{ 404{
385 struct inet_sock *inet = inet_sk(sk); 405 struct inet_sock *inet = inet_sk(sk);
386 int val=0,err; 406 int val=0,err;
387 407
388 if (level != SOL_IP)
389 return -ENOPROTOOPT;
390
391 if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) | 408 if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) |
392 (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) | 409 (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) |
393 (1<<IP_RETOPTS) | (1<<IP_TOS) | 410 (1<<IP_RETOPTS) | (1<<IP_TOS) |
394 (1<<IP_TTL) | (1<<IP_HDRINCL) | 411 (1<<IP_TTL) | (1<<IP_HDRINCL) |
395 (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) | 412 (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) |
396 (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND))) || 413 (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) |
414 (1<<IP_PASSSEC))) ||
397 optname == IP_MULTICAST_TTL || 415 optname == IP_MULTICAST_TTL ||
398 optname == IP_MULTICAST_LOOP) { 416 optname == IP_MULTICAST_LOOP) {
399 if (optlen >= sizeof(int)) { 417 if (optlen >= sizeof(int)) {
@@ -478,6 +496,12 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
478 else 496 else
479 inet->cmsg_flags &= ~IP_CMSG_RETOPTS; 497 inet->cmsg_flags &= ~IP_CMSG_RETOPTS;
480 break; 498 break;
499 case IP_PASSSEC:
500 if (val)
501 inet->cmsg_flags |= IP_CMSG_PASSSEC;
502 else
503 inet->cmsg_flags &= ~IP_CMSG_PASSSEC;
504 break;
481 case IP_TOS: /* This sets both TOS and Precedence */ 505 case IP_TOS: /* This sets both TOS and Precedence */
482 if (sk->sk_type == SOCK_STREAM) { 506 if (sk->sk_type == SOCK_STREAM) {
483 val &= ~3; 507 val &= ~3;
@@ -849,12 +873,7 @@ mc_msf_out:
849 break; 873 break;
850 874
851 default: 875 default:
852#ifdef CONFIG_NETFILTER
853 err = nf_setsockopt(sk, PF_INET, optname, optval,
854 optlen);
855#else
856 err = -ENOPROTOOPT; 876 err = -ENOPROTOOPT;
857#endif
858 break; 877 break;
859 } 878 }
860 release_sock(sk); 879 release_sock(sk);
@@ -865,12 +884,68 @@ e_inval:
865 return -EINVAL; 884 return -EINVAL;
866} 885}
867 886
887int ip_setsockopt(struct sock *sk, int level,
888 int optname, char __user *optval, int optlen)
889{
890 int err;
891
892 if (level != SOL_IP)
893 return -ENOPROTOOPT;
894
895 err = do_ip_setsockopt(sk, level, optname, optval, optlen);
896#ifdef CONFIG_NETFILTER
897 /* we need to exclude all possible ENOPROTOOPTs except default case */
898 if (err == -ENOPROTOOPT && optname != IP_HDRINCL &&
899 optname != IP_IPSEC_POLICY && optname != IP_XFRM_POLICY
900#ifdef CONFIG_IP_MROUTE
901 && (optname < MRT_BASE || optname > (MRT_BASE + 10))
902#endif
903 ) {
904 lock_sock(sk);
905 err = nf_setsockopt(sk, PF_INET, optname, optval, optlen);
906 release_sock(sk);
907 }
908#endif
909 return err;
910}
911
912#ifdef CONFIG_COMPAT
913int compat_ip_setsockopt(struct sock *sk, int level, int optname,
914 char __user *optval, int optlen)
915{
916 int err;
917
918 if (level != SOL_IP)
919 return -ENOPROTOOPT;
920
921 err = do_ip_setsockopt(sk, level, optname, optval, optlen);
922#ifdef CONFIG_NETFILTER
923 /* we need to exclude all possible ENOPROTOOPTs except default case */
924 if (err == -ENOPROTOOPT && optname != IP_HDRINCL &&
925 optname != IP_IPSEC_POLICY && optname != IP_XFRM_POLICY
926#ifdef CONFIG_IP_MROUTE
927 && (optname < MRT_BASE || optname > (MRT_BASE + 10))
928#endif
929 ) {
930 lock_sock(sk);
931 err = compat_nf_setsockopt(sk, PF_INET, optname,
932 optval, optlen);
933 release_sock(sk);
934 }
935#endif
936 return err;
937}
938
939EXPORT_SYMBOL(compat_ip_setsockopt);
940#endif
941
868/* 942/*
869 * Get the options. Note for future reference. The GET of IP options gets the 943 * Get the options. Note for future reference. The GET of IP options gets the
870 * _received_ ones. The set sets the _sent_ ones. 944 * _received_ ones. The set sets the _sent_ ones.
871 */ 945 */
872 946
873int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) 947static int do_ip_getsockopt(struct sock *sk, int level, int optname,
948 char __user *optval, int __user *optlen)
874{ 949{
875 struct inet_sock *inet = inet_sk(sk); 950 struct inet_sock *inet = inet_sk(sk);
876 int val; 951 int val;
@@ -932,6 +1007,9 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
932 case IP_RETOPTS: 1007 case IP_RETOPTS:
933 val = (inet->cmsg_flags & IP_CMSG_RETOPTS) != 0; 1008 val = (inet->cmsg_flags & IP_CMSG_RETOPTS) != 0;
934 break; 1009 break;
1010 case IP_PASSSEC:
1011 val = (inet->cmsg_flags & IP_CMSG_PASSSEC) != 0;
1012 break;
935 case IP_TOS: 1013 case IP_TOS:
936 val = inet->tos; 1014 val = inet->tos;
937 break; 1015 break;
@@ -1051,17 +1129,8 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
1051 val = inet->freebind; 1129 val = inet->freebind;
1052 break; 1130 break;
1053 default: 1131 default:
1054#ifdef CONFIG_NETFILTER
1055 val = nf_getsockopt(sk, PF_INET, optname, optval,
1056 &len);
1057 release_sock(sk);
1058 if (val >= 0)
1059 val = put_user(len, optlen);
1060 return val;
1061#else
1062 release_sock(sk); 1132 release_sock(sk);
1063 return -ENOPROTOOPT; 1133 return -ENOPROTOOPT;
1064#endif
1065 } 1134 }
1066 release_sock(sk); 1135 release_sock(sk);
1067 1136
@@ -1082,6 +1151,67 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
1082 return 0; 1151 return 0;
1083} 1152}
1084 1153
1154int ip_getsockopt(struct sock *sk, int level,
1155 int optname, char __user *optval, int __user *optlen)
1156{
1157 int err;
1158
1159 err = do_ip_getsockopt(sk, level, optname, optval, optlen);
1160#ifdef CONFIG_NETFILTER
1161 /* we need to exclude all possible ENOPROTOOPTs except default case */
1162 if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS
1163#ifdef CONFIG_IP_MROUTE
1164 && (optname < MRT_BASE || optname > MRT_BASE+10)
1165#endif
1166 ) {
1167 int len;
1168
1169 if(get_user(len,optlen))
1170 return -EFAULT;
1171
1172 lock_sock(sk);
1173 err = nf_getsockopt(sk, PF_INET, optname, optval,
1174 &len);
1175 release_sock(sk);
1176 if (err >= 0)
1177 err = put_user(len, optlen);
1178 return err;
1179 }
1180#endif
1181 return err;
1182}
1183
1184#ifdef CONFIG_COMPAT
1185int compat_ip_getsockopt(struct sock *sk, int level, int optname,
1186 char __user *optval, int __user *optlen)
1187{
1188 int err = do_ip_getsockopt(sk, level, optname, optval, optlen);
1189#ifdef CONFIG_NETFILTER
1190 /* we need to exclude all possible ENOPROTOOPTs except default case */
1191 if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS
1192#ifdef CONFIG_IP_MROUTE
1193 && (optname < MRT_BASE || optname > MRT_BASE+10)
1194#endif
1195 ) {
1196 int len;
1197
1198 if (get_user(len, optlen))
1199 return -EFAULT;
1200
1201 lock_sock(sk);
1202 err = compat_nf_getsockopt(sk, PF_INET, optname, optval, &len);
1203 release_sock(sk);
1204 if (err >= 0)
1205 err = put_user(len, optlen);
1206 return err;
1207 }
1208#endif
1209 return err;
1210}
1211
1212EXPORT_SYMBOL(compat_ip_getsockopt);
1213#endif
1214
1085EXPORT_SYMBOL(ip_cmsg_recv); 1215EXPORT_SYMBOL(ip_cmsg_recv);
1086 1216
1087EXPORT_SYMBOL(ip_getsockopt); 1217EXPORT_SYMBOL(ip_getsockopt);
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index d64e2ec8da7b..c95020f7c81e 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -24,6 +24,7 @@
24#include <linux/list.h> 24#include <linux/list.h>
25#include <linux/vmalloc.h> 25#include <linux/vmalloc.h>
26#include <linux/rtnetlink.h> 26#include <linux/rtnetlink.h>
27#include <linux/mutex.h>
27#include <net/ip.h> 28#include <net/ip.h>
28#include <net/xfrm.h> 29#include <net/xfrm.h>
29#include <net/icmp.h> 30#include <net/icmp.h>
@@ -36,7 +37,7 @@ struct ipcomp_tfms {
36 int users; 37 int users;
37}; 38};
38 39
39static DECLARE_MUTEX(ipcomp_resource_sem); 40static DEFINE_MUTEX(ipcomp_resource_mutex);
40static void **ipcomp_scratches; 41static void **ipcomp_scratches;
41static int ipcomp_scratch_users; 42static int ipcomp_scratch_users;
42static LIST_HEAD(ipcomp_tfms_list); 43static LIST_HEAD(ipcomp_tfms_list);
@@ -253,7 +254,7 @@ error:
253} 254}
254 255
255/* 256/*
256 * Must be protected by xfrm_cfg_sem. State and tunnel user references are 257 * Must be protected by xfrm_cfg_mutex. State and tunnel user references are
257 * always incremented on success. 258 * always incremented on success.
258 */ 259 */
259static int ipcomp_tunnel_attach(struct xfrm_state *x) 260static int ipcomp_tunnel_attach(struct xfrm_state *x)
@@ -411,9 +412,9 @@ static void ipcomp_destroy(struct xfrm_state *x)
411 if (!ipcd) 412 if (!ipcd)
412 return; 413 return;
413 xfrm_state_delete_tunnel(x); 414 xfrm_state_delete_tunnel(x);
414 down(&ipcomp_resource_sem); 415 mutex_lock(&ipcomp_resource_mutex);
415 ipcomp_free_data(ipcd); 416 ipcomp_free_data(ipcd);
416 up(&ipcomp_resource_sem); 417 mutex_unlock(&ipcomp_resource_mutex);
417 kfree(ipcd); 418 kfree(ipcd);
418} 419}
419 420
@@ -440,14 +441,14 @@ static int ipcomp_init_state(struct xfrm_state *x)
440 if (x->props.mode) 441 if (x->props.mode)
441 x->props.header_len += sizeof(struct iphdr); 442 x->props.header_len += sizeof(struct iphdr);
442 443
443 down(&ipcomp_resource_sem); 444 mutex_lock(&ipcomp_resource_mutex);
444 if (!ipcomp_alloc_scratches()) 445 if (!ipcomp_alloc_scratches())
445 goto error; 446 goto error;
446 447
447 ipcd->tfms = ipcomp_alloc_tfms(x->calg->alg_name); 448 ipcd->tfms = ipcomp_alloc_tfms(x->calg->alg_name);
448 if (!ipcd->tfms) 449 if (!ipcd->tfms)
449 goto error; 450 goto error;
450 up(&ipcomp_resource_sem); 451 mutex_unlock(&ipcomp_resource_mutex);
451 452
452 if (x->props.mode) { 453 if (x->props.mode) {
453 err = ipcomp_tunnel_attach(x); 454 err = ipcomp_tunnel_attach(x);
@@ -464,10 +465,10 @@ out:
464 return err; 465 return err;
465 466
466error_tunnel: 467error_tunnel:
467 down(&ipcomp_resource_sem); 468 mutex_lock(&ipcomp_resource_mutex);
468error: 469error:
469 ipcomp_free_data(ipcd); 470 ipcomp_free_data(ipcd);
470 up(&ipcomp_resource_sem); 471 mutex_unlock(&ipcomp_resource_mutex);
471 kfree(ipcd); 472 kfree(ipcd);
472 goto out; 473 goto out;
473} 474}
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index bb3613ec448c..cb8a92f18ef6 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -186,7 +186,7 @@ static int __init ic_open_devs(void)
186 unsigned short oflags; 186 unsigned short oflags;
187 187
188 last = &ic_first_dev; 188 last = &ic_first_dev;
189 rtnl_shlock(); 189 rtnl_lock();
190 190
191 /* bring loopback device up first */ 191 /* bring loopback device up first */
192 if (dev_change_flags(&loopback_dev, loopback_dev.flags | IFF_UP) < 0) 192 if (dev_change_flags(&loopback_dev, loopback_dev.flags | IFF_UP) < 0)
@@ -215,7 +215,7 @@ static int __init ic_open_devs(void)
215 continue; 215 continue;
216 } 216 }
217 if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) { 217 if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) {
218 rtnl_shunlock(); 218 rtnl_unlock();
219 return -1; 219 return -1;
220 } 220 }
221 d->dev = dev; 221 d->dev = dev;
@@ -232,7 +232,7 @@ static int __init ic_open_devs(void)
232 dev->name, able, d->xid)); 232 dev->name, able, d->xid));
233 } 233 }
234 } 234 }
235 rtnl_shunlock(); 235 rtnl_unlock();
236 236
237 *last = NULL; 237 *last = NULL;
238 238
@@ -251,7 +251,7 @@ static void __init ic_close_devs(void)
251 struct ic_device *d, *next; 251 struct ic_device *d, *next;
252 struct net_device *dev; 252 struct net_device *dev;
253 253
254 rtnl_shlock(); 254 rtnl_lock();
255 next = ic_first_dev; 255 next = ic_first_dev;
256 while ((d = next)) { 256 while ((d = next)) {
257 next = d->next; 257 next = d->next;
@@ -262,7 +262,7 @@ static void __init ic_close_devs(void)
262 } 262 }
263 kfree(d); 263 kfree(d);
264 } 264 }
265 rtnl_shunlock(); 265 rtnl_unlock();
266} 266}
267 267
268/* 268/*
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 5c94c222e3f3..717ab7d6d7b6 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -415,10 +415,10 @@ static int vif_add(struct vifctl *vifc, int mrtsock)
415 return -ENOBUFS; 415 return -ENOBUFS;
416 break; 416 break;
417 case 0: 417 case 0:
418 dev=ip_dev_find(vifc->vifc_lcl_addr.s_addr); 418 dev = ip_dev_find(vifc->vifc_lcl_addr.s_addr);
419 if (!dev) 419 if (!dev)
420 return -EADDRNOTAVAIL; 420 return -EADDRNOTAVAIL;
421 __dev_put(dev); 421 dev_put(dev);
422 break; 422 break;
423 default: 423 default:
424 return -EINVAL; 424 return -EINVAL;
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c
index 9b176a942ac5..e7752334d296 100644
--- a/net/ipv4/ipvs/ip_vs_app.c
+++ b/net/ipv4/ipvs/ip_vs_app.c
@@ -31,6 +31,7 @@
31#include <linux/stat.h> 31#include <linux/stat.h>
32#include <linux/proc_fs.h> 32#include <linux/proc_fs.h>
33#include <linux/seq_file.h> 33#include <linux/seq_file.h>
34#include <linux/mutex.h>
34 35
35#include <net/ip_vs.h> 36#include <net/ip_vs.h>
36 37
@@ -40,7 +41,7 @@ EXPORT_SYMBOL(register_ip_vs_app_inc);
40 41
41/* ipvs application list head */ 42/* ipvs application list head */
42static LIST_HEAD(ip_vs_app_list); 43static LIST_HEAD(ip_vs_app_list);
43static DECLARE_MUTEX(__ip_vs_app_mutex); 44static DEFINE_MUTEX(__ip_vs_app_mutex);
44 45
45 46
46/* 47/*
@@ -173,11 +174,11 @@ register_ip_vs_app_inc(struct ip_vs_app *app, __u16 proto, __u16 port)
173{ 174{
174 int result; 175 int result;
175 176
176 down(&__ip_vs_app_mutex); 177 mutex_lock(&__ip_vs_app_mutex);
177 178
178 result = ip_vs_app_inc_new(app, proto, port); 179 result = ip_vs_app_inc_new(app, proto, port);
179 180
180 up(&__ip_vs_app_mutex); 181 mutex_unlock(&__ip_vs_app_mutex);
181 182
182 return result; 183 return result;
183} 184}
@@ -191,11 +192,11 @@ int register_ip_vs_app(struct ip_vs_app *app)
191 /* increase the module use count */ 192 /* increase the module use count */
192 ip_vs_use_count_inc(); 193 ip_vs_use_count_inc();
193 194
194 down(&__ip_vs_app_mutex); 195 mutex_lock(&__ip_vs_app_mutex);
195 196
196 list_add(&app->a_list, &ip_vs_app_list); 197 list_add(&app->a_list, &ip_vs_app_list);
197 198
198 up(&__ip_vs_app_mutex); 199 mutex_unlock(&__ip_vs_app_mutex);
199 200
200 return 0; 201 return 0;
201} 202}
@@ -209,7 +210,7 @@ void unregister_ip_vs_app(struct ip_vs_app *app)
209{ 210{
210 struct ip_vs_app *inc, *nxt; 211 struct ip_vs_app *inc, *nxt;
211 212
212 down(&__ip_vs_app_mutex); 213 mutex_lock(&__ip_vs_app_mutex);
213 214
214 list_for_each_entry_safe(inc, nxt, &app->incs_list, a_list) { 215 list_for_each_entry_safe(inc, nxt, &app->incs_list, a_list) {
215 ip_vs_app_inc_release(inc); 216 ip_vs_app_inc_release(inc);
@@ -217,7 +218,7 @@ void unregister_ip_vs_app(struct ip_vs_app *app)
217 218
218 list_del(&app->a_list); 219 list_del(&app->a_list);
219 220
220 up(&__ip_vs_app_mutex); 221 mutex_unlock(&__ip_vs_app_mutex);
221 222
222 /* decrease the module use count */ 223 /* decrease the module use count */
223 ip_vs_use_count_dec(); 224 ip_vs_use_count_dec();
@@ -498,7 +499,7 @@ static struct ip_vs_app *ip_vs_app_idx(loff_t pos)
498 499
499static void *ip_vs_app_seq_start(struct seq_file *seq, loff_t *pos) 500static void *ip_vs_app_seq_start(struct seq_file *seq, loff_t *pos)
500{ 501{
501 down(&__ip_vs_app_mutex); 502 mutex_lock(&__ip_vs_app_mutex);
502 503
503 return *pos ? ip_vs_app_idx(*pos - 1) : SEQ_START_TOKEN; 504 return *pos ? ip_vs_app_idx(*pos - 1) : SEQ_START_TOKEN;
504} 505}
@@ -530,7 +531,7 @@ static void *ip_vs_app_seq_next(struct seq_file *seq, void *v, loff_t *pos)
530 531
531static void ip_vs_app_seq_stop(struct seq_file *seq, void *v) 532static void ip_vs_app_seq_stop(struct seq_file *seq, void *v)
532{ 533{
533 up(&__ip_vs_app_mutex); 534 mutex_unlock(&__ip_vs_app_mutex);
534} 535}
535 536
536static int ip_vs_app_seq_show(struct seq_file *seq, void *v) 537static int ip_vs_app_seq_show(struct seq_file *seq, void *v)
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index db783036e4d8..882b842c25d4 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -168,6 +168,26 @@ config IP_NF_PPTP
168 If you want to compile it as a module, say M here and read 168 If you want to compile it as a module, say M here and read
169 Documentation/modules.txt. If unsure, say `N'. 169 Documentation/modules.txt. If unsure, say `N'.
170 170
171config IP_NF_H323
172 tristate 'H.323 protocol support'
173 depends on IP_NF_CONNTRACK
174 help
175 H.323 is a VoIP signalling protocol from ITU-T. As one of the most
176 important VoIP protocols, it is widely used by voice hardware and
177 software including voice gateways, IP phones, Netmeeting, OpenPhone,
178 Gnomemeeting, etc.
179
180 With this module you can support H.323 on a connection tracking/NAT
181 firewall.
182
183 This module supports RAS, Fast-start, H.245 tunnelling, RTP/RTCP
184 and T.120 based data and applications including audio, video, FAX,
185 chat, whiteboard, file transfer, etc. For more information, please
186 see http://nath323.sourceforge.net/.
187
188 If you want to compile it as a module, say 'M' here and read
189 Documentation/modules.txt. If unsure, say 'N'.
190
171config IP_NF_QUEUE 191config IP_NF_QUEUE
172 tristate "IP Userspace queueing via NETLINK (OBSOLETE)" 192 tristate "IP Userspace queueing via NETLINK (OBSOLETE)"
173 help 193 help
@@ -303,16 +323,6 @@ config IP_NF_MATCH_HASHLIMIT
303 destination IP' or `500pps from any given source IP' with a single 323 destination IP' or `500pps from any given source IP' with a single
304 IPtables rule. 324 IPtables rule.
305 325
306config IP_NF_MATCH_POLICY
307 tristate "IPsec policy match support"
308 depends on IP_NF_IPTABLES && XFRM
309 help
310 Policy matching allows you to match packets based on the
311 IPsec policy that was used during decapsulation/will
312 be used during encapsulation.
313
314 To compile it as a module, choose M here. If unsure, say N.
315
316# `filter', generic and specific targets 326# `filter', generic and specific targets
317config IP_NF_FILTER 327config IP_NF_FILTER
318 tristate "Packet filtering" 328 tristate "Packet filtering"
@@ -494,6 +504,12 @@ config IP_NF_NAT_PPTP
494 default IP_NF_NAT if IP_NF_PPTP=y 504 default IP_NF_NAT if IP_NF_PPTP=y
495 default m if IP_NF_PPTP=m 505 default m if IP_NF_PPTP=m
496 506
507config IP_NF_NAT_H323
508 tristate
509 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
510 default IP_NF_NAT if IP_NF_H323=y
511 default m if IP_NF_H323=m
512
497# mangle + specific targets 513# mangle + specific targets
498config IP_NF_MANGLE 514config IP_NF_MANGLE
499 tristate "Packet mangling" 515 tristate "Packet mangling"
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index e5c5b3202f02..f2cd9a6c5b91 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -10,6 +10,9 @@ iptable_nat-objs := ip_nat_rule.o ip_nat_standalone.o
10ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o 10ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o
11ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o 11ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o
12 12
13ip_conntrack_h323-objs := ip_conntrack_helper_h323.o ip_conntrack_helper_h323_asn1.o
14ip_nat_h323-objs := ip_nat_helper_h323.o
15
13# connection tracking 16# connection tracking
14obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o 17obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
15obj-$(CONFIG_IP_NF_NAT) += ip_nat.o 18obj-$(CONFIG_IP_NF_NAT) += ip_nat.o
@@ -22,6 +25,7 @@ obj-$(CONFIG_IP_NF_CONNTRACK_NETLINK) += ip_conntrack_netlink.o
22obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o 25obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
23 26
24# connection tracking helpers 27# connection tracking helpers
28obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
25obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o 29obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o
26obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o 30obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
27obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o 31obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
@@ -30,6 +34,7 @@ obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
30obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o 34obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o
31 35
32# NAT helpers 36# NAT helpers
37obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
33obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o 38obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
34obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o 39obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
35obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o 40obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
@@ -57,7 +62,6 @@ obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o
57obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o 62obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o
58obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o 63obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
59obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o 64obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
60obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
61 65
62# targets 66# targets
63obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o 67obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 7d7ab94a7a2e..ff0c594a4198 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -22,7 +22,7 @@
22#include <linux/init.h> 22#include <linux/init.h>
23 23
24#include <asm/uaccess.h> 24#include <asm/uaccess.h>
25#include <asm/semaphore.h> 25#include <linux/mutex.h>
26 26
27#include <linux/netfilter/x_tables.h> 27#include <linux/netfilter/x_tables.h>
28#include <linux/netfilter_arp/arp_tables.h> 28#include <linux/netfilter_arp/arp_tables.h>
@@ -208,6 +208,7 @@ static unsigned int arpt_error(struct sk_buff **pskb,
208 const struct net_device *in, 208 const struct net_device *in,
209 const struct net_device *out, 209 const struct net_device *out,
210 unsigned int hooknum, 210 unsigned int hooknum,
211 const struct xt_target *target,
211 const void *targinfo, 212 const void *targinfo,
212 void *userinfo) 213 void *userinfo)
213{ 214{
@@ -300,6 +301,7 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
300 verdict = t->u.kernel.target->target(pskb, 301 verdict = t->u.kernel.target->target(pskb,
301 in, out, 302 in, out,
302 hook, 303 hook,
304 t->u.kernel.target,
303 t->data, 305 t->data,
304 userdata); 306 userdata);
305 307
@@ -480,26 +482,31 @@ static inline int check_entry(struct arpt_entry *e, const char *name, unsigned i
480 } 482 }
481 t->u.kernel.target = target; 483 t->u.kernel.target = target;
482 484
485 ret = xt_check_target(target, NF_ARP, t->u.target_size - sizeof(*t),
486 name, e->comefrom, 0, 0);
487 if (ret)
488 goto err;
489
483 if (t->u.kernel.target == &arpt_standard_target) { 490 if (t->u.kernel.target == &arpt_standard_target) {
484 if (!standard_check(t, size)) { 491 if (!standard_check(t, size)) {
485 ret = -EINVAL; 492 ret = -EINVAL;
486 goto out; 493 goto out;
487 } 494 }
488 } else if (t->u.kernel.target->checkentry 495 } else if (t->u.kernel.target->checkentry
489 && !t->u.kernel.target->checkentry(name, e, t->data, 496 && !t->u.kernel.target->checkentry(name, e, target, t->data,
490 t->u.target_size 497 t->u.target_size
491 - sizeof(*t), 498 - sizeof(*t),
492 e->comefrom)) { 499 e->comefrom)) {
493 module_put(t->u.kernel.target->me);
494 duprintf("arp_tables: check failed for `%s'.\n", 500 duprintf("arp_tables: check failed for `%s'.\n",
495 t->u.kernel.target->name); 501 t->u.kernel.target->name);
496 ret = -EINVAL; 502 ret = -EINVAL;
497 goto out; 503 goto err;
498 } 504 }
499 505
500 (*i)++; 506 (*i)++;
501 return 0; 507 return 0;
502 508err:
509 module_put(t->u.kernel.target->me);
503out: 510out:
504 return ret; 511 return ret;
505} 512}
@@ -555,7 +562,7 @@ static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i)
555 562
556 t = arpt_get_target(e); 563 t = arpt_get_target(e);
557 if (t->u.kernel.target->destroy) 564 if (t->u.kernel.target->destroy)
558 t->u.kernel.target->destroy(t->data, 565 t->u.kernel.target->destroy(t->u.kernel.target, t->data,
559 t->u.target_size - sizeof(*t)); 566 t->u.target_size - sizeof(*t));
560 module_put(t->u.kernel.target->me); 567 module_put(t->u.kernel.target->me);
561 return 0; 568 return 0;
@@ -1138,11 +1145,15 @@ void arpt_unregister_table(struct arpt_table *table)
1138/* The built-in targets: standard (NULL) and error. */ 1145/* The built-in targets: standard (NULL) and error. */
1139static struct arpt_target arpt_standard_target = { 1146static struct arpt_target arpt_standard_target = {
1140 .name = ARPT_STANDARD_TARGET, 1147 .name = ARPT_STANDARD_TARGET,
1148 .targetsize = sizeof(int),
1149 .family = NF_ARP,
1141}; 1150};
1142 1151
1143static struct arpt_target arpt_error_target = { 1152static struct arpt_target arpt_error_target = {
1144 .name = ARPT_ERROR_TARGET, 1153 .name = ARPT_ERROR_TARGET,
1145 .target = arpt_error, 1154 .target = arpt_error,
1155 .targetsize = ARPT_FUNCTION_MAXNAMELEN,
1156 .family = NF_ARP,
1146}; 1157};
1147 1158
1148static struct nf_sockopt_ops arpt_sockopts = { 1159static struct nf_sockopt_ops arpt_sockopts = {
@@ -1162,8 +1173,8 @@ static int __init init(void)
1162 xt_proto_init(NF_ARP); 1173 xt_proto_init(NF_ARP);
1163 1174
1164 /* Noone else will be downing sem now, so we won't sleep */ 1175 /* Noone else will be downing sem now, so we won't sleep */
1165 xt_register_target(NF_ARP, &arpt_standard_target); 1176 xt_register_target(&arpt_standard_target);
1166 xt_register_target(NF_ARP, &arpt_error_target); 1177 xt_register_target(&arpt_error_target);
1167 1178
1168 /* Register setsockopt */ 1179 /* Register setsockopt */
1169 ret = nf_register_sockopt(&arpt_sockopts); 1180 ret = nf_register_sockopt(&arpt_sockopts);
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
index c97650a16a5b..0f2a95350e26 100644
--- a/net/ipv4/netfilter/arpt_mangle.c
+++ b/net/ipv4/netfilter/arpt_mangle.c
@@ -8,9 +8,10 @@ MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
8MODULE_DESCRIPTION("arptables arp payload mangle target"); 8MODULE_DESCRIPTION("arptables arp payload mangle target");
9 9
10static unsigned int 10static unsigned int
11target(struct sk_buff **pskb, const struct net_device *in, 11target(struct sk_buff **pskb,
12 const struct net_device *out, unsigned int hooknum, const void *targinfo, 12 const struct net_device *in, const struct net_device *out,
13 void *userinfo) 13 unsigned int hooknum, const struct xt_target *target,
14 const void *targinfo, void *userinfo)
14{ 15{
15 const struct arpt_mangle *mangle = targinfo; 16 const struct arpt_mangle *mangle = targinfo;
16 struct arphdr *arp; 17 struct arphdr *arp;
@@ -65,8 +66,8 @@ target(struct sk_buff **pskb, const struct net_device *in,
65} 66}
66 67
67static int 68static int
68checkentry(const char *tablename, const void *e, void *targinfo, 69checkentry(const char *tablename, const void *e, const struct xt_target *target,
69 unsigned int targinfosize, unsigned int hook_mask) 70 void *targinfo, unsigned int targinfosize, unsigned int hook_mask)
70{ 71{
71 const struct arpt_mangle *mangle = targinfo; 72 const struct arpt_mangle *mangle = targinfo;
72 73
@@ -80,12 +81,12 @@ checkentry(const char *tablename, const void *e, void *targinfo,
80 return 1; 81 return 1;
81} 82}
82 83
83static struct arpt_target arpt_mangle_reg 84static struct arpt_target arpt_mangle_reg = {
84= { 85 .name = "mangle",
85 .name = "mangle", 86 .target = target,
86 .target = target, 87 .targetsize = sizeof(struct arpt_mangle),
87 .checkentry = checkentry, 88 .checkentry = checkentry,
88 .me = THIS_MODULE, 89 .me = THIS_MODULE,
89}; 90};
90 91
91static int __init init(void) 92static int __init init(void)
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 84c66dbfedaf..9e34034729a6 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -77,8 +77,8 @@ unsigned int ip_ct_log_invalid;
77static LIST_HEAD(unconfirmed); 77static LIST_HEAD(unconfirmed);
78static int ip_conntrack_vmalloc; 78static int ip_conntrack_vmalloc;
79 79
80static unsigned int ip_conntrack_next_id = 1; 80static unsigned int ip_conntrack_next_id;
81static unsigned int ip_conntrack_expect_next_id = 1; 81static unsigned int ip_conntrack_expect_next_id;
82#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS 82#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
83struct notifier_block *ip_conntrack_chain; 83struct notifier_block *ip_conntrack_chain;
84struct notifier_block *ip_conntrack_expect_chain; 84struct notifier_block *ip_conntrack_expect_chain;
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
new file mode 100644
index 000000000000..daeb1395faa4
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
@@ -0,0 +1,1731 @@
1/*
2 * H.323 connection tracking helper
3 *
4 * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
5 *
6 * This source code is licensed under General Public License version 2.
7 *
8 * Based on the 'brute force' H.323 connection tracking module by
9 * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
10 *
11 * For more information, please see http://nath323.sourceforge.net/
12 *
13 * Changes:
14 * 2006-02-01 - initial version 0.1
15 *
16 * 2006-02-20 - version 0.2
17 * 1. Changed source format to follow kernel conventions
18 * 2. Deleted some unnecessary structures
19 * 3. Minor fixes
20 *
21 * 2006-03-10 - version 0.3
22 * 1. Added support for multiple TPKTs in one packet (suggested by
23 * Patrick McHardy)
24 * 2. Avoid excessive stack usage (based on Patrick McHardy's patch)
25 * 3. Added support for non-linear skb (based on Patrick McHardy's patch)
26 * 4. Fixed missing H.245 module owner (Patrick McHardy)
27 * 5. Avoid long RAS expectation chains (Patrick McHardy)
28 * 6. Fixed incorrect __exit attribute (Patrick McHardy)
29 * 7. Eliminated unnecessary return code
30 * 8. Fixed incorrect use of NAT data from conntrack code (suggested by
31 * Patrick McHardy)
32 * 9. Fixed TTL calculation error in RCF
33 * 10. Added TTL support in RRQ
34 * 11. Better support for separate TPKT header and data
35 *
36 * 2006-03-15 - version 0.4
37 * 1. Added support for T.120 channels
38 * 2. Added parameter gkrouted_only (suggested by Patrick McHardy)
39 * 3. Splitted ASN.1 code and data (suggested by Patrick McHardy)
40 * 4. Sort ASN.1 data to avoid forwarding declarations (suggested by
41 * Patrick McHardy)
42 * 5. Reset next TPKT data length in get_tpkt_data()
43 */
44
45#include <linux/config.h>
46#include <linux/module.h>
47#include <linux/netfilter.h>
48#include <linux/ip.h>
49#include <net/tcp.h>
50#include <linux/netfilter_ipv4/ip_conntrack.h>
51#include <linux/netfilter_ipv4/ip_conntrack_core.h>
52#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
53#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
54#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
55#include <linux/moduleparam.h>
56
57#include "ip_conntrack_helper_h323_asn1.h"
58
59#if 0
60#define DEBUGP printk
61#else
62#define DEBUGP(format, args...)
63#endif
64
65/* Parameters */
66static int gkrouted_only = 1;
67module_param(gkrouted_only, int, 0600);
68MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");
69
70/* Hooks for NAT */
71int (*set_h245_addr_hook) (struct sk_buff ** pskb,
72 unsigned char **data, int dataoff,
73 H245_TransportAddress * addr,
74 u_int32_t ip, u_int16_t port);
75int (*set_h225_addr_hook) (struct sk_buff ** pskb,
76 unsigned char **data, int dataoff,
77 TransportAddress * addr,
78 u_int32_t ip, u_int16_t port);
79int (*set_sig_addr_hook) (struct sk_buff ** pskb,
80 struct ip_conntrack * ct,
81 enum ip_conntrack_info ctinfo,
82 unsigned char **data,
83 TransportAddress * addr, int count);
84int (*set_ras_addr_hook) (struct sk_buff ** pskb,
85 struct ip_conntrack * ct,
86 enum ip_conntrack_info ctinfo,
87 unsigned char **data,
88 TransportAddress * addr, int count);
89int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
90 struct ip_conntrack * ct,
91 enum ip_conntrack_info ctinfo,
92 unsigned char **data, int dataoff,
93 H245_TransportAddress * addr,
94 u_int16_t port, u_int16_t rtp_port,
95 struct ip_conntrack_expect * rtp_exp,
96 struct ip_conntrack_expect * rtcp_exp);
97int (*nat_t120_hook) (struct sk_buff ** pskb,
98 struct ip_conntrack * ct,
99 enum ip_conntrack_info ctinfo,
100 unsigned char **data, int dataoff,
101 H245_TransportAddress * addr, u_int16_t port,
102 struct ip_conntrack_expect * exp);
103int (*nat_h245_hook) (struct sk_buff ** pskb,
104 struct ip_conntrack * ct,
105 enum ip_conntrack_info ctinfo,
106 unsigned char **data, int dataoff,
107 TransportAddress * addr, u_int16_t port,
108 struct ip_conntrack_expect * exp);
109int (*nat_q931_hook) (struct sk_buff ** pskb,
110 struct ip_conntrack * ct,
111 enum ip_conntrack_info ctinfo,
112 unsigned char **data, TransportAddress * addr, int idx,
113 u_int16_t port, struct ip_conntrack_expect * exp);
114
115
116static DEFINE_SPINLOCK(ip_h323_lock);
117static char *h323_buffer;
118
119/****************************************************************************/
120static int get_tpkt_data(struct sk_buff **pskb, struct ip_conntrack *ct,
121 enum ip_conntrack_info ctinfo,
122 unsigned char **data, int *datalen, int *dataoff)
123{
124 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
125 int dir = CTINFO2DIR(ctinfo);
126 struct tcphdr _tcph, *th;
127 int tcpdatalen;
128 int tcpdataoff;
129 unsigned char *tpkt;
130 int tpktlen;
131 int tpktoff;
132
133 /* Get TCP header */
134 th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4,
135 sizeof(_tcph), &_tcph);
136 if (th == NULL)
137 return 0;
138
139 /* Get TCP data offset */
140 tcpdataoff = (*pskb)->nh.iph->ihl * 4 + th->doff * 4;
141
142 /* Get TCP data length */
143 tcpdatalen = (*pskb)->len - tcpdataoff;
144 if (tcpdatalen <= 0) /* No TCP data */
145 goto clear_out;
146
147 if (*data == NULL) { /* first TPKT */
148 /* Get first TPKT pointer */
149 tpkt = skb_header_pointer(*pskb, tcpdataoff, tcpdatalen,
150 h323_buffer);
151 BUG_ON(tpkt == NULL);
152
153 /* Validate TPKT identifier */
154 if (tcpdatalen < 4 || tpkt[0] != 0x03 || tpkt[1] != 0) {
155 /* Netmeeting sends TPKT header and data separately */
156 if (info->tpkt_len[dir] > 0) {
157 DEBUGP("ip_ct_h323: previous packet "
158 "indicated separate TPKT data of %hu "
159 "bytes\n", info->tpkt_len[dir]);
160 if (info->tpkt_len[dir] <= tcpdatalen) {
161 /* Yes, there was a TPKT header
162 * received */
163 *data = tpkt;
164 *datalen = info->tpkt_len[dir];
165 *dataoff = 0;
166 goto out;
167 }
168
169 /* Fragmented TPKT */
170 if (net_ratelimit())
171 printk("ip_ct_h323: "
172 "fragmented TPKT\n");
173 goto clear_out;
174 }
175
176 /* It is not even a TPKT */
177 return 0;
178 }
179 tpktoff = 0;
180 } else { /* Next TPKT */
181 tpktoff = *dataoff + *datalen;
182 tcpdatalen -= tpktoff;
183 if (tcpdatalen <= 4) /* No more TPKT */
184 goto clear_out;
185 tpkt = *data + *datalen;
186
187 /* Validate TPKT identifier */
188 if (tpkt[0] != 0x03 || tpkt[1] != 0)
189 goto clear_out;
190 }
191
192 /* Validate TPKT length */
193 tpktlen = tpkt[2] * 256 + tpkt[3];
194 if (tpktlen > tcpdatalen) {
195 if (tcpdatalen == 4) { /* Separate TPKT header */
196 /* Netmeeting sends TPKT header and data separately */
197 DEBUGP("ip_ct_h323: separate TPKT header indicates "
198 "there will be TPKT data of %hu bytes\n",
199 tpktlen - 4);
200 info->tpkt_len[dir] = tpktlen - 4;
201 return 0;
202 }
203
204 if (net_ratelimit())
205 printk("ip_ct_h323: incomplete TPKT (fragmented?)\n");
206 goto clear_out;
207 }
208
209 /* This is the encapsulated data */
210 *data = tpkt + 4;
211 *datalen = tpktlen - 4;
212 *dataoff = tpktoff + 4;
213
214 out:
215 /* Clear TPKT length */
216 info->tpkt_len[dir] = 0;
217 return 1;
218
219 clear_out:
220 info->tpkt_len[dir] = 0;
221 return 0;
222}
223
224/****************************************************************************/
225int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
226 u_int32_t * ip, u_int16_t * port)
227{
228 unsigned char *p;
229
230 if (addr->choice != eH245_TransportAddress_unicastAddress ||
231 addr->unicastAddress.choice != eUnicastAddress_iPAddress)
232 return 0;
233
234 p = data + addr->unicastAddress.iPAddress.network;
235 *ip = htonl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]));
236 *port = (p[4] << 8) | (p[5]);
237
238 return 1;
239}
240
241/****************************************************************************/
242static int expect_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct,
243 enum ip_conntrack_info ctinfo,
244 unsigned char **data, int dataoff,
245 H245_TransportAddress * addr)
246{
247 int dir = CTINFO2DIR(ctinfo);
248 int ret = 0;
249 u_int32_t ip;
250 u_int16_t port;
251 u_int16_t rtp_port;
252 struct ip_conntrack_expect *rtp_exp;
253 struct ip_conntrack_expect *rtcp_exp;
254
255 /* Read RTP or RTCP address */
256 if (!get_h245_addr(*data, addr, &ip, &port) ||
257 ip != ct->tuplehash[dir].tuple.src.ip || port == 0)
258 return 0;
259
260 /* RTP port is even */
261 rtp_port = port & (~1);
262
263 /* Create expect for RTP */
264 if ((rtp_exp = ip_conntrack_expect_alloc(ct)) == NULL)
265 return -1;
266 rtp_exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
267 rtp_exp->tuple.src.u.udp.port = 0;
268 rtp_exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
269 rtp_exp->tuple.dst.u.udp.port = htons(rtp_port);
270 rtp_exp->tuple.dst.protonum = IPPROTO_UDP;
271 rtp_exp->mask.src.ip = 0xFFFFFFFF;
272 rtp_exp->mask.src.u.udp.port = 0;
273 rtp_exp->mask.dst.ip = 0xFFFFFFFF;
274 rtp_exp->mask.dst.u.udp.port = 0xFFFF;
275 rtp_exp->mask.dst.protonum = 0xFF;
276 rtp_exp->flags = 0;
277
278 /* Create expect for RTCP */
279 if ((rtcp_exp = ip_conntrack_expect_alloc(ct)) == NULL) {
280 ip_conntrack_expect_put(rtp_exp);
281 return -1;
282 }
283 rtcp_exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
284 rtcp_exp->tuple.src.u.udp.port = 0;
285 rtcp_exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
286 rtcp_exp->tuple.dst.u.udp.port = htons(rtp_port + 1);
287 rtcp_exp->tuple.dst.protonum = IPPROTO_UDP;
288 rtcp_exp->mask.src.ip = 0xFFFFFFFF;
289 rtcp_exp->mask.src.u.udp.port = 0;
290 rtcp_exp->mask.dst.ip = 0xFFFFFFFF;
291 rtcp_exp->mask.dst.u.udp.port = 0xFFFF;
292 rtcp_exp->mask.dst.protonum = 0xFF;
293 rtcp_exp->flags = 0;
294
295 if (ct->tuplehash[dir].tuple.src.ip !=
296 ct->tuplehash[!dir].tuple.dst.ip && nat_rtp_rtcp_hook) {
297 /* NAT needed */
298 ret = nat_rtp_rtcp_hook(pskb, ct, ctinfo, data, dataoff,
299 addr, port, rtp_port, rtp_exp,
300 rtcp_exp);
301 } else { /* Conntrack only */
302 rtp_exp->expectfn = NULL;
303 rtcp_exp->expectfn = NULL;
304
305 if (ip_conntrack_expect_related(rtp_exp) == 0) {
306 if (ip_conntrack_expect_related(rtcp_exp) == 0) {
307 DEBUGP("ip_ct_h323: expect RTP "
308 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
309 NIPQUAD(rtp_exp->tuple.src.ip),
310 ntohs(rtp_exp->tuple.src.u.udp.port),
311 NIPQUAD(rtp_exp->tuple.dst.ip),
312 ntohs(rtp_exp->tuple.dst.u.udp.port));
313 DEBUGP("ip_ct_h323: expect RTCP "
314 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
315 NIPQUAD(rtcp_exp->tuple.src.ip),
316 ntohs(rtcp_exp->tuple.src.u.udp.port),
317 NIPQUAD(rtcp_exp->tuple.dst.ip),
318 ntohs(rtcp_exp->tuple.dst.u.udp.port));
319 } else {
320 ip_conntrack_unexpect_related(rtp_exp);
321 ret = -1;
322 }
323 } else
324 ret = -1;
325 }
326
327 ip_conntrack_expect_put(rtp_exp);
328 ip_conntrack_expect_put(rtcp_exp);
329
330 return ret;
331}
332
333/****************************************************************************/
334static int expect_t120(struct sk_buff **pskb,
335 struct ip_conntrack *ct,
336 enum ip_conntrack_info ctinfo,
337 unsigned char **data, int dataoff,
338 H245_TransportAddress * addr)
339{
340 int dir = CTINFO2DIR(ctinfo);
341 int ret = 0;
342 u_int32_t ip;
343 u_int16_t port;
344 struct ip_conntrack_expect *exp = NULL;
345
346 /* Read T.120 address */
347 if (!get_h245_addr(*data, addr, &ip, &port) ||
348 ip != ct->tuplehash[dir].tuple.src.ip || port == 0)
349 return 0;
350
351 /* Create expect for T.120 connections */
352 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
353 return -1;
354 exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
355 exp->tuple.src.u.tcp.port = 0;
356 exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
357 exp->tuple.dst.u.tcp.port = htons(port);
358 exp->tuple.dst.protonum = IPPROTO_TCP;
359 exp->mask.src.ip = 0xFFFFFFFF;
360 exp->mask.src.u.tcp.port = 0;
361 exp->mask.dst.ip = 0xFFFFFFFF;
362 exp->mask.dst.u.tcp.port = 0xFFFF;
363 exp->mask.dst.protonum = 0xFF;
364 exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple channels */
365
366 if (ct->tuplehash[dir].tuple.src.ip !=
367 ct->tuplehash[!dir].tuple.dst.ip && nat_t120_hook) {
368 /* NAT needed */
369 ret = nat_t120_hook(pskb, ct, ctinfo, data, dataoff, addr,
370 port, exp);
371 } else { /* Conntrack only */
372 exp->expectfn = NULL;
373 if (ip_conntrack_expect_related(exp) == 0) {
374 DEBUGP("ip_ct_h323: expect T.120 "
375 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
376 NIPQUAD(exp->tuple.src.ip),
377 ntohs(exp->tuple.src.u.tcp.port),
378 NIPQUAD(exp->tuple.dst.ip),
379 ntohs(exp->tuple.dst.u.tcp.port));
380 } else
381 ret = -1;
382 }
383
384 ip_conntrack_expect_put(exp);
385
386 return ret;
387}
388
389/****************************************************************************/
390static int process_h245_channel(struct sk_buff **pskb,
391 struct ip_conntrack *ct,
392 enum ip_conntrack_info ctinfo,
393 unsigned char **data, int dataoff,
394 H2250LogicalChannelParameters * channel)
395{
396 int ret;
397
398 if (channel->options & eH2250LogicalChannelParameters_mediaChannel) {
399 /* RTP */
400 ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
401 &channel->mediaChannel);
402 if (ret < 0)
403 return -1;
404 }
405
406 if (channel->
407 options & eH2250LogicalChannelParameters_mediaControlChannel) {
408 /* RTCP */
409 ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
410 &channel->mediaControlChannel);
411 if (ret < 0)
412 return -1;
413 }
414
415 return 0;
416}
417
418/****************************************************************************/
419static int process_olc(struct sk_buff **pskb, struct ip_conntrack *ct,
420 enum ip_conntrack_info ctinfo,
421 unsigned char **data, int dataoff,
422 OpenLogicalChannel * olc)
423{
424 int ret;
425
426 DEBUGP("ip_ct_h323: OpenLogicalChannel\n");
427
428 if (olc->forwardLogicalChannelParameters.multiplexParameters.choice ==
429 eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
430 {
431 ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff,
432 &olc->
433 forwardLogicalChannelParameters.
434 multiplexParameters.
435 h2250LogicalChannelParameters);
436 if (ret < 0)
437 return -1;
438 }
439
440 if ((olc->options &
441 eOpenLogicalChannel_reverseLogicalChannelParameters) &&
442 (olc->reverseLogicalChannelParameters.options &
443 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters)
444 && (olc->reverseLogicalChannelParameters.multiplexParameters.
445 choice ==
446 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))
447 {
448 ret =
449 process_h245_channel(pskb, ct, ctinfo, data, dataoff,
450 &olc->
451 reverseLogicalChannelParameters.
452 multiplexParameters.
453 h2250LogicalChannelParameters);
454 if (ret < 0)
455 return -1;
456 }
457
458 if ((olc->options & eOpenLogicalChannel_separateStack) &&
459 olc->forwardLogicalChannelParameters.dataType.choice ==
460 eDataType_data &&
461 olc->forwardLogicalChannelParameters.dataType.data.application.
462 choice == eDataApplicationCapability_application_t120 &&
463 olc->forwardLogicalChannelParameters.dataType.data.application.
464 t120.choice == eDataProtocolCapability_separateLANStack &&
465 olc->separateStack.networkAddress.choice ==
466 eNetworkAccessParameters_networkAddress_localAreaAddress) {
467 ret = expect_t120(pskb, ct, ctinfo, data, dataoff,
468 &olc->separateStack.networkAddress.
469 localAreaAddress);
470 if (ret < 0)
471 return -1;
472 }
473
474 return 0;
475}
476
477/****************************************************************************/
478static int process_olca(struct sk_buff **pskb, struct ip_conntrack *ct,
479 enum ip_conntrack_info ctinfo,
480 unsigned char **data, int dataoff,
481 OpenLogicalChannelAck * olca)
482{
483 H2250LogicalChannelAckParameters *ack;
484 int ret;
485
486 DEBUGP("ip_ct_h323: OpenLogicalChannelAck\n");
487
488 if ((olca->options &
489 eOpenLogicalChannelAck_reverseLogicalChannelParameters) &&
490 (olca->reverseLogicalChannelParameters.options &
491 eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters)
492 && (olca->reverseLogicalChannelParameters.multiplexParameters.
493 choice ==
494 eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))
495 {
496 ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff,
497 &olca->
498 reverseLogicalChannelParameters.
499 multiplexParameters.
500 h2250LogicalChannelParameters);
501 if (ret < 0)
502 return -1;
503 }
504
505 if ((olca->options &
506 eOpenLogicalChannelAck_forwardMultiplexAckParameters) &&
507 (olca->forwardMultiplexAckParameters.choice ==
508 eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters))
509 {
510 ack = &olca->forwardMultiplexAckParameters.
511 h2250LogicalChannelAckParameters;
512 if (ack->options &
513 eH2250LogicalChannelAckParameters_mediaChannel) {
514 /* RTP */
515 ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
516 &ack->mediaChannel);
517 if (ret < 0)
518 return -1;
519 }
520
521 if (ack->options &
522 eH2250LogicalChannelAckParameters_mediaControlChannel) {
523 /* RTCP */
524 ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
525 &ack->mediaControlChannel);
526 if (ret < 0)
527 return -1;
528 }
529 }
530
531 return 0;
532}
533
534/****************************************************************************/
535static int process_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
536 enum ip_conntrack_info ctinfo,
537 unsigned char **data, int dataoff,
538 MultimediaSystemControlMessage * mscm)
539{
540 switch (mscm->choice) {
541 case eMultimediaSystemControlMessage_request:
542 if (mscm->request.choice ==
543 eRequestMessage_openLogicalChannel) {
544 return process_olc(pskb, ct, ctinfo, data, dataoff,
545 &mscm->request.openLogicalChannel);
546 }
547 DEBUGP("ip_ct_h323: H.245 Request %d\n",
548 mscm->request.choice);
549 break;
550 case eMultimediaSystemControlMessage_response:
551 if (mscm->response.choice ==
552 eResponseMessage_openLogicalChannelAck) {
553 return process_olca(pskb, ct, ctinfo, data, dataoff,
554 &mscm->response.
555 openLogicalChannelAck);
556 }
557 DEBUGP("ip_ct_h323: H.245 Response %d\n",
558 mscm->response.choice);
559 break;
560 default:
561 DEBUGP("ip_ct_h323: H.245 signal %d\n", mscm->choice);
562 break;
563 }
564
565 return 0;
566}
567
568/****************************************************************************/
569static int h245_help(struct sk_buff **pskb, struct ip_conntrack *ct,
570 enum ip_conntrack_info ctinfo)
571{
572 static MultimediaSystemControlMessage mscm;
573 unsigned char *data = NULL;
574 int datalen;
575 int dataoff;
576 int ret;
577
578 /* Until there's been traffic both ways, don't look in packets. */
579 if (ctinfo != IP_CT_ESTABLISHED
580 && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
581 return NF_ACCEPT;
582 }
583 DEBUGP("ip_ct_h245: skblen = %u\n", (*pskb)->len);
584
585 spin_lock_bh(&ip_h323_lock);
586
587 /* Process each TPKT */
588 while (get_tpkt_data(pskb, ct, ctinfo, &data, &datalen, &dataoff)) {
589 DEBUGP("ip_ct_h245: TPKT %u.%u.%u.%u->%u.%u.%u.%u, len=%d\n",
590 NIPQUAD((*pskb)->nh.iph->saddr),
591 NIPQUAD((*pskb)->nh.iph->daddr), datalen);
592
593 /* Decode H.245 signal */
594 ret = DecodeMultimediaSystemControlMessage(data, datalen,
595 &mscm);
596 if (ret < 0) {
597 if (net_ratelimit())
598 printk("ip_ct_h245: decoding error: %s\n",
599 ret == H323_ERROR_BOUND ?
600 "out of bound" : "out of range");
601 /* We don't drop when decoding error */
602 break;
603 }
604
605 /* Process H.245 signal */
606 if (process_h245(pskb, ct, ctinfo, &data, dataoff, &mscm) < 0)
607 goto drop;
608 }
609
610 spin_unlock_bh(&ip_h323_lock);
611 return NF_ACCEPT;
612
613 drop:
614 spin_unlock_bh(&ip_h323_lock);
615 if (net_ratelimit())
616 printk("ip_ct_h245: packet dropped\n");
617 return NF_DROP;
618}
619
620/****************************************************************************/
621static struct ip_conntrack_helper ip_conntrack_helper_h245 = {
622 .name = "H.245",
623 .me = THIS_MODULE,
624 .max_expected = H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */ ,
625 .timeout = 240,
626 .tuple = {.dst = {.protonum = IPPROTO_TCP}},
627 .mask = {.src = {.u = {0xFFFF}},
628 .dst = {.protonum = 0xFF}},
629 .help = h245_help
630};
631
632/****************************************************************************/
633void ip_conntrack_h245_expect(struct ip_conntrack *new,
634 struct ip_conntrack_expect *this)
635{
636 write_lock_bh(&ip_conntrack_lock);
637 new->helper = &ip_conntrack_helper_h245;
638 write_unlock_bh(&ip_conntrack_lock);
639}
640
641/****************************************************************************/
642int get_h225_addr(unsigned char *data, TransportAddress * addr,
643 u_int32_t * ip, u_int16_t * port)
644{
645 unsigned char *p;
646
647 if (addr->choice != eTransportAddress_ipAddress)
648 return 0;
649
650 p = data + addr->ipAddress.ip;
651 *ip = htonl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]));
652 *port = (p[4] << 8) | (p[5]);
653
654 return 1;
655}
656
657/****************************************************************************/
658static int expect_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
659 enum ip_conntrack_info ctinfo,
660 unsigned char **data, int dataoff,
661 TransportAddress * addr)
662{
663 int dir = CTINFO2DIR(ctinfo);
664 int ret = 0;
665 u_int32_t ip;
666 u_int16_t port;
667 struct ip_conntrack_expect *exp = NULL;
668
669 /* Read h245Address */
670 if (!get_h225_addr(*data, addr, &ip, &port) ||
671 ip != ct->tuplehash[dir].tuple.src.ip || port == 0)
672 return 0;
673
674 /* Create expect for h245 connection */
675 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
676 return -1;
677 exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
678 exp->tuple.src.u.tcp.port = 0;
679 exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
680 exp->tuple.dst.u.tcp.port = htons(port);
681 exp->tuple.dst.protonum = IPPROTO_TCP;
682 exp->mask.src.ip = 0xFFFFFFFF;
683 exp->mask.src.u.tcp.port = 0;
684 exp->mask.dst.ip = 0xFFFFFFFF;
685 exp->mask.dst.u.tcp.port = 0xFFFF;
686 exp->mask.dst.protonum = 0xFF;
687 exp->flags = 0;
688
689 if (ct->tuplehash[dir].tuple.src.ip !=
690 ct->tuplehash[!dir].tuple.dst.ip && nat_h245_hook) {
691 /* NAT needed */
692 ret = nat_h245_hook(pskb, ct, ctinfo, data, dataoff, addr,
693 port, exp);
694 } else { /* Conntrack only */
695 exp->expectfn = ip_conntrack_h245_expect;
696
697 if (ip_conntrack_expect_related(exp) == 0) {
698 DEBUGP("ip_ct_q931: expect H.245 "
699 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
700 NIPQUAD(exp->tuple.src.ip),
701 ntohs(exp->tuple.src.u.tcp.port),
702 NIPQUAD(exp->tuple.dst.ip),
703 ntohs(exp->tuple.dst.u.tcp.port));
704 } else
705 ret = -1;
706 }
707
708 ip_conntrack_expect_put(exp);
709
710 return ret;
711}
712
713/****************************************************************************/
714static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct,
715 enum ip_conntrack_info ctinfo,
716 unsigned char **data, int dataoff,
717 Setup_UUIE * setup)
718{
719 int dir = CTINFO2DIR(ctinfo);
720 int ret;
721 int i;
722 u_int32_t ip;
723 u_int16_t port;
724
725 DEBUGP("ip_ct_q931: Setup\n");
726
727 if (setup->options & eSetup_UUIE_h245Address) {
728 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
729 &setup->h245Address);
730 if (ret < 0)
731 return -1;
732 }
733
734 if ((setup->options & eSetup_UUIE_destCallSignalAddress) &&
735 (set_h225_addr_hook) &&
736 get_h225_addr(*data, &setup->destCallSignalAddress, &ip, &port) &&
737 ip != ct->tuplehash[!dir].tuple.src.ip) {
738 DEBUGP("ip_ct_q931: set destCallSignalAddress "
739 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
740 NIPQUAD(ip), port,
741 NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
742 ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
743 ret = set_h225_addr_hook(pskb, data, dataoff,
744 &setup->destCallSignalAddress,
745 ct->tuplehash[!dir].tuple.src.ip,
746 ntohs(ct->tuplehash[!dir].tuple.src.
747 u.tcp.port));
748 if (ret < 0)
749 return -1;
750 }
751
752 if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) &&
753 (set_h225_addr_hook) &&
754 get_h225_addr(*data, &setup->sourceCallSignalAddress, &ip, &port)
755 && ip != ct->tuplehash[!dir].tuple.dst.ip) {
756 DEBUGP("ip_ct_q931: set sourceCallSignalAddress "
757 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
758 NIPQUAD(ip), port,
759 NIPQUAD(ct->tuplehash[!dir].tuple.dst.ip),
760 ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
761 ret = set_h225_addr_hook(pskb, data, dataoff,
762 &setup->sourceCallSignalAddress,
763 ct->tuplehash[!dir].tuple.dst.ip,
764 ntohs(ct->tuplehash[!dir].tuple.dst.
765 u.tcp.port));
766 if (ret < 0)
767 return -1;
768 }
769
770 if (setup->options & eSetup_UUIE_fastStart) {
771 for (i = 0; i < setup->fastStart.count; i++) {
772 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
773 &setup->fastStart.item[i]);
774 if (ret < 0)
775 return -1;
776 }
777 }
778
779 return 0;
780}
781
782/****************************************************************************/
783static int process_callproceeding(struct sk_buff **pskb,
784 struct ip_conntrack *ct,
785 enum ip_conntrack_info ctinfo,
786 unsigned char **data, int dataoff,
787 CallProceeding_UUIE * callproc)
788{
789 int ret;
790 int i;
791
792 DEBUGP("ip_ct_q931: CallProceeding\n");
793
794 if (callproc->options & eCallProceeding_UUIE_h245Address) {
795 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
796 &callproc->h245Address);
797 if (ret < 0)
798 return -1;
799 }
800
801 if (callproc->options & eCallProceeding_UUIE_fastStart) {
802 for (i = 0; i < callproc->fastStart.count; i++) {
803 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
804 &callproc->fastStart.item[i]);
805 if (ret < 0)
806 return -1;
807 }
808 }
809
810 return 0;
811}
812
813/****************************************************************************/
814static int process_connect(struct sk_buff **pskb, struct ip_conntrack *ct,
815 enum ip_conntrack_info ctinfo,
816 unsigned char **data, int dataoff,
817 Connect_UUIE * connect)
818{
819 int ret;
820 int i;
821
822 DEBUGP("ip_ct_q931: Connect\n");
823
824 if (connect->options & eConnect_UUIE_h245Address) {
825 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
826 &connect->h245Address);
827 if (ret < 0)
828 return -1;
829 }
830
831 if (connect->options & eConnect_UUIE_fastStart) {
832 for (i = 0; i < connect->fastStart.count; i++) {
833 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
834 &connect->fastStart.item[i]);
835 if (ret < 0)
836 return -1;
837 }
838 }
839
840 return 0;
841}
842
843/****************************************************************************/
844static int process_alerting(struct sk_buff **pskb, struct ip_conntrack *ct,
845 enum ip_conntrack_info ctinfo,
846 unsigned char **data, int dataoff,
847 Alerting_UUIE * alert)
848{
849 int ret;
850 int i;
851
852 DEBUGP("ip_ct_q931: Alerting\n");
853
854 if (alert->options & eAlerting_UUIE_h245Address) {
855 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
856 &alert->h245Address);
857 if (ret < 0)
858 return -1;
859 }
860
861 if (alert->options & eAlerting_UUIE_fastStart) {
862 for (i = 0; i < alert->fastStart.count; i++) {
863 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
864 &alert->fastStart.item[i]);
865 if (ret < 0)
866 return -1;
867 }
868 }
869
870 return 0;
871}
872
873/****************************************************************************/
874static int process_information(struct sk_buff **pskb,
875 struct ip_conntrack *ct,
876 enum ip_conntrack_info ctinfo,
877 unsigned char **data, int dataoff,
878 Information_UUIE * info)
879{
880 int ret;
881 int i;
882
883 DEBUGP("ip_ct_q931: Information\n");
884
885 if (info->options & eInformation_UUIE_fastStart) {
886 for (i = 0; i < info->fastStart.count; i++) {
887 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
888 &info->fastStart.item[i]);
889 if (ret < 0)
890 return -1;
891 }
892 }
893
894 return 0;
895}
896
897/****************************************************************************/
898static int process_facility(struct sk_buff **pskb, struct ip_conntrack *ct,
899 enum ip_conntrack_info ctinfo,
900 unsigned char **data, int dataoff,
901 Facility_UUIE * facility)
902{
903 int ret;
904 int i;
905
906 DEBUGP("ip_ct_q931: Facility\n");
907
908 if (facility->options & eFacility_UUIE_h245Address) {
909 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
910 &facility->h245Address);
911 if (ret < 0)
912 return -1;
913 }
914
915 if (facility->options & eFacility_UUIE_fastStart) {
916 for (i = 0; i < facility->fastStart.count; i++) {
917 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
918 &facility->fastStart.item[i]);
919 if (ret < 0)
920 return -1;
921 }
922 }
923
924 return 0;
925}
926
927/****************************************************************************/
928static int process_progress(struct sk_buff **pskb, struct ip_conntrack *ct,
929 enum ip_conntrack_info ctinfo,
930 unsigned char **data, int dataoff,
931 Progress_UUIE * progress)
932{
933 int ret;
934 int i;
935
936 DEBUGP("ip_ct_q931: Progress\n");
937
938 if (progress->options & eProgress_UUIE_h245Address) {
939 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
940 &progress->h245Address);
941 if (ret < 0)
942 return -1;
943 }
944
945 if (progress->options & eProgress_UUIE_fastStart) {
946 for (i = 0; i < progress->fastStart.count; i++) {
947 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
948 &progress->fastStart.item[i]);
949 if (ret < 0)
950 return -1;
951 }
952 }
953
954 return 0;
955}
956
957/****************************************************************************/
958static int process_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
959 enum ip_conntrack_info ctinfo,
960 unsigned char **data, int dataoff, Q931 * q931)
961{
962 H323_UU_PDU *pdu = &q931->UUIE.h323_uu_pdu;
963 int i;
964 int ret = 0;
965
966 switch (pdu->h323_message_body.choice) {
967 case eH323_UU_PDU_h323_message_body_setup:
968 ret = process_setup(pskb, ct, ctinfo, data, dataoff,
969 &pdu->h323_message_body.setup);
970 break;
971 case eH323_UU_PDU_h323_message_body_callProceeding:
972 ret = process_callproceeding(pskb, ct, ctinfo, data, dataoff,
973 &pdu->h323_message_body.
974 callProceeding);
975 break;
976 case eH323_UU_PDU_h323_message_body_connect:
977 ret = process_connect(pskb, ct, ctinfo, data, dataoff,
978 &pdu->h323_message_body.connect);
979 break;
980 case eH323_UU_PDU_h323_message_body_alerting:
981 ret = process_alerting(pskb, ct, ctinfo, data, dataoff,
982 &pdu->h323_message_body.alerting);
983 break;
984 case eH323_UU_PDU_h323_message_body_information:
985 ret = process_information(pskb, ct, ctinfo, data, dataoff,
986 &pdu->h323_message_body.
987 information);
988 break;
989 case eH323_UU_PDU_h323_message_body_facility:
990 ret = process_facility(pskb, ct, ctinfo, data, dataoff,
991 &pdu->h323_message_body.facility);
992 break;
993 case eH323_UU_PDU_h323_message_body_progress:
994 ret = process_progress(pskb, ct, ctinfo, data, dataoff,
995 &pdu->h323_message_body.progress);
996 break;
997 default:
998 DEBUGP("ip_ct_q931: Q.931 signal %d\n",
999 pdu->h323_message_body.choice);
1000 break;
1001 }
1002
1003 if (ret < 0)
1004 return -1;
1005
1006 if (pdu->options & eH323_UU_PDU_h245Control) {
1007 for (i = 0; i < pdu->h245Control.count; i++) {
1008 ret = process_h245(pskb, ct, ctinfo, data, dataoff,
1009 &pdu->h245Control.item[i]);
1010 if (ret < 0)
1011 return -1;
1012 }
1013 }
1014
1015 return 0;
1016}
1017
1018/****************************************************************************/
1019static int q931_help(struct sk_buff **pskb, struct ip_conntrack *ct,
1020 enum ip_conntrack_info ctinfo)
1021{
1022 static Q931 q931;
1023 unsigned char *data = NULL;
1024 int datalen;
1025 int dataoff;
1026 int ret;
1027
1028 /* Until there's been traffic both ways, don't look in packets. */
1029 if (ctinfo != IP_CT_ESTABLISHED
1030 && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
1031 return NF_ACCEPT;
1032 }
1033 DEBUGP("ip_ct_q931: skblen = %u\n", (*pskb)->len);
1034
1035 spin_lock_bh(&ip_h323_lock);
1036
1037 /* Process each TPKT */
1038 while (get_tpkt_data(pskb, ct, ctinfo, &data, &datalen, &dataoff)) {
1039 DEBUGP("ip_ct_q931: TPKT %u.%u.%u.%u->%u.%u.%u.%u, len=%d\n",
1040 NIPQUAD((*pskb)->nh.iph->saddr),
1041 NIPQUAD((*pskb)->nh.iph->daddr), datalen);
1042
1043 /* Decode Q.931 signal */
1044 ret = DecodeQ931(data, datalen, &q931);
1045 if (ret < 0) {
1046 if (net_ratelimit())
1047 printk("ip_ct_q931: decoding error: %s\n",
1048 ret == H323_ERROR_BOUND ?
1049 "out of bound" : "out of range");
1050 /* We don't drop when decoding error */
1051 break;
1052 }
1053
1054 /* Process Q.931 signal */
1055 if (process_q931(pskb, ct, ctinfo, &data, dataoff, &q931) < 0)
1056 goto drop;
1057 }
1058
1059 spin_unlock_bh(&ip_h323_lock);
1060 return NF_ACCEPT;
1061
1062 drop:
1063 spin_unlock_bh(&ip_h323_lock);
1064 if (net_ratelimit())
1065 printk("ip_ct_q931: packet dropped\n");
1066 return NF_DROP;
1067}
1068
1069/****************************************************************************/
1070static struct ip_conntrack_helper ip_conntrack_helper_q931 = {
1071 .name = "Q.931",
1072 .me = THIS_MODULE,
1073 .max_expected = H323_RTP_CHANNEL_MAX * 4 + 4 /* T.120 and H.245 */ ,
1074 .timeout = 240,
1075 .tuple = {.src = {.u = {__constant_htons(Q931_PORT)}},
1076 .dst = {.protonum = IPPROTO_TCP}},
1077 .mask = {.src = {.u = {0xFFFF}},
1078 .dst = {.protonum = 0xFF}},
1079 .help = q931_help
1080};
1081
1082/****************************************************************************/
1083void ip_conntrack_q931_expect(struct ip_conntrack *new,
1084 struct ip_conntrack_expect *this)
1085{
1086 write_lock_bh(&ip_conntrack_lock);
1087 new->helper = &ip_conntrack_helper_q931;
1088 write_unlock_bh(&ip_conntrack_lock);
1089}
1090
1091/****************************************************************************/
1092static unsigned char *get_udp_data(struct sk_buff **pskb, int *datalen)
1093{
1094 struct udphdr _uh, *uh;
1095 int dataoff;
1096
1097 uh = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4, sizeof(_uh),
1098 &_uh);
1099 if (uh == NULL)
1100 return NULL;
1101 dataoff = (*pskb)->nh.iph->ihl * 4 + sizeof(_uh);
1102 if (dataoff >= (*pskb)->len)
1103 return NULL;
1104 *datalen = (*pskb)->len - dataoff;
1105 return skb_header_pointer(*pskb, dataoff, *datalen, h323_buffer);
1106}
1107
1108/****************************************************************************/
1109static struct ip_conntrack_expect *find_expect(struct ip_conntrack *ct,
1110 u_int32_t ip, u_int16_t port)
1111{
1112 struct ip_conntrack_expect *exp;
1113 struct ip_conntrack_tuple tuple;
1114
1115 tuple.src.ip = 0;
1116 tuple.src.u.tcp.port = 0;
1117 tuple.dst.ip = ip;
1118 tuple.dst.u.tcp.port = htons(port);
1119 tuple.dst.protonum = IPPROTO_TCP;
1120
1121 exp = __ip_conntrack_expect_find(&tuple);
1122 if (exp->master == ct)
1123 return exp;
1124 return NULL;
1125}
1126
1127/****************************************************************************/
1128static int set_expect_timeout(struct ip_conntrack_expect *exp,
1129 unsigned timeout)
1130{
1131 if (!exp || !del_timer(&exp->timeout))
1132 return 0;
1133
1134 exp->timeout.expires = jiffies + timeout * HZ;
1135 add_timer(&exp->timeout);
1136
1137 return 1;
1138}
1139
1140/****************************************************************************/
1141static int expect_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
1142 enum ip_conntrack_info ctinfo,
1143 unsigned char **data,
1144 TransportAddress * addr, int count)
1145{
1146 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
1147 int dir = CTINFO2DIR(ctinfo);
1148 int ret = 0;
1149 int i;
1150 u_int32_t ip;
1151 u_int16_t port;
1152 struct ip_conntrack_expect *exp;
1153
1154 /* Look for the first related address */
1155 for (i = 0; i < count; i++) {
1156 if (get_h225_addr(*data, &addr[i], &ip, &port) &&
1157 ip == ct->tuplehash[dir].tuple.src.ip && port != 0)
1158 break;
1159 }
1160
1161 if (i >= count) /* Not found */
1162 return 0;
1163
1164 /* Create expect for Q.931 */
1165 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
1166 return -1;
1167 exp->tuple.src.ip = gkrouted_only ? /* only accept calls from GK? */
1168 ct->tuplehash[!dir].tuple.src.ip : 0;
1169 exp->tuple.src.u.tcp.port = 0;
1170 exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
1171 exp->tuple.dst.u.tcp.port = htons(port);
1172 exp->tuple.dst.protonum = IPPROTO_TCP;
1173 exp->mask.src.ip = gkrouted_only ? 0xFFFFFFFF : 0;
1174 exp->mask.src.u.tcp.port = 0;
1175 exp->mask.dst.ip = 0xFFFFFFFF;
1176 exp->mask.dst.u.tcp.port = 0xFFFF;
1177 exp->mask.dst.protonum = 0xFF;
1178 exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple calls */
1179
1180 if (nat_q931_hook) { /* Need NAT */
1181 ret = nat_q931_hook(pskb, ct, ctinfo, data, addr, i,
1182 port, exp);
1183 } else { /* Conntrack only */
1184 exp->expectfn = ip_conntrack_q931_expect;
1185
1186 if (ip_conntrack_expect_related(exp) == 0) {
1187 DEBUGP("ip_ct_ras: expect Q.931 "
1188 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
1189 NIPQUAD(exp->tuple.src.ip),
1190 ntohs(exp->tuple.src.u.tcp.port),
1191 NIPQUAD(exp->tuple.dst.ip),
1192 ntohs(exp->tuple.dst.u.tcp.port));
1193
1194 /* Save port for looking up expect in processing RCF */
1195 info->sig_port[dir] = port;
1196 } else
1197 ret = -1;
1198 }
1199
1200 ip_conntrack_expect_put(exp);
1201
1202 return ret;
1203}
1204
1205/****************************************************************************/
1206static int process_grq(struct sk_buff **pskb, struct ip_conntrack *ct,
1207 enum ip_conntrack_info ctinfo,
1208 unsigned char **data, GatekeeperRequest * grq)
1209{
1210 DEBUGP("ip_ct_ras: GRQ\n");
1211
1212 if (set_ras_addr_hook) /* NATed */
1213 return set_ras_addr_hook(pskb, ct, ctinfo, data,
1214 &grq->rasAddress, 1);
1215 return 0;
1216}
1217
1218/* Declare before using */
1219static void ip_conntrack_ras_expect(struct ip_conntrack *new,
1220 struct ip_conntrack_expect *this);
1221
1222/****************************************************************************/
1223static int process_gcf(struct sk_buff **pskb, struct ip_conntrack *ct,
1224 enum ip_conntrack_info ctinfo,
1225 unsigned char **data, GatekeeperConfirm * gcf)
1226{
1227 int dir = CTINFO2DIR(ctinfo);
1228 int ret = 0;
1229 u_int32_t ip;
1230 u_int16_t port;
1231 struct ip_conntrack_expect *exp;
1232
1233 DEBUGP("ip_ct_ras: GCF\n");
1234
1235 if (!get_h225_addr(*data, &gcf->rasAddress, &ip, &port))
1236 return 0;
1237
1238 /* Registration port is the same as discovery port */
1239 if (ip == ct->tuplehash[dir].tuple.src.ip &&
1240 port == ntohs(ct->tuplehash[dir].tuple.src.u.udp.port))
1241 return 0;
1242
1243 /* Avoid RAS expectation loops. A GCF is never expected. */
1244 if (test_bit(IPS_EXPECTED_BIT, &ct->status))
1245 return 0;
1246
1247 /* Need new expect */
1248 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
1249 return -1;
1250 exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
1251 exp->tuple.src.u.tcp.port = 0;
1252 exp->tuple.dst.ip = ip;
1253 exp->tuple.dst.u.tcp.port = htons(port);
1254 exp->tuple.dst.protonum = IPPROTO_UDP;
1255 exp->mask.src.ip = 0xFFFFFFFF;
1256 exp->mask.src.u.tcp.port = 0;
1257 exp->mask.dst.ip = 0xFFFFFFFF;
1258 exp->mask.dst.u.tcp.port = 0xFFFF;
1259 exp->mask.dst.protonum = 0xFF;
1260 exp->flags = 0;
1261 exp->expectfn = ip_conntrack_ras_expect;
1262 if (ip_conntrack_expect_related(exp) == 0) {
1263 DEBUGP("ip_ct_ras: expect RAS "
1264 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
1265 NIPQUAD(exp->tuple.src.ip),
1266 ntohs(exp->tuple.src.u.tcp.port),
1267 NIPQUAD(exp->tuple.dst.ip),
1268 ntohs(exp->tuple.dst.u.tcp.port));
1269 } else
1270 ret = -1;
1271
1272 ip_conntrack_expect_put(exp);
1273
1274 return ret;
1275}
1276
1277/****************************************************************************/
1278static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct,
1279 enum ip_conntrack_info ctinfo,
1280 unsigned char **data, RegistrationRequest * rrq)
1281{
1282 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
1283 int ret;
1284
1285 DEBUGP("ip_ct_ras: RRQ\n");
1286
1287 ret = expect_q931(pskb, ct, ctinfo, data,
1288 rrq->callSignalAddress.item,
1289 rrq->callSignalAddress.count);
1290 if (ret < 0)
1291 return -1;
1292
1293 if (set_ras_addr_hook) {
1294 ret = set_ras_addr_hook(pskb, ct, ctinfo, data,
1295 rrq->rasAddress.item,
1296 rrq->rasAddress.count);
1297 if (ret < 0)
1298 return -1;
1299 }
1300
1301 if (rrq->options & eRegistrationRequest_timeToLive) {
1302 DEBUGP("ip_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
1303 info->timeout = rrq->timeToLive;
1304 } else
1305 info->timeout = 0;
1306
1307 return 0;
1308}
1309
1310/****************************************************************************/
1311static int process_rcf(struct sk_buff **pskb, struct ip_conntrack *ct,
1312 enum ip_conntrack_info ctinfo,
1313 unsigned char **data, RegistrationConfirm * rcf)
1314{
1315 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
1316 int dir = CTINFO2DIR(ctinfo);
1317 int ret;
1318 struct ip_conntrack_expect *exp;
1319
1320 DEBUGP("ip_ct_ras: RCF\n");
1321
1322 if (set_sig_addr_hook) {
1323 ret = set_sig_addr_hook(pskb, ct, ctinfo, data,
1324 rcf->callSignalAddress.item,
1325 rcf->callSignalAddress.count);
1326 if (ret < 0)
1327 return -1;
1328 }
1329
1330 if (rcf->options & eRegistrationConfirm_timeToLive) {
1331 DEBUGP("ip_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive);
1332 info->timeout = rcf->timeToLive;
1333 }
1334
1335 if (info->timeout > 0) {
1336 DEBUGP
1337 ("ip_ct_ras: set RAS connection timeout to %u seconds\n",
1338 info->timeout);
1339 ip_ct_refresh_acct(ct, ctinfo, NULL, info->timeout * HZ);
1340
1341 /* Set expect timeout */
1342 read_lock_bh(&ip_conntrack_lock);
1343 exp = find_expect(ct, ct->tuplehash[dir].tuple.dst.ip,
1344 info->sig_port[!dir]);
1345 if (exp) {
1346 DEBUGP("ip_ct_ras: set Q.931 expect "
1347 "(%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu) "
1348 "timeout to %u seconds\n",
1349 NIPQUAD(exp->tuple.src.ip),
1350 ntohs(exp->tuple.src.u.tcp.port),
1351 NIPQUAD(exp->tuple.dst.ip),
1352 ntohs(exp->tuple.dst.u.tcp.port),
1353 info->timeout);
1354 set_expect_timeout(exp, info->timeout);
1355 }
1356 read_unlock_bh(&ip_conntrack_lock);
1357 }
1358
1359 return 0;
1360}
1361
1362/****************************************************************************/
1363static int process_urq(struct sk_buff **pskb, struct ip_conntrack *ct,
1364 enum ip_conntrack_info ctinfo,
1365 unsigned char **data, UnregistrationRequest * urq)
1366{
1367 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
1368 int dir = CTINFO2DIR(ctinfo);
1369 int ret;
1370
1371 DEBUGP("ip_ct_ras: URQ\n");
1372
1373 if (set_sig_addr_hook) {
1374 ret = set_sig_addr_hook(pskb, ct, ctinfo, data,
1375 urq->callSignalAddress.item,
1376 urq->callSignalAddress.count);
1377 if (ret < 0)
1378 return -1;
1379 }
1380
1381 /* Clear old expect */
1382 ip_ct_remove_expectations(ct);
1383 info->sig_port[dir] = 0;
1384 info->sig_port[!dir] = 0;
1385
1386 /* Give it 30 seconds for UCF or URJ */
1387 ip_ct_refresh_acct(ct, ctinfo, NULL, 30 * HZ);
1388
1389 return 0;
1390}
1391
1392/****************************************************************************/
1393static int process_arq(struct sk_buff **pskb, struct ip_conntrack *ct,
1394 enum ip_conntrack_info ctinfo,
1395 unsigned char **data, AdmissionRequest * arq)
1396{
1397 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
1398 int dir = CTINFO2DIR(ctinfo);
1399 u_int32_t ip;
1400 u_int16_t port;
1401
1402 DEBUGP("ip_ct_ras: ARQ\n");
1403
1404 if ((arq->options & eAdmissionRequest_destCallSignalAddress) &&
1405 get_h225_addr(*data, &arq->destCallSignalAddress, &ip, &port) &&
1406 ip == ct->tuplehash[dir].tuple.src.ip &&
1407 port == info->sig_port[dir] && set_h225_addr_hook) {
1408 /* Answering ARQ */
1409 return set_h225_addr_hook(pskb, data, 0,
1410 &arq->destCallSignalAddress,
1411 ct->tuplehash[!dir].tuple.dst.ip,
1412 info->sig_port[!dir]);
1413 }
1414
1415 if ((arq->options & eAdmissionRequest_srcCallSignalAddress) &&
1416 get_h225_addr(*data, &arq->srcCallSignalAddress, &ip, &port) &&
1417 ip == ct->tuplehash[dir].tuple.src.ip && set_h225_addr_hook) {
1418 /* Calling ARQ */
1419 return set_h225_addr_hook(pskb, data, 0,
1420 &arq->srcCallSignalAddress,
1421 ct->tuplehash[!dir].tuple.dst.ip,
1422 port);
1423 }
1424
1425 return 0;
1426}
1427
1428/****************************************************************************/
1429static int process_acf(struct sk_buff **pskb, struct ip_conntrack *ct,
1430 enum ip_conntrack_info ctinfo,
1431 unsigned char **data, AdmissionConfirm * acf)
1432{
1433 int dir = CTINFO2DIR(ctinfo);
1434 int ret = 0;
1435 u_int32_t ip;
1436 u_int16_t port;
1437 struct ip_conntrack_expect *exp;
1438
1439 DEBUGP("ip_ct_ras: ACF\n");
1440
1441 if (!get_h225_addr(*data, &acf->destCallSignalAddress, &ip, &port))
1442 return 0;
1443
1444 if (ip == ct->tuplehash[dir].tuple.dst.ip) { /* Answering ACF */
1445 if (set_sig_addr_hook)
1446 return set_sig_addr_hook(pskb, ct, ctinfo, data,
1447 &acf->destCallSignalAddress,
1448 1);
1449 return 0;
1450 }
1451
1452 /* Need new expect */
1453 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
1454 return -1;
1455 exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
1456 exp->tuple.src.u.tcp.port = 0;
1457 exp->tuple.dst.ip = ip;
1458 exp->tuple.dst.u.tcp.port = htons(port);
1459 exp->tuple.dst.protonum = IPPROTO_TCP;
1460 exp->mask.src.ip = 0xFFFFFFFF;
1461 exp->mask.src.u.tcp.port = 0;
1462 exp->mask.dst.ip = 0xFFFFFFFF;
1463 exp->mask.dst.u.tcp.port = 0xFFFF;
1464 exp->mask.dst.protonum = 0xFF;
1465 exp->flags = IP_CT_EXPECT_PERMANENT;
1466 exp->expectfn = ip_conntrack_q931_expect;
1467
1468 if (ip_conntrack_expect_related(exp) == 0) {
1469 DEBUGP("ip_ct_ras: expect Q.931 "
1470 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
1471 NIPQUAD(exp->tuple.src.ip),
1472 ntohs(exp->tuple.src.u.tcp.port),
1473 NIPQUAD(exp->tuple.dst.ip),
1474 ntohs(exp->tuple.dst.u.tcp.port));
1475 } else
1476 ret = -1;
1477
1478 ip_conntrack_expect_put(exp);
1479
1480 return ret;
1481}
1482
1483/****************************************************************************/
1484static int process_lrq(struct sk_buff **pskb, struct ip_conntrack *ct,
1485 enum ip_conntrack_info ctinfo,
1486 unsigned char **data, LocationRequest * lrq)
1487{
1488 DEBUGP("ip_ct_ras: LRQ\n");
1489
1490 if (set_ras_addr_hook)
1491 return set_ras_addr_hook(pskb, ct, ctinfo, data,
1492 &lrq->replyAddress, 1);
1493 return 0;
1494}
1495
1496/****************************************************************************/
1497static int process_lcf(struct sk_buff **pskb, struct ip_conntrack *ct,
1498 enum ip_conntrack_info ctinfo,
1499 unsigned char **data, LocationConfirm * lcf)
1500{
1501 int dir = CTINFO2DIR(ctinfo);
1502 int ret = 0;
1503 u_int32_t ip;
1504 u_int16_t port;
1505 struct ip_conntrack_expect *exp = NULL;
1506
1507 DEBUGP("ip_ct_ras: LCF\n");
1508
1509 if (!get_h225_addr(*data, &lcf->callSignalAddress, &ip, &port))
1510 return 0;
1511
1512 /* Need new expect for call signal */
1513 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
1514 return -1;
1515 exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
1516 exp->tuple.src.u.tcp.port = 0;
1517 exp->tuple.dst.ip = ip;
1518 exp->tuple.dst.u.tcp.port = htons(port);
1519 exp->tuple.dst.protonum = IPPROTO_TCP;
1520 exp->mask.src.ip = 0xFFFFFFFF;
1521 exp->mask.src.u.tcp.port = 0;
1522 exp->mask.dst.ip = 0xFFFFFFFF;
1523 exp->mask.dst.u.tcp.port = 0xFFFF;
1524 exp->mask.dst.protonum = 0xFF;
1525 exp->flags = IP_CT_EXPECT_PERMANENT;
1526 exp->expectfn = ip_conntrack_q931_expect;
1527
1528 if (ip_conntrack_expect_related(exp) == 0) {
1529 DEBUGP("ip_ct_ras: expect Q.931 "
1530 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
1531 NIPQUAD(exp->tuple.src.ip),
1532 ntohs(exp->tuple.src.u.tcp.port),
1533 NIPQUAD(exp->tuple.dst.ip),
1534 ntohs(exp->tuple.dst.u.tcp.port));
1535 } else
1536 ret = -1;
1537
1538 ip_conntrack_expect_put(exp);
1539
1540 /* Ignore rasAddress */
1541
1542 return ret;
1543}
1544
1545/****************************************************************************/
1546static int process_irr(struct sk_buff **pskb, struct ip_conntrack *ct,
1547 enum ip_conntrack_info ctinfo,
1548 unsigned char **data, InfoRequestResponse * irr)
1549{
1550 int ret;
1551
1552 DEBUGP("ip_ct_ras: IRR\n");
1553
1554 if (set_ras_addr_hook) {
1555 ret = set_ras_addr_hook(pskb, ct, ctinfo, data,
1556 &irr->rasAddress, 1);
1557 if (ret < 0)
1558 return -1;
1559 }
1560
1561 if (set_sig_addr_hook) {
1562 ret = set_sig_addr_hook(pskb, ct, ctinfo, data,
1563 irr->callSignalAddress.item,
1564 irr->callSignalAddress.count);
1565 if (ret < 0)
1566 return -1;
1567 }
1568
1569 return 0;
1570}
1571
1572/****************************************************************************/
1573static int process_ras(struct sk_buff **pskb, struct ip_conntrack *ct,
1574 enum ip_conntrack_info ctinfo,
1575 unsigned char **data, RasMessage * ras)
1576{
1577 switch (ras->choice) {
1578 case eRasMessage_gatekeeperRequest:
1579 return process_grq(pskb, ct, ctinfo, data,
1580 &ras->gatekeeperRequest);
1581 case eRasMessage_gatekeeperConfirm:
1582 return process_gcf(pskb, ct, ctinfo, data,
1583 &ras->gatekeeperConfirm);
1584 case eRasMessage_registrationRequest:
1585 return process_rrq(pskb, ct, ctinfo, data,
1586 &ras->registrationRequest);
1587 case eRasMessage_registrationConfirm:
1588 return process_rcf(pskb, ct, ctinfo, data,
1589 &ras->registrationConfirm);
1590 case eRasMessage_unregistrationRequest:
1591 return process_urq(pskb, ct, ctinfo, data,
1592 &ras->unregistrationRequest);
1593 case eRasMessage_admissionRequest:
1594 return process_arq(pskb, ct, ctinfo, data,
1595 &ras->admissionRequest);
1596 case eRasMessage_admissionConfirm:
1597 return process_acf(pskb, ct, ctinfo, data,
1598 &ras->admissionConfirm);
1599 case eRasMessage_locationRequest:
1600 return process_lrq(pskb, ct, ctinfo, data,
1601 &ras->locationRequest);
1602 case eRasMessage_locationConfirm:
1603 return process_lcf(pskb, ct, ctinfo, data,
1604 &ras->locationConfirm);
1605 case eRasMessage_infoRequestResponse:
1606 return process_irr(pskb, ct, ctinfo, data,
1607 &ras->infoRequestResponse);
1608 default:
1609 DEBUGP("ip_ct_ras: RAS message %d\n", ras->choice);
1610 break;
1611 }
1612
1613 return 0;
1614}
1615
1616/****************************************************************************/
1617static int ras_help(struct sk_buff **pskb, struct ip_conntrack *ct,
1618 enum ip_conntrack_info ctinfo)
1619{
1620 static RasMessage ras;
1621 unsigned char *data;
1622 int datalen = 0;
1623 int ret;
1624
1625 DEBUGP("ip_ct_ras: skblen = %u\n", (*pskb)->len);
1626
1627 spin_lock_bh(&ip_h323_lock);
1628
1629 /* Get UDP data */
1630 data = get_udp_data(pskb, &datalen);
1631 if (data == NULL)
1632 goto accept;
1633 DEBUGP("ip_ct_ras: RAS message %u.%u.%u.%u->%u.%u.%u.%u, len=%d\n",
1634 NIPQUAD((*pskb)->nh.iph->saddr),
1635 NIPQUAD((*pskb)->nh.iph->daddr), datalen);
1636
1637 /* Decode RAS message */
1638 ret = DecodeRasMessage(data, datalen, &ras);
1639 if (ret < 0) {
1640 if (net_ratelimit())
1641 printk("ip_ct_ras: decoding error: %s\n",
1642 ret == H323_ERROR_BOUND ?
1643 "out of bound" : "out of range");
1644 goto accept;
1645 }
1646
1647 /* Process RAS message */
1648 if (process_ras(pskb, ct, ctinfo, &data, &ras) < 0)
1649 goto drop;
1650
1651 accept:
1652 spin_unlock_bh(&ip_h323_lock);
1653 return NF_ACCEPT;
1654
1655 drop:
1656 spin_unlock_bh(&ip_h323_lock);
1657 if (net_ratelimit())
1658 printk("ip_ct_ras: packet dropped\n");
1659 return NF_DROP;
1660}
1661
1662/****************************************************************************/
1663static struct ip_conntrack_helper ip_conntrack_helper_ras = {
1664 .name = "RAS",
1665 .me = THIS_MODULE,
1666 .max_expected = 32,
1667 .timeout = 240,
1668 .tuple = {.src = {.u = {__constant_htons(RAS_PORT)}},
1669 .dst = {.protonum = IPPROTO_UDP}},
1670 .mask = {.src = {.u = {0xFFFE}},
1671 .dst = {.protonum = 0xFF}},
1672 .help = ras_help,
1673};
1674
1675/****************************************************************************/
1676static void ip_conntrack_ras_expect(struct ip_conntrack *new,
1677 struct ip_conntrack_expect *this)
1678{
1679 write_lock_bh(&ip_conntrack_lock);
1680 new->helper = &ip_conntrack_helper_ras;
1681 write_unlock_bh(&ip_conntrack_lock);
1682}
1683
1684/****************************************************************************/
1685/* Not __exit - called from init() */
1686static void fini(void)
1687{
1688 ip_conntrack_helper_unregister(&ip_conntrack_helper_ras);
1689 ip_conntrack_helper_unregister(&ip_conntrack_helper_q931);
1690 kfree(h323_buffer);
1691 DEBUGP("ip_ct_h323: fini\n");
1692}
1693
1694/****************************************************************************/
1695static int __init init(void)
1696{
1697 int ret;
1698
1699 h323_buffer = kmalloc(65536, GFP_KERNEL);
1700 if (!h323_buffer)
1701 return -ENOMEM;
1702 if ((ret = ip_conntrack_helper_register(&ip_conntrack_helper_q931)) ||
1703 (ret = ip_conntrack_helper_register(&ip_conntrack_helper_ras))) {
1704 fini();
1705 return ret;
1706 }
1707
1708 DEBUGP("ip_ct_h323: init success\n");
1709 return 0;
1710}
1711
1712/****************************************************************************/
1713module_init(init);
1714module_exit(fini);
1715
1716EXPORT_SYMBOL(get_h245_addr);
1717EXPORT_SYMBOL(get_h225_addr);
1718EXPORT_SYMBOL(ip_conntrack_h245_expect);
1719EXPORT_SYMBOL(ip_conntrack_q931_expect);
1720EXPORT_SYMBOL(set_h245_addr_hook);
1721EXPORT_SYMBOL(set_h225_addr_hook);
1722EXPORT_SYMBOL(set_sig_addr_hook);
1723EXPORT_SYMBOL(set_ras_addr_hook);
1724EXPORT_SYMBOL(nat_rtp_rtcp_hook);
1725EXPORT_SYMBOL(nat_t120_hook);
1726EXPORT_SYMBOL(nat_h245_hook);
1727EXPORT_SYMBOL(nat_q931_hook);
1728
1729MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
1730MODULE_DESCRIPTION("H.323 connection tracking helper");
1731MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
new file mode 100644
index 000000000000..afa525129b51
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
@@ -0,0 +1,870 @@
1/****************************************************************************
2 * ip_conntrack_helper_h323_asn1.c - BER and PER decoding library for H.323
3 * conntrack/NAT module.
4 *
5 * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@hotmail.com>
6 *
7 * This source code is licensed under General Public License version 2.
8 *
9 * See ip_conntrack_helper_h323_asn1.h for details.
10 *
11 ****************************************************************************/
12
13#ifdef __KERNEL__
14#include <linux/kernel.h>
15#else
16#include <stdio.h>
17#endif
18#include "ip_conntrack_helper_h323_asn1.h"
19
20/* Trace Flag */
21#ifndef H323_TRACE
22#define H323_TRACE 0
23#endif
24
25#if H323_TRACE
26#define TAB_SIZE 4
27#define IFTHEN(cond, act) if(cond){act;}
28#ifdef __KERNEL__
29#define PRINT printk
30#else
31#define PRINT printf
32#endif
33#define FNAME(name) name,
34#else
35#define IFTHEN(cond, act)
36#define PRINT(fmt, args...)
37#define FNAME(name)
38#endif
39
40/* ASN.1 Types */
41#define NUL 0
42#define BOOL 1
43#define OID 2
44#define INT 3
45#define ENUM 4
46#define BITSTR 5
47#define NUMSTR 6
48#define NUMDGT 6
49#define TBCDSTR 6
50#define OCTSTR 7
51#define PRTSTR 7
52#define IA5STR 7
53#define GENSTR 7
54#define BMPSTR 8
55#define SEQ 9
56#define SET 9
57#define SEQOF 10
58#define SETOF 10
59#define CHOICE 11
60
61/* Constraint Types */
62#define FIXD 0
63/* #define BITS 1-8 */
64#define BYTE 9
65#define WORD 10
66#define CONS 11
67#define SEMI 12
68#define UNCO 13
69
70/* ASN.1 Type Attributes */
71#define SKIP 0
72#define STOP 1
73#define DECODE 2
74#define EXT 4
75#define OPEN 8
76#define OPT 16
77
78
79/* ASN.1 Field Structure */
80typedef struct field_t {
81#if H323_TRACE
82 char *name;
83#endif
84 unsigned char type;
85 unsigned char sz;
86 unsigned char lb;
87 unsigned char ub;
88 unsigned short attr;
89 unsigned short offset;
90 struct field_t *fields;
91} field_t;
92
93/* Bit Stream */
94typedef struct {
95 unsigned char *buf;
96 unsigned char *beg;
97 unsigned char *end;
98 unsigned char *cur;
99 unsigned bit;
100} bitstr_t;
101
102/* Tool Functions */
103#define INC_BIT(bs) if((++bs->bit)>7){bs->cur++;bs->bit=0;}
104#define INC_BITS(bs,b) if((bs->bit+=b)>7){bs->cur+=bs->bit>>3;bs->bit&=7;}
105#define BYTE_ALIGN(bs) if(bs->bit){bs->cur++;bs->bit=0;}
106#define CHECK_BOUND(bs,n) if(bs->cur+(n)>bs->end)return(H323_ERROR_BOUND)
107static unsigned get_len(bitstr_t * bs);
108static unsigned get_bit(bitstr_t * bs);
109static unsigned get_bits(bitstr_t * bs, unsigned b);
110static unsigned get_bitmap(bitstr_t * bs, unsigned b);
111static unsigned get_uint(bitstr_t * bs, int b);
112
113/* Decoder Functions */
114static int decode_nul(bitstr_t * bs, field_t * f, char *base, int level);
115static int decode_bool(bitstr_t * bs, field_t * f, char *base, int level);
116static int decode_oid(bitstr_t * bs, field_t * f, char *base, int level);
117static int decode_int(bitstr_t * bs, field_t * f, char *base, int level);
118static int decode_enum(bitstr_t * bs, field_t * f, char *base, int level);
119static int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level);
120static int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level);
121static int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level);
122static int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level);
123static int decode_seq(bitstr_t * bs, field_t * f, char *base, int level);
124static int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level);
125static int decode_choice(bitstr_t * bs, field_t * f, char *base, int level);
126
127/* Decoder Functions Vector */
128typedef int (*decoder_t) (bitstr_t *, field_t *, char *, int);
129static decoder_t Decoders[] = {
130 decode_nul,
131 decode_bool,
132 decode_oid,
133 decode_int,
134 decode_enum,
135 decode_bitstr,
136 decode_numstr,
137 decode_octstr,
138 decode_bmpstr,
139 decode_seq,
140 decode_seqof,
141 decode_choice,
142};
143
144/****************************************************************************
145 * H.323 Types
146 ****************************************************************************/
147#include "ip_conntrack_helper_h323_types.c"
148
149/****************************************************************************
150 * Functions
151 ****************************************************************************/
152/* Assume bs is aligned && v < 16384 */
153unsigned get_len(bitstr_t * bs)
154{
155 unsigned v;
156
157 v = *bs->cur++;
158
159 if (v & 0x80) {
160 v &= 0x3f;
161 v <<= 8;
162 v += *bs->cur++;
163 }
164
165 return v;
166}
167
168/****************************************************************************/
169unsigned get_bit(bitstr_t * bs)
170{
171 unsigned b = (*bs->cur) & (0x80 >> bs->bit);
172
173 INC_BIT(bs);
174
175 return b;
176}
177
178/****************************************************************************/
179/* Assume b <= 8 */
180unsigned get_bits(bitstr_t * bs, unsigned b)
181{
182 unsigned v, l;
183
184 v = (*bs->cur) & (0xffU >> bs->bit);
185 l = b + bs->bit;
186
187 if (l < 8) {
188 v >>= 8 - l;
189 bs->bit = l;
190 } else if (l == 8) {
191 bs->cur++;
192 bs->bit = 0;
193 } else { /* l > 8 */
194
195 v <<= 8;
196 v += *(++bs->cur);
197 v >>= 16 - l;
198 bs->bit = l - 8;
199 }
200
201 return v;
202}
203
204/****************************************************************************/
205/* Assume b <= 32 */
206unsigned get_bitmap(bitstr_t * bs, unsigned b)
207{
208 unsigned v, l, shift, bytes;
209
210 if (!b)
211 return 0;
212
213 l = bs->bit + b;
214
215 if (l < 8) {
216 v = (unsigned) (*bs->cur) << (bs->bit + 24);
217 bs->bit = l;
218 } else if (l == 8) {
219 v = (unsigned) (*bs->cur++) << (bs->bit + 24);
220 bs->bit = 0;
221 } else {
222 for (bytes = l >> 3, shift = 24, v = 0; bytes;
223 bytes--, shift -= 8)
224 v |= (unsigned) (*bs->cur++) << shift;
225
226 if (l < 32) {
227 v |= (unsigned) (*bs->cur) << shift;
228 v <<= bs->bit;
229 } else if (l > 32) {
230 v <<= bs->bit;
231 v |= (*bs->cur) >> (8 - bs->bit);
232 }
233
234 bs->bit = l & 0x7;
235 }
236
237 v &= 0xffffffff << (32 - b);
238
239 return v;
240}
241
242/****************************************************************************
243 * Assume bs is aligned and sizeof(unsigned int) == 4
244 ****************************************************************************/
245unsigned get_uint(bitstr_t * bs, int b)
246{
247 unsigned v = 0;
248
249 switch (b) {
250 case 4:
251 v |= *bs->cur++;
252 v <<= 8;
253 case 3:
254 v |= *bs->cur++;
255 v <<= 8;
256 case 2:
257 v |= *bs->cur++;
258 v <<= 8;
259 case 1:
260 v |= *bs->cur++;
261 break;
262 }
263 return v;
264}
265
266/****************************************************************************/
267int decode_nul(bitstr_t * bs, field_t * f, char *base, int level)
268{
269 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
270
271 return H323_ERROR_NONE;
272}
273
274/****************************************************************************/
275int decode_bool(bitstr_t * bs, field_t * f, char *base, int level)
276{
277 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
278
279 INC_BIT(bs);
280
281 CHECK_BOUND(bs, 0);
282 return H323_ERROR_NONE;
283}
284
285/****************************************************************************/
286int decode_oid(bitstr_t * bs, field_t * f, char *base, int level)
287{
288 int len;
289
290 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
291
292 BYTE_ALIGN(bs);
293 CHECK_BOUND(bs, 1);
294 len = *bs->cur++;
295 bs->cur += len;
296
297 CHECK_BOUND(bs, 0);
298 return H323_ERROR_NONE;
299}
300
301/****************************************************************************/
302int decode_int(bitstr_t * bs, field_t * f, char *base, int level)
303{
304 unsigned len;
305
306 PRINT("%*.s%s", level * TAB_SIZE, " ", f->name);
307
308 switch (f->sz) {
309 case BYTE: /* Range == 256 */
310 BYTE_ALIGN(bs);
311 bs->cur++;
312 break;
313 case WORD: /* 257 <= Range <= 64K */
314 BYTE_ALIGN(bs);
315 bs->cur += 2;
316 break;
317 case CONS: /* 64K < Range < 4G */
318 len = get_bits(bs, 2) + 1;
319 BYTE_ALIGN(bs);
320 if (base && (f->attr & DECODE)) { /* timeToLive */
321 unsigned v = get_uint(bs, len) + f->lb;
322 PRINT(" = %u", v);
323 *((unsigned *) (base + f->offset)) = v;
324 }
325 bs->cur += len;
326 break;
327 case UNCO:
328 BYTE_ALIGN(bs);
329 CHECK_BOUND(bs, 2);
330 len = get_len(bs);
331 bs->cur += len;
332 break;
333 default: /* 2 <= Range <= 255 */
334 INC_BITS(bs, f->sz);
335 break;
336 }
337
338 PRINT("\n");
339
340 CHECK_BOUND(bs, 0);
341 return H323_ERROR_NONE;
342}
343
344/****************************************************************************/
345int decode_enum(bitstr_t * bs, field_t * f, char *base, int level)
346{
347 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
348
349 if ((f->attr & EXT) && get_bit(bs)) {
350 INC_BITS(bs, 7);
351 } else {
352 INC_BITS(bs, f->sz);
353 }
354
355 CHECK_BOUND(bs, 0);
356 return H323_ERROR_NONE;
357}
358
359/****************************************************************************/
360int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level)
361{
362 unsigned len;
363
364 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
365
366 BYTE_ALIGN(bs);
367 switch (f->sz) {
368 case FIXD: /* fixed length > 16 */
369 len = f->lb;
370 break;
371 case WORD: /* 2-byte length */
372 CHECK_BOUND(bs, 2);
373 len = (*bs->cur++) << 8;
374 len += (*bs->cur++) + f->lb;
375 break;
376 case SEMI:
377 CHECK_BOUND(bs, 2);
378 len = get_len(bs);
379 break;
380 default:
381 len = 0;
382 break;
383 }
384
385 bs->cur += len >> 3;
386 bs->bit = len & 7;
387
388 CHECK_BOUND(bs, 0);
389 return H323_ERROR_NONE;
390}
391
392/****************************************************************************/
393int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level)
394{
395 unsigned len;
396
397 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
398
399 /* 2 <= Range <= 255 */
400 len = get_bits(bs, f->sz) + f->lb;
401
402 BYTE_ALIGN(bs);
403 INC_BITS(bs, (len << 2));
404
405 CHECK_BOUND(bs, 0);
406 return H323_ERROR_NONE;
407}
408
409/****************************************************************************/
410int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level)
411{
412 unsigned len;
413
414 PRINT("%*.s%s", level * TAB_SIZE, " ", f->name);
415
416 switch (f->sz) {
417 case FIXD: /* Range == 1 */
418 if (f->lb > 2) {
419 BYTE_ALIGN(bs);
420 if (base && (f->attr & DECODE)) {
421 /* The IP Address */
422 IFTHEN(f->lb == 4,
423 PRINT(" = %d.%d.%d.%d:%d",
424 bs->cur[0], bs->cur[1],
425 bs->cur[2], bs->cur[3],
426 bs->cur[4] * 256 + bs->cur[5]));
427 *((unsigned *) (base + f->offset)) =
428 bs->cur - bs->buf;
429 }
430 }
431 len = f->lb;
432 break;
433 case BYTE: /* Range == 256 */
434 BYTE_ALIGN(bs);
435 CHECK_BOUND(bs, 1);
436 len = (*bs->cur++) + f->lb;
437 break;
438 case SEMI:
439 BYTE_ALIGN(bs);
440 CHECK_BOUND(bs, 2);
441 len = get_len(bs) + f->lb;
442 break;
443 default: /* 2 <= Range <= 255 */
444 len = get_bits(bs, f->sz) + f->lb;
445 BYTE_ALIGN(bs);
446 break;
447 }
448
449 bs->cur += len;
450
451 PRINT("\n");
452
453 CHECK_BOUND(bs, 0);
454 return H323_ERROR_NONE;
455}
456
457/****************************************************************************/
458int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level)
459{
460 unsigned len;
461
462 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
463
464 switch (f->sz) {
465 case BYTE: /* Range == 256 */
466 BYTE_ALIGN(bs);
467 CHECK_BOUND(bs, 1);
468 len = (*bs->cur++) + f->lb;
469 break;
470 default: /* 2 <= Range <= 255 */
471 len = get_bits(bs, f->sz) + f->lb;
472 BYTE_ALIGN(bs);
473 break;
474 }
475
476 bs->cur += len << 1;
477
478 CHECK_BOUND(bs, 0);
479 return H323_ERROR_NONE;
480}
481
482/****************************************************************************/
483int decode_seq(bitstr_t * bs, field_t * f, char *base, int level)
484{
485 unsigned ext, bmp, i, opt, len = 0, bmp2, bmp2_len;
486 int err;
487 field_t *son;
488 unsigned char *beg = NULL;
489
490 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
491
492 /* Decode? */
493 base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
494
495 /* Extensible? */
496 ext = (f->attr & EXT) ? get_bit(bs) : 0;
497
498 /* Get fields bitmap */
499 bmp = get_bitmap(bs, f->sz);
500 if (base)
501 *(unsigned *) base = bmp;
502
503 /* Decode the root components */
504 for (i = opt = 0, son = f->fields; i < f->lb; i++, son++) {
505 if (son->attr & STOP) {
506 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
507 son->name);
508 return H323_ERROR_STOP;
509 }
510
511 if (son->attr & OPT) { /* Optional component */
512 if (!((0x80000000U >> (opt++)) & bmp)) /* Not exist */
513 continue;
514 }
515
516 /* Decode */
517 if (son->attr & OPEN) { /* Open field */
518 CHECK_BOUND(bs, 2);
519 len = get_len(bs);
520 CHECK_BOUND(bs, len);
521 if (!base) {
522 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
523 " ", son->name);
524 bs->cur += len;
525 continue;
526 }
527 beg = bs->cur;
528
529 /* Decode */
530 if ((err = (Decoders[son->type]) (bs, son, base,
531 level + 1)) >
532 H323_ERROR_STOP)
533 return err;
534
535 bs->cur = beg + len;
536 bs->bit = 0;
537 } else if ((err = (Decoders[son->type]) (bs, son, base,
538 level + 1)))
539 return err;
540 }
541
542 /* No extension? */
543 if (!ext)
544 return H323_ERROR_NONE;
545
546 /* Get the extension bitmap */
547 bmp2_len = get_bits(bs, 7) + 1;
548 CHECK_BOUND(bs, (bmp2_len + 7) >> 3);
549 bmp2 = get_bitmap(bs, bmp2_len);
550 bmp |= bmp2 >> f->sz;
551 if (base)
552 *(unsigned *) base = bmp;
553 BYTE_ALIGN(bs);
554
555 /* Decode the extension components */
556 for (opt = 0; opt < bmp2_len; opt++, i++, son++) {
557 if (son->attr & STOP) {
558 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
559 son->name);
560 return H323_ERROR_STOP;
561 }
562
563 if (!((0x80000000 >> opt) & bmp2)) /* Not present */
564 continue;
565
566 /* Check Range */
567 if (i >= f->ub) { /* Newer Version? */
568 CHECK_BOUND(bs, 2);
569 len = get_len(bs);
570 CHECK_BOUND(bs, len);
571 bs->cur += len;
572 continue;
573 }
574
575 CHECK_BOUND(bs, 2);
576 len = get_len(bs);
577 CHECK_BOUND(bs, len);
578 if (!base || !(son->attr & DECODE)) {
579 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
580 son->name);
581 bs->cur += len;
582 continue;
583 }
584 beg = bs->cur;
585
586 if ((err = (Decoders[son->type]) (bs, son, base,
587 level + 1)) >
588 H323_ERROR_STOP)
589 return err;
590
591 bs->cur = beg + len;
592 bs->bit = 0;
593 }
594 return H323_ERROR_NONE;
595}
596
597/****************************************************************************/
598int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level)
599{
600 unsigned count, effective_count = 0, i, len = 0;
601 int err;
602 field_t *son;
603 unsigned char *beg = NULL;
604
605 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
606
607 /* Decode? */
608 base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
609
610 /* Decode item count */
611 switch (f->sz) {
612 case BYTE:
613 BYTE_ALIGN(bs);
614 CHECK_BOUND(bs, 1);
615 count = *bs->cur++;
616 break;
617 case WORD:
618 BYTE_ALIGN(bs);
619 CHECK_BOUND(bs, 2);
620 count = *bs->cur++;
621 count <<= 8;
622 count = *bs->cur++;
623 break;
624 case SEMI:
625 BYTE_ALIGN(bs);
626 CHECK_BOUND(bs, 2);
627 count = get_len(bs);
628 break;
629 default:
630 count = get_bits(bs, f->sz);
631 break;
632 }
633 count += f->lb;
634
635 /* Write Count */
636 if (base) {
637 effective_count = count > f->ub ? f->ub : count;
638 *(unsigned *) base = effective_count;
639 base += sizeof(unsigned);
640 }
641
642 /* Decode nested field */
643 son = f->fields;
644 if (base)
645 base -= son->offset;
646 for (i = 0; i < count; i++) {
647 if (son->attr & OPEN) {
648 BYTE_ALIGN(bs);
649 len = get_len(bs);
650 CHECK_BOUND(bs, len);
651 if (!base || !(son->attr & DECODE)) {
652 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
653 " ", son->name);
654 bs->cur += len;
655 continue;
656 }
657 beg = bs->cur;
658
659 if ((err = (Decoders[son->type]) (bs, son,
660 i <
661 effective_count ?
662 base : NULL,
663 level + 1)) >
664 H323_ERROR_STOP)
665 return err;
666
667 bs->cur = beg + len;
668 bs->bit = 0;
669 } else
670 if ((err = (Decoders[son->type]) (bs, son,
671 i < effective_count ?
672 base : NULL,
673 level + 1)))
674 return err;
675
676 if (base)
677 base += son->offset;
678 }
679
680 return H323_ERROR_NONE;
681}
682
683
684/****************************************************************************/
685int decode_choice(bitstr_t * bs, field_t * f, char *base, int level)
686{
687 unsigned type, ext, len = 0;
688 int err;
689 field_t *son;
690 unsigned char *beg = NULL;
691
692 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
693
694 /* Decode? */
695 base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
696
697 /* Decode the choice index number */
698 if ((f->attr & EXT) && get_bit(bs)) {
699 ext = 1;
700 type = get_bits(bs, 7) + f->lb;
701 } else {
702 ext = 0;
703 type = get_bits(bs, f->sz);
704 }
705
706 /* Check Range */
707 if (type >= f->ub) { /* Newer version? */
708 BYTE_ALIGN(bs);
709 len = get_len(bs);
710 CHECK_BOUND(bs, len);
711 bs->cur += len;
712 return H323_ERROR_NONE;
713 }
714
715 /* Write Type */
716 if (base)
717 *(unsigned *) base = type;
718
719 /* Transfer to son level */
720 son = &f->fields[type];
721 if (son->attr & STOP) {
722 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", son->name);
723 return H323_ERROR_STOP;
724 }
725
726 if (ext || (son->attr & OPEN)) {
727 BYTE_ALIGN(bs);
728 len = get_len(bs);
729 CHECK_BOUND(bs, len);
730 if (!base || !(son->attr & DECODE)) {
731 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
732 son->name);
733 bs->cur += len;
734 return H323_ERROR_NONE;
735 }
736 beg = bs->cur;
737
738 if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) >
739 H323_ERROR_STOP)
740 return err;
741
742 bs->cur = beg + len;
743 bs->bit = 0;
744 } else if ((err = (Decoders[son->type]) (bs, son, base, level + 1)))
745 return err;
746
747 return H323_ERROR_NONE;
748}
749
750/****************************************************************************/
751int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras)
752{
753 static field_t ras_message = {
754 FNAME("RasMessage") CHOICE, 5, 24, 32, DECODE | EXT,
755 0, _RasMessage
756 };
757 bitstr_t bs;
758
759 bs.buf = bs.beg = bs.cur = buf;
760 bs.end = buf + sz;
761 bs.bit = 0;
762
763 return decode_choice(&bs, &ras_message, (char *) ras, 0);
764}
765
766/****************************************************************************/
767static int DecodeH323_UserInformation(unsigned char *buf, unsigned char *beg,
768 size_t sz, H323_UserInformation * uuie)
769{
770 static field_t h323_userinformation = {
771 FNAME("H323-UserInformation") SEQ, 1, 2, 2, DECODE | EXT,
772 0, _H323_UserInformation
773 };
774 bitstr_t bs;
775
776 bs.buf = buf;
777 bs.beg = bs.cur = beg;
778 bs.end = beg + sz;
779 bs.bit = 0;
780
781 return decode_seq(&bs, &h323_userinformation, (char *) uuie, 0);
782}
783
784/****************************************************************************/
785int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz,
786 MultimediaSystemControlMessage *
787 mscm)
788{
789 static field_t multimediasystemcontrolmessage = {
790 FNAME("MultimediaSystemControlMessage") CHOICE, 2, 4, 4,
791 DECODE | EXT, 0, _MultimediaSystemControlMessage
792 };
793 bitstr_t bs;
794
795 bs.buf = bs.beg = bs.cur = buf;
796 bs.end = buf + sz;
797 bs.bit = 0;
798
799 return decode_choice(&bs, &multimediasystemcontrolmessage,
800 (char *) mscm, 0);
801}
802
803/****************************************************************************/
804int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931)
805{
806 unsigned char *p = buf;
807 int len;
808
809 if (!p || sz < 1)
810 return H323_ERROR_BOUND;
811
812 /* Protocol Discriminator */
813 if (*p != 0x08) {
814 PRINT("Unknown Protocol Discriminator\n");
815 return H323_ERROR_RANGE;
816 }
817 p++;
818 sz--;
819
820 /* CallReferenceValue */
821 if (sz < 1)
822 return H323_ERROR_BOUND;
823 len = *p++;
824 sz--;
825 if (sz < len)
826 return H323_ERROR_BOUND;
827 p += len;
828 sz -= len;
829
830 /* Message Type */
831 if (sz < 1)
832 return H323_ERROR_BOUND;
833 q931->MessageType = *p++;
834 PRINT("MessageType = %02X\n", q931->MessageType);
835 if (*p & 0x80) {
836 p++;
837 sz--;
838 }
839
840 /* Decode Information Elements */
841 while (sz > 0) {
842 if (*p == 0x7e) { /* UserUserIE */
843 if (sz < 3)
844 break;
845 p++;
846 len = *p++ << 8;
847 len |= *p++;
848 sz -= 3;
849 if (sz < len)
850 break;
851 p++;
852 len--;
853 return DecodeH323_UserInformation(buf, p, len,
854 &q931->UUIE);
855 }
856 p++;
857 sz--;
858 if (sz < 1)
859 break;
860 len = *p++;
861 if (sz < len)
862 break;
863 p += len;
864 sz -= len;
865 }
866
867 PRINT("Q.931 UUIE not found\n");
868
869 return H323_ERROR_BOUND;
870}
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h
new file mode 100644
index 000000000000..0bd828081c0c
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h
@@ -0,0 +1,98 @@
1/****************************************************************************
2 * ip_conntrack_helper_h323_asn1.h - BER and PER decoding library for H.323
3 * conntrack/NAT module.
4 *
5 * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@hotmail.com>
6 *
7 * This source code is licensed under General Public License version 2.
8 *
9 *
10 * This library is based on H.225 version 4, H.235 version 2 and H.245
11 * version 7. It is extremely optimized to decode only the absolutely
12 * necessary objects in a signal for Linux kernel NAT module use, so don't
13 * expect it to be a full ASN.1 library.
14 *
15 * Features:
16 *
17 * 1. Small. The total size of code plus data is less than 20 KB (IA32).
18 * 2. Fast. Decoding Netmeeting's Setup signal 1 million times on a PIII 866
19 * takes only 3.9 seconds.
20 * 3. No memory allocation. It uses a static object. No need to initialize or
21 * cleanup.
22 * 4. Thread safe.
23 * 5. Support embedded architectures that has no misaligned memory access
24 * support.
25 *
26 * Limitations:
27 *
28 * 1. At most 30 faststart entries. Actually this is limited by ethernet's MTU.
29 * If a Setup signal contains more than 30 faststart, the packet size will
30 * very likely exceed the MTU size, then the TPKT will be fragmented. I
31 * don't know how to handle this in a Netfilter module. Anybody can help?
32 * Although I think 30 is enough for most of the cases.
33 * 2. IPv4 addresses only.
34 *
35 ****************************************************************************/
36
37#ifndef _IP_CONNTRACK_HELPER_H323_ASN1_H_
38#define _IP_CONNTRACK_HELPER_H323_ASN1_H_
39
40/*****************************************************************************
41 * H.323 Types
42 ****************************************************************************/
43#include "ip_conntrack_helper_h323_types.h"
44
45typedef struct {
46 enum {
47 Q931_NationalEscape = 0x00,
48 Q931_Alerting = 0x01,
49 Q931_CallProceeding = 0x02,
50 Q931_Connect = 0x07,
51 Q931_ConnectAck = 0x0F,
52 Q931_Progress = 0x03,
53 Q931_Setup = 0x05,
54 Q931_SetupAck = 0x0D,
55 Q931_Resume = 0x26,
56 Q931_ResumeAck = 0x2E,
57 Q931_ResumeReject = 0x22,
58 Q931_Suspend = 0x25,
59 Q931_SuspendAck = 0x2D,
60 Q931_SuspendReject = 0x21,
61 Q931_UserInformation = 0x20,
62 Q931_Disconnect = 0x45,
63 Q931_Release = 0x4D,
64 Q931_ReleaseComplete = 0x5A,
65 Q931_Restart = 0x46,
66 Q931_RestartAck = 0x4E,
67 Q931_Segment = 0x60,
68 Q931_CongestionCtrl = 0x79,
69 Q931_Information = 0x7B,
70 Q931_Notify = 0x6E,
71 Q931_Status = 0x7D,
72 Q931_StatusEnquiry = 0x75,
73 Q931_Facility = 0x62
74 } MessageType;
75 H323_UserInformation UUIE;
76} Q931;
77
78/*****************************************************************************
79 * Decode Functions Return Codes
80 ****************************************************************************/
81
82#define H323_ERROR_NONE 0 /* Decoded successfully */
83#define H323_ERROR_STOP 1 /* Decoding stopped, not really an error */
84#define H323_ERROR_BOUND -1
85#define H323_ERROR_RANGE -2
86
87
88/*****************************************************************************
89 * Decode Functions
90 ****************************************************************************/
91
92int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras);
93int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931);
94int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz,
95 MultimediaSystemControlMessage *
96 mscm);
97
98#endif
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
new file mode 100644
index 000000000000..022c47b9f6c9
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
@@ -0,0 +1,1926 @@
1/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006
2 *
3 * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
4 *
5 * This source code is licensed under General Public License version 2.
6 */
7
8static field_t _TransportAddress_ipAddress[] = { /* SEQUENCE */
9 {FNAME("ip") OCTSTR, FIXD, 4, 0, DECODE,
10 offsetof(TransportAddress_ipAddress, ip), NULL},
11 {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL},
12};
13
14static field_t _TransportAddress_ipSourceRoute_route[] = { /* SEQUENCE OF */
15 {FNAME("item") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
16};
17
18static field_t _TransportAddress_ipSourceRoute_routing[] = { /* CHOICE */
19 {FNAME("strict") NUL, FIXD, 0, 0, SKIP, 0, NULL},
20 {FNAME("loose") NUL, FIXD, 0, 0, SKIP, 0, NULL},
21};
22
23static field_t _TransportAddress_ipSourceRoute[] = { /* SEQUENCE */
24 {FNAME("ip") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
25 {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL},
26 {FNAME("route") SEQOF, SEMI, 0, 0, SKIP, 0,
27 _TransportAddress_ipSourceRoute_route},
28 {FNAME("routing") CHOICE, 1, 2, 2, SKIP | EXT, 0,
29 _TransportAddress_ipSourceRoute_routing},
30};
31
32static field_t _TransportAddress_ipxAddress[] = { /* SEQUENCE */
33 {FNAME("node") OCTSTR, FIXD, 6, 0, SKIP, 0, NULL},
34 {FNAME("netnum") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
35 {FNAME("port") OCTSTR, FIXD, 2, 0, SKIP, 0, NULL},
36};
37
38static field_t _TransportAddress_ip6Address[] = { /* SEQUENCE */
39 {FNAME("ip") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
40 {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL},
41};
42
43static field_t _H221NonStandard[] = { /* SEQUENCE */
44 {FNAME("t35CountryCode") INT, BYTE, 0, 0, SKIP, 0, NULL},
45 {FNAME("t35Extension") INT, BYTE, 0, 0, SKIP, 0, NULL},
46 {FNAME("manufacturerCode") INT, WORD, 0, 0, SKIP, 0, NULL},
47};
48
49static field_t _NonStandardIdentifier[] = { /* CHOICE */
50 {FNAME("object") OID, BYTE, 0, 0, SKIP, 0, NULL},
51 {FNAME("h221NonStandard") SEQ, 0, 3, 3, SKIP | EXT, 0,
52 _H221NonStandard},
53};
54
55static field_t _NonStandardParameter[] = { /* SEQUENCE */
56 {FNAME("nonStandardIdentifier") CHOICE, 1, 2, 2, SKIP | EXT, 0,
57 _NonStandardIdentifier},
58 {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
59};
60
61static field_t _TransportAddress[] = { /* CHOICE */
62 {FNAME("ipAddress") SEQ, 0, 2, 2, DECODE,
63 offsetof(TransportAddress, ipAddress), _TransportAddress_ipAddress},
64 {FNAME("ipSourceRoute") SEQ, 0, 4, 4, SKIP | EXT, 0,
65 _TransportAddress_ipSourceRoute},
66 {FNAME("ipxAddress") SEQ, 0, 3, 3, SKIP, 0,
67 _TransportAddress_ipxAddress},
68 {FNAME("ip6Address") SEQ, 0, 2, 2, SKIP | EXT, 0,
69 _TransportAddress_ip6Address},
70 {FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
71 {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL},
72 {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0,
73 _NonStandardParameter},
74};
75
76static field_t _AliasAddress[] = { /* CHOICE */
77 {FNAME("dialedDigits") NUMDGT, 7, 1, 0, SKIP, 0, NULL},
78 {FNAME("h323-ID") BMPSTR, BYTE, 1, 0, SKIP, 0, NULL},
79 {FNAME("url-ID") IA5STR, WORD, 1, 0, SKIP, 0, NULL},
80 {FNAME("transportID") CHOICE, 3, 7, 7, SKIP | EXT, 0, NULL},
81 {FNAME("email-ID") IA5STR, WORD, 1, 0, SKIP, 0, NULL},
82 {FNAME("partyNumber") CHOICE, 3, 5, 5, SKIP | EXT, 0, NULL},
83 {FNAME("mobileUIM") CHOICE, 1, 2, 2, SKIP | EXT, 0, NULL},
84};
85
86static field_t _Setup_UUIE_sourceAddress[] = { /* SEQUENCE OF */
87 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
88};
89
90static field_t _VendorIdentifier[] = { /* SEQUENCE */
91 {FNAME("vendor") SEQ, 0, 3, 3, SKIP | EXT, 0, _H221NonStandard},
92 {FNAME("productId") OCTSTR, BYTE, 1, 0, SKIP | OPT, 0, NULL},
93 {FNAME("versionId") OCTSTR, BYTE, 1, 0, SKIP | OPT, 0, NULL},
94};
95
96static field_t _GatekeeperInfo[] = { /* SEQUENCE */
97 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
98 _NonStandardParameter},
99};
100
101static field_t _H310Caps[] = { /* SEQUENCE */
102 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
103 _NonStandardParameter},
104 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
105 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
106};
107
108static field_t _H320Caps[] = { /* SEQUENCE */
109 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
110 _NonStandardParameter},
111 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
112 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
113};
114
115static field_t _H321Caps[] = { /* SEQUENCE */
116 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
117 _NonStandardParameter},
118 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
119 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
120};
121
122static field_t _H322Caps[] = { /* SEQUENCE */
123 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
124 _NonStandardParameter},
125 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
126 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
127};
128
129static field_t _H323Caps[] = { /* SEQUENCE */
130 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
131 _NonStandardParameter},
132 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
133 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
134};
135
136static field_t _H324Caps[] = { /* SEQUENCE */
137 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
138 _NonStandardParameter},
139 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
140 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
141};
142
143static field_t _VoiceCaps[] = { /* SEQUENCE */
144 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
145 _NonStandardParameter},
146 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
147 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
148};
149
150static field_t _T120OnlyCaps[] = { /* SEQUENCE */
151 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
152 _NonStandardParameter},
153 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
154 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
155};
156
157static field_t _SupportedProtocols[] = { /* CHOICE */
158 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP, 0,
159 _NonStandardParameter},
160 {FNAME("h310") SEQ, 1, 1, 3, SKIP | EXT, 0, _H310Caps},
161 {FNAME("h320") SEQ, 1, 1, 3, SKIP | EXT, 0, _H320Caps},
162 {FNAME("h321") SEQ, 1, 1, 3, SKIP | EXT, 0, _H321Caps},
163 {FNAME("h322") SEQ, 1, 1, 3, SKIP | EXT, 0, _H322Caps},
164 {FNAME("h323") SEQ, 1, 1, 3, SKIP | EXT, 0, _H323Caps},
165 {FNAME("h324") SEQ, 1, 1, 3, SKIP | EXT, 0, _H324Caps},
166 {FNAME("voice") SEQ, 1, 1, 3, SKIP | EXT, 0, _VoiceCaps},
167 {FNAME("t120-only") SEQ, 1, 1, 3, SKIP | EXT, 0, _T120OnlyCaps},
168 {FNAME("nonStandardProtocol") SEQ, 2, 3, 3, SKIP | EXT, 0, NULL},
169 {FNAME("t38FaxAnnexbOnly") SEQ, 2, 5, 5, SKIP | EXT, 0, NULL},
170};
171
172static field_t _GatewayInfo_protocol[] = { /* SEQUENCE OF */
173 {FNAME("item") CHOICE, 4, 9, 11, SKIP | EXT, 0, _SupportedProtocols},
174};
175
176static field_t _GatewayInfo[] = { /* SEQUENCE */
177 {FNAME("protocol") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
178 _GatewayInfo_protocol},
179 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
180 _NonStandardParameter},
181};
182
183static field_t _McuInfo[] = { /* SEQUENCE */
184 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
185 _NonStandardParameter},
186 {FNAME("protocol") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
187};
188
189static field_t _TerminalInfo[] = { /* SEQUENCE */
190 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
191 _NonStandardParameter},
192};
193
194static field_t _EndpointType[] = { /* SEQUENCE */
195 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
196 _NonStandardParameter},
197 {FNAME("vendor") SEQ, 2, 3, 3, SKIP | EXT | OPT, 0,
198 _VendorIdentifier},
199 {FNAME("gatekeeper") SEQ, 1, 1, 1, SKIP | EXT | OPT, 0,
200 _GatekeeperInfo},
201 {FNAME("gateway") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, _GatewayInfo},
202 {FNAME("mcu") SEQ, 1, 1, 2, SKIP | EXT | OPT, 0, _McuInfo},
203 {FNAME("terminal") SEQ, 1, 1, 1, SKIP | EXT | OPT, 0, _TerminalInfo},
204 {FNAME("mc") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
205 {FNAME("undefinedNode") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
206 {FNAME("set") BITSTR, FIXD, 32, 0, SKIP | OPT, 0, NULL},
207 {FNAME("supportedTunnelledProtocols") SEQOF, SEMI, 0, 0, SKIP | OPT,
208 0, NULL},
209};
210
211static field_t _Setup_UUIE_destinationAddress[] = { /* SEQUENCE OF */
212 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
213};
214
215static field_t _Setup_UUIE_destExtraCallInfo[] = { /* SEQUENCE OF */
216 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
217};
218
219static field_t _Setup_UUIE_destExtraCRV[] = { /* SEQUENCE OF */
220 {FNAME("item") INT, WORD, 0, 0, SKIP, 0, NULL},
221};
222
223static field_t _Setup_UUIE_conferenceGoal[] = { /* CHOICE */
224 {FNAME("create") NUL, FIXD, 0, 0, SKIP, 0, NULL},
225 {FNAME("join") NUL, FIXD, 0, 0, SKIP, 0, NULL},
226 {FNAME("invite") NUL, FIXD, 0, 0, SKIP, 0, NULL},
227 {FNAME("capability-negotiation") NUL, FIXD, 0, 0, SKIP, 0, NULL},
228 {FNAME("callIndependentSupplementaryService") NUL, FIXD, 0, 0, SKIP,
229 0, NULL},
230};
231
232static field_t _Q954Details[] = { /* SEQUENCE */
233 {FNAME("conferenceCalling") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
234 {FNAME("threePartyService") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
235};
236
237static field_t _QseriesOptions[] = { /* SEQUENCE */
238 {FNAME("q932Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
239 {FNAME("q951Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
240 {FNAME("q952Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
241 {FNAME("q953Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
242 {FNAME("q955Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
243 {FNAME("q956Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
244 {FNAME("q957Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
245 {FNAME("q954Info") SEQ, 0, 2, 2, SKIP | EXT, 0, _Q954Details},
246};
247
248static field_t _CallType[] = { /* CHOICE */
249 {FNAME("pointToPoint") NUL, FIXD, 0, 0, SKIP, 0, NULL},
250 {FNAME("oneToN") NUL, FIXD, 0, 0, SKIP, 0, NULL},
251 {FNAME("nToOne") NUL, FIXD, 0, 0, SKIP, 0, NULL},
252 {FNAME("nToN") NUL, FIXD, 0, 0, SKIP, 0, NULL},
253};
254
255static field_t _H245_NonStandardIdentifier_h221NonStandard[] = { /* SEQUENCE */
256 {FNAME("t35CountryCode") INT, BYTE, 0, 0, SKIP, 0, NULL},
257 {FNAME("t35Extension") INT, BYTE, 0, 0, SKIP, 0, NULL},
258 {FNAME("manufacturerCode") INT, WORD, 0, 0, SKIP, 0, NULL},
259};
260
261static field_t _H245_NonStandardIdentifier[] = { /* CHOICE */
262 {FNAME("object") OID, BYTE, 0, 0, SKIP, 0, NULL},
263 {FNAME("h221NonStandard") SEQ, 0, 3, 3, SKIP, 0,
264 _H245_NonStandardIdentifier_h221NonStandard},
265};
266
267static field_t _H245_NonStandardParameter[] = { /* SEQUENCE */
268 {FNAME("nonStandardIdentifier") CHOICE, 1, 2, 2, SKIP, 0,
269 _H245_NonStandardIdentifier},
270 {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
271};
272
273static field_t _H261VideoCapability[] = { /* SEQUENCE */
274 {FNAME("qcifMPI") INT, 2, 1, 0, SKIP | OPT, 0, NULL},
275 {FNAME("cifMPI") INT, 2, 1, 0, SKIP | OPT, 0, NULL},
276 {FNAME("temporalSpatialTradeOffCapability") BOOL, FIXD, 0, 0, SKIP, 0,
277 NULL},
278 {FNAME("maxBitRate") INT, WORD, 1, 0, SKIP, 0, NULL},
279 {FNAME("stillImageTransmission") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
280 {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
281};
282
283static field_t _H262VideoCapability[] = { /* SEQUENCE */
284 {FNAME("profileAndLevel-SPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
285 {FNAME("profileAndLevel-MPatLL") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
286 {FNAME("profileAndLevel-MPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
287 {FNAME("profileAndLevel-MPatH-14") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
288 {FNAME("profileAndLevel-MPatHL") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
289 {FNAME("profileAndLevel-SNRatLL") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
290 {FNAME("profileAndLevel-SNRatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
291 {FNAME("profileAndLevel-SpatialatH-14") BOOL, FIXD, 0, 0, SKIP, 0,
292 NULL},
293 {FNAME("profileAndLevel-HPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
294 {FNAME("profileAndLevel-HPatH-14") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
295 {FNAME("profileAndLevel-HPatHL") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
296 {FNAME("videoBitRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
297 {FNAME("vbvBufferSize") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
298 {FNAME("samplesPerLine") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
299 {FNAME("linesPerFrame") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
300 {FNAME("framesPerSecond") INT, 4, 0, 0, SKIP | OPT, 0, NULL},
301 {FNAME("luminanceSampleRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
302 {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
303};
304
305static field_t _H263VideoCapability[] = { /* SEQUENCE */
306 {FNAME("sqcifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
307 {FNAME("qcifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
308 {FNAME("cifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
309 {FNAME("cif4MPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
310 {FNAME("cif16MPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
311 {FNAME("maxBitRate") INT, CONS, 1, 0, SKIP, 0, NULL},
312 {FNAME("unrestrictedVector") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
313 {FNAME("arithmeticCoding") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
314 {FNAME("advancedPrediction") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
315 {FNAME("pbFrames") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
316 {FNAME("temporalSpatialTradeOffCapability") BOOL, FIXD, 0, 0, SKIP, 0,
317 NULL},
318 {FNAME("hrd-B") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
319 {FNAME("bppMaxKb") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
320 {FNAME("slowSqcifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
321 {FNAME("slowQcifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
322 {FNAME("slowCifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
323 {FNAME("slowCif4MPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
324 {FNAME("slowCif16MPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
325 {FNAME("errorCompensation") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
326 {FNAME("enhancementLayerInfo") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0,
327 NULL},
328 {FNAME("h263Options") SEQ, 5, 29, 31, SKIP | EXT | OPT, 0, NULL},
329};
330
331static field_t _IS11172VideoCapability[] = { /* SEQUENCE */
332 {FNAME("constrainedBitstream") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
333 {FNAME("videoBitRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
334 {FNAME("vbvBufferSize") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
335 {FNAME("samplesPerLine") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
336 {FNAME("linesPerFrame") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
337 {FNAME("pictureRate") INT, 4, 0, 0, SKIP | OPT, 0, NULL},
338 {FNAME("luminanceSampleRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
339 {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
340};
341
342static field_t _VideoCapability[] = { /* CHOICE */
343 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
344 _H245_NonStandardParameter},
345 {FNAME("h261VideoCapability") SEQ, 2, 5, 6, SKIP | EXT, 0,
346 _H261VideoCapability},
347 {FNAME("h262VideoCapability") SEQ, 6, 17, 18, SKIP | EXT, 0,
348 _H262VideoCapability},
349 {FNAME("h263VideoCapability") SEQ, 7, 13, 21, SKIP | EXT, 0,
350 _H263VideoCapability},
351 {FNAME("is11172VideoCapability") SEQ, 6, 7, 8, SKIP | EXT, 0,
352 _IS11172VideoCapability},
353 {FNAME("genericVideoCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL},
354};
355
356static field_t _AudioCapability_g7231[] = { /* SEQUENCE */
357 {FNAME("maxAl-sduAudioFrames") INT, BYTE, 1, 0, SKIP, 0, NULL},
358 {FNAME("silenceSuppression") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
359};
360
361static field_t _IS11172AudioCapability[] = { /* SEQUENCE */
362 {FNAME("audioLayer1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
363 {FNAME("audioLayer2") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
364 {FNAME("audioLayer3") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
365 {FNAME("audioSampling32k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
366 {FNAME("audioSampling44k1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
367 {FNAME("audioSampling48k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
368 {FNAME("singleChannel") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
369 {FNAME("twoChannels") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
370 {FNAME("bitRate") INT, WORD, 1, 0, SKIP, 0, NULL},
371};
372
373static field_t _IS13818AudioCapability[] = { /* SEQUENCE */
374 {FNAME("audioLayer1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
375 {FNAME("audioLayer2") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
376 {FNAME("audioLayer3") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
377 {FNAME("audioSampling16k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
378 {FNAME("audioSampling22k05") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
379 {FNAME("audioSampling24k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
380 {FNAME("audioSampling32k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
381 {FNAME("audioSampling44k1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
382 {FNAME("audioSampling48k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
383 {FNAME("singleChannel") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
384 {FNAME("twoChannels") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
385 {FNAME("threeChannels2-1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
386 {FNAME("threeChannels3-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
387 {FNAME("fourChannels2-0-2-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
388 {FNAME("fourChannels2-2") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
389 {FNAME("fourChannels3-1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
390 {FNAME("fiveChannels3-0-2-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
391 {FNAME("fiveChannels3-2") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
392 {FNAME("lowFrequencyEnhancement") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
393 {FNAME("multilingual") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
394 {FNAME("bitRate") INT, WORD, 1, 0, SKIP, 0, NULL},
395};
396
397static field_t _AudioCapability[] = { /* CHOICE */
398 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
399 _H245_NonStandardParameter},
400 {FNAME("g711Alaw64k") INT, BYTE, 1, 0, SKIP, 0, NULL},
401 {FNAME("g711Alaw56k") INT, BYTE, 1, 0, SKIP, 0, NULL},
402 {FNAME("g711Ulaw64k") INT, BYTE, 1, 0, SKIP, 0, NULL},
403 {FNAME("g711Ulaw56k") INT, BYTE, 1, 0, SKIP, 0, NULL},
404 {FNAME("g722-64k") INT, BYTE, 1, 0, SKIP, 0, NULL},
405 {FNAME("g722-56k") INT, BYTE, 1, 0, SKIP, 0, NULL},
406 {FNAME("g722-48k") INT, BYTE, 1, 0, SKIP, 0, NULL},
407 {FNAME("g7231") SEQ, 0, 2, 2, SKIP, 0, _AudioCapability_g7231},
408 {FNAME("g728") INT, BYTE, 1, 0, SKIP, 0, NULL},
409 {FNAME("g729") INT, BYTE, 1, 0, SKIP, 0, NULL},
410 {FNAME("g729AnnexA") INT, BYTE, 1, 0, SKIP, 0, NULL},
411 {FNAME("is11172AudioCapability") SEQ, 0, 9, 9, SKIP | EXT, 0,
412 _IS11172AudioCapability},
413 {FNAME("is13818AudioCapability") SEQ, 0, 21, 21, SKIP | EXT, 0,
414 _IS13818AudioCapability},
415 {FNAME("g729wAnnexB") INT, BYTE, 1, 0, SKIP, 0, NULL},
416 {FNAME("g729AnnexAwAnnexB") INT, BYTE, 1, 0, SKIP, 0, NULL},
417 {FNAME("g7231AnnexCCapability") SEQ, 1, 3, 3, SKIP | EXT, 0, NULL},
418 {FNAME("gsmFullRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL},
419 {FNAME("gsmHalfRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL},
420 {FNAME("gsmEnhancedFullRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL},
421 {FNAME("genericAudioCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL},
422 {FNAME("g729Extensions") SEQ, 1, 8, 8, SKIP | EXT, 0, NULL},
423};
424
425static field_t _DataProtocolCapability[] = { /* CHOICE */
426 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
427 _H245_NonStandardParameter},
428 {FNAME("v14buffered") NUL, FIXD, 0, 0, SKIP, 0, NULL},
429 {FNAME("v42lapm") NUL, FIXD, 0, 0, SKIP, 0, NULL},
430 {FNAME("hdlcFrameTunnelling") NUL, FIXD, 0, 0, SKIP, 0, NULL},
431 {FNAME("h310SeparateVCStack") NUL, FIXD, 0, 0, SKIP, 0, NULL},
432 {FNAME("h310SingleVCStack") NUL, FIXD, 0, 0, SKIP, 0, NULL},
433 {FNAME("transparent") NUL, FIXD, 0, 0, SKIP, 0, NULL},
434 {FNAME("segmentationAndReassembly") NUL, FIXD, 0, 0, SKIP, 0, NULL},
435 {FNAME("hdlcFrameTunnelingwSAR") NUL, FIXD, 0, 0, SKIP, 0, NULL},
436 {FNAME("v120") NUL, FIXD, 0, 0, SKIP, 0, NULL},
437 {FNAME("separateLANStack") NUL, FIXD, 0, 0, SKIP, 0, NULL},
438 {FNAME("v76wCompression") CHOICE, 2, 3, 3, SKIP | EXT, 0, NULL},
439 {FNAME("tcp") NUL, FIXD, 0, 0, SKIP, 0, NULL},
440 {FNAME("udp") NUL, FIXD, 0, 0, SKIP, 0, NULL},
441};
442
443static field_t _T84Profile_t84Restricted[] = { /* SEQUENCE */
444 {FNAME("qcif") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
445 {FNAME("cif") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
446 {FNAME("ccir601Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
447 {FNAME("ccir601Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
448 {FNAME("hdtvSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
449 {FNAME("hdtvProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
450 {FNAME("g3FacsMH200x100") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
451 {FNAME("g3FacsMH200x200") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
452 {FNAME("g4FacsMMR200x100") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
453 {FNAME("g4FacsMMR200x200") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
454 {FNAME("jbig200x200Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
455 {FNAME("jbig200x200Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
456 {FNAME("jbig300x300Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
457 {FNAME("jbig300x300Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
458 {FNAME("digPhotoLow") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
459 {FNAME("digPhotoMedSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
460 {FNAME("digPhotoMedProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
461 {FNAME("digPhotoHighSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
462 {FNAME("digPhotoHighProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
463};
464
465static field_t _T84Profile[] = { /* CHOICE */
466 {FNAME("t84Unrestricted") NUL, FIXD, 0, 0, SKIP, 0, NULL},
467 {FNAME("t84Restricted") SEQ, 0, 19, 19, SKIP | EXT, 0,
468 _T84Profile_t84Restricted},
469};
470
471static field_t _DataApplicationCapability_application_t84[] = { /* SEQUENCE */
472 {FNAME("t84Protocol") CHOICE, 3, 7, 14, SKIP | EXT, 0,
473 _DataProtocolCapability},
474 {FNAME("t84Profile") CHOICE, 1, 2, 2, SKIP, 0, _T84Profile},
475};
476
477static field_t _DataApplicationCapability_application_nlpid[] = { /* SEQUENCE */
478 {FNAME("nlpidProtocol") CHOICE, 3, 7, 14, SKIP | EXT, 0,
479 _DataProtocolCapability},
480 {FNAME("nlpidData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
481};
482
483static field_t _DataApplicationCapability_application[] = { /* CHOICE */
484 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
485 _H245_NonStandardParameter},
486 {FNAME("t120") CHOICE, 3, 7, 14, DECODE | EXT,
487 offsetof(DataApplicationCapability_application, t120),
488 _DataProtocolCapability},
489 {FNAME("dsm-cc") CHOICE, 3, 7, 14, SKIP | EXT, 0,
490 _DataProtocolCapability},
491 {FNAME("userData") CHOICE, 3, 7, 14, SKIP | EXT, 0,
492 _DataProtocolCapability},
493 {FNAME("t84") SEQ, 0, 2, 2, SKIP, 0,
494 _DataApplicationCapability_application_t84},
495 {FNAME("t434") CHOICE, 3, 7, 14, SKIP | EXT, 0,
496 _DataProtocolCapability},
497 {FNAME("h224") CHOICE, 3, 7, 14, SKIP | EXT, 0,
498 _DataProtocolCapability},
499 {FNAME("nlpid") SEQ, 0, 2, 2, SKIP, 0,
500 _DataApplicationCapability_application_nlpid},
501 {FNAME("dsvdControl") NUL, FIXD, 0, 0, SKIP, 0, NULL},
502 {FNAME("h222DataPartitioning") CHOICE, 3, 7, 14, SKIP | EXT, 0,
503 _DataProtocolCapability},
504 {FNAME("t30fax") CHOICE, 3, 7, 14, SKIP | EXT, 0, NULL},
505 {FNAME("t140") CHOICE, 3, 7, 14, SKIP | EXT, 0, NULL},
506 {FNAME("t38fax") SEQ, 0, 2, 2, SKIP, 0, NULL},
507 {FNAME("genericDataCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL},
508};
509
510static field_t _DataApplicationCapability[] = { /* SEQUENCE */
511 {FNAME("application") CHOICE, 4, 10, 14, DECODE | EXT,
512 offsetof(DataApplicationCapability, application),
513 _DataApplicationCapability_application},
514 {FNAME("maxBitRate") INT, CONS, 0, 0, SKIP, 0, NULL},
515};
516
517static field_t _EncryptionMode[] = { /* CHOICE */
518 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
519 _H245_NonStandardParameter},
520 {FNAME("h233Encryption") NUL, FIXD, 0, 0, SKIP, 0, NULL},
521};
522
523static field_t _DataType[] = { /* CHOICE */
524 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
525 _H245_NonStandardParameter},
526 {FNAME("nullData") NUL, FIXD, 0, 0, SKIP, 0, NULL},
527 {FNAME("videoData") CHOICE, 3, 5, 6, SKIP | EXT, 0, _VideoCapability},
528 {FNAME("audioData") CHOICE, 4, 14, 22, SKIP | EXT, 0,
529 _AudioCapability},
530 {FNAME("data") SEQ, 0, 2, 2, DECODE | EXT, offsetof(DataType, data),
531 _DataApplicationCapability},
532 {FNAME("encryptionData") CHOICE, 1, 2, 2, SKIP | EXT, 0,
533 _EncryptionMode},
534 {FNAME("h235Control") SEQ, 0, 2, 2, SKIP, 0, NULL},
535 {FNAME("h235Media") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL},
536 {FNAME("multiplexedStream") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL},
537};
538
539static field_t _H222LogicalChannelParameters[] = { /* SEQUENCE */
540 {FNAME("resourceID") INT, WORD, 0, 0, SKIP, 0, NULL},
541 {FNAME("subChannelID") INT, WORD, 0, 0, SKIP, 0, NULL},
542 {FNAME("pcr-pid") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
543 {FNAME("programDescriptors") OCTSTR, SEMI, 0, 0, SKIP | OPT, 0, NULL},
544 {FNAME("streamDescriptors") OCTSTR, SEMI, 0, 0, SKIP | OPT, 0, NULL},
545};
546
547static field_t _H223LogicalChannelParameters_adaptationLayerType_al3[] = { /* SEQUENCE */
548 {FNAME("controlFieldOctets") INT, 2, 0, 0, SKIP, 0, NULL},
549 {FNAME("sendBufferSize") INT, CONS, 0, 0, SKIP, 0, NULL},
550};
551
552static field_t _H223LogicalChannelParameters_adaptationLayerType[] = { /* CHOICE */
553 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
554 _H245_NonStandardParameter},
555 {FNAME("al1Framed") NUL, FIXD, 0, 0, SKIP, 0, NULL},
556 {FNAME("al1NotFramed") NUL, FIXD, 0, 0, SKIP, 0, NULL},
557 {FNAME("al2WithoutSequenceNumbers") NUL, FIXD, 0, 0, SKIP, 0, NULL},
558 {FNAME("al2WithSequenceNumbers") NUL, FIXD, 0, 0, SKIP, 0, NULL},
559 {FNAME("al3") SEQ, 0, 2, 2, SKIP, 0,
560 _H223LogicalChannelParameters_adaptationLayerType_al3},
561 {FNAME("al1M") SEQ, 0, 7, 8, SKIP | EXT, 0, NULL},
562 {FNAME("al2M") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL},
563 {FNAME("al3M") SEQ, 0, 5, 6, SKIP | EXT, 0, NULL},
564};
565
566static field_t _H223LogicalChannelParameters[] = { /* SEQUENCE */
567 {FNAME("adaptationLayerType") CHOICE, 3, 6, 9, SKIP | EXT, 0,
568 _H223LogicalChannelParameters_adaptationLayerType},
569 {FNAME("segmentableFlag") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
570};
571
572static field_t _CRCLength[] = { /* CHOICE */
573 {FNAME("crc8bit") NUL, FIXD, 0, 0, SKIP, 0, NULL},
574 {FNAME("crc16bit") NUL, FIXD, 0, 0, SKIP, 0, NULL},
575 {FNAME("crc32bit") NUL, FIXD, 0, 0, SKIP, 0, NULL},
576};
577
578static field_t _V76HDLCParameters[] = { /* SEQUENCE */
579 {FNAME("crcLength") CHOICE, 2, 3, 3, SKIP | EXT, 0, _CRCLength},
580 {FNAME("n401") INT, WORD, 1, 0, SKIP, 0, NULL},
581 {FNAME("loopbackTestProcedure") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
582};
583
584static field_t _V76LogicalChannelParameters_suspendResume[] = { /* CHOICE */
585 {FNAME("noSuspendResume") NUL, FIXD, 0, 0, SKIP, 0, NULL},
586 {FNAME("suspendResumewAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL},
587 {FNAME("suspendResumewoAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL},
588};
589
590static field_t _V76LogicalChannelParameters_mode_eRM_recovery[] = { /* CHOICE */
591 {FNAME("rej") NUL, FIXD, 0, 0, SKIP, 0, NULL},
592 {FNAME("sREJ") NUL, FIXD, 0, 0, SKIP, 0, NULL},
593 {FNAME("mSREJ") NUL, FIXD, 0, 0, SKIP, 0, NULL},
594};
595
596static field_t _V76LogicalChannelParameters_mode_eRM[] = { /* SEQUENCE */
597 {FNAME("windowSize") INT, 7, 1, 0, SKIP, 0, NULL},
598 {FNAME("recovery") CHOICE, 2, 3, 3, SKIP | EXT, 0,
599 _V76LogicalChannelParameters_mode_eRM_recovery},
600};
601
602static field_t _V76LogicalChannelParameters_mode[] = { /* CHOICE */
603 {FNAME("eRM") SEQ, 0, 2, 2, SKIP | EXT, 0,
604 _V76LogicalChannelParameters_mode_eRM},
605 {FNAME("uNERM") NUL, FIXD, 0, 0, SKIP, 0, NULL},
606};
607
608static field_t _V75Parameters[] = { /* SEQUENCE */
609 {FNAME("audioHeaderPresent") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
610};
611
612static field_t _V76LogicalChannelParameters[] = { /* SEQUENCE */
613 {FNAME("hdlcParameters") SEQ, 0, 3, 3, SKIP | EXT, 0,
614 _V76HDLCParameters},
615 {FNAME("suspendResume") CHOICE, 2, 3, 3, SKIP | EXT, 0,
616 _V76LogicalChannelParameters_suspendResume},
617 {FNAME("uIH") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
618 {FNAME("mode") CHOICE, 1, 2, 2, SKIP | EXT, 0,
619 _V76LogicalChannelParameters_mode},
620 {FNAME("v75Parameters") SEQ, 0, 1, 1, SKIP | EXT, 0, _V75Parameters},
621};
622
623static field_t _H2250LogicalChannelParameters_nonStandard[] = { /* SEQUENCE OF */
624 {FNAME("item") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter},
625};
626
627static field_t _UnicastAddress_iPAddress[] = { /* SEQUENCE */
628 {FNAME("network") OCTSTR, FIXD, 4, 0, DECODE,
629 offsetof(UnicastAddress_iPAddress, network), NULL},
630 {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
631};
632
633static field_t _UnicastAddress_iPXAddress[] = { /* SEQUENCE */
634 {FNAME("node") OCTSTR, FIXD, 6, 0, SKIP, 0, NULL},
635 {FNAME("netnum") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
636 {FNAME("tsapIdentifier") OCTSTR, FIXD, 2, 0, SKIP, 0, NULL},
637};
638
639static field_t _UnicastAddress_iP6Address[] = { /* SEQUENCE */
640 {FNAME("network") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
641 {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
642};
643
644static field_t _UnicastAddress_iPSourceRouteAddress_routing[] = { /* CHOICE */
645 {FNAME("strict") NUL, FIXD, 0, 0, SKIP, 0, NULL},
646 {FNAME("loose") NUL, FIXD, 0, 0, SKIP, 0, NULL},
647};
648
649static field_t _UnicastAddress_iPSourceRouteAddress_route[] = { /* SEQUENCE OF */
650 {FNAME("item") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
651};
652
653static field_t _UnicastAddress_iPSourceRouteAddress[] = { /* SEQUENCE */
654 {FNAME("routing") CHOICE, 1, 2, 2, SKIP, 0,
655 _UnicastAddress_iPSourceRouteAddress_routing},
656 {FNAME("network") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
657 {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
658 {FNAME("route") SEQOF, SEMI, 0, 0, SKIP, 0,
659 _UnicastAddress_iPSourceRouteAddress_route},
660};
661
662static field_t _UnicastAddress[] = { /* CHOICE */
663 {FNAME("iPAddress") SEQ, 0, 2, 2, DECODE | EXT,
664 offsetof(UnicastAddress, iPAddress), _UnicastAddress_iPAddress},
665 {FNAME("iPXAddress") SEQ, 0, 3, 3, SKIP | EXT, 0,
666 _UnicastAddress_iPXAddress},
667 {FNAME("iP6Address") SEQ, 0, 2, 2, SKIP | EXT, 0,
668 _UnicastAddress_iP6Address},
669 {FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
670 {FNAME("iPSourceRouteAddress") SEQ, 0, 4, 4, SKIP | EXT, 0,
671 _UnicastAddress_iPSourceRouteAddress},
672 {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL},
673 {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, NULL},
674};
675
676static field_t _MulticastAddress_iPAddress[] = { /* SEQUENCE */
677 {FNAME("network") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
678 {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
679};
680
681static field_t _MulticastAddress_iP6Address[] = { /* SEQUENCE */
682 {FNAME("network") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
683 {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
684};
685
686static field_t _MulticastAddress[] = { /* CHOICE */
687 {FNAME("iPAddress") SEQ, 0, 2, 2, SKIP | EXT, 0,
688 _MulticastAddress_iPAddress},
689 {FNAME("iP6Address") SEQ, 0, 2, 2, SKIP | EXT, 0,
690 _MulticastAddress_iP6Address},
691 {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL},
692 {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, NULL},
693};
694
695static field_t _H245_TransportAddress[] = { /* CHOICE */
696 {FNAME("unicastAddress") CHOICE, 3, 5, 7, DECODE | EXT,
697 offsetof(H245_TransportAddress, unicastAddress), _UnicastAddress},
698 {FNAME("multicastAddress") CHOICE, 1, 2, 4, SKIP | EXT, 0,
699 _MulticastAddress},
700};
701
702static field_t _H2250LogicalChannelParameters[] = { /* SEQUENCE */
703 {FNAME("nonStandard") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
704 _H2250LogicalChannelParameters_nonStandard},
705 {FNAME("sessionID") INT, BYTE, 0, 0, SKIP, 0, NULL},
706 {FNAME("associatedSessionID") INT, 8, 1, 0, SKIP | OPT, 0, NULL},
707 {FNAME("mediaChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT,
708 offsetof(H2250LogicalChannelParameters, mediaChannel),
709 _H245_TransportAddress},
710 {FNAME("mediaGuaranteedDelivery") BOOL, FIXD, 0, 0, SKIP | OPT, 0,
711 NULL},
712 {FNAME("mediaControlChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT,
713 offsetof(H2250LogicalChannelParameters, mediaControlChannel),
714 _H245_TransportAddress},
715 {FNAME("mediaControlGuaranteedDelivery") BOOL, FIXD, 0, 0, STOP | OPT,
716 0, NULL},
717 {FNAME("silenceSuppression") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL},
718 {FNAME("destination") SEQ, 0, 2, 2, STOP | EXT | OPT, 0, NULL},
719 {FNAME("dynamicRTPPayloadType") INT, 5, 96, 0, STOP | OPT, 0, NULL},
720 {FNAME("mediaPacketization") CHOICE, 0, 1, 2, STOP | EXT | OPT, 0,
721 NULL},
722 {FNAME("transportCapability") SEQ, 3, 3, 3, STOP | EXT | OPT, 0,
723 NULL},
724 {FNAME("redundancyEncoding") SEQ, 1, 2, 2, STOP | EXT | OPT, 0, NULL},
725 {FNAME("source") SEQ, 0, 2, 2, SKIP | EXT | OPT, 0, NULL},
726};
727
728static field_t _OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */
729 {FNAME("h222LogicalChannelParameters") SEQ, 3, 5, 5, SKIP | EXT, 0,
730 _H222LogicalChannelParameters},
731 {FNAME("h223LogicalChannelParameters") SEQ, 0, 2, 2, SKIP | EXT, 0,
732 _H223LogicalChannelParameters},
733 {FNAME("v76LogicalChannelParameters") SEQ, 0, 5, 5, SKIP | EXT, 0,
734 _V76LogicalChannelParameters},
735 {FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT,
736 offsetof
737 (OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters,
738 h2250LogicalChannelParameters), _H2250LogicalChannelParameters},
739 {FNAME("none") NUL, FIXD, 0, 0, SKIP, 0, NULL},
740};
741
742static field_t _OpenLogicalChannel_forwardLogicalChannelParameters[] = { /* SEQUENCE */
743 {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
744 {FNAME("dataType") CHOICE, 3, 6, 9, DECODE | EXT,
745 offsetof(OpenLogicalChannel_forwardLogicalChannelParameters,
746 dataType), _DataType},
747 {FNAME("multiplexParameters") CHOICE, 2, 3, 5, DECODE | EXT,
748 offsetof(OpenLogicalChannel_forwardLogicalChannelParameters,
749 multiplexParameters),
750 _OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters},
751 {FNAME("forwardLogicalChannelDependency") INT, WORD, 1, 0, SKIP | OPT,
752 0, NULL},
753 {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
754};
755
756static field_t _OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */
757 {FNAME("h223LogicalChannelParameters") SEQ, 0, 2, 2, SKIP | EXT, 0,
758 _H223LogicalChannelParameters},
759 {FNAME("v76LogicalChannelParameters") SEQ, 0, 5, 5, SKIP | EXT, 0,
760 _V76LogicalChannelParameters},
761 {FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT,
762 offsetof
763 (OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters,
764 h2250LogicalChannelParameters), _H2250LogicalChannelParameters},
765};
766
767static field_t _OpenLogicalChannel_reverseLogicalChannelParameters[] = { /* SEQUENCE */
768 {FNAME("dataType") CHOICE, 3, 6, 9, SKIP | EXT, 0, _DataType},
769 {FNAME("multiplexParameters") CHOICE, 1, 2, 3, DECODE | EXT | OPT,
770 offsetof(OpenLogicalChannel_reverseLogicalChannelParameters,
771 multiplexParameters),
772 _OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters},
773 {FNAME("reverseLogicalChannelDependency") INT, WORD, 1, 0, SKIP | OPT,
774 0, NULL},
775 {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
776};
777
778static field_t _NetworkAccessParameters_distribution[] = { /* CHOICE */
779 {FNAME("unicast") NUL, FIXD, 0, 0, SKIP, 0, NULL},
780 {FNAME("multicast") NUL, FIXD, 0, 0, SKIP, 0, NULL},
781};
782
783static field_t _Q2931Address_address[] = { /* CHOICE */
784 {FNAME("internationalNumber") NUMSTR, 4, 1, 0, SKIP, 0, NULL},
785 {FNAME("nsapAddress") OCTSTR, 5, 1, 0, SKIP, 0, NULL},
786};
787
788static field_t _Q2931Address[] = { /* SEQUENCE */
789 {FNAME("address") CHOICE, 1, 2, 2, SKIP | EXT, 0,
790 _Q2931Address_address},
791 {FNAME("subaddress") OCTSTR, 5, 1, 0, SKIP | OPT, 0, NULL},
792};
793
794static field_t _NetworkAccessParameters_networkAddress[] = { /* CHOICE */
795 {FNAME("q2931Address") SEQ, 1, 2, 2, SKIP | EXT, 0, _Q2931Address},
796 {FNAME("e164Address") NUMDGT, 7, 1, 0, SKIP, 0, NULL},
797 {FNAME("localAreaAddress") CHOICE, 1, 2, 2, DECODE | EXT,
798 offsetof(NetworkAccessParameters_networkAddress, localAreaAddress),
799 _H245_TransportAddress},
800};
801
802static field_t _NetworkAccessParameters[] = { /* SEQUENCE */
803 {FNAME("distribution") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0,
804 _NetworkAccessParameters_distribution},
805 {FNAME("networkAddress") CHOICE, 2, 3, 3, DECODE | EXT,
806 offsetof(NetworkAccessParameters, networkAddress),
807 _NetworkAccessParameters_networkAddress},
808 {FNAME("associateConference") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
809 {FNAME("externalReference") OCTSTR, 8, 1, 0, SKIP | OPT, 0, NULL},
810 {FNAME("t120SetupProcedure") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
811 NULL},
812};
813
814static field_t _OpenLogicalChannel[] = { /* SEQUENCE */
815 {FNAME("forwardLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL},
816 {FNAME("forwardLogicalChannelParameters") SEQ, 1, 3, 5, DECODE | EXT,
817 offsetof(OpenLogicalChannel, forwardLogicalChannelParameters),
818 _OpenLogicalChannel_forwardLogicalChannelParameters},
819 {FNAME("reverseLogicalChannelParameters") SEQ, 1, 2, 4,
820 DECODE | EXT | OPT, offsetof(OpenLogicalChannel,
821 reverseLogicalChannelParameters),
822 _OpenLogicalChannel_reverseLogicalChannelParameters},
823 {FNAME("separateStack") SEQ, 2, 4, 5, DECODE | EXT | OPT,
824 offsetof(OpenLogicalChannel, separateStack),
825 _NetworkAccessParameters},
826 {FNAME("encryptionSync") SEQ, 2, 4, 4, STOP | EXT | OPT, 0, NULL},
827};
828
829static field_t _Setup_UUIE_fastStart[] = { /* SEQUENCE OF */
830 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
831 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
832 ,
833};
834
835static field_t _Setup_UUIE[] = { /* SEQUENCE */
836 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
837 {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
838 offsetof(Setup_UUIE, h245Address), _TransportAddress},
839 {FNAME("sourceAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
840 _Setup_UUIE_sourceAddress},
841 {FNAME("sourceInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType},
842 {FNAME("destinationAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
843 _Setup_UUIE_destinationAddress},
844 {FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
845 offsetof(Setup_UUIE, destCallSignalAddress), _TransportAddress},
846 {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
847 _Setup_UUIE_destExtraCallInfo},
848 {FNAME("destExtraCRV") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
849 _Setup_UUIE_destExtraCRV},
850 {FNAME("activeMC") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
851 {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
852 {FNAME("conferenceGoal") CHOICE, 2, 3, 5, SKIP | EXT, 0,
853 _Setup_UUIE_conferenceGoal},
854 {FNAME("callServices") SEQ, 0, 8, 8, SKIP | EXT | OPT, 0,
855 _QseriesOptions},
856 {FNAME("callType") CHOICE, 2, 4, 4, SKIP | EXT, 0, _CallType},
857 {FNAME("sourceCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
858 offsetof(Setup_UUIE, sourceCallSignalAddress), _TransportAddress},
859 {FNAME("remoteExtensionAddress") CHOICE, 1, 2, 7, SKIP | EXT | OPT, 0,
860 NULL},
861 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
862 {FNAME("h245SecurityCapability") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
863 NULL},
864 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
865 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
866 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
867 offsetof(Setup_UUIE, fastStart), _Setup_UUIE_fastStart},
868 {FNAME("mediaWaitForConnect") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
869 {FNAME("canOverlapSend") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
870 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
871 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
872 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
873 {FNAME("connectionParameters") SEQ, 0, 3, 3, SKIP | EXT | OPT, 0,
874 NULL},
875 {FNAME("language") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
876 {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
877 NULL},
878 {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0,
879 NULL},
880 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
881 {FNAME("symmetricOperationRequired") NUL, FIXD, 0, 0, SKIP | OPT, 0,
882 NULL},
883 {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL},
884 {FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL},
885 {FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
886 {FNAME("neededFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
887 {FNAME("desiredFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
888 {FNAME("supportedFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
889 {FNAME("parallelH245Control") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
890 {FNAME("additionalSourceAddresses") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
891 NULL},
892};
893
894static field_t _CallProceeding_UUIE_fastStart[] = { /* SEQUENCE OF */
895 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
896 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
897 ,
898};
899
900static field_t _CallProceeding_UUIE[] = { /* SEQUENCE */
901 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
902 {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0,
903 _EndpointType},
904 {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
905 offsetof(CallProceeding_UUIE, h245Address), _TransportAddress},
906 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
907 {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
908 NULL},
909 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
910 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
911 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
912 offsetof(CallProceeding_UUIE, fastStart),
913 _CallProceeding_UUIE_fastStart},
914 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
915 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
916 {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
917 {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
918};
919
920static field_t _Connect_UUIE_fastStart[] = { /* SEQUENCE OF */
921 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
922 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
923 ,
924};
925
926static field_t _Connect_UUIE[] = { /* SEQUENCE */
927 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
928 {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
929 offsetof(Connect_UUIE, h245Address), _TransportAddress},
930 {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0,
931 _EndpointType},
932 {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
933 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
934 {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
935 NULL},
936 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
937 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
938 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
939 offsetof(Connect_UUIE, fastStart), _Connect_UUIE_fastStart},
940 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
941 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
942 {FNAME("language") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
943 {FNAME("connectedAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
944 {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
945 NULL},
946 {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0,
947 NULL},
948 {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
949 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
950 {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL},
951 {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
952};
953
954static field_t _Alerting_UUIE_fastStart[] = { /* SEQUENCE OF */
955 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
956 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
957 ,
958};
959
960static field_t _Alerting_UUIE[] = { /* SEQUENCE */
961 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
962 {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0,
963 _EndpointType},
964 {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
965 offsetof(Alerting_UUIE, h245Address), _TransportAddress},
966 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
967 {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
968 NULL},
969 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
970 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
971 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
972 offsetof(Alerting_UUIE, fastStart), _Alerting_UUIE_fastStart},
973 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
974 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
975 {FNAME("alertingAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
976 {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
977 NULL},
978 {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0,
979 NULL},
980 {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
981 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
982 {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL},
983 {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
984};
985
986static field_t _Information_UUIE_fastStart[] = { /* SEQUENCE OF */
987 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
988 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
989 ,
990};
991
992static field_t _Information_UUIE[] = { /* SEQUENCE */
993 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
994 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
995 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
996 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
997 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
998 offsetof(Information_UUIE, fastStart), _Information_UUIE_fastStart},
999 {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
1000 {FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL},
1001};
1002
1003static field_t _ReleaseCompleteReason[] = { /* CHOICE */
1004 {FNAME("noBandwidth") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1005 {FNAME("gatekeeperResources") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1006 {FNAME("unreachableDestination") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1007 {FNAME("destinationRejection") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1008 {FNAME("invalidRevision") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1009 {FNAME("noPermission") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1010 {FNAME("unreachableGatekeeper") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1011 {FNAME("gatewayResources") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1012 {FNAME("badFormatAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1013 {FNAME("adaptiveBusy") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1014 {FNAME("inConf") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1015 {FNAME("undefinedReason") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1016 {FNAME("facilityCallDeflection") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1017 {FNAME("securityDenied") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1018 {FNAME("calledPartyNotRegistered") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1019 {FNAME("callerNotRegistered") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1020 {FNAME("newConnectionNeeded") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1021 {FNAME("nonStandardReason") SEQ, 0, 2, 2, SKIP, 0, NULL},
1022 {FNAME("replaceWithConferenceInvite") OCTSTR, FIXD, 16, 0, SKIP, 0,
1023 NULL},
1024 {FNAME("genericDataReason") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1025 {FNAME("neededFeatureNotSupported") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1026 {FNAME("tunnelledSignallingRejected") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1027};
1028
1029static field_t _ReleaseComplete_UUIE[] = { /* SEQUENCE */
1030 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1031 {FNAME("reason") CHOICE, 4, 12, 22, SKIP | EXT | OPT, 0,
1032 _ReleaseCompleteReason},
1033 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
1034 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1035 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1036 {FNAME("busyAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1037 {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
1038 NULL},
1039 {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0,
1040 NULL},
1041 {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL},
1042 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1043 {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
1044};
1045
1046static field_t _Facility_UUIE_alternativeAliasAddress[] = { /* SEQUENCE OF */
1047 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1048};
1049
1050static field_t _FacilityReason[] = { /* CHOICE */
1051 {FNAME("routeCallToGatekeeper") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1052 {FNAME("callForwarded") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1053 {FNAME("routeCallToMC") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1054 {FNAME("undefinedReason") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1055 {FNAME("conferenceListChoice") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1056 {FNAME("startH245") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1057 {FNAME("noH245") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1058 {FNAME("newTokens") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1059 {FNAME("featureSetUpdate") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1060 {FNAME("forwardedElements") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1061 {FNAME("transportedInformation") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1062};
1063
1064static field_t _Facility_UUIE_fastStart[] = { /* SEQUENCE OF */
1065 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
1066 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
1067 ,
1068};
1069
1070static field_t _Facility_UUIE[] = { /* SEQUENCE */
1071 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1072 {FNAME("alternativeAddress") CHOICE, 3, 7, 7, SKIP | EXT | OPT, 0,
1073 _TransportAddress},
1074 {FNAME("alternativeAliasAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1075 _Facility_UUIE_alternativeAliasAddress},
1076 {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL},
1077 {FNAME("reason") CHOICE, 2, 4, 11, DECODE | EXT,
1078 offsetof(Facility_UUIE, reason), _FacilityReason},
1079 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
1080 {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1081 {FNAME("remoteExtensionAddress") CHOICE, 1, 2, 7, SKIP | EXT | OPT, 0,
1082 NULL},
1083 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1084 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1085 {FNAME("conferences") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1086 {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
1087 offsetof(Facility_UUIE, h245Address), _TransportAddress},
1088 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
1089 offsetof(Facility_UUIE, fastStart), _Facility_UUIE_fastStart},
1090 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1091 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1092 {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
1093 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1094 {FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL},
1095 {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
1096 {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT | OPT, 0, NULL},
1097 {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
1098 NULL},
1099};
1100
1101static field_t _CallIdentifier[] = { /* SEQUENCE */
1102 {FNAME("guid") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
1103};
1104
1105static field_t _SecurityServiceMode[] = { /* CHOICE */
1106 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _NonStandardParameter},
1107 {FNAME("none") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1108 {FNAME("default") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1109};
1110
1111static field_t _SecurityCapabilities[] = { /* SEQUENCE */
1112 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP | OPT, 0,
1113 _NonStandardParameter},
1114 {FNAME("encryption") CHOICE, 2, 3, 3, SKIP | EXT, 0,
1115 _SecurityServiceMode},
1116 {FNAME("authenticaton") CHOICE, 2, 3, 3, SKIP | EXT, 0,
1117 _SecurityServiceMode},
1118 {FNAME("integrity") CHOICE, 2, 3, 3, SKIP | EXT, 0,
1119 _SecurityServiceMode},
1120};
1121
1122static field_t _H245Security[] = { /* CHOICE */
1123 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _NonStandardParameter},
1124 {FNAME("noSecurity") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1125 {FNAME("tls") SEQ, 1, 4, 4, SKIP | EXT, 0, _SecurityCapabilities},
1126 {FNAME("ipsec") SEQ, 1, 4, 4, SKIP | EXT, 0, _SecurityCapabilities},
1127};
1128
1129static field_t _DHset[] = { /* SEQUENCE */
1130 {FNAME("halfkey") BITSTR, WORD, 0, 0, SKIP, 0, NULL},
1131 {FNAME("modSize") BITSTR, WORD, 0, 0, SKIP, 0, NULL},
1132 {FNAME("generator") BITSTR, WORD, 0, 0, SKIP, 0, NULL},
1133};
1134
1135static field_t _TypedCertificate[] = { /* SEQUENCE */
1136 {FNAME("type") OID, BYTE, 0, 0, SKIP, 0, NULL},
1137 {FNAME("certificate") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
1138};
1139
1140static field_t _H235_NonStandardParameter[] = { /* SEQUENCE */
1141 {FNAME("nonStandardIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1142 {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
1143};
1144
1145static field_t _ClearToken[] = { /* SEQUENCE */
1146 {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1147 {FNAME("timeStamp") INT, CONS, 1, 0, SKIP | OPT, 0, NULL},
1148 {FNAME("password") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1149 {FNAME("dhkey") SEQ, 0, 3, 3, SKIP | EXT | OPT, 0, _DHset},
1150 {FNAME("challenge") OCTSTR, 7, 8, 0, SKIP | OPT, 0, NULL},
1151 {FNAME("random") INT, UNCO, 0, 0, SKIP | OPT, 0, NULL},
1152 {FNAME("certificate") SEQ, 0, 2, 2, SKIP | EXT | OPT, 0,
1153 _TypedCertificate},
1154 {FNAME("generalID") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1155 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP | OPT, 0,
1156 _H235_NonStandardParameter},
1157 {FNAME("eckasdhkey") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0, NULL},
1158 {FNAME("sendersID") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1159};
1160
1161static field_t _Progress_UUIE_tokens[] = { /* SEQUENCE OF */
1162 {FNAME("item") SEQ, 8, 9, 11, SKIP | EXT, 0, _ClearToken},
1163};
1164
1165static field_t _Params[] = { /* SEQUENCE */
1166 {FNAME("ranInt") INT, UNCO, 0, 0, SKIP | OPT, 0, NULL},
1167 {FNAME("iv8") OCTSTR, FIXD, 8, 0, SKIP | OPT, 0, NULL},
1168 {FNAME("iv16") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL},
1169};
1170
1171static field_t _CryptoH323Token_cryptoEPPwdHash_token[] = { /* SEQUENCE */
1172 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1173 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1174 {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1175};
1176
1177static field_t _CryptoH323Token_cryptoEPPwdHash[] = { /* SEQUENCE */
1178 {FNAME("alias") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1179 {FNAME("timeStamp") INT, CONS, 1, 0, SKIP, 0, NULL},
1180 {FNAME("token") SEQ, 0, 3, 3, SKIP, 0,
1181 _CryptoH323Token_cryptoEPPwdHash_token},
1182};
1183
1184static field_t _CryptoH323Token_cryptoGKPwdHash_token[] = { /* SEQUENCE */
1185 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1186 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1187 {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1188};
1189
1190static field_t _CryptoH323Token_cryptoGKPwdHash[] = { /* SEQUENCE */
1191 {FNAME("gatekeeperId") BMPSTR, 7, 1, 0, SKIP, 0, NULL},
1192 {FNAME("timeStamp") INT, CONS, 1, 0, SKIP, 0, NULL},
1193 {FNAME("token") SEQ, 0, 3, 3, SKIP, 0,
1194 _CryptoH323Token_cryptoGKPwdHash_token},
1195};
1196
1197static field_t _CryptoH323Token_cryptoEPPwdEncr[] = { /* SEQUENCE */
1198 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1199 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1200 {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
1201};
1202
1203static field_t _CryptoH323Token_cryptoGKPwdEncr[] = { /* SEQUENCE */
1204 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1205 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1206 {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
1207};
1208
1209static field_t _CryptoH323Token_cryptoEPCert[] = { /* SEQUENCE */
1210 {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL},
1211 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1212 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1213 {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1214};
1215
1216static field_t _CryptoH323Token_cryptoGKCert[] = { /* SEQUENCE */
1217 {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL},
1218 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1219 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1220 {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1221};
1222
1223static field_t _CryptoH323Token_cryptoFastStart[] = { /* SEQUENCE */
1224 {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL},
1225 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1226 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1227 {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1228};
1229
1230static field_t _CryptoToken_cryptoEncryptedToken_token[] = { /* SEQUENCE */
1231 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1232 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1233 {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
1234};
1235
1236static field_t _CryptoToken_cryptoEncryptedToken[] = { /* SEQUENCE */
1237 {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1238 {FNAME("token") SEQ, 0, 3, 3, SKIP, 0,
1239 _CryptoToken_cryptoEncryptedToken_token},
1240};
1241
1242static field_t _CryptoToken_cryptoSignedToken_token[] = { /* SEQUENCE */
1243 {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL},
1244 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1245 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1246 {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1247};
1248
1249static field_t _CryptoToken_cryptoSignedToken[] = { /* SEQUENCE */
1250 {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1251 {FNAME("token") SEQ, 0, 4, 4, SKIP, 0,
1252 _CryptoToken_cryptoSignedToken_token},
1253};
1254
1255static field_t _CryptoToken_cryptoHashedToken_token[] = { /* SEQUENCE */
1256 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1257 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1258 {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1259};
1260
1261static field_t _CryptoToken_cryptoHashedToken[] = { /* SEQUENCE */
1262 {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1263 {FNAME("hashedVals") SEQ, 8, 9, 11, SKIP | EXT, 0, _ClearToken},
1264 {FNAME("token") SEQ, 0, 3, 3, SKIP, 0,
1265 _CryptoToken_cryptoHashedToken_token},
1266};
1267
1268static field_t _CryptoToken_cryptoPwdEncr[] = { /* SEQUENCE */
1269 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1270 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1271 {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
1272};
1273
1274static field_t _CryptoToken[] = { /* CHOICE */
1275 {FNAME("cryptoEncryptedToken") SEQ, 0, 2, 2, SKIP, 0,
1276 _CryptoToken_cryptoEncryptedToken},
1277 {FNAME("cryptoSignedToken") SEQ, 0, 2, 2, SKIP, 0,
1278 _CryptoToken_cryptoSignedToken},
1279 {FNAME("cryptoHashedToken") SEQ, 0, 3, 3, SKIP, 0,
1280 _CryptoToken_cryptoHashedToken},
1281 {FNAME("cryptoPwdEncr") SEQ, 0, 3, 3, SKIP, 0,
1282 _CryptoToken_cryptoPwdEncr},
1283};
1284
1285static field_t _CryptoH323Token[] = { /* CHOICE */
1286 {FNAME("cryptoEPPwdHash") SEQ, 0, 3, 3, SKIP, 0,
1287 _CryptoH323Token_cryptoEPPwdHash},
1288 {FNAME("cryptoGKPwdHash") SEQ, 0, 3, 3, SKIP, 0,
1289 _CryptoH323Token_cryptoGKPwdHash},
1290 {FNAME("cryptoEPPwdEncr") SEQ, 0, 3, 3, SKIP, 0,
1291 _CryptoH323Token_cryptoEPPwdEncr},
1292 {FNAME("cryptoGKPwdEncr") SEQ, 0, 3, 3, SKIP, 0,
1293 _CryptoH323Token_cryptoGKPwdEncr},
1294 {FNAME("cryptoEPCert") SEQ, 0, 4, 4, SKIP, 0,
1295 _CryptoH323Token_cryptoEPCert},
1296 {FNAME("cryptoGKCert") SEQ, 0, 4, 4, SKIP, 0,
1297 _CryptoH323Token_cryptoGKCert},
1298 {FNAME("cryptoFastStart") SEQ, 0, 4, 4, SKIP, 0,
1299 _CryptoH323Token_cryptoFastStart},
1300 {FNAME("nestedcryptoToken") CHOICE, 2, 4, 4, SKIP | EXT, 0,
1301 _CryptoToken},
1302};
1303
1304static field_t _Progress_UUIE_cryptoTokens[] = { /* SEQUENCE OF */
1305 {FNAME("item") CHOICE, 3, 8, 8, SKIP | EXT, 0, _CryptoH323Token},
1306};
1307
1308static field_t _Progress_UUIE_fastStart[] = { /* SEQUENCE OF */
1309 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
1310 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
1311 ,
1312};
1313
1314static field_t _Progress_UUIE[] = { /* SEQUENCE */
1315 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1316 {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0,
1317 _EndpointType},
1318 {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
1319 offsetof(Progress_UUIE, h245Address), _TransportAddress},
1320 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0,
1321 _CallIdentifier},
1322 {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
1323 _H245Security},
1324 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1325 _Progress_UUIE_tokens},
1326 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1327 _Progress_UUIE_cryptoTokens},
1328 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
1329 offsetof(Progress_UUIE, fastStart), _Progress_UUIE_fastStart},
1330 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1331 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1332 {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
1333};
1334
1335static field_t _H323_UU_PDU_h323_message_body[] = { /* CHOICE */
1336 {FNAME("setup") SEQ, 7, 13, 39, DECODE | EXT,
1337 offsetof(H323_UU_PDU_h323_message_body, setup), _Setup_UUIE},
1338 {FNAME("callProceeding") SEQ, 1, 3, 12, DECODE | EXT,
1339 offsetof(H323_UU_PDU_h323_message_body, callProceeding),
1340 _CallProceeding_UUIE},
1341 {FNAME("connect") SEQ, 1, 4, 19, DECODE | EXT,
1342 offsetof(H323_UU_PDU_h323_message_body, connect), _Connect_UUIE},
1343 {FNAME("alerting") SEQ, 1, 3, 17, DECODE | EXT,
1344 offsetof(H323_UU_PDU_h323_message_body, alerting), _Alerting_UUIE},
1345 {FNAME("information") SEQ, 0, 1, 7, DECODE | EXT,
1346 offsetof(H323_UU_PDU_h323_message_body, information),
1347 _Information_UUIE},
1348 {FNAME("releaseComplete") SEQ, 1, 2, 11, SKIP | EXT, 0,
1349 _ReleaseComplete_UUIE},
1350 {FNAME("facility") SEQ, 3, 5, 21, DECODE | EXT,
1351 offsetof(H323_UU_PDU_h323_message_body, facility), _Facility_UUIE},
1352 {FNAME("progress") SEQ, 5, 8, 11, DECODE | EXT,
1353 offsetof(H323_UU_PDU_h323_message_body, progress), _Progress_UUIE},
1354 {FNAME("empty") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1355 {FNAME("status") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL},
1356 {FNAME("statusInquiry") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL},
1357 {FNAME("setupAcknowledge") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL},
1358 {FNAME("notify") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL},
1359};
1360
1361static field_t _RequestMessage[] = { /* CHOICE */
1362 {FNAME("nonStandard") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1363 {FNAME("masterSlaveDetermination") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1364 {FNAME("terminalCapabilitySet") SEQ, 3, 5, 5, STOP | EXT, 0, NULL},
1365 {FNAME("openLogicalChannel") SEQ, 1, 3, 5, DECODE | EXT,
1366 offsetof(RequestMessage, openLogicalChannel), _OpenLogicalChannel},
1367 {FNAME("closeLogicalChannel") SEQ, 0, 2, 3, STOP | EXT, 0, NULL},
1368 {FNAME("requestChannelClose") SEQ, 0, 1, 3, STOP | EXT, 0, NULL},
1369 {FNAME("multiplexEntrySend") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1370 {FNAME("requestMultiplexEntry") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1371 {FNAME("requestMode") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1372 {FNAME("roundTripDelayRequest") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1373 {FNAME("maintenanceLoopRequest") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1374 {FNAME("communicationModeRequest") SEQ, 0, 0, 0, STOP | EXT, 0, NULL},
1375 {FNAME("conferenceRequest") CHOICE, 3, 8, 16, STOP | EXT, 0, NULL},
1376 {FNAME("multilinkRequest") CHOICE, 3, 5, 5, STOP | EXT, 0, NULL},
1377 {FNAME("logicalChannelRateRequest") SEQ, 0, 3, 3, STOP | EXT, 0,
1378 NULL},
1379};
1380
1381static field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */
1382 {FNAME("h222LogicalChannelParameters") SEQ, 3, 5, 5, SKIP | EXT, 0,
1383 _H222LogicalChannelParameters},
1384 {FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT,
1385 offsetof
1386 (OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters,
1387 h2250LogicalChannelParameters), _H2250LogicalChannelParameters},
1388};
1389
1390static field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters[] = { /* SEQUENCE */
1391 {FNAME("reverseLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL},
1392 {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
1393 {FNAME("multiplexParameters") CHOICE, 0, 1, 2, DECODE | EXT | OPT,
1394 offsetof(OpenLogicalChannelAck_reverseLogicalChannelParameters,
1395 multiplexParameters),
1396 _OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters},
1397 {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
1398};
1399
1400static field_t _H2250LogicalChannelAckParameters_nonStandard[] = { /* SEQUENCE OF */
1401 {FNAME("item") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter},
1402};
1403
1404static field_t _H2250LogicalChannelAckParameters[] = { /* SEQUENCE */
1405 {FNAME("nonStandard") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1406 _H2250LogicalChannelAckParameters_nonStandard},
1407 {FNAME("sessionID") INT, 8, 1, 0, SKIP | OPT, 0, NULL},
1408 {FNAME("mediaChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT,
1409 offsetof(H2250LogicalChannelAckParameters, mediaChannel),
1410 _H245_TransportAddress},
1411 {FNAME("mediaControlChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT,
1412 offsetof(H2250LogicalChannelAckParameters, mediaControlChannel),
1413 _H245_TransportAddress},
1414 {FNAME("dynamicRTPPayloadType") INT, 5, 96, 0, SKIP | OPT, 0, NULL},
1415 {FNAME("flowControlToZero") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1416 {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
1417};
1418
1419static field_t _OpenLogicalChannelAck_forwardMultiplexAckParameters[] = { /* CHOICE */
1420 {FNAME("h2250LogicalChannelAckParameters") SEQ, 5, 5, 7, DECODE | EXT,
1421 offsetof(OpenLogicalChannelAck_forwardMultiplexAckParameters,
1422 h2250LogicalChannelAckParameters),
1423 _H2250LogicalChannelAckParameters},
1424};
1425
1426static field_t _OpenLogicalChannelAck[] = { /* SEQUENCE */
1427 {FNAME("forwardLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL},
1428 {FNAME("reverseLogicalChannelParameters") SEQ, 2, 3, 4,
1429 DECODE | EXT | OPT, offsetof(OpenLogicalChannelAck,
1430 reverseLogicalChannelParameters),
1431 _OpenLogicalChannelAck_reverseLogicalChannelParameters},
1432 {FNAME("separateStack") SEQ, 2, 4, 5, SKIP | EXT | OPT, 0, NULL},
1433 {FNAME("forwardMultiplexAckParameters") CHOICE, 0, 1, 1,
1434 DECODE | EXT | OPT, offsetof(OpenLogicalChannelAck,
1435 forwardMultiplexAckParameters),
1436 _OpenLogicalChannelAck_forwardMultiplexAckParameters},
1437 {FNAME("encryptionSync") SEQ, 2, 4, 4, STOP | EXT | OPT, 0, NULL},
1438};
1439
1440static field_t _ResponseMessage[] = { /* CHOICE */
1441 {FNAME("nonStandard") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1442 {FNAME("masterSlaveDeterminationAck") SEQ, 0, 1, 1, STOP | EXT, 0,
1443 NULL},
1444 {FNAME("masterSlaveDeterminationReject") SEQ, 0, 1, 1, STOP | EXT, 0,
1445 NULL},
1446 {FNAME("terminalCapabilitySetAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1447 {FNAME("terminalCapabilitySetReject") SEQ, 0, 2, 2, STOP | EXT, 0,
1448 NULL},
1449 {FNAME("openLogicalChannelAck") SEQ, 1, 2, 5, DECODE | EXT,
1450 offsetof(ResponseMessage, openLogicalChannelAck),
1451 _OpenLogicalChannelAck},
1452 {FNAME("openLogicalChannelReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1453 {FNAME("closeLogicalChannelAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1454 {FNAME("requestChannelCloseAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1455 {FNAME("requestChannelCloseReject") SEQ, 0, 2, 2, STOP | EXT, 0,
1456 NULL},
1457 {FNAME("multiplexEntrySendAck") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1458 {FNAME("multiplexEntrySendReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1459 {FNAME("requestMultiplexEntryAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1460 {FNAME("requestMultiplexEntryReject") SEQ, 0, 2, 2, STOP | EXT, 0,
1461 NULL},
1462 {FNAME("requestModeAck") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1463 {FNAME("requestModeReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1464 {FNAME("roundTripDelayResponse") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1465 {FNAME("maintenanceLoopAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1466 {FNAME("maintenanceLoopReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1467 {FNAME("communicationModeResponse") CHOICE, 0, 1, 1, STOP | EXT, 0,
1468 NULL},
1469 {FNAME("conferenceResponse") CHOICE, 3, 8, 16, STOP | EXT, 0, NULL},
1470 {FNAME("multilinkResponse") CHOICE, 3, 5, 5, STOP | EXT, 0, NULL},
1471 {FNAME("logicalChannelRateAcknowledge") SEQ, 0, 3, 3, STOP | EXT, 0,
1472 NULL},
1473 {FNAME("logicalChannelRateReject") SEQ, 1, 4, 4, STOP | EXT, 0, NULL},
1474};
1475
1476static field_t _MultimediaSystemControlMessage[] = { /* CHOICE */
1477 {FNAME("request") CHOICE, 4, 11, 15, DECODE | EXT,
1478 offsetof(MultimediaSystemControlMessage, request), _RequestMessage},
1479 {FNAME("response") CHOICE, 5, 19, 24, DECODE | EXT,
1480 offsetof(MultimediaSystemControlMessage, response),
1481 _ResponseMessage},
1482 {FNAME("command") CHOICE, 3, 7, 12, STOP | EXT, 0, NULL},
1483 {FNAME("indication") CHOICE, 4, 14, 23, STOP | EXT, 0, NULL},
1484};
1485
1486static field_t _H323_UU_PDU_h245Control[] = { /* SEQUENCE OF */
1487 {FNAME("item") CHOICE, 2, 4, 4, DECODE | OPEN | EXT,
1488 sizeof(MultimediaSystemControlMessage),
1489 _MultimediaSystemControlMessage}
1490 ,
1491};
1492
1493static field_t _H323_UU_PDU[] = { /* SEQUENCE */
1494 {FNAME("h323-message-body") CHOICE, 3, 7, 13, DECODE | EXT,
1495 offsetof(H323_UU_PDU, h323_message_body),
1496 _H323_UU_PDU_h323_message_body},
1497 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1498 _NonStandardParameter},
1499 {FNAME("h4501SupplementaryService") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1500 NULL},
1501 {FNAME("h245Tunneling") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1502 {FNAME("h245Control") SEQOF, SEMI, 0, 4, DECODE | OPT,
1503 offsetof(H323_UU_PDU, h245Control), _H323_UU_PDU_h245Control},
1504 {FNAME("nonStandardControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1505 {FNAME("callLinkage") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
1506 {FNAME("tunnelledSignallingMessage") SEQ, 2, 4, 4, STOP | EXT | OPT,
1507 0, NULL},
1508 {FNAME("provisionalRespToH245Tunneling") NUL, FIXD, 0, 0, STOP | OPT,
1509 0, NULL},
1510 {FNAME("stimulusControl") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
1511 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1512};
1513
1514static field_t _H323_UserInformation[] = { /* SEQUENCE */
1515 {FNAME("h323-uu-pdu") SEQ, 1, 2, 11, DECODE | EXT,
1516 offsetof(H323_UserInformation, h323_uu_pdu), _H323_UU_PDU},
1517 {FNAME("user-data") SEQ, 0, 2, 2, STOP | EXT | OPT, 0, NULL},
1518};
1519
1520static field_t _GatekeeperRequest[] = { /* SEQUENCE */
1521 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1522 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1523 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1524 _NonStandardParameter},
1525 {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1526 offsetof(GatekeeperRequest, rasAddress), _TransportAddress},
1527 {FNAME("endpointType") SEQ, 6, 8, 10, STOP | EXT, 0, NULL},
1528 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
1529 {FNAME("callServices") SEQ, 0, 8, 8, STOP | EXT | OPT, 0, NULL},
1530 {FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1531 {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1532 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1533 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1534 {FNAME("authenticationCapability") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1535 NULL},
1536 {FNAME("algorithmOIDs") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1537 {FNAME("integrity") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1538 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1539 {FNAME("supportsAltGK") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL},
1540 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1541 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1542};
1543
1544static field_t _GatekeeperConfirm[] = { /* SEQUENCE */
1545 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1546 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1547 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1548 _NonStandardParameter},
1549 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1550 {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1551 offsetof(GatekeeperConfirm, rasAddress), _TransportAddress},
1552 {FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1553 {FNAME("authenticationMode") CHOICE, 3, 7, 8, STOP | EXT | OPT, 0,
1554 NULL},
1555 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1556 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1557 {FNAME("algorithmOID") OID, BYTE, 0, 0, STOP | OPT, 0, NULL},
1558 {FNAME("integrity") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1559 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1560 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1561 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1562};
1563
1564static field_t _RegistrationRequest_callSignalAddress[] = { /* SEQUENCE OF */
1565 {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
1566 sizeof(TransportAddress), _TransportAddress}
1567 ,
1568};
1569
1570static field_t _RegistrationRequest_rasAddress[] = { /* SEQUENCE OF */
1571 {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
1572 sizeof(TransportAddress), _TransportAddress}
1573 ,
1574};
1575
1576static field_t _RegistrationRequest_terminalAlias[] = { /* SEQUENCE OF */
1577 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1578};
1579
1580static field_t _RegistrationRequest[] = { /* SEQUENCE */
1581 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1582 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1583 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1584 _NonStandardParameter},
1585 {FNAME("discoveryComplete") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1586 {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE,
1587 offsetof(RegistrationRequest, callSignalAddress),
1588 _RegistrationRequest_callSignalAddress},
1589 {FNAME("rasAddress") SEQOF, SEMI, 0, 10, DECODE,
1590 offsetof(RegistrationRequest, rasAddress),
1591 _RegistrationRequest_rasAddress},
1592 {FNAME("terminalType") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType},
1593 {FNAME("terminalAlias") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1594 _RegistrationRequest_terminalAlias},
1595 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1596 {FNAME("endpointVendor") SEQ, 2, 3, 3, SKIP | EXT, 0,
1597 _VendorIdentifier},
1598 {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1599 {FNAME("timeToLive") INT, CONS, 1, 0, DECODE | OPT,
1600 offsetof(RegistrationRequest, timeToLive), NULL},
1601 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1602 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1603 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1604 {FNAME("keepAlive") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1605 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
1606 {FNAME("willSupplyUUIEs") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1607 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1608 {FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT,
1609 0, NULL},
1610 {FNAME("additiveRegistration") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL},
1611 {FNAME("terminalAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1612 NULL},
1613 {FNAME("supportsAltGK") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL},
1614 {FNAME("usageReportingCapability") SEQ, 3, 4, 4, STOP | EXT | OPT, 0,
1615 NULL},
1616 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL},
1617 {FNAME("supportedH248Packages") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1618 NULL},
1619 {FNAME("callCreditCapability") SEQ, 2, 2, 2, STOP | EXT | OPT, 0,
1620 NULL},
1621 {FNAME("capacityReportingCapability") SEQ, 0, 1, 1, STOP | EXT | OPT,
1622 0, NULL},
1623 {FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
1624 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1625 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1626};
1627
1628static field_t _RegistrationConfirm_callSignalAddress[] = { /* SEQUENCE OF */
1629 {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
1630 sizeof(TransportAddress), _TransportAddress}
1631 ,
1632};
1633
1634static field_t _RegistrationConfirm_terminalAlias[] = { /* SEQUENCE OF */
1635 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1636};
1637
1638static field_t _RegistrationConfirm[] = { /* SEQUENCE */
1639 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1640 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1641 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1642 _NonStandardParameter},
1643 {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE,
1644 offsetof(RegistrationConfirm, callSignalAddress),
1645 _RegistrationConfirm_callSignalAddress},
1646 {FNAME("terminalAlias") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1647 _RegistrationConfirm_terminalAlias},
1648 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1649 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL},
1650 {FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1651 {FNAME("timeToLive") INT, CONS, 1, 0, DECODE | OPT,
1652 offsetof(RegistrationConfirm, timeToLive), NULL},
1653 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1654 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1655 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1656 {FNAME("willRespondToIRR") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1657 {FNAME("preGrantedARQ") SEQ, 0, 4, 8, STOP | EXT | OPT, 0, NULL},
1658 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1659 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1660 {FNAME("supportsAdditiveRegistration") NUL, FIXD, 0, 0, STOP | OPT, 0,
1661 NULL},
1662 {FNAME("terminalAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1663 NULL},
1664 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1665 {FNAME("usageSpec") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1666 {FNAME("featureServerAlias") CHOICE, 1, 2, 7, STOP | EXT | OPT, 0,
1667 NULL},
1668 {FNAME("capacityReportingSpec") SEQ, 0, 1, 1, STOP | EXT | OPT, 0,
1669 NULL},
1670 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1671 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1672};
1673
1674static field_t _UnregistrationRequest_callSignalAddress[] = { /* SEQUENCE OF */
1675 {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
1676 sizeof(TransportAddress), _TransportAddress}
1677 ,
1678};
1679
1680static field_t _UnregistrationRequest[] = { /* SEQUENCE */
1681 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1682 {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE,
1683 offsetof(UnregistrationRequest, callSignalAddress),
1684 _UnregistrationRequest_callSignalAddress},
1685 {FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1686 {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1687 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
1688 {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1689 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
1690 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1691 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1692 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1693 {FNAME("reason") CHOICE, 2, 4, 5, STOP | EXT | OPT, 0, NULL},
1694 {FNAME("endpointAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1695 NULL},
1696 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1697 {FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1698 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1699};
1700
1701static field_t _CallModel[] = { /* CHOICE */
1702 {FNAME("direct") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1703 {FNAME("gatekeeperRouted") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1704};
1705
1706static field_t _AdmissionRequest_destinationInfo[] = { /* SEQUENCE OF */
1707 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1708};
1709
1710static field_t _AdmissionRequest_destExtraCallInfo[] = { /* SEQUENCE OF */
1711 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1712};
1713
1714static field_t _AdmissionRequest_srcInfo[] = { /* SEQUENCE OF */
1715 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1716};
1717
1718static field_t _AdmissionRequest[] = { /* SEQUENCE */
1719 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1720 {FNAME("callType") CHOICE, 2, 4, 4, SKIP | EXT, 0, _CallType},
1721 {FNAME("callModel") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0, _CallModel},
1722 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL},
1723 {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1724 _AdmissionRequest_destinationInfo},
1725 {FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
1726 offsetof(AdmissionRequest, destCallSignalAddress),
1727 _TransportAddress},
1728 {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1729 _AdmissionRequest_destExtraCallInfo},
1730 {FNAME("srcInfo") SEQOF, SEMI, 0, 0, SKIP, 0,
1731 _AdmissionRequest_srcInfo},
1732 {FNAME("srcCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
1733 offsetof(AdmissionRequest, srcCallSignalAddress), _TransportAddress},
1734 {FNAME("bandWidth") INT, CONS, 0, 0, STOP, 0, NULL},
1735 {FNAME("callReferenceValue") INT, WORD, 0, 0, STOP, 0, NULL},
1736 {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1737 {FNAME("callServices") SEQ, 0, 8, 8, STOP | EXT | OPT, 0, NULL},
1738 {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, STOP, 0, NULL},
1739 {FNAME("activeMC") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1740 {FNAME("answerCall") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1741 {FNAME("canMapAlias") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1742 {FNAME("callIdentifier") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1743 {FNAME("srcAlternatives") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1744 {FNAME("destAlternatives") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1745 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
1746 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1747 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1748 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1749 {FNAME("transportQOS") CHOICE, 2, 3, 3, STOP | EXT | OPT, 0, NULL},
1750 {FNAME("willSupplyUUIEs") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1751 {FNAME("callLinkage") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
1752 {FNAME("gatewayDataRate") SEQ, 2, 3, 3, STOP | EXT | OPT, 0, NULL},
1753 {FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
1754 {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
1755 {FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1756 {FNAME("desiredTunnelledProtocol") SEQ, 1, 2, 2, STOP | EXT | OPT, 0,
1757 NULL},
1758 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1759 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1760};
1761
1762static field_t _AdmissionConfirm[] = { /* SEQUENCE */
1763 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1764 {FNAME("bandWidth") INT, CONS, 0, 0, SKIP, 0, NULL},
1765 {FNAME("callModel") CHOICE, 1, 2, 2, SKIP | EXT, 0, _CallModel},
1766 {FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1767 offsetof(AdmissionConfirm, destCallSignalAddress),
1768 _TransportAddress},
1769 {FNAME("irrFrequency") INT, WORD, 1, 0, STOP | OPT, 0, NULL},
1770 {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1771 {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1772 {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1773 {FNAME("destinationType") SEQ, 6, 8, 10, STOP | EXT | OPT, 0, NULL},
1774 {FNAME("remoteExtensionAddress") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1775 NULL},
1776 {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1777 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1778 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1779 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1780 {FNAME("transportQOS") CHOICE, 2, 3, 3, STOP | EXT | OPT, 0, NULL},
1781 {FNAME("willRespondToIRR") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1782 {FNAME("uuiesRequested") SEQ, 0, 9, 13, STOP | EXT, 0, NULL},
1783 {FNAME("language") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1784 {FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT,
1785 0, NULL},
1786 {FNAME("useSpecifiedTransport") CHOICE, 1, 2, 2, STOP | EXT | OPT, 0,
1787 NULL},
1788 {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
1789 {FNAME("usageSpec") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1790 {FNAME("supportedProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1791 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1792 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL},
1793 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1794 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1795};
1796
1797static field_t _LocationRequest_destinationInfo[] = { /* SEQUENCE OF */
1798 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1799};
1800
1801static field_t _LocationRequest[] = { /* SEQUENCE */
1802 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1803 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1804 {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, SKIP, 0,
1805 _LocationRequest_destinationInfo},
1806 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1807 _NonStandardParameter},
1808 {FNAME("replyAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1809 offsetof(LocationRequest, replyAddress), _TransportAddress},
1810 {FNAME("sourceInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1811 {FNAME("canMapAlias") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1812 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
1813 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1814 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1815 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1816 {FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1817 {FNAME("desiredTunnelledProtocol") SEQ, 1, 2, 2, STOP | EXT | OPT, 0,
1818 NULL},
1819 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1820 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1821 {FNAME("hopCount") INT, 8, 1, 0, STOP | OPT, 0, NULL},
1822 {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
1823};
1824
1825static field_t _LocationConfirm[] = { /* SEQUENCE */
1826 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1827 {FNAME("callSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1828 offsetof(LocationConfirm, callSignalAddress), _TransportAddress},
1829 {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1830 offsetof(LocationConfirm, rasAddress), _TransportAddress},
1831 {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1832 {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1833 {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1834 {FNAME("destinationType") SEQ, 6, 8, 10, STOP | EXT | OPT, 0, NULL},
1835 {FNAME("remoteExtensionAddress") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1836 NULL},
1837 {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1838 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1839 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1840 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1841 {FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT,
1842 0, NULL},
1843 {FNAME("supportedProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1844 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL},
1845 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1846 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1847 {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
1848 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1849};
1850
1851static field_t _InfoRequestResponse_callSignalAddress[] = { /* SEQUENCE OF */
1852 {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
1853 sizeof(TransportAddress), _TransportAddress}
1854 ,
1855};
1856
1857static field_t _InfoRequestResponse[] = { /* SEQUENCE */
1858 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1859 _NonStandardParameter},
1860 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1861 {FNAME("endpointType") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType},
1862 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL},
1863 {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1864 offsetof(InfoRequestResponse, rasAddress), _TransportAddress},
1865 {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE,
1866 offsetof(InfoRequestResponse, callSignalAddress),
1867 _InfoRequestResponse_callSignalAddress},
1868 {FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1869 {FNAME("perCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1870 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1871 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1872 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1873 {FNAME("needResponse") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1874 {FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
1875 {FNAME("irrStatus") CHOICE, 2, 4, 4, STOP | EXT | OPT, 0, NULL},
1876 {FNAME("unsolicited") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1877 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1878};
1879
1880static field_t _RasMessage[] = { /* CHOICE */
1881 {FNAME("gatekeeperRequest") SEQ, 4, 8, 18, DECODE | EXT,
1882 offsetof(RasMessage, gatekeeperRequest), _GatekeeperRequest},
1883 {FNAME("gatekeeperConfirm") SEQ, 2, 5, 14, DECODE | EXT,
1884 offsetof(RasMessage, gatekeeperConfirm), _GatekeeperConfirm},
1885 {FNAME("gatekeeperReject") SEQ, 2, 5, 11, STOP | EXT, 0, NULL},
1886 {FNAME("registrationRequest") SEQ, 3, 10, 31, DECODE | EXT,
1887 offsetof(RasMessage, registrationRequest), _RegistrationRequest},
1888 {FNAME("registrationConfirm") SEQ, 3, 7, 24, DECODE | EXT,
1889 offsetof(RasMessage, registrationConfirm), _RegistrationConfirm},
1890 {FNAME("registrationReject") SEQ, 2, 5, 11, STOP | EXT, 0, NULL},
1891 {FNAME("unregistrationRequest") SEQ, 3, 5, 15, DECODE | EXT,
1892 offsetof(RasMessage, unregistrationRequest), _UnregistrationRequest},
1893 {FNAME("unregistrationConfirm") SEQ, 1, 2, 6, STOP | EXT, 0, NULL},
1894 {FNAME("unregistrationReject") SEQ, 1, 3, 8, STOP | EXT, 0, NULL},
1895 {FNAME("admissionRequest") SEQ, 7, 16, 34, DECODE | EXT,
1896 offsetof(RasMessage, admissionRequest), _AdmissionRequest},
1897 {FNAME("admissionConfirm") SEQ, 2, 6, 27, DECODE | EXT,
1898 offsetof(RasMessage, admissionConfirm), _AdmissionConfirm},
1899 {FNAME("admissionReject") SEQ, 1, 3, 11, STOP | EXT, 0, NULL},
1900 {FNAME("bandwidthRequest") SEQ, 2, 7, 18, STOP | EXT, 0, NULL},
1901 {FNAME("bandwidthConfirm") SEQ, 1, 3, 8, STOP | EXT, 0, NULL},
1902 {FNAME("bandwidthReject") SEQ, 1, 4, 9, STOP | EXT, 0, NULL},
1903 {FNAME("disengageRequest") SEQ, 1, 6, 19, STOP | EXT, 0, NULL},
1904 {FNAME("disengageConfirm") SEQ, 1, 2, 9, STOP | EXT, 0, NULL},
1905 {FNAME("disengageReject") SEQ, 1, 3, 8, STOP | EXT, 0, NULL},
1906 {FNAME("locationRequest") SEQ, 2, 5, 17, DECODE | EXT,
1907 offsetof(RasMessage, locationRequest), _LocationRequest},
1908 {FNAME("locationConfirm") SEQ, 1, 4, 19, DECODE | EXT,
1909 offsetof(RasMessage, locationConfirm), _LocationConfirm},
1910 {FNAME("locationReject") SEQ, 1, 3, 10, STOP | EXT, 0, NULL},
1911 {FNAME("infoRequest") SEQ, 2, 4, 15, STOP | EXT, 0, NULL},
1912 {FNAME("infoRequestResponse") SEQ, 3, 8, 16, DECODE | EXT,
1913 offsetof(RasMessage, infoRequestResponse), _InfoRequestResponse},
1914 {FNAME("nonStandardMessage") SEQ, 0, 2, 7, STOP | EXT, 0, NULL},
1915 {FNAME("unknownMessageResponse") SEQ, 0, 1, 5, STOP | EXT, 0, NULL},
1916 {FNAME("requestInProgress") SEQ, 4, 6, 6, STOP | EXT, 0, NULL},
1917 {FNAME("resourcesAvailableIndicate") SEQ, 4, 9, 11, STOP | EXT, 0,
1918 NULL},
1919 {FNAME("resourcesAvailableConfirm") SEQ, 4, 6, 7, STOP | EXT, 0,
1920 NULL},
1921 {FNAME("infoRequestAck") SEQ, 4, 5, 5, STOP | EXT, 0, NULL},
1922 {FNAME("infoRequestNak") SEQ, 5, 7, 7, STOP | EXT, 0, NULL},
1923 {FNAME("serviceControlIndication") SEQ, 8, 10, 10, STOP | EXT, 0,
1924 NULL},
1925 {FNAME("serviceControlResponse") SEQ, 7, 8, 8, STOP | EXT, 0, NULL},
1926};
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h
new file mode 100644
index 000000000000..cc98f7aa5abe
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h
@@ -0,0 +1,938 @@
1/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006
2 *
3 * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
4 *
5 * This source code is licensed under General Public License version 2.
6 */
7
8typedef struct TransportAddress_ipAddress { /* SEQUENCE */
9 int options; /* No use */
10 unsigned ip;
11} TransportAddress_ipAddress;
12
13typedef struct TransportAddress { /* CHOICE */
14 enum {
15 eTransportAddress_ipAddress,
16 eTransportAddress_ipSourceRoute,
17 eTransportAddress_ipxAddress,
18 eTransportAddress_ip6Address,
19 eTransportAddress_netBios,
20 eTransportAddress_nsap,
21 eTransportAddress_nonStandardAddress,
22 } choice;
23 union {
24 TransportAddress_ipAddress ipAddress;
25 };
26} TransportAddress;
27
28typedef struct DataProtocolCapability { /* CHOICE */
29 enum {
30 eDataProtocolCapability_nonStandard,
31 eDataProtocolCapability_v14buffered,
32 eDataProtocolCapability_v42lapm,
33 eDataProtocolCapability_hdlcFrameTunnelling,
34 eDataProtocolCapability_h310SeparateVCStack,
35 eDataProtocolCapability_h310SingleVCStack,
36 eDataProtocolCapability_transparent,
37 eDataProtocolCapability_segmentationAndReassembly,
38 eDataProtocolCapability_hdlcFrameTunnelingwSAR,
39 eDataProtocolCapability_v120,
40 eDataProtocolCapability_separateLANStack,
41 eDataProtocolCapability_v76wCompression,
42 eDataProtocolCapability_tcp,
43 eDataProtocolCapability_udp,
44 } choice;
45} DataProtocolCapability;
46
47typedef struct DataApplicationCapability_application { /* CHOICE */
48 enum {
49 eDataApplicationCapability_application_nonStandard,
50 eDataApplicationCapability_application_t120,
51 eDataApplicationCapability_application_dsm_cc,
52 eDataApplicationCapability_application_userData,
53 eDataApplicationCapability_application_t84,
54 eDataApplicationCapability_application_t434,
55 eDataApplicationCapability_application_h224,
56 eDataApplicationCapability_application_nlpid,
57 eDataApplicationCapability_application_dsvdControl,
58 eDataApplicationCapability_application_h222DataPartitioning,
59 eDataApplicationCapability_application_t30fax,
60 eDataApplicationCapability_application_t140,
61 eDataApplicationCapability_application_t38fax,
62 eDataApplicationCapability_application_genericDataCapability,
63 } choice;
64 union {
65 DataProtocolCapability t120;
66 };
67} DataApplicationCapability_application;
68
69typedef struct DataApplicationCapability { /* SEQUENCE */
70 int options; /* No use */
71 DataApplicationCapability_application application;
72} DataApplicationCapability;
73
74typedef struct DataType { /* CHOICE */
75 enum {
76 eDataType_nonStandard,
77 eDataType_nullData,
78 eDataType_videoData,
79 eDataType_audioData,
80 eDataType_data,
81 eDataType_encryptionData,
82 eDataType_h235Control,
83 eDataType_h235Media,
84 eDataType_multiplexedStream,
85 } choice;
86 union {
87 DataApplicationCapability data;
88 };
89} DataType;
90
91typedef struct UnicastAddress_iPAddress { /* SEQUENCE */
92 int options; /* No use */
93 unsigned network;
94} UnicastAddress_iPAddress;
95
96typedef struct UnicastAddress { /* CHOICE */
97 enum {
98 eUnicastAddress_iPAddress,
99 eUnicastAddress_iPXAddress,
100 eUnicastAddress_iP6Address,
101 eUnicastAddress_netBios,
102 eUnicastAddress_iPSourceRouteAddress,
103 eUnicastAddress_nsap,
104 eUnicastAddress_nonStandardAddress,
105 } choice;
106 union {
107 UnicastAddress_iPAddress iPAddress;
108 };
109} UnicastAddress;
110
111typedef struct H245_TransportAddress { /* CHOICE */
112 enum {
113 eH245_TransportAddress_unicastAddress,
114 eH245_TransportAddress_multicastAddress,
115 } choice;
116 union {
117 UnicastAddress unicastAddress;
118 };
119} H245_TransportAddress;
120
121typedef struct H2250LogicalChannelParameters { /* SEQUENCE */
122 enum {
123 eH2250LogicalChannelParameters_nonStandard = (1 << 31),
124 eH2250LogicalChannelParameters_associatedSessionID =
125 (1 << 30),
126 eH2250LogicalChannelParameters_mediaChannel = (1 << 29),
127 eH2250LogicalChannelParameters_mediaGuaranteedDelivery =
128 (1 << 28),
129 eH2250LogicalChannelParameters_mediaControlChannel =
130 (1 << 27),
131 eH2250LogicalChannelParameters_mediaControlGuaranteedDelivery
132 = (1 << 26),
133 eH2250LogicalChannelParameters_silenceSuppression = (1 << 25),
134 eH2250LogicalChannelParameters_destination = (1 << 24),
135 eH2250LogicalChannelParameters_dynamicRTPPayloadType =
136 (1 << 23),
137 eH2250LogicalChannelParameters_mediaPacketization = (1 << 22),
138 eH2250LogicalChannelParameters_transportCapability =
139 (1 << 21),
140 eH2250LogicalChannelParameters_redundancyEncoding = (1 << 20),
141 eH2250LogicalChannelParameters_source = (1 << 19),
142 } options;
143 H245_TransportAddress mediaChannel;
144 H245_TransportAddress mediaControlChannel;
145} H2250LogicalChannelParameters;
146
147typedef struct OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters { /* CHOICE */
148 enum {
149 eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters,
150 eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters,
151 eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters,
152 eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters,
153 eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_none,
154 } choice;
155 union {
156 H2250LogicalChannelParameters h2250LogicalChannelParameters;
157 };
158} OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters;
159
160typedef struct OpenLogicalChannel_forwardLogicalChannelParameters { /* SEQUENCE */
161 enum {
162 eOpenLogicalChannel_forwardLogicalChannelParameters_portNumber
163 = (1 << 31),
164 eOpenLogicalChannel_forwardLogicalChannelParameters_forwardLogicalChannelDependency
165 = (1 << 30),
166 eOpenLogicalChannel_forwardLogicalChannelParameters_replacementFor
167 = (1 << 29),
168 } options;
169 DataType dataType;
170 OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters
171 multiplexParameters;
172} OpenLogicalChannel_forwardLogicalChannelParameters;
173
174typedef struct OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */
175 enum {
176 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters,
177 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters,
178 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters,
179 } choice;
180 union {
181 H2250LogicalChannelParameters h2250LogicalChannelParameters;
182 };
183} OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters;
184
185typedef struct OpenLogicalChannel_reverseLogicalChannelParameters { /* SEQUENCE */
186 enum {
187 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters
188 = (1 << 31),
189 eOpenLogicalChannel_reverseLogicalChannelParameters_reverseLogicalChannelDependency
190 = (1 << 30),
191 eOpenLogicalChannel_reverseLogicalChannelParameters_replacementFor
192 = (1 << 29),
193 } options;
194 OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters
195 multiplexParameters;
196} OpenLogicalChannel_reverseLogicalChannelParameters;
197
198typedef struct NetworkAccessParameters_networkAddress { /* CHOICE */
199 enum {
200 eNetworkAccessParameters_networkAddress_q2931Address,
201 eNetworkAccessParameters_networkAddress_e164Address,
202 eNetworkAccessParameters_networkAddress_localAreaAddress,
203 } choice;
204 union {
205 H245_TransportAddress localAreaAddress;
206 };
207} NetworkAccessParameters_networkAddress;
208
209typedef struct NetworkAccessParameters { /* SEQUENCE */
210 enum {
211 eNetworkAccessParameters_distribution = (1 << 31),
212 eNetworkAccessParameters_externalReference = (1 << 30),
213 eNetworkAccessParameters_t120SetupProcedure = (1 << 29),
214 } options;
215 NetworkAccessParameters_networkAddress networkAddress;
216} NetworkAccessParameters;
217
218typedef struct OpenLogicalChannel { /* SEQUENCE */
219 enum {
220 eOpenLogicalChannel_reverseLogicalChannelParameters =
221 (1 << 31),
222 eOpenLogicalChannel_separateStack = (1 << 30),
223 eOpenLogicalChannel_encryptionSync = (1 << 29),
224 } options;
225 OpenLogicalChannel_forwardLogicalChannelParameters
226 forwardLogicalChannelParameters;
227 OpenLogicalChannel_reverseLogicalChannelParameters
228 reverseLogicalChannelParameters;
229 NetworkAccessParameters separateStack;
230} OpenLogicalChannel;
231
232typedef struct Setup_UUIE_fastStart { /* SEQUENCE OF */
233 int count;
234 OpenLogicalChannel item[30];
235} Setup_UUIE_fastStart;
236
237typedef struct Setup_UUIE { /* SEQUENCE */
238 enum {
239 eSetup_UUIE_h245Address = (1 << 31),
240 eSetup_UUIE_sourceAddress = (1 << 30),
241 eSetup_UUIE_destinationAddress = (1 << 29),
242 eSetup_UUIE_destCallSignalAddress = (1 << 28),
243 eSetup_UUIE_destExtraCallInfo = (1 << 27),
244 eSetup_UUIE_destExtraCRV = (1 << 26),
245 eSetup_UUIE_callServices = (1 << 25),
246 eSetup_UUIE_sourceCallSignalAddress = (1 << 24),
247 eSetup_UUIE_remoteExtensionAddress = (1 << 23),
248 eSetup_UUIE_callIdentifier = (1 << 22),
249 eSetup_UUIE_h245SecurityCapability = (1 << 21),
250 eSetup_UUIE_tokens = (1 << 20),
251 eSetup_UUIE_cryptoTokens = (1 << 19),
252 eSetup_UUIE_fastStart = (1 << 18),
253 eSetup_UUIE_mediaWaitForConnect = (1 << 17),
254 eSetup_UUIE_canOverlapSend = (1 << 16),
255 eSetup_UUIE_endpointIdentifier = (1 << 15),
256 eSetup_UUIE_multipleCalls = (1 << 14),
257 eSetup_UUIE_maintainConnection = (1 << 13),
258 eSetup_UUIE_connectionParameters = (1 << 12),
259 eSetup_UUIE_language = (1 << 11),
260 eSetup_UUIE_presentationIndicator = (1 << 10),
261 eSetup_UUIE_screeningIndicator = (1 << 9),
262 eSetup_UUIE_serviceControl = (1 << 8),
263 eSetup_UUIE_symmetricOperationRequired = (1 << 7),
264 eSetup_UUIE_capacity = (1 << 6),
265 eSetup_UUIE_circuitInfo = (1 << 5),
266 eSetup_UUIE_desiredProtocols = (1 << 4),
267 eSetup_UUIE_neededFeatures = (1 << 3),
268 eSetup_UUIE_desiredFeatures = (1 << 2),
269 eSetup_UUIE_supportedFeatures = (1 << 1),
270 eSetup_UUIE_parallelH245Control = (1 << 0),
271 } options;
272 TransportAddress h245Address;
273 TransportAddress destCallSignalAddress;
274 TransportAddress sourceCallSignalAddress;
275 Setup_UUIE_fastStart fastStart;
276} Setup_UUIE;
277
278typedef struct CallProceeding_UUIE_fastStart { /* SEQUENCE OF */
279 int count;
280 OpenLogicalChannel item[30];
281} CallProceeding_UUIE_fastStart;
282
283typedef struct CallProceeding_UUIE { /* SEQUENCE */
284 enum {
285 eCallProceeding_UUIE_h245Address = (1 << 31),
286 eCallProceeding_UUIE_callIdentifier = (1 << 30),
287 eCallProceeding_UUIE_h245SecurityMode = (1 << 29),
288 eCallProceeding_UUIE_tokens = (1 << 28),
289 eCallProceeding_UUIE_cryptoTokens = (1 << 27),
290 eCallProceeding_UUIE_fastStart = (1 << 26),
291 eCallProceeding_UUIE_multipleCalls = (1 << 25),
292 eCallProceeding_UUIE_maintainConnection = (1 << 24),
293 eCallProceeding_UUIE_fastConnectRefused = (1 << 23),
294 eCallProceeding_UUIE_featureSet = (1 << 22),
295 } options;
296 TransportAddress h245Address;
297 CallProceeding_UUIE_fastStart fastStart;
298} CallProceeding_UUIE;
299
300typedef struct Connect_UUIE_fastStart { /* SEQUENCE OF */
301 int count;
302 OpenLogicalChannel item[30];
303} Connect_UUIE_fastStart;
304
305typedef struct Connect_UUIE { /* SEQUENCE */
306 enum {
307 eConnect_UUIE_h245Address = (1 << 31),
308 eConnect_UUIE_callIdentifier = (1 << 30),
309 eConnect_UUIE_h245SecurityMode = (1 << 29),
310 eConnect_UUIE_tokens = (1 << 28),
311 eConnect_UUIE_cryptoTokens = (1 << 27),
312 eConnect_UUIE_fastStart = (1 << 26),
313 eConnect_UUIE_multipleCalls = (1 << 25),
314 eConnect_UUIE_maintainConnection = (1 << 24),
315 eConnect_UUIE_language = (1 << 23),
316 eConnect_UUIE_connectedAddress = (1 << 22),
317 eConnect_UUIE_presentationIndicator = (1 << 21),
318 eConnect_UUIE_screeningIndicator = (1 << 20),
319 eConnect_UUIE_fastConnectRefused = (1 << 19),
320 eConnect_UUIE_serviceControl = (1 << 18),
321 eConnect_UUIE_capacity = (1 << 17),
322 eConnect_UUIE_featureSet = (1 << 16),
323 } options;
324 TransportAddress h245Address;
325 Connect_UUIE_fastStart fastStart;
326} Connect_UUIE;
327
328typedef struct Alerting_UUIE_fastStart { /* SEQUENCE OF */
329 int count;
330 OpenLogicalChannel item[30];
331} Alerting_UUIE_fastStart;
332
333typedef struct Alerting_UUIE { /* SEQUENCE */
334 enum {
335 eAlerting_UUIE_h245Address = (1 << 31),
336 eAlerting_UUIE_callIdentifier = (1 << 30),
337 eAlerting_UUIE_h245SecurityMode = (1 << 29),
338 eAlerting_UUIE_tokens = (1 << 28),
339 eAlerting_UUIE_cryptoTokens = (1 << 27),
340 eAlerting_UUIE_fastStart = (1 << 26),
341 eAlerting_UUIE_multipleCalls = (1 << 25),
342 eAlerting_UUIE_maintainConnection = (1 << 24),
343 eAlerting_UUIE_alertingAddress = (1 << 23),
344 eAlerting_UUIE_presentationIndicator = (1 << 22),
345 eAlerting_UUIE_screeningIndicator = (1 << 21),
346 eAlerting_UUIE_fastConnectRefused = (1 << 20),
347 eAlerting_UUIE_serviceControl = (1 << 19),
348 eAlerting_UUIE_capacity = (1 << 18),
349 eAlerting_UUIE_featureSet = (1 << 17),
350 } options;
351 TransportAddress h245Address;
352 Alerting_UUIE_fastStart fastStart;
353} Alerting_UUIE;
354
355typedef struct Information_UUIE_fastStart { /* SEQUENCE OF */
356 int count;
357 OpenLogicalChannel item[30];
358} Information_UUIE_fastStart;
359
360typedef struct Information_UUIE { /* SEQUENCE */
361 enum {
362 eInformation_UUIE_callIdentifier = (1 << 31),
363 eInformation_UUIE_tokens = (1 << 30),
364 eInformation_UUIE_cryptoTokens = (1 << 29),
365 eInformation_UUIE_fastStart = (1 << 28),
366 eInformation_UUIE_fastConnectRefused = (1 << 27),
367 eInformation_UUIE_circuitInfo = (1 << 26),
368 } options;
369 Information_UUIE_fastStart fastStart;
370} Information_UUIE;
371
372typedef struct FacilityReason { /* CHOICE */
373 enum {
374 eFacilityReason_routeCallToGatekeeper,
375 eFacilityReason_callForwarded,
376 eFacilityReason_routeCallToMC,
377 eFacilityReason_undefinedReason,
378 eFacilityReason_conferenceListChoice,
379 eFacilityReason_startH245,
380 eFacilityReason_noH245,
381 eFacilityReason_newTokens,
382 eFacilityReason_featureSetUpdate,
383 eFacilityReason_forwardedElements,
384 eFacilityReason_transportedInformation,
385 } choice;
386} FacilityReason;
387
388typedef struct Facility_UUIE_fastStart { /* SEQUENCE OF */
389 int count;
390 OpenLogicalChannel item[30];
391} Facility_UUIE_fastStart;
392
393typedef struct Facility_UUIE { /* SEQUENCE */
394 enum {
395 eFacility_UUIE_alternativeAddress = (1 << 31),
396 eFacility_UUIE_alternativeAliasAddress = (1 << 30),
397 eFacility_UUIE_conferenceID = (1 << 29),
398 eFacility_UUIE_callIdentifier = (1 << 28),
399 eFacility_UUIE_destExtraCallInfo = (1 << 27),
400 eFacility_UUIE_remoteExtensionAddress = (1 << 26),
401 eFacility_UUIE_tokens = (1 << 25),
402 eFacility_UUIE_cryptoTokens = (1 << 24),
403 eFacility_UUIE_conferences = (1 << 23),
404 eFacility_UUIE_h245Address = (1 << 22),
405 eFacility_UUIE_fastStart = (1 << 21),
406 eFacility_UUIE_multipleCalls = (1 << 20),
407 eFacility_UUIE_maintainConnection = (1 << 19),
408 eFacility_UUIE_fastConnectRefused = (1 << 18),
409 eFacility_UUIE_serviceControl = (1 << 17),
410 eFacility_UUIE_circuitInfo = (1 << 16),
411 eFacility_UUIE_featureSet = (1 << 15),
412 eFacility_UUIE_destinationInfo = (1 << 14),
413 eFacility_UUIE_h245SecurityMode = (1 << 13),
414 } options;
415 FacilityReason reason;
416 TransportAddress h245Address;
417 Facility_UUIE_fastStart fastStart;
418} Facility_UUIE;
419
420typedef struct Progress_UUIE_fastStart { /* SEQUENCE OF */
421 int count;
422 OpenLogicalChannel item[30];
423} Progress_UUIE_fastStart;
424
425typedef struct Progress_UUIE { /* SEQUENCE */
426 enum {
427 eProgress_UUIE_h245Address = (1 << 31),
428 eProgress_UUIE_h245SecurityMode = (1 << 30),
429 eProgress_UUIE_tokens = (1 << 29),
430 eProgress_UUIE_cryptoTokens = (1 << 28),
431 eProgress_UUIE_fastStart = (1 << 27),
432 eProgress_UUIE_multipleCalls = (1 << 26),
433 eProgress_UUIE_maintainConnection = (1 << 25),
434 eProgress_UUIE_fastConnectRefused = (1 << 24),
435 } options;
436 TransportAddress h245Address;
437 Progress_UUIE_fastStart fastStart;
438} Progress_UUIE;
439
440typedef struct H323_UU_PDU_h323_message_body { /* CHOICE */
441 enum {
442 eH323_UU_PDU_h323_message_body_setup,
443 eH323_UU_PDU_h323_message_body_callProceeding,
444 eH323_UU_PDU_h323_message_body_connect,
445 eH323_UU_PDU_h323_message_body_alerting,
446 eH323_UU_PDU_h323_message_body_information,
447 eH323_UU_PDU_h323_message_body_releaseComplete,
448 eH323_UU_PDU_h323_message_body_facility,
449 eH323_UU_PDU_h323_message_body_progress,
450 eH323_UU_PDU_h323_message_body_empty,
451 eH323_UU_PDU_h323_message_body_status,
452 eH323_UU_PDU_h323_message_body_statusInquiry,
453 eH323_UU_PDU_h323_message_body_setupAcknowledge,
454 eH323_UU_PDU_h323_message_body_notify,
455 } choice;
456 union {
457 Setup_UUIE setup;
458 CallProceeding_UUIE callProceeding;
459 Connect_UUIE connect;
460 Alerting_UUIE alerting;
461 Information_UUIE information;
462 Facility_UUIE facility;
463 Progress_UUIE progress;
464 };
465} H323_UU_PDU_h323_message_body;
466
467typedef struct RequestMessage { /* CHOICE */
468 enum {
469 eRequestMessage_nonStandard,
470 eRequestMessage_masterSlaveDetermination,
471 eRequestMessage_terminalCapabilitySet,
472 eRequestMessage_openLogicalChannel,
473 eRequestMessage_closeLogicalChannel,
474 eRequestMessage_requestChannelClose,
475 eRequestMessage_multiplexEntrySend,
476 eRequestMessage_requestMultiplexEntry,
477 eRequestMessage_requestMode,
478 eRequestMessage_roundTripDelayRequest,
479 eRequestMessage_maintenanceLoopRequest,
480 eRequestMessage_communicationModeRequest,
481 eRequestMessage_conferenceRequest,
482 eRequestMessage_multilinkRequest,
483 eRequestMessage_logicalChannelRateRequest,
484 } choice;
485 union {
486 OpenLogicalChannel openLogicalChannel;
487 };
488} RequestMessage;
489
490typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */
491 enum {
492 eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters,
493 eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters,
494 } choice;
495 union {
496 H2250LogicalChannelParameters h2250LogicalChannelParameters;
497 };
498} OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters;
499
500typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters { /* SEQUENCE */
501 enum {
502 eOpenLogicalChannelAck_reverseLogicalChannelParameters_portNumber
503 = (1 << 31),
504 eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters
505 = (1 << 30),
506 eOpenLogicalChannelAck_reverseLogicalChannelParameters_replacementFor
507 = (1 << 29),
508 } options;
509 OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters
510 multiplexParameters;
511} OpenLogicalChannelAck_reverseLogicalChannelParameters;
512
513typedef struct H2250LogicalChannelAckParameters { /* SEQUENCE */
514 enum {
515 eH2250LogicalChannelAckParameters_nonStandard = (1 << 31),
516 eH2250LogicalChannelAckParameters_sessionID = (1 << 30),
517 eH2250LogicalChannelAckParameters_mediaChannel = (1 << 29),
518 eH2250LogicalChannelAckParameters_mediaControlChannel =
519 (1 << 28),
520 eH2250LogicalChannelAckParameters_dynamicRTPPayloadType =
521 (1 << 27),
522 eH2250LogicalChannelAckParameters_flowControlToZero =
523 (1 << 26),
524 eH2250LogicalChannelAckParameters_portNumber = (1 << 25),
525 } options;
526 H245_TransportAddress mediaChannel;
527 H245_TransportAddress mediaControlChannel;
528} H2250LogicalChannelAckParameters;
529
530typedef struct OpenLogicalChannelAck_forwardMultiplexAckParameters { /* CHOICE */
531 enum {
532 eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters,
533 } choice;
534 union {
535 H2250LogicalChannelAckParameters
536 h2250LogicalChannelAckParameters;
537 };
538} OpenLogicalChannelAck_forwardMultiplexAckParameters;
539
540typedef struct OpenLogicalChannelAck { /* SEQUENCE */
541 enum {
542 eOpenLogicalChannelAck_reverseLogicalChannelParameters =
543 (1 << 31),
544 eOpenLogicalChannelAck_separateStack = (1 << 30),
545 eOpenLogicalChannelAck_forwardMultiplexAckParameters =
546 (1 << 29),
547 eOpenLogicalChannelAck_encryptionSync = (1 << 28),
548 } options;
549 OpenLogicalChannelAck_reverseLogicalChannelParameters
550 reverseLogicalChannelParameters;
551 OpenLogicalChannelAck_forwardMultiplexAckParameters
552 forwardMultiplexAckParameters;
553} OpenLogicalChannelAck;
554
555typedef struct ResponseMessage { /* CHOICE */
556 enum {
557 eResponseMessage_nonStandard,
558 eResponseMessage_masterSlaveDeterminationAck,
559 eResponseMessage_masterSlaveDeterminationReject,
560 eResponseMessage_terminalCapabilitySetAck,
561 eResponseMessage_terminalCapabilitySetReject,
562 eResponseMessage_openLogicalChannelAck,
563 eResponseMessage_openLogicalChannelReject,
564 eResponseMessage_closeLogicalChannelAck,
565 eResponseMessage_requestChannelCloseAck,
566 eResponseMessage_requestChannelCloseReject,
567 eResponseMessage_multiplexEntrySendAck,
568 eResponseMessage_multiplexEntrySendReject,
569 eResponseMessage_requestMultiplexEntryAck,
570 eResponseMessage_requestMultiplexEntryReject,
571 eResponseMessage_requestModeAck,
572 eResponseMessage_requestModeReject,
573 eResponseMessage_roundTripDelayResponse,
574 eResponseMessage_maintenanceLoopAck,
575 eResponseMessage_maintenanceLoopReject,
576 eResponseMessage_communicationModeResponse,
577 eResponseMessage_conferenceResponse,
578 eResponseMessage_multilinkResponse,
579 eResponseMessage_logicalChannelRateAcknowledge,
580 eResponseMessage_logicalChannelRateReject,
581 } choice;
582 union {
583 OpenLogicalChannelAck openLogicalChannelAck;
584 };
585} ResponseMessage;
586
587typedef struct MultimediaSystemControlMessage { /* CHOICE */
588 enum {
589 eMultimediaSystemControlMessage_request,
590 eMultimediaSystemControlMessage_response,
591 eMultimediaSystemControlMessage_command,
592 eMultimediaSystemControlMessage_indication,
593 } choice;
594 union {
595 RequestMessage request;
596 ResponseMessage response;
597 };
598} MultimediaSystemControlMessage;
599
600typedef struct H323_UU_PDU_h245Control { /* SEQUENCE OF */
601 int count;
602 MultimediaSystemControlMessage item[4];
603} H323_UU_PDU_h245Control;
604
605typedef struct H323_UU_PDU { /* SEQUENCE */
606 enum {
607 eH323_UU_PDU_nonStandardData = (1 << 31),
608 eH323_UU_PDU_h4501SupplementaryService = (1 << 30),
609 eH323_UU_PDU_h245Tunneling = (1 << 29),
610 eH323_UU_PDU_h245Control = (1 << 28),
611 eH323_UU_PDU_nonStandardControl = (1 << 27),
612 eH323_UU_PDU_callLinkage = (1 << 26),
613 eH323_UU_PDU_tunnelledSignallingMessage = (1 << 25),
614 eH323_UU_PDU_provisionalRespToH245Tunneling = (1 << 24),
615 eH323_UU_PDU_stimulusControl = (1 << 23),
616 eH323_UU_PDU_genericData = (1 << 22),
617 } options;
618 H323_UU_PDU_h323_message_body h323_message_body;
619 H323_UU_PDU_h245Control h245Control;
620} H323_UU_PDU;
621
622typedef struct H323_UserInformation { /* SEQUENCE */
623 enum {
624 eH323_UserInformation_user_data = (1 << 31),
625 } options;
626 H323_UU_PDU h323_uu_pdu;
627} H323_UserInformation;
628
629typedef struct GatekeeperRequest { /* SEQUENCE */
630 enum {
631 eGatekeeperRequest_nonStandardData = (1 << 31),
632 eGatekeeperRequest_gatekeeperIdentifier = (1 << 30),
633 eGatekeeperRequest_callServices = (1 << 29),
634 eGatekeeperRequest_endpointAlias = (1 << 28),
635 eGatekeeperRequest_alternateEndpoints = (1 << 27),
636 eGatekeeperRequest_tokens = (1 << 26),
637 eGatekeeperRequest_cryptoTokens = (1 << 25),
638 eGatekeeperRequest_authenticationCapability = (1 << 24),
639 eGatekeeperRequest_algorithmOIDs = (1 << 23),
640 eGatekeeperRequest_integrity = (1 << 22),
641 eGatekeeperRequest_integrityCheckValue = (1 << 21),
642 eGatekeeperRequest_supportsAltGK = (1 << 20),
643 eGatekeeperRequest_featureSet = (1 << 19),
644 eGatekeeperRequest_genericData = (1 << 18),
645 } options;
646 TransportAddress rasAddress;
647} GatekeeperRequest;
648
649typedef struct GatekeeperConfirm { /* SEQUENCE */
650 enum {
651 eGatekeeperConfirm_nonStandardData = (1 << 31),
652 eGatekeeperConfirm_gatekeeperIdentifier = (1 << 30),
653 eGatekeeperConfirm_alternateGatekeeper = (1 << 29),
654 eGatekeeperConfirm_authenticationMode = (1 << 28),
655 eGatekeeperConfirm_tokens = (1 << 27),
656 eGatekeeperConfirm_cryptoTokens = (1 << 26),
657 eGatekeeperConfirm_algorithmOID = (1 << 25),
658 eGatekeeperConfirm_integrity = (1 << 24),
659 eGatekeeperConfirm_integrityCheckValue = (1 << 23),
660 eGatekeeperConfirm_featureSet = (1 << 22),
661 eGatekeeperConfirm_genericData = (1 << 21),
662 } options;
663 TransportAddress rasAddress;
664} GatekeeperConfirm;
665
666typedef struct RegistrationRequest_callSignalAddress { /* SEQUENCE OF */
667 int count;
668 TransportAddress item[10];
669} RegistrationRequest_callSignalAddress;
670
671typedef struct RegistrationRequest_rasAddress { /* SEQUENCE OF */
672 int count;
673 TransportAddress item[10];
674} RegistrationRequest_rasAddress;
675
676typedef struct RegistrationRequest { /* SEQUENCE */
677 enum {
678 eRegistrationRequest_nonStandardData = (1 << 31),
679 eRegistrationRequest_terminalAlias = (1 << 30),
680 eRegistrationRequest_gatekeeperIdentifier = (1 << 29),
681 eRegistrationRequest_alternateEndpoints = (1 << 28),
682 eRegistrationRequest_timeToLive = (1 << 27),
683 eRegistrationRequest_tokens = (1 << 26),
684 eRegistrationRequest_cryptoTokens = (1 << 25),
685 eRegistrationRequest_integrityCheckValue = (1 << 24),
686 eRegistrationRequest_keepAlive = (1 << 23),
687 eRegistrationRequest_endpointIdentifier = (1 << 22),
688 eRegistrationRequest_willSupplyUUIEs = (1 << 21),
689 eRegistrationRequest_maintainConnection = (1 << 20),
690 eRegistrationRequest_alternateTransportAddresses = (1 << 19),
691 eRegistrationRequest_additiveRegistration = (1 << 18),
692 eRegistrationRequest_terminalAliasPattern = (1 << 17),
693 eRegistrationRequest_supportsAltGK = (1 << 16),
694 eRegistrationRequest_usageReportingCapability = (1 << 15),
695 eRegistrationRequest_multipleCalls = (1 << 14),
696 eRegistrationRequest_supportedH248Packages = (1 << 13),
697 eRegistrationRequest_callCreditCapability = (1 << 12),
698 eRegistrationRequest_capacityReportingCapability = (1 << 11),
699 eRegistrationRequest_capacity = (1 << 10),
700 eRegistrationRequest_featureSet = (1 << 9),
701 eRegistrationRequest_genericData = (1 << 8),
702 } options;
703 RegistrationRequest_callSignalAddress callSignalAddress;
704 RegistrationRequest_rasAddress rasAddress;
705 unsigned timeToLive;
706} RegistrationRequest;
707
708typedef struct RegistrationConfirm_callSignalAddress { /* SEQUENCE OF */
709 int count;
710 TransportAddress item[10];
711} RegistrationConfirm_callSignalAddress;
712
713typedef struct RegistrationConfirm { /* SEQUENCE */
714 enum {
715 eRegistrationConfirm_nonStandardData = (1 << 31),
716 eRegistrationConfirm_terminalAlias = (1 << 30),
717 eRegistrationConfirm_gatekeeperIdentifier = (1 << 29),
718 eRegistrationConfirm_alternateGatekeeper = (1 << 28),
719 eRegistrationConfirm_timeToLive = (1 << 27),
720 eRegistrationConfirm_tokens = (1 << 26),
721 eRegistrationConfirm_cryptoTokens = (1 << 25),
722 eRegistrationConfirm_integrityCheckValue = (1 << 24),
723 eRegistrationConfirm_willRespondToIRR = (1 << 23),
724 eRegistrationConfirm_preGrantedARQ = (1 << 22),
725 eRegistrationConfirm_maintainConnection = (1 << 21),
726 eRegistrationConfirm_serviceControl = (1 << 20),
727 eRegistrationConfirm_supportsAdditiveRegistration = (1 << 19),
728 eRegistrationConfirm_terminalAliasPattern = (1 << 18),
729 eRegistrationConfirm_supportedPrefixes = (1 << 17),
730 eRegistrationConfirm_usageSpec = (1 << 16),
731 eRegistrationConfirm_featureServerAlias = (1 << 15),
732 eRegistrationConfirm_capacityReportingSpec = (1 << 14),
733 eRegistrationConfirm_featureSet = (1 << 13),
734 eRegistrationConfirm_genericData = (1 << 12),
735 } options;
736 RegistrationConfirm_callSignalAddress callSignalAddress;
737 unsigned timeToLive;
738} RegistrationConfirm;
739
740typedef struct UnregistrationRequest_callSignalAddress { /* SEQUENCE OF */
741 int count;
742 TransportAddress item[10];
743} UnregistrationRequest_callSignalAddress;
744
745typedef struct UnregistrationRequest { /* SEQUENCE */
746 enum {
747 eUnregistrationRequest_endpointAlias = (1 << 31),
748 eUnregistrationRequest_nonStandardData = (1 << 30),
749 eUnregistrationRequest_endpointIdentifier = (1 << 29),
750 eUnregistrationRequest_alternateEndpoints = (1 << 28),
751 eUnregistrationRequest_gatekeeperIdentifier = (1 << 27),
752 eUnregistrationRequest_tokens = (1 << 26),
753 eUnregistrationRequest_cryptoTokens = (1 << 25),
754 eUnregistrationRequest_integrityCheckValue = (1 << 24),
755 eUnregistrationRequest_reason = (1 << 23),
756 eUnregistrationRequest_endpointAliasPattern = (1 << 22),
757 eUnregistrationRequest_supportedPrefixes = (1 << 21),
758 eUnregistrationRequest_alternateGatekeeper = (1 << 20),
759 eUnregistrationRequest_genericData = (1 << 19),
760 } options;
761 UnregistrationRequest_callSignalAddress callSignalAddress;
762} UnregistrationRequest;
763
764typedef struct AdmissionRequest { /* SEQUENCE */
765 enum {
766 eAdmissionRequest_callModel = (1 << 31),
767 eAdmissionRequest_destinationInfo = (1 << 30),
768 eAdmissionRequest_destCallSignalAddress = (1 << 29),
769 eAdmissionRequest_destExtraCallInfo = (1 << 28),
770 eAdmissionRequest_srcCallSignalAddress = (1 << 27),
771 eAdmissionRequest_nonStandardData = (1 << 26),
772 eAdmissionRequest_callServices = (1 << 25),
773 eAdmissionRequest_canMapAlias = (1 << 24),
774 eAdmissionRequest_callIdentifier = (1 << 23),
775 eAdmissionRequest_srcAlternatives = (1 << 22),
776 eAdmissionRequest_destAlternatives = (1 << 21),
777 eAdmissionRequest_gatekeeperIdentifier = (1 << 20),
778 eAdmissionRequest_tokens = (1 << 19),
779 eAdmissionRequest_cryptoTokens = (1 << 18),
780 eAdmissionRequest_integrityCheckValue = (1 << 17),
781 eAdmissionRequest_transportQOS = (1 << 16),
782 eAdmissionRequest_willSupplyUUIEs = (1 << 15),
783 eAdmissionRequest_callLinkage = (1 << 14),
784 eAdmissionRequest_gatewayDataRate = (1 << 13),
785 eAdmissionRequest_capacity = (1 << 12),
786 eAdmissionRequest_circuitInfo = (1 << 11),
787 eAdmissionRequest_desiredProtocols = (1 << 10),
788 eAdmissionRequest_desiredTunnelledProtocol = (1 << 9),
789 eAdmissionRequest_featureSet = (1 << 8),
790 eAdmissionRequest_genericData = (1 << 7),
791 } options;
792 TransportAddress destCallSignalAddress;
793 TransportAddress srcCallSignalAddress;
794} AdmissionRequest;
795
796typedef struct AdmissionConfirm { /* SEQUENCE */
797 enum {
798 eAdmissionConfirm_irrFrequency = (1 << 31),
799 eAdmissionConfirm_nonStandardData = (1 << 30),
800 eAdmissionConfirm_destinationInfo = (1 << 29),
801 eAdmissionConfirm_destExtraCallInfo = (1 << 28),
802 eAdmissionConfirm_destinationType = (1 << 27),
803 eAdmissionConfirm_remoteExtensionAddress = (1 << 26),
804 eAdmissionConfirm_alternateEndpoints = (1 << 25),
805 eAdmissionConfirm_tokens = (1 << 24),
806 eAdmissionConfirm_cryptoTokens = (1 << 23),
807 eAdmissionConfirm_integrityCheckValue = (1 << 22),
808 eAdmissionConfirm_transportQOS = (1 << 21),
809 eAdmissionConfirm_willRespondToIRR = (1 << 20),
810 eAdmissionConfirm_uuiesRequested = (1 << 19),
811 eAdmissionConfirm_language = (1 << 18),
812 eAdmissionConfirm_alternateTransportAddresses = (1 << 17),
813 eAdmissionConfirm_useSpecifiedTransport = (1 << 16),
814 eAdmissionConfirm_circuitInfo = (1 << 15),
815 eAdmissionConfirm_usageSpec = (1 << 14),
816 eAdmissionConfirm_supportedProtocols = (1 << 13),
817 eAdmissionConfirm_serviceControl = (1 << 12),
818 eAdmissionConfirm_multipleCalls = (1 << 11),
819 eAdmissionConfirm_featureSet = (1 << 10),
820 eAdmissionConfirm_genericData = (1 << 9),
821 } options;
822 TransportAddress destCallSignalAddress;
823} AdmissionConfirm;
824
825typedef struct LocationRequest { /* SEQUENCE */
826 enum {
827 eLocationRequest_endpointIdentifier = (1 << 31),
828 eLocationRequest_nonStandardData = (1 << 30),
829 eLocationRequest_sourceInfo = (1 << 29),
830 eLocationRequest_canMapAlias = (1 << 28),
831 eLocationRequest_gatekeeperIdentifier = (1 << 27),
832 eLocationRequest_tokens = (1 << 26),
833 eLocationRequest_cryptoTokens = (1 << 25),
834 eLocationRequest_integrityCheckValue = (1 << 24),
835 eLocationRequest_desiredProtocols = (1 << 23),
836 eLocationRequest_desiredTunnelledProtocol = (1 << 22),
837 eLocationRequest_featureSet = (1 << 21),
838 eLocationRequest_genericData = (1 << 20),
839 eLocationRequest_hopCount = (1 << 19),
840 eLocationRequest_circuitInfo = (1 << 18),
841 } options;
842 TransportAddress replyAddress;
843} LocationRequest;
844
845typedef struct LocationConfirm { /* SEQUENCE */
846 enum {
847 eLocationConfirm_nonStandardData = (1 << 31),
848 eLocationConfirm_destinationInfo = (1 << 30),
849 eLocationConfirm_destExtraCallInfo = (1 << 29),
850 eLocationConfirm_destinationType = (1 << 28),
851 eLocationConfirm_remoteExtensionAddress = (1 << 27),
852 eLocationConfirm_alternateEndpoints = (1 << 26),
853 eLocationConfirm_tokens = (1 << 25),
854 eLocationConfirm_cryptoTokens = (1 << 24),
855 eLocationConfirm_integrityCheckValue = (1 << 23),
856 eLocationConfirm_alternateTransportAddresses = (1 << 22),
857 eLocationConfirm_supportedProtocols = (1 << 21),
858 eLocationConfirm_multipleCalls = (1 << 20),
859 eLocationConfirm_featureSet = (1 << 19),
860 eLocationConfirm_genericData = (1 << 18),
861 eLocationConfirm_circuitInfo = (1 << 17),
862 eLocationConfirm_serviceControl = (1 << 16),
863 } options;
864 TransportAddress callSignalAddress;
865 TransportAddress rasAddress;
866} LocationConfirm;
867
868typedef struct InfoRequestResponse_callSignalAddress { /* SEQUENCE OF */
869 int count;
870 TransportAddress item[10];
871} InfoRequestResponse_callSignalAddress;
872
873typedef struct InfoRequestResponse { /* SEQUENCE */
874 enum {
875 eInfoRequestResponse_nonStandardData = (1 << 31),
876 eInfoRequestResponse_endpointAlias = (1 << 30),
877 eInfoRequestResponse_perCallInfo = (1 << 29),
878 eInfoRequestResponse_tokens = (1 << 28),
879 eInfoRequestResponse_cryptoTokens = (1 << 27),
880 eInfoRequestResponse_integrityCheckValue = (1 << 26),
881 eInfoRequestResponse_needResponse = (1 << 25),
882 eInfoRequestResponse_capacity = (1 << 24),
883 eInfoRequestResponse_irrStatus = (1 << 23),
884 eInfoRequestResponse_unsolicited = (1 << 22),
885 eInfoRequestResponse_genericData = (1 << 21),
886 } options;
887 TransportAddress rasAddress;
888 InfoRequestResponse_callSignalAddress callSignalAddress;
889} InfoRequestResponse;
890
891typedef struct RasMessage { /* CHOICE */
892 enum {
893 eRasMessage_gatekeeperRequest,
894 eRasMessage_gatekeeperConfirm,
895 eRasMessage_gatekeeperReject,
896 eRasMessage_registrationRequest,
897 eRasMessage_registrationConfirm,
898 eRasMessage_registrationReject,
899 eRasMessage_unregistrationRequest,
900 eRasMessage_unregistrationConfirm,
901 eRasMessage_unregistrationReject,
902 eRasMessage_admissionRequest,
903 eRasMessage_admissionConfirm,
904 eRasMessage_admissionReject,
905 eRasMessage_bandwidthRequest,
906 eRasMessage_bandwidthConfirm,
907 eRasMessage_bandwidthReject,
908 eRasMessage_disengageRequest,
909 eRasMessage_disengageConfirm,
910 eRasMessage_disengageReject,
911 eRasMessage_locationRequest,
912 eRasMessage_locationConfirm,
913 eRasMessage_locationReject,
914 eRasMessage_infoRequest,
915 eRasMessage_infoRequestResponse,
916 eRasMessage_nonStandardMessage,
917 eRasMessage_unknownMessageResponse,
918 eRasMessage_requestInProgress,
919 eRasMessage_resourcesAvailableIndicate,
920 eRasMessage_resourcesAvailableConfirm,
921 eRasMessage_infoRequestAck,
922 eRasMessage_infoRequestNak,
923 eRasMessage_serviceControlIndication,
924 eRasMessage_serviceControlResponse,
925 } choice;
926 union {
927 GatekeeperRequest gatekeeperRequest;
928 GatekeeperConfirm gatekeeperConfirm;
929 RegistrationRequest registrationRequest;
930 RegistrationConfirm registrationConfirm;
931 UnregistrationRequest unregistrationRequest;
932 AdmissionRequest admissionRequest;
933 AdmissionConfirm admissionConfirm;
934 LocationRequest locationRequest;
935 LocationConfirm locationConfirm;
936 InfoRequestResponse infoRequestResponse;
937 };
938} RasMessage;
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index e0b5926c76f9..9b6e19bae90f 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -4,7 +4,7 @@
4 * (C) 2001 by Jay Schulist <jschlst@samba.org> 4 * (C) 2001 by Jay Schulist <jschlst@samba.org>
5 * (C) 2002-2005 by Harald Welte <laforge@gnumonks.org> 5 * (C) 2002-2005 by Harald Welte <laforge@gnumonks.org>
6 * (C) 2003 by Patrick Mchardy <kaber@trash.net> 6 * (C) 2003 by Patrick Mchardy <kaber@trash.net>
7 * (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net> 7 * (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net>
8 * 8 *
9 * I've reworked this stuff to use attributes instead of conntrack 9 * I've reworked this stuff to use attributes instead of conntrack
10 * structures. 5.44 am. I need more tea. --pablo 05/07/11. 10 * structures. 5.44 am. I need more tea. --pablo 05/07/11.
@@ -53,20 +53,18 @@ static char __initdata version[] = "0.90";
53 53
54static inline int 54static inline int
55ctnetlink_dump_tuples_proto(struct sk_buff *skb, 55ctnetlink_dump_tuples_proto(struct sk_buff *skb,
56 const struct ip_conntrack_tuple *tuple) 56 const struct ip_conntrack_tuple *tuple,
57 struct ip_conntrack_protocol *proto)
57{ 58{
58 struct ip_conntrack_protocol *proto;
59 int ret = 0; 59 int ret = 0;
60 struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
60 61
61 NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum); 62 NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
62 63
63 /* If no protocol helper is found, this function will return the
64 * generic protocol helper, so proto won't *ever* be NULL */
65 proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
66 if (likely(proto->tuple_to_nfattr)) 64 if (likely(proto->tuple_to_nfattr))
67 ret = proto->tuple_to_nfattr(skb, tuple); 65 ret = proto->tuple_to_nfattr(skb, tuple);
68 66
69 ip_conntrack_proto_put(proto); 67 NFA_NEST_END(skb, nest_parms);
70 68
71 return ret; 69 return ret;
72 70
@@ -75,28 +73,41 @@ nfattr_failure:
75} 73}
76 74
77static inline int 75static inline int
78ctnetlink_dump_tuples(struct sk_buff *skb, 76ctnetlink_dump_tuples_ip(struct sk_buff *skb,
79 const struct ip_conntrack_tuple *tuple) 77 const struct ip_conntrack_tuple *tuple)
80{ 78{
81 struct nfattr *nest_parms; 79 struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
82 int ret;
83 80
84 nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
85 NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), &tuple->src.ip); 81 NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), &tuple->src.ip);
86 NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t), &tuple->dst.ip); 82 NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t), &tuple->dst.ip);
87 NFA_NEST_END(skb, nest_parms);
88 83
89 nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
90 ret = ctnetlink_dump_tuples_proto(skb, tuple);
91 NFA_NEST_END(skb, nest_parms); 84 NFA_NEST_END(skb, nest_parms);
92 85
93 return ret; 86 return 0;
94 87
95nfattr_failure: 88nfattr_failure:
96 return -1; 89 return -1;
97} 90}
98 91
99static inline int 92static inline int
93ctnetlink_dump_tuples(struct sk_buff *skb,
94 const struct ip_conntrack_tuple *tuple)
95{
96 int ret;
97 struct ip_conntrack_protocol *proto;
98
99 ret = ctnetlink_dump_tuples_ip(skb, tuple);
100 if (unlikely(ret < 0))
101 return ret;
102
103 proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
104 ret = ctnetlink_dump_tuples_proto(skb, tuple, proto);
105 ip_conntrack_proto_put(proto);
106
107 return ret;
108}
109
110static inline int
100ctnetlink_dump_status(struct sk_buff *skb, const struct ip_conntrack *ct) 111ctnetlink_dump_status(struct sk_buff *skb, const struct ip_conntrack *ct)
101{ 112{
102 u_int32_t status = htonl((u_int32_t) ct->status); 113 u_int32_t status = htonl((u_int32_t) ct->status);
@@ -327,9 +338,10 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
327 group = NFNLGRP_CONNTRACK_UPDATE; 338 group = NFNLGRP_CONNTRACK_UPDATE;
328 } else 339 } else
329 return NOTIFY_DONE; 340 return NOTIFY_DONE;
330 341
331 /* FIXME: Check if there are any listeners before, don't hurt performance */ 342 if (!nfnetlink_has_listeners(group))
332 343 return NOTIFY_DONE;
344
333 skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); 345 skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
334 if (!skb) 346 if (!skb)
335 return NOTIFY_DONE; 347 return NOTIFY_DONE;
@@ -1134,6 +1146,33 @@ nfattr_failure:
1134} 1146}
1135 1147
1136static inline int 1148static inline int
1149ctnetlink_exp_dump_mask(struct sk_buff *skb,
1150 const struct ip_conntrack_tuple *tuple,
1151 const struct ip_conntrack_tuple *mask)
1152{
1153 int ret;
1154 struct ip_conntrack_protocol *proto;
1155 struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
1156
1157 ret = ctnetlink_dump_tuples_ip(skb, mask);
1158 if (unlikely(ret < 0))
1159 goto nfattr_failure;
1160
1161 proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
1162 ret = ctnetlink_dump_tuples_proto(skb, mask, proto);
1163 ip_conntrack_proto_put(proto);
1164 if (unlikely(ret < 0))
1165 goto nfattr_failure;
1166
1167 NFA_NEST_END(skb, nest_parms);
1168
1169 return 0;
1170
1171nfattr_failure:
1172 return -1;
1173}
1174
1175static inline int
1137ctnetlink_exp_dump_expect(struct sk_buff *skb, 1176ctnetlink_exp_dump_expect(struct sk_buff *skb,
1138 const struct ip_conntrack_expect *exp) 1177 const struct ip_conntrack_expect *exp)
1139{ 1178{
@@ -1143,7 +1182,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
1143 1182
1144 if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0) 1183 if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
1145 goto nfattr_failure; 1184 goto nfattr_failure;
1146 if (ctnetlink_exp_dump_tuple(skb, &exp->mask, CTA_EXPECT_MASK) < 0) 1185 if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
1147 goto nfattr_failure; 1186 goto nfattr_failure;
1148 if (ctnetlink_exp_dump_tuple(skb, 1187 if (ctnetlink_exp_dump_tuple(skb,
1149 &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple, 1188 &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c
new file mode 100644
index 000000000000..a0bc883928c0
--- /dev/null
+++ b/net/ipv4/netfilter/ip_nat_helper_h323.c
@@ -0,0 +1,605 @@
1/*
2 * H.323 extension for NAT alteration.
3 *
4 * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
5 *
6 * This source code is licensed under General Public License version 2.
7 *
8 * Based on the 'brute force' H.323 NAT module by
9 * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
10 *
11 * Changes:
12 * 2006-02-01 - initial version 0.1
13 *
14 * 2006-02-20 - version 0.2
15 * 1. Changed source format to follow kernel conventions
16 * 2. Deleted some unnecessary structures
17 * 3. Minor fixes
18 *
19 * 2006-03-10 - version 0.3
20 * 1. Added support for multiple TPKTs in one packet (suggested by
21 * Patrick McHardy)
22 * 2. Added support for non-linear skb (based on Patrick McHardy's patch)
23 * 3. Eliminated unnecessary return code
24 *
25 * 2006-03-15 - version 0.4
26 * 1. Added support for T.120 channels
27 * 2. Added parameter gkrouted_only (suggested by Patrick McHardy)
28 */
29
30#include <linux/module.h>
31#include <linux/netfilter_ipv4.h>
32#include <linux/netfilter.h>
33#include <linux/ip.h>
34#include <linux/tcp.h>
35#include <linux/moduleparam.h>
36#include <net/tcp.h>
37#include <linux/netfilter_ipv4/ip_nat.h>
38#include <linux/netfilter_ipv4/ip_nat_helper.h>
39#include <linux/netfilter_ipv4/ip_nat_rule.h>
40#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
41#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
42#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
43
44#include "ip_conntrack_helper_h323_asn1.h"
45
46#if 0
47#define DEBUGP printk
48#else
49#define DEBUGP(format, args...)
50#endif
51
52extern int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
53 u_int32_t * ip, u_int16_t * port);
54extern int get_h225_addr(unsigned char *data, TransportAddress * addr,
55 u_int32_t * ip, u_int16_t * port);
56extern void ip_conntrack_h245_expect(struct ip_conntrack *new,
57 struct ip_conntrack_expect *this);
58extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
59 struct ip_conntrack_expect *this);
60extern int (*set_h245_addr_hook) (struct sk_buff ** pskb,
61 unsigned char **data, int dataoff,
62 H245_TransportAddress * addr,
63 u_int32_t ip, u_int16_t port);
64extern int (*set_h225_addr_hook) (struct sk_buff ** pskb,
65 unsigned char **data, int dataoff,
66 TransportAddress * addr,
67 u_int32_t ip, u_int16_t port);
68extern int (*set_sig_addr_hook) (struct sk_buff ** pskb,
69 struct ip_conntrack * ct,
70 enum ip_conntrack_info ctinfo,
71 unsigned char **data,
72 TransportAddress * addr, int count);
73extern int (*set_ras_addr_hook) (struct sk_buff ** pskb,
74 struct ip_conntrack * ct,
75 enum ip_conntrack_info ctinfo,
76 unsigned char **data,
77 TransportAddress * addr, int count);
78extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
79 struct ip_conntrack * ct,
80 enum ip_conntrack_info ctinfo,
81 unsigned char **data, int dataoff,
82 H245_TransportAddress * addr,
83 u_int16_t port, u_int16_t rtp_port,
84 struct ip_conntrack_expect * rtp_exp,
85 struct ip_conntrack_expect * rtcp_exp);
86extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
87 enum ip_conntrack_info ctinfo,
88 unsigned char **data, int dataoff,
89 H245_TransportAddress * addr, u_int16_t port,
90 struct ip_conntrack_expect * exp);
91extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
92 enum ip_conntrack_info ctinfo,
93 unsigned char **data, int dataoff,
94 TransportAddress * addr, u_int16_t port,
95 struct ip_conntrack_expect * exp);
96extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
97 enum ip_conntrack_info ctinfo,
98 unsigned char **data, TransportAddress * addr,
99 int idx, u_int16_t port,
100 struct ip_conntrack_expect * exp);
101
102
103/****************************************************************************/
104static int set_addr(struct sk_buff **pskb,
105 unsigned char **data, int dataoff,
106 unsigned int addroff, u_int32_t ip, u_int16_t port)
107{
108 enum ip_conntrack_info ctinfo;
109 struct ip_conntrack *ct = ip_conntrack_get(*pskb, &ctinfo);
110 struct {
111 u_int32_t ip;
112 u_int16_t port;
113 } __attribute__ ((__packed__)) buf;
114 struct tcphdr _tcph, *th;
115
116 buf.ip = ip;
117 buf.port = htons(port);
118 addroff += dataoff;
119
120 if ((*pskb)->nh.iph->protocol == IPPROTO_TCP) {
121 if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
122 addroff, sizeof(buf),
123 (char *) &buf, sizeof(buf))) {
124 if (net_ratelimit())
125 printk("ip_nat_h323: ip_nat_mangle_tcp_packet"
126 " error\n");
127 return -1;
128 }
129
130 /* Relocate data pointer */
131 th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4,
132 sizeof(_tcph), &_tcph);
133 if (th == NULL)
134 return -1;
135 *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
136 th->doff * 4 + dataoff;
137 } else {
138 if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
139 addroff, sizeof(buf),
140 (char *) &buf, sizeof(buf))) {
141 if (net_ratelimit())
142 printk("ip_nat_h323: ip_nat_mangle_udp_packet"
143 " error\n");
144 return -1;
145 }
146 /* ip_nat_mangle_udp_packet uses skb_make_writable() to copy
147 * or pull everything in a linear buffer, so we can safely
148 * use the skb pointers now */
149 *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
150 sizeof(struct udphdr);
151 }
152
153 return 0;
154}
155
156/****************************************************************************/
157static int set_h225_addr(struct sk_buff **pskb,
158 unsigned char **data, int dataoff,
159 TransportAddress * addr,
160 u_int32_t ip, u_int16_t port)
161{
162 return set_addr(pskb, data, dataoff, addr->ipAddress.ip, ip, port);
163}
164
165/****************************************************************************/
166static int set_h245_addr(struct sk_buff **pskb,
167 unsigned char **data, int dataoff,
168 H245_TransportAddress * addr,
169 u_int32_t ip, u_int16_t port)
170{
171 return set_addr(pskb, data, dataoff,
172 addr->unicastAddress.iPAddress.network, ip, port);
173}
174
175/****************************************************************************/
176static int set_sig_addr(struct sk_buff **pskb, struct ip_conntrack *ct,
177 enum ip_conntrack_info ctinfo,
178 unsigned char **data,
179 TransportAddress * addr, int count)
180{
181 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
182 int dir = CTINFO2DIR(ctinfo);
183 int i;
184 u_int32_t ip;
185 u_int16_t port;
186
187 for (i = 0; i < count; i++) {
188 if (get_h225_addr(*data, &addr[i], &ip, &port)) {
189 if (ip == ct->tuplehash[dir].tuple.src.ip &&
190 port == info->sig_port[dir]) {
191 /* GW->GK */
192
193 /* Fix for Gnomemeeting */
194 if (i > 0 &&
195 get_h225_addr(*data, &addr[0],
196 &ip, &port) &&
197 (ntohl(ip) & 0xff000000) == 0x7f000000)
198 i = 0;
199
200 DEBUGP
201 ("ip_nat_ras: set signal address "
202 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
203 NIPQUAD(ip), port,
204 NIPQUAD(ct->tuplehash[!dir].tuple.dst.
205 ip), info->sig_port[!dir]);
206 return set_h225_addr(pskb, data, 0, &addr[i],
207 ct->tuplehash[!dir].
208 tuple.dst.ip,
209 info->sig_port[!dir]);
210 } else if (ip == ct->tuplehash[dir].tuple.dst.ip &&
211 port == info->sig_port[dir]) {
212 /* GK->GW */
213 DEBUGP
214 ("ip_nat_ras: set signal address "
215 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
216 NIPQUAD(ip), port,
217 NIPQUAD(ct->tuplehash[!dir].tuple.src.
218 ip), info->sig_port[!dir]);
219 return set_h225_addr(pskb, data, 0, &addr[i],
220 ct->tuplehash[!dir].
221 tuple.src.ip,
222 info->sig_port[!dir]);
223 }
224 }
225 }
226
227 return 0;
228}
229
230/****************************************************************************/
231static int set_ras_addr(struct sk_buff **pskb, struct ip_conntrack *ct,
232 enum ip_conntrack_info ctinfo,
233 unsigned char **data,
234 TransportAddress * addr, int count)
235{
236 int dir = CTINFO2DIR(ctinfo);
237 int i;
238 u_int32_t ip;
239 u_int16_t port;
240
241 for (i = 0; i < count; i++) {
242 if (get_h225_addr(*data, &addr[i], &ip, &port) &&
243 ip == ct->tuplehash[dir].tuple.src.ip &&
244 port == ntohs(ct->tuplehash[dir].tuple.src.u.udp.port)) {
245 DEBUGP("ip_nat_ras: set rasAddress "
246 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
247 NIPQUAD(ip), port,
248 NIPQUAD(ct->tuplehash[!dir].tuple.dst.ip),
249 ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.
250 port));
251 return set_h225_addr(pskb, data, 0, &addr[i],
252 ct->tuplehash[!dir].tuple.dst.ip,
253 ntohs(ct->tuplehash[!dir].tuple.
254 dst.u.udp.port));
255 }
256 }
257
258 return 0;
259}
260
261/****************************************************************************/
262static int nat_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct,
263 enum ip_conntrack_info ctinfo,
264 unsigned char **data, int dataoff,
265 H245_TransportAddress * addr,
266 u_int16_t port, u_int16_t rtp_port,
267 struct ip_conntrack_expect *rtp_exp,
268 struct ip_conntrack_expect *rtcp_exp)
269{
270 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
271 int dir = CTINFO2DIR(ctinfo);
272 int i;
273 u_int16_t nated_port;
274
275 /* Set expectations for NAT */
276 rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
277 rtp_exp->expectfn = ip_nat_follow_master;
278 rtp_exp->dir = !dir;
279 rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
280 rtcp_exp->expectfn = ip_nat_follow_master;
281 rtcp_exp->dir = !dir;
282
283 /* Lookup existing expects */
284 for (i = 0; i < H323_RTP_CHANNEL_MAX; i++) {
285 if (info->rtp_port[i][dir] == rtp_port) {
286 /* Expected */
287
288 /* Use allocated ports first. This will refresh
289 * the expects */
290 rtp_exp->tuple.dst.u.udp.port =
291 htons(info->rtp_port[i][dir]);
292 rtcp_exp->tuple.dst.u.udp.port =
293 htons(info->rtp_port[i][dir] + 1);
294 break;
295 } else if (info->rtp_port[i][dir] == 0) {
296 /* Not expected */
297 break;
298 }
299 }
300
301 /* Run out of expectations */
302 if (i >= H323_RTP_CHANNEL_MAX) {
303 if (net_ratelimit())
304 printk("ip_nat_h323: out of expectations\n");
305 return 0;
306 }
307
308 /* Try to get a pair of ports. */
309 for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port);
310 nated_port != 0; nated_port += 2) {
311 rtp_exp->tuple.dst.u.udp.port = htons(nated_port);
312 if (ip_conntrack_expect_related(rtp_exp) == 0) {
313 rtcp_exp->tuple.dst.u.udp.port =
314 htons(nated_port + 1);
315 if (ip_conntrack_expect_related(rtcp_exp) == 0)
316 break;
317 ip_conntrack_unexpect_related(rtp_exp);
318 }
319 }
320
321 if (nated_port == 0) { /* No port available */
322 if (net_ratelimit())
323 printk("ip_nat_h323: out of RTP ports\n");
324 return 0;
325 }
326
327 /* Modify signal */
328 if (set_h245_addr(pskb, data, dataoff, addr,
329 ct->tuplehash[!dir].tuple.dst.ip,
330 (port & 1) ? nated_port + 1 : nated_port) == 0) {
331 /* Save ports */
332 info->rtp_port[i][dir] = rtp_port;
333 info->rtp_port[i][!dir] = nated_port;
334 } else {
335 ip_conntrack_unexpect_related(rtp_exp);
336 ip_conntrack_unexpect_related(rtcp_exp);
337 return -1;
338 }
339
340 /* Success */
341 DEBUGP("ip_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
342 NIPQUAD(rtp_exp->tuple.src.ip),
343 ntohs(rtp_exp->tuple.src.u.udp.port),
344 NIPQUAD(rtp_exp->tuple.dst.ip),
345 ntohs(rtp_exp->tuple.dst.u.udp.port));
346 DEBUGP("ip_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
347 NIPQUAD(rtcp_exp->tuple.src.ip),
348 ntohs(rtcp_exp->tuple.src.u.udp.port),
349 NIPQUAD(rtcp_exp->tuple.dst.ip),
350 ntohs(rtcp_exp->tuple.dst.u.udp.port));
351
352 return 0;
353}
354
355/****************************************************************************/
356static int nat_t120(struct sk_buff **pskb, struct ip_conntrack *ct,
357 enum ip_conntrack_info ctinfo,
358 unsigned char **data, int dataoff,
359 H245_TransportAddress * addr, u_int16_t port,
360 struct ip_conntrack_expect *exp)
361{
362 int dir = CTINFO2DIR(ctinfo);
363 u_int16_t nated_port = port;
364
365 /* Set expectations for NAT */
366 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
367 exp->expectfn = ip_nat_follow_master;
368 exp->dir = !dir;
369
370 /* Try to get same port: if not, try to change it. */
371 for (; nated_port != 0; nated_port++) {
372 exp->tuple.dst.u.tcp.port = htons(nated_port);
373 if (ip_conntrack_expect_related(exp) == 0)
374 break;
375 }
376
377 if (nated_port == 0) { /* No port available */
378 if (net_ratelimit())
379 printk("ip_nat_h323: out of TCP ports\n");
380 return 0;
381 }
382
383 /* Modify signal */
384 if (set_h245_addr(pskb, data, dataoff, addr,
385 ct->tuplehash[!dir].tuple.dst.ip, nated_port) < 0) {
386 ip_conntrack_unexpect_related(exp);
387 return -1;
388 }
389
390 DEBUGP("ip_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
391 NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
392 NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
393
394 return 0;
395}
396
397/****************************************************************************
398 * This conntrack expect function replaces ip_conntrack_h245_expect()
399 * which was set by ip_conntrack_helper_h323.c. It calls both
400 * ip_nat_follow_master() and ip_conntrack_h245_expect()
401 ****************************************************************************/
402static void ip_nat_h245_expect(struct ip_conntrack *new,
403 struct ip_conntrack_expect *this)
404{
405 ip_nat_follow_master(new, this);
406 ip_conntrack_h245_expect(new, this);
407}
408
409/****************************************************************************/
410static int nat_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
411 enum ip_conntrack_info ctinfo,
412 unsigned char **data, int dataoff,
413 TransportAddress * addr, u_int16_t port,
414 struct ip_conntrack_expect *exp)
415{
416 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
417 int dir = CTINFO2DIR(ctinfo);
418 u_int16_t nated_port = port;
419
420 /* Set expectations for NAT */
421 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
422 exp->expectfn = ip_nat_h245_expect;
423 exp->dir = !dir;
424
425 /* Check existing expects */
426 if (info->sig_port[dir] == port)
427 nated_port = info->sig_port[!dir];
428
429 /* Try to get same port: if not, try to change it. */
430 for (; nated_port != 0; nated_port++) {
431 exp->tuple.dst.u.tcp.port = htons(nated_port);
432 if (ip_conntrack_expect_related(exp) == 0)
433 break;
434 }
435
436 if (nated_port == 0) { /* No port available */
437 if (net_ratelimit())
438 printk("ip_nat_q931: out of TCP ports\n");
439 return 0;
440 }
441
442 /* Modify signal */
443 if (set_h225_addr(pskb, data, dataoff, addr,
444 ct->tuplehash[!dir].tuple.dst.ip,
445 nated_port) == 0) {
446 /* Save ports */
447 info->sig_port[dir] = port;
448 info->sig_port[!dir] = nated_port;
449 } else {
450 ip_conntrack_unexpect_related(exp);
451 return -1;
452 }
453
454 DEBUGP("ip_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
455 NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
456 NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
457
458 return 0;
459}
460
461/****************************************************************************
462 * This conntrack expect function replaces ip_conntrack_q931_expect()
463 * which was set by ip_conntrack_helper_h323.c.
464 ****************************************************************************/
465static void ip_nat_q931_expect(struct ip_conntrack *new,
466 struct ip_conntrack_expect *this)
467{
468 struct ip_nat_range range;
469
470 if (this->tuple.src.ip != 0) { /* Only accept calls from GK */
471 ip_nat_follow_master(new, this);
472 goto out;
473 }
474
475 /* This must be a fresh one. */
476 BUG_ON(new->status & IPS_NAT_DONE_MASK);
477
478 /* Change src to where master sends to */
479 range.flags = IP_NAT_RANGE_MAP_IPS;
480 range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.ip;
481
482 /* hook doesn't matter, but it has to do source manip */
483 ip_nat_setup_info(new, &range, NF_IP_POST_ROUTING);
484
485 /* For DST manip, map port here to where it's expected. */
486 range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
487 range.min = range.max = this->saved_proto;
488 range.min_ip = range.max_ip =
489 new->master->tuplehash[!this->dir].tuple.src.ip;
490
491 /* hook doesn't matter, but it has to do destination manip */
492 ip_nat_setup_info(new, &range, NF_IP_PRE_ROUTING);
493
494 out:
495 ip_conntrack_q931_expect(new, this);
496}
497
498/****************************************************************************/
499static int nat_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
500 enum ip_conntrack_info ctinfo,
501 unsigned char **data, TransportAddress * addr, int idx,
502 u_int16_t port, struct ip_conntrack_expect *exp)
503{
504 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
505 int dir = CTINFO2DIR(ctinfo);
506 u_int16_t nated_port = port;
507 u_int32_t ip;
508
509 /* Set expectations for NAT */
510 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
511 exp->expectfn = ip_nat_q931_expect;
512 exp->dir = !dir;
513
514 /* Check existing expects */
515 if (info->sig_port[dir] == port)
516 nated_port = info->sig_port[!dir];
517
518 /* Try to get same port: if not, try to change it. */
519 for (; nated_port != 0; nated_port++) {
520 exp->tuple.dst.u.tcp.port = htons(nated_port);
521 if (ip_conntrack_expect_related(exp) == 0)
522 break;
523 }
524
525 if (nated_port == 0) { /* No port available */
526 if (net_ratelimit())
527 printk("ip_nat_ras: out of TCP ports\n");
528 return 0;
529 }
530
531 /* Modify signal */
532 if (set_h225_addr(pskb, data, 0, &addr[idx],
533 ct->tuplehash[!dir].tuple.dst.ip,
534 nated_port) == 0) {
535 /* Save ports */
536 info->sig_port[dir] = port;
537 info->sig_port[!dir] = nated_port;
538
539 /* Fix for Gnomemeeting */
540 if (idx > 0 &&
541 get_h225_addr(*data, &addr[0], &ip, &port) &&
542 (ntohl(ip) & 0xff000000) == 0x7f000000) {
543 set_h225_addr_hook(pskb, data, 0, &addr[0],
544 ct->tuplehash[!dir].tuple.dst.ip,
545 info->sig_port[!dir]);
546 }
547 } else {
548 ip_conntrack_unexpect_related(exp);
549 return -1;
550 }
551
552 /* Success */
553 DEBUGP("ip_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
554 NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
555 NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
556
557 return 0;
558}
559
560/****************************************************************************/
561static int __init init(void)
562{
563 BUG_ON(set_h245_addr_hook != NULL);
564 BUG_ON(set_h225_addr_hook != NULL);
565 BUG_ON(set_sig_addr_hook != NULL);
566 BUG_ON(set_ras_addr_hook != NULL);
567 BUG_ON(nat_rtp_rtcp_hook != NULL);
568 BUG_ON(nat_t120_hook != NULL);
569 BUG_ON(nat_h245_hook != NULL);
570 BUG_ON(nat_q931_hook != NULL);
571
572 set_h245_addr_hook = set_h245_addr;
573 set_h225_addr_hook = set_h225_addr;
574 set_sig_addr_hook = set_sig_addr;
575 set_ras_addr_hook = set_ras_addr;
576 nat_rtp_rtcp_hook = nat_rtp_rtcp;
577 nat_t120_hook = nat_t120;
578 nat_h245_hook = nat_h245;
579 nat_q931_hook = nat_q931;
580
581 DEBUGP("ip_nat_h323: init success\n");
582 return 0;
583}
584
585/****************************************************************************/
586static void __exit fini(void)
587{
588 set_h245_addr_hook = NULL;
589 set_h225_addr_hook = NULL;
590 set_sig_addr_hook = NULL;
591 set_ras_addr_hook = NULL;
592 nat_rtp_rtcp_hook = NULL;
593 nat_t120_hook = NULL;
594 nat_h245_hook = NULL;
595 nat_q931_hook = NULL;
596 synchronize_net();
597}
598
599/****************************************************************************/
600module_init(init);
601module_exit(fini);
602
603MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
604MODULE_DESCRIPTION("H.323 NAT helper");
605MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c
index ac004895781a..b9c016c063b8 100644
--- a/net/ipv4/netfilter/ip_nat_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c
@@ -52,6 +52,8 @@
52 52
53#define IP_NAT_PPTP_VERSION "3.0" 53#define IP_NAT_PPTP_VERSION "3.0"
54 54
55#define REQ_CID(req, off) (*(u_int16_t *)((char *)(req) + (off)))
56
55MODULE_LICENSE("GPL"); 57MODULE_LICENSE("GPL");
56MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); 58MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
57MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP"); 59MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
@@ -198,7 +200,7 @@ pptp_outbound_pkt(struct sk_buff **pskb,
198 /* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass 200 /* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass
199 * down to here */ 201 * down to here */
200 DEBUGP("altering call id from 0x%04x to 0x%04x\n", 202 DEBUGP("altering call id from 0x%04x to 0x%04x\n",
201 ntohs(*(u_int16_t *)pptpReq + cid_off), ntohs(new_callid)); 203 ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid));
202 204
203 /* mangle packet */ 205 /* mangle packet */
204 if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 206 if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
@@ -342,7 +344,7 @@ pptp_inbound_pkt(struct sk_buff **pskb,
342 344
343 /* mangle packet */ 345 /* mangle packet */
344 DEBUGP("altering peer call id from 0x%04x to 0x%04x\n", 346 DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
345 ntohs(*(u_int16_t *)pptpReq + pcid_off), ntohs(new_pcid)); 347 ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid));
346 348
347 if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 349 if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
348 pcid_off + sizeof(struct pptp_pkt_hdr) + 350 pcid_off + sizeof(struct pptp_pkt_hdr) +
@@ -353,7 +355,7 @@ pptp_inbound_pkt(struct sk_buff **pskb,
353 355
354 if (new_cid) { 356 if (new_cid) {
355 DEBUGP("altering call id from 0x%04x to 0x%04x\n", 357 DEBUGP("altering call id from 0x%04x to 0x%04x\n",
356 ntohs(*(u_int16_t *)pptpReq + cid_off), ntohs(new_cid)); 358 ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_cid));
357 if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 359 if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
358 cid_off + sizeof(struct pptp_pkt_hdr) + 360 cid_off + sizeof(struct pptp_pkt_hdr) +
359 sizeof(struct PptpControlHeader), 361 sizeof(struct PptpControlHeader),
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
index 1de86282d232..efba8c4e42e0 100644
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ b/net/ipv4/netfilter/ip_nat_rule.c
@@ -103,6 +103,7 @@ static unsigned int ipt_snat_target(struct sk_buff **pskb,
103 const struct net_device *in, 103 const struct net_device *in,
104 const struct net_device *out, 104 const struct net_device *out,
105 unsigned int hooknum, 105 unsigned int hooknum,
106 const struct ipt_target *target,
106 const void *targinfo, 107 const void *targinfo,
107 void *userinfo) 108 void *userinfo)
108{ 109{
@@ -145,6 +146,7 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb,
145 const struct net_device *in, 146 const struct net_device *in,
146 const struct net_device *out, 147 const struct net_device *out,
147 unsigned int hooknum, 148 unsigned int hooknum,
149 const struct ipt_target *target,
148 const void *targinfo, 150 const void *targinfo,
149 void *userinfo) 151 void *userinfo)
150{ 152{
@@ -170,6 +172,7 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb,
170 172
171static int ipt_snat_checkentry(const char *tablename, 173static int ipt_snat_checkentry(const char *tablename,
172 const void *entry, 174 const void *entry,
175 const struct ipt_target *target,
173 void *targinfo, 176 void *targinfo,
174 unsigned int targinfosize, 177 unsigned int targinfosize,
175 unsigned int hook_mask) 178 unsigned int hook_mask)
@@ -181,28 +184,12 @@ static int ipt_snat_checkentry(const char *tablename,
181 printk("SNAT: multiple ranges no longer supported\n"); 184 printk("SNAT: multiple ranges no longer supported\n");
182 return 0; 185 return 0;
183 } 186 }
184
185 if (targinfosize != IPT_ALIGN(sizeof(struct ip_nat_multi_range_compat))) {
186 DEBUGP("SNAT: Target size %u wrong for %u ranges\n",
187 targinfosize, mr->rangesize);
188 return 0;
189 }
190
191 /* Only allow these for NAT. */
192 if (strcmp(tablename, "nat") != 0) {
193 DEBUGP("SNAT: wrong table %s\n", tablename);
194 return 0;
195 }
196
197 if (hook_mask & ~(1 << NF_IP_POST_ROUTING)) {
198 DEBUGP("SNAT: hook mask 0x%x bad\n", hook_mask);
199 return 0;
200 }
201 return 1; 187 return 1;
202} 188}
203 189
204static int ipt_dnat_checkentry(const char *tablename, 190static int ipt_dnat_checkentry(const char *tablename,
205 const void *entry, 191 const void *entry,
192 const struct ipt_target *target,
206 void *targinfo, 193 void *targinfo,
207 unsigned int targinfosize, 194 unsigned int targinfosize,
208 unsigned int hook_mask) 195 unsigned int hook_mask)
@@ -214,24 +201,6 @@ static int ipt_dnat_checkentry(const char *tablename,
214 printk("DNAT: multiple ranges no longer supported\n"); 201 printk("DNAT: multiple ranges no longer supported\n");
215 return 0; 202 return 0;
216 } 203 }
217
218 if (targinfosize != IPT_ALIGN(sizeof(struct ip_nat_multi_range_compat))) {
219 DEBUGP("DNAT: Target size %u wrong for %u ranges\n",
220 targinfosize, mr->rangesize);
221 return 0;
222 }
223
224 /* Only allow these for NAT. */
225 if (strcmp(tablename, "nat") != 0) {
226 DEBUGP("DNAT: wrong table %s\n", tablename);
227 return 0;
228 }
229
230 if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))) {
231 DEBUGP("DNAT: hook mask 0x%x bad\n", hook_mask);
232 return 0;
233 }
234
235 return 1; 204 return 1;
236} 205}
237 206
@@ -299,12 +268,18 @@ int ip_nat_rule_find(struct sk_buff **pskb,
299static struct ipt_target ipt_snat_reg = { 268static struct ipt_target ipt_snat_reg = {
300 .name = "SNAT", 269 .name = "SNAT",
301 .target = ipt_snat_target, 270 .target = ipt_snat_target,
271 .targetsize = sizeof(struct ip_nat_multi_range_compat),
272 .table = "nat",
273 .hooks = 1 << NF_IP_POST_ROUTING,
302 .checkentry = ipt_snat_checkentry, 274 .checkentry = ipt_snat_checkentry,
303}; 275};
304 276
305static struct ipt_target ipt_dnat_reg = { 277static struct ipt_target ipt_dnat_reg = {
306 .name = "DNAT", 278 .name = "DNAT",
307 .target = ipt_dnat_target, 279 .target = ipt_dnat_target,
280 .targetsize = sizeof(struct ip_nat_multi_range_compat),
281 .table = "nat",
282 .hooks = 1 << NF_IP_PRE_ROUTING,
308 .checkentry = ipt_dnat_checkentry, 283 .checkentry = ipt_dnat_checkentry,
309}; 284};
310 285
diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
index 4f95d477805c..f029da2a60ee 100644
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c
@@ -250,6 +250,7 @@ static unsigned char asn1_header_decode(struct asn1_ctx *ctx,
250 if (!asn1_id_decode(ctx, cls, con, tag)) 250 if (!asn1_id_decode(ctx, cls, con, tag))
251 return 0; 251 return 0;
252 252
253 def = len = 0;
253 if (!asn1_length_decode(ctx, &def, &len)) 254 if (!asn1_length_decode(ctx, &def, &len))
254 return 0; 255 return 0;
255 256
@@ -669,7 +670,7 @@ static unsigned char snmp_object_decode(struct asn1_ctx *ctx,
669 unsigned char *eoc, *end, *p; 670 unsigned char *eoc, *end, *p;
670 unsigned long *lp, *id; 671 unsigned long *lp, *id;
671 unsigned long ul; 672 unsigned long ul;
672 long l; 673 long l;
673 674
674 *obj = NULL; 675 *obj = NULL;
675 id = NULL; 676 id = NULL;
@@ -699,11 +700,13 @@ static unsigned char snmp_object_decode(struct asn1_ctx *ctx,
699 return 0; 700 return 0;
700 } 701 }
701 702
703 type = 0;
702 if (!snmp_tag_cls2syntax(tag, cls, &type)) { 704 if (!snmp_tag_cls2syntax(tag, cls, &type)) {
703 kfree(id); 705 kfree(id);
704 return 0; 706 return 0;
705 } 707 }
706 708
709 l = 0;
707 switch (type) { 710 switch (type) {
708 case SNMP_INTEGER: 711 case SNMP_INTEGER:
709 len = sizeof(long); 712 len = sizeof(long);
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 08f80e2ea2aa..1655866c55b9 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -35,6 +35,7 @@
35#include <linux/sysctl.h> 35#include <linux/sysctl.h>
36#include <linux/proc_fs.h> 36#include <linux/proc_fs.h>
37#include <linux/security.h> 37#include <linux/security.h>
38#include <linux/mutex.h>
38#include <net/sock.h> 39#include <net/sock.h>
39#include <net/route.h> 40#include <net/route.h>
40 41
@@ -61,7 +62,7 @@ static unsigned int queue_dropped = 0;
61static unsigned int queue_user_dropped = 0; 62static unsigned int queue_user_dropped = 0;
62static struct sock *ipqnl; 63static struct sock *ipqnl;
63static LIST_HEAD(queue_list); 64static LIST_HEAD(queue_list);
64static DECLARE_MUTEX(ipqnl_sem); 65static DEFINE_MUTEX(ipqnl_mutex);
65 66
66static void 67static void
67ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict) 68ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict)
@@ -539,7 +540,7 @@ ipq_rcv_sk(struct sock *sk, int len)
539 struct sk_buff *skb; 540 struct sk_buff *skb;
540 unsigned int qlen; 541 unsigned int qlen;
541 542
542 down(&ipqnl_sem); 543 mutex_lock(&ipqnl_mutex);
543 544
544 for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) { 545 for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
545 skb = skb_dequeue(&sk->sk_receive_queue); 546 skb = skb_dequeue(&sk->sk_receive_queue);
@@ -547,7 +548,7 @@ ipq_rcv_sk(struct sock *sk, int len)
547 kfree_skb(skb); 548 kfree_skb(skb);
548 } 549 }
549 550
550 up(&ipqnl_sem); 551 mutex_unlock(&ipqnl_mutex);
551} 552}
552 553
553static int 554static int
@@ -708,8 +709,8 @@ cleanup_sysctl:
708 709
709cleanup_ipqnl: 710cleanup_ipqnl:
710 sock_release(ipqnl->sk_socket); 711 sock_release(ipqnl->sk_socket);
711 down(&ipqnl_sem); 712 mutex_lock(&ipqnl_mutex);
712 up(&ipqnl_sem); 713 mutex_unlock(&ipqnl_mutex);
713 714
714cleanup_netlink_notifier: 715cleanup_netlink_notifier:
715 netlink_unregister_notifier(&ipq_nl_notifier); 716 netlink_unregister_notifier(&ipq_nl_notifier);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 16f47c675fef..a7b194c4d79d 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -25,7 +25,7 @@
25#include <linux/icmp.h> 25#include <linux/icmp.h>
26#include <net/ip.h> 26#include <net/ip.h>
27#include <asm/uaccess.h> 27#include <asm/uaccess.h>
28#include <asm/semaphore.h> 28#include <linux/mutex.h>
29#include <linux/proc_fs.h> 29#include <linux/proc_fs.h>
30#include <linux/err.h> 30#include <linux/err.h>
31#include <linux/cpumask.h> 31#include <linux/cpumask.h>
@@ -179,6 +179,7 @@ ipt_error(struct sk_buff **pskb,
179 const struct net_device *in, 179 const struct net_device *in,
180 const struct net_device *out, 180 const struct net_device *out,
181 unsigned int hooknum, 181 unsigned int hooknum,
182 const struct xt_target *target,
182 const void *targinfo, 183 const void *targinfo,
183 void *userinfo) 184 void *userinfo)
184{ 185{
@@ -197,8 +198,8 @@ int do_match(struct ipt_entry_match *m,
197 int *hotdrop) 198 int *hotdrop)
198{ 199{
199 /* Stop iteration if it doesn't match */ 200 /* Stop iteration if it doesn't match */
200 if (!m->u.kernel.match->match(skb, in, out, m->data, offset, 201 if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data,
201 skb->nh.iph->ihl*4, hotdrop)) 202 offset, skb->nh.iph->ihl*4, hotdrop))
202 return 1; 203 return 1;
203 else 204 else
204 return 0; 205 return 0;
@@ -305,6 +306,7 @@ ipt_do_table(struct sk_buff **pskb,
305 verdict = t->u.kernel.target->target(pskb, 306 verdict = t->u.kernel.target->target(pskb,
306 in, out, 307 in, out,
307 hook, 308 hook,
309 t->u.kernel.target,
308 t->data, 310 t->data,
309 userdata); 311 userdata);
310 312
@@ -464,7 +466,7 @@ cleanup_match(struct ipt_entry_match *m, unsigned int *i)
464 return 1; 466 return 1;
465 467
466 if (m->u.kernel.match->destroy) 468 if (m->u.kernel.match->destroy)
467 m->u.kernel.match->destroy(m->data, 469 m->u.kernel.match->destroy(m->u.kernel.match, m->data,
468 m->u.match_size - sizeof(*m)); 470 m->u.match_size - sizeof(*m));
469 module_put(m->u.kernel.match->me); 471 module_put(m->u.kernel.match->me);
470 return 0; 472 return 0;
@@ -477,21 +479,12 @@ standard_check(const struct ipt_entry_target *t,
477 struct ipt_standard_target *targ = (void *)t; 479 struct ipt_standard_target *targ = (void *)t;
478 480
479 /* Check standard info. */ 481 /* Check standard info. */
480 if (t->u.target_size
481 != IPT_ALIGN(sizeof(struct ipt_standard_target))) {
482 duprintf("standard_check: target size %u != %u\n",
483 t->u.target_size,
484 IPT_ALIGN(sizeof(struct ipt_standard_target)));
485 return 0;
486 }
487
488 if (targ->verdict >= 0 482 if (targ->verdict >= 0
489 && targ->verdict > max_offset - sizeof(struct ipt_entry)) { 483 && targ->verdict > max_offset - sizeof(struct ipt_entry)) {
490 duprintf("ipt_standard_check: bad verdict (%i)\n", 484 duprintf("ipt_standard_check: bad verdict (%i)\n",
491 targ->verdict); 485 targ->verdict);
492 return 0; 486 return 0;
493 } 487 }
494
495 if (targ->verdict < -NF_MAX_VERDICT - 1) { 488 if (targ->verdict < -NF_MAX_VERDICT - 1) {
496 duprintf("ipt_standard_check: bad negative verdict (%i)\n", 489 duprintf("ipt_standard_check: bad negative verdict (%i)\n",
497 targ->verdict); 490 targ->verdict);
@@ -508,6 +501,7 @@ check_match(struct ipt_entry_match *m,
508 unsigned int *i) 501 unsigned int *i)
509{ 502{
510 struct ipt_match *match; 503 struct ipt_match *match;
504 int ret;
511 505
512 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name, 506 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
513 m->u.user.revision), 507 m->u.user.revision),
@@ -518,18 +512,27 @@ check_match(struct ipt_entry_match *m,
518 } 512 }
519 m->u.kernel.match = match; 513 m->u.kernel.match = match;
520 514
515 ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m),
516 name, hookmask, ip->proto,
517 ip->invflags & IPT_INV_PROTO);
518 if (ret)
519 goto err;
520
521 if (m->u.kernel.match->checkentry 521 if (m->u.kernel.match->checkentry
522 && !m->u.kernel.match->checkentry(name, ip, m->data, 522 && !m->u.kernel.match->checkentry(name, ip, match, m->data,
523 m->u.match_size - sizeof(*m), 523 m->u.match_size - sizeof(*m),
524 hookmask)) { 524 hookmask)) {
525 module_put(m->u.kernel.match->me);
526 duprintf("ip_tables: check failed for `%s'.\n", 525 duprintf("ip_tables: check failed for `%s'.\n",
527 m->u.kernel.match->name); 526 m->u.kernel.match->name);
528 return -EINVAL; 527 ret = -EINVAL;
528 goto err;
529 } 529 }
530 530
531 (*i)++; 531 (*i)++;
532 return 0; 532 return 0;
533err:
534 module_put(m->u.kernel.match->me);
535 return ret;
533} 536}
534 537
535static struct ipt_target ipt_standard_target; 538static struct ipt_target ipt_standard_target;
@@ -565,26 +568,32 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
565 } 568 }
566 t->u.kernel.target = target; 569 t->u.kernel.target = target;
567 570
571 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
572 name, e->comefrom, e->ip.proto,
573 e->ip.invflags & IPT_INV_PROTO);
574 if (ret)
575 goto err;
576
568 if (t->u.kernel.target == &ipt_standard_target) { 577 if (t->u.kernel.target == &ipt_standard_target) {
569 if (!standard_check(t, size)) { 578 if (!standard_check(t, size)) {
570 ret = -EINVAL; 579 ret = -EINVAL;
571 goto cleanup_matches; 580 goto cleanup_matches;
572 } 581 }
573 } else if (t->u.kernel.target->checkentry 582 } else if (t->u.kernel.target->checkentry
574 && !t->u.kernel.target->checkentry(name, e, t->data, 583 && !t->u.kernel.target->checkentry(name, e, target, t->data,
575 t->u.target_size 584 t->u.target_size
576 - sizeof(*t), 585 - sizeof(*t),
577 e->comefrom)) { 586 e->comefrom)) {
578 module_put(t->u.kernel.target->me);
579 duprintf("ip_tables: check failed for `%s'.\n", 587 duprintf("ip_tables: check failed for `%s'.\n",
580 t->u.kernel.target->name); 588 t->u.kernel.target->name);
581 ret = -EINVAL; 589 ret = -EINVAL;
582 goto cleanup_matches; 590 goto err;
583 } 591 }
584 592
585 (*i)++; 593 (*i)++;
586 return 0; 594 return 0;
587 595 err:
596 module_put(t->u.kernel.target->me);
588 cleanup_matches: 597 cleanup_matches:
589 IPT_MATCH_ITERATE(e, cleanup_match, &j); 598 IPT_MATCH_ITERATE(e, cleanup_match, &j);
590 return ret; 599 return ret;
@@ -645,7 +654,7 @@ cleanup_entry(struct ipt_entry *e, unsigned int *i)
645 IPT_MATCH_ITERATE(e, cleanup_match, NULL); 654 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
646 t = ipt_get_target(e); 655 t = ipt_get_target(e);
647 if (t->u.kernel.target->destroy) 656 if (t->u.kernel.target->destroy)
648 t->u.kernel.target->destroy(t->data, 657 t->u.kernel.target->destroy(t->u.kernel.target, t->data,
649 t->u.target_size - sizeof(*t)); 658 t->u.target_size - sizeof(*t));
650 module_put(t->u.kernel.target->me); 659 module_put(t->u.kernel.target->me);
651 return 0; 660 return 0;
@@ -1277,6 +1286,7 @@ static int
1277icmp_match(const struct sk_buff *skb, 1286icmp_match(const struct sk_buff *skb,
1278 const struct net_device *in, 1287 const struct net_device *in,
1279 const struct net_device *out, 1288 const struct net_device *out,
1289 const struct xt_match *match,
1280 const void *matchinfo, 1290 const void *matchinfo,
1281 int offset, 1291 int offset,
1282 unsigned int protoff, 1292 unsigned int protoff,
@@ -1310,28 +1320,29 @@ icmp_match(const struct sk_buff *skb,
1310static int 1320static int
1311icmp_checkentry(const char *tablename, 1321icmp_checkentry(const char *tablename,
1312 const void *info, 1322 const void *info,
1323 const struct xt_match *match,
1313 void *matchinfo, 1324 void *matchinfo,
1314 unsigned int matchsize, 1325 unsigned int matchsize,
1315 unsigned int hook_mask) 1326 unsigned int hook_mask)
1316{ 1327{
1317 const struct ipt_ip *ip = info;
1318 const struct ipt_icmp *icmpinfo = matchinfo; 1328 const struct ipt_icmp *icmpinfo = matchinfo;
1319 1329
1320 /* Must specify proto == ICMP, and no unknown invflags */ 1330 /* Must specify no unknown invflags */
1321 return ip->proto == IPPROTO_ICMP 1331 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
1322 && !(ip->invflags & IPT_INV_PROTO)
1323 && matchsize == IPT_ALIGN(sizeof(struct ipt_icmp))
1324 && !(icmpinfo->invflags & ~IPT_ICMP_INV);
1325} 1332}
1326 1333
1327/* The built-in targets: standard (NULL) and error. */ 1334/* The built-in targets: standard (NULL) and error. */
1328static struct ipt_target ipt_standard_target = { 1335static struct ipt_target ipt_standard_target = {
1329 .name = IPT_STANDARD_TARGET, 1336 .name = IPT_STANDARD_TARGET,
1337 .targetsize = sizeof(int),
1338 .family = AF_INET,
1330}; 1339};
1331 1340
1332static struct ipt_target ipt_error_target = { 1341static struct ipt_target ipt_error_target = {
1333 .name = IPT_ERROR_TARGET, 1342 .name = IPT_ERROR_TARGET,
1334 .target = ipt_error, 1343 .target = ipt_error,
1344 .targetsize = IPT_FUNCTION_MAXNAMELEN,
1345 .family = AF_INET,
1335}; 1346};
1336 1347
1337static struct nf_sockopt_ops ipt_sockopts = { 1348static struct nf_sockopt_ops ipt_sockopts = {
@@ -1346,8 +1357,11 @@ static struct nf_sockopt_ops ipt_sockopts = {
1346 1357
1347static struct ipt_match icmp_matchstruct = { 1358static struct ipt_match icmp_matchstruct = {
1348 .name = "icmp", 1359 .name = "icmp",
1349 .match = &icmp_match, 1360 .match = icmp_match,
1350 .checkentry = &icmp_checkentry, 1361 .matchsize = sizeof(struct ipt_icmp),
1362 .proto = IPPROTO_ICMP,
1363 .family = AF_INET,
1364 .checkentry = icmp_checkentry,
1351}; 1365};
1352 1366
1353static int __init init(void) 1367static int __init init(void)
@@ -1357,9 +1371,9 @@ static int __init init(void)
1357 xt_proto_init(AF_INET); 1371 xt_proto_init(AF_INET);
1358 1372
1359 /* Noone else will be downing sem now, so we won't sleep */ 1373 /* Noone else will be downing sem now, so we won't sleep */
1360 xt_register_target(AF_INET, &ipt_standard_target); 1374 xt_register_target(&ipt_standard_target);
1361 xt_register_target(AF_INET, &ipt_error_target); 1375 xt_register_target(&ipt_error_target);
1362 xt_register_match(AF_INET, &icmp_matchstruct); 1376 xt_register_match(&icmp_matchstruct);
1363 1377
1364 /* Register setsockopt */ 1378 /* Register setsockopt */
1365 ret = nf_register_sockopt(&ipt_sockopts); 1379 ret = nf_register_sockopt(&ipt_sockopts);
@@ -1376,9 +1390,9 @@ static void __exit fini(void)
1376{ 1390{
1377 nf_unregister_sockopt(&ipt_sockopts); 1391 nf_unregister_sockopt(&ipt_sockopts);
1378 1392
1379 xt_unregister_match(AF_INET, &icmp_matchstruct); 1393 xt_unregister_match(&icmp_matchstruct);
1380 xt_unregister_target(AF_INET, &ipt_error_target); 1394 xt_unregister_target(&ipt_error_target);
1381 xt_unregister_target(AF_INET, &ipt_standard_target); 1395 xt_unregister_target(&ipt_standard_target);
1382 1396
1383 xt_proto_fini(AF_INET); 1397 xt_proto_fini(AF_INET);
1384} 1398}
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index d9bc971f03af..61e11edcd6af 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -311,6 +311,7 @@ target(struct sk_buff **pskb,
311 const struct net_device *in, 311 const struct net_device *in,
312 const struct net_device *out, 312 const struct net_device *out,
313 unsigned int hooknum, 313 unsigned int hooknum,
314 const struct xt_target *target,
314 const void *targinfo, 315 const void *targinfo,
315 void *userinfo) 316 void *userinfo)
316{ 317{
@@ -380,6 +381,7 @@ target(struct sk_buff **pskb,
380static int 381static int
381checkentry(const char *tablename, 382checkentry(const char *tablename,
382 const void *e_void, 383 const void *e_void,
384 const struct xt_target *target,
383 void *targinfo, 385 void *targinfo,
384 unsigned int targinfosize, 386 unsigned int targinfosize,
385 unsigned int hook_mask) 387 unsigned int hook_mask)
@@ -389,13 +391,6 @@ checkentry(const char *tablename,
389 391
390 struct clusterip_config *config; 392 struct clusterip_config *config;
391 393
392 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_clusterip_tgt_info))) {
393 printk(KERN_WARNING "CLUSTERIP: targinfosize %u != %Zu\n",
394 targinfosize,
395 IPT_ALIGN(sizeof(struct ipt_clusterip_tgt_info)));
396 return 0;
397 }
398
399 if (cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP && 394 if (cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP &&
400 cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT && 395 cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT &&
401 cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) { 396 cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) {
@@ -465,9 +460,10 @@ checkentry(const char *tablename,
465} 460}
466 461
467/* drop reference count of cluster config when rule is deleted */ 462/* drop reference count of cluster config when rule is deleted */
468static void destroy(void *matchinfo, unsigned int matchinfosize) 463static void destroy(const struct xt_target *target, void *targinfo,
464 unsigned int targinfosize)
469{ 465{
470 struct ipt_clusterip_tgt_info *cipinfo = matchinfo; 466 struct ipt_clusterip_tgt_info *cipinfo = targinfo;
471 467
472 /* if no more entries are referencing the config, remove it 468 /* if no more entries are referencing the config, remove it
473 * from the list and destroy the proc entry */ 469 * from the list and destroy the proc entry */
@@ -476,12 +472,13 @@ static void destroy(void *matchinfo, unsigned int matchinfosize)
476 clusterip_config_put(cipinfo->config); 472 clusterip_config_put(cipinfo->config);
477} 473}
478 474
479static struct ipt_target clusterip_tgt = { 475static struct ipt_target clusterip_tgt = {
480 .name = "CLUSTERIP", 476 .name = "CLUSTERIP",
481 .target = &target, 477 .target = target,
482 .checkentry = &checkentry, 478 .targetsize = sizeof(struct ipt_clusterip_tgt_info),
483 .destroy = &destroy, 479 .checkentry = checkentry,
484 .me = THIS_MODULE 480 .destroy = destroy,
481 .me = THIS_MODULE
485}; 482};
486 483
487 484
diff --git a/net/ipv4/netfilter/ipt_DSCP.c b/net/ipv4/netfilter/ipt_DSCP.c
index 898cdf79ce18..cfb0b90e598a 100644
--- a/net/ipv4/netfilter/ipt_DSCP.c
+++ b/net/ipv4/netfilter/ipt_DSCP.c
@@ -29,6 +29,7 @@ target(struct sk_buff **pskb,
29 const struct net_device *in, 29 const struct net_device *in,
30 const struct net_device *out, 30 const struct net_device *out,
31 unsigned int hooknum, 31 unsigned int hooknum,
32 const struct xt_target *target,
32 const void *targinfo, 33 const void *targinfo,
33 void *userinfo) 34 void *userinfo)
34{ 35{
@@ -58,35 +59,25 @@ target(struct sk_buff **pskb,
58static int 59static int
59checkentry(const char *tablename, 60checkentry(const char *tablename,
60 const void *e_void, 61 const void *e_void,
62 const struct xt_target *target,
61 void *targinfo, 63 void *targinfo,
62 unsigned int targinfosize, 64 unsigned int targinfosize,
63 unsigned int hook_mask) 65 unsigned int hook_mask)
64{ 66{
65 const u_int8_t dscp = ((struct ipt_DSCP_info *)targinfo)->dscp; 67 const u_int8_t dscp = ((struct ipt_DSCP_info *)targinfo)->dscp;
66 68
67 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_DSCP_info))) {
68 printk(KERN_WARNING "DSCP: targinfosize %u != %Zu\n",
69 targinfosize,
70 IPT_ALIGN(sizeof(struct ipt_DSCP_info)));
71 return 0;
72 }
73
74 if (strcmp(tablename, "mangle") != 0) {
75 printk(KERN_WARNING "DSCP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
76 return 0;
77 }
78
79 if ((dscp > IPT_DSCP_MAX)) { 69 if ((dscp > IPT_DSCP_MAX)) {
80 printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp); 70 printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp);
81 return 0; 71 return 0;
82 } 72 }
83
84 return 1; 73 return 1;
85} 74}
86 75
87static struct ipt_target ipt_dscp_reg = { 76static struct ipt_target ipt_dscp_reg = {
88 .name = "DSCP", 77 .name = "DSCP",
89 .target = target, 78 .target = target,
79 .targetsize = sizeof(struct ipt_DSCP_info),
80 .table = "mangle",
90 .checkentry = checkentry, 81 .checkentry = checkentry,
91 .me = THIS_MODULE, 82 .me = THIS_MODULE,
92}; 83};
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index 706445426a6d..b9b80f90c84e 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -94,6 +94,7 @@ target(struct sk_buff **pskb,
94 const struct net_device *in, 94 const struct net_device *in,
95 const struct net_device *out, 95 const struct net_device *out,
96 unsigned int hooknum, 96 unsigned int hooknum,
97 const struct xt_target *target,
97 const void *targinfo, 98 const void *targinfo,
98 void *userinfo) 99 void *userinfo)
99{ 100{
@@ -114,6 +115,7 @@ target(struct sk_buff **pskb,
114static int 115static int
115checkentry(const char *tablename, 116checkentry(const char *tablename,
116 const void *e_void, 117 const void *e_void,
118 const struct xt_target *target,
117 void *targinfo, 119 void *targinfo,
118 unsigned int targinfosize, 120 unsigned int targinfosize,
119 unsigned int hook_mask) 121 unsigned int hook_mask)
@@ -121,18 +123,6 @@ checkentry(const char *tablename,
121 const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo; 123 const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo;
122 const struct ipt_entry *e = e_void; 124 const struct ipt_entry *e = e_void;
123 125
124 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ECN_info))) {
125 printk(KERN_WARNING "ECN: targinfosize %u != %Zu\n",
126 targinfosize,
127 IPT_ALIGN(sizeof(struct ipt_ECN_info)));
128 return 0;
129 }
130
131 if (strcmp(tablename, "mangle") != 0) {
132 printk(KERN_WARNING "ECN: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
133 return 0;
134 }
135
136 if (einfo->operation & IPT_ECN_OP_MASK) { 126 if (einfo->operation & IPT_ECN_OP_MASK) {
137 printk(KERN_WARNING "ECN: unsupported ECN operation %x\n", 127 printk(KERN_WARNING "ECN: unsupported ECN operation %x\n",
138 einfo->operation); 128 einfo->operation);
@@ -143,20 +133,20 @@ checkentry(const char *tablename,
143 einfo->ip_ect); 133 einfo->ip_ect);
144 return 0; 134 return 0;
145 } 135 }
146
147 if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)) 136 if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR))
148 && (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO))) { 137 && (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO))) {
149 printk(KERN_WARNING "ECN: cannot use TCP operations on a " 138 printk(KERN_WARNING "ECN: cannot use TCP operations on a "
150 "non-tcp rule\n"); 139 "non-tcp rule\n");
151 return 0; 140 return 0;
152 } 141 }
153
154 return 1; 142 return 1;
155} 143}
156 144
157static struct ipt_target ipt_ecn_reg = { 145static struct ipt_target ipt_ecn_reg = {
158 .name = "ECN", 146 .name = "ECN",
159 .target = target, 147 .target = target,
148 .targetsize = sizeof(struct ipt_ECN_info),
149 .table = "mangle",
160 .checkentry = checkentry, 150 .checkentry = checkentry,
161 .me = THIS_MODULE, 151 .me = THIS_MODULE,
162}; 152};
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index cc27545ff97f..750d3221b280 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -415,6 +415,7 @@ ipt_log_target(struct sk_buff **pskb,
415 const struct net_device *in, 415 const struct net_device *in,
416 const struct net_device *out, 416 const struct net_device *out,
417 unsigned int hooknum, 417 unsigned int hooknum,
418 const struct xt_target *target,
418 const void *targinfo, 419 const void *targinfo,
419 void *userinfo) 420 void *userinfo)
420{ 421{
@@ -437,35 +438,29 @@ ipt_log_target(struct sk_buff **pskb,
437 438
438static int ipt_log_checkentry(const char *tablename, 439static int ipt_log_checkentry(const char *tablename,
439 const void *e, 440 const void *e,
441 const struct xt_target *target,
440 void *targinfo, 442 void *targinfo,
441 unsigned int targinfosize, 443 unsigned int targinfosize,
442 unsigned int hook_mask) 444 unsigned int hook_mask)
443{ 445{
444 const struct ipt_log_info *loginfo = targinfo; 446 const struct ipt_log_info *loginfo = targinfo;
445 447
446 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_log_info))) {
447 DEBUGP("LOG: targinfosize %u != %u\n",
448 targinfosize, IPT_ALIGN(sizeof(struct ipt_log_info)));
449 return 0;
450 }
451
452 if (loginfo->level >= 8) { 448 if (loginfo->level >= 8) {
453 DEBUGP("LOG: level %u >= 8\n", loginfo->level); 449 DEBUGP("LOG: level %u >= 8\n", loginfo->level);
454 return 0; 450 return 0;
455 } 451 }
456
457 if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') { 452 if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
458 DEBUGP("LOG: prefix term %i\n", 453 DEBUGP("LOG: prefix term %i\n",
459 loginfo->prefix[sizeof(loginfo->prefix)-1]); 454 loginfo->prefix[sizeof(loginfo->prefix)-1]);
460 return 0; 455 return 0;
461 } 456 }
462
463 return 1; 457 return 1;
464} 458}
465 459
466static struct ipt_target ipt_log_reg = { 460static struct ipt_target ipt_log_reg = {
467 .name = "LOG", 461 .name = "LOG",
468 .target = ipt_log_target, 462 .target = ipt_log_target,
463 .targetsize = sizeof(struct ipt_log_info),
469 .checkentry = ipt_log_checkentry, 464 .checkentry = ipt_log_checkentry,
470 .me = THIS_MODULE, 465 .me = THIS_MODULE,
471}; 466};
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 12c56d3343ca..e0c321c3bae5 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -41,25 +41,13 @@ static DEFINE_RWLOCK(masq_lock);
41static int 41static int
42masquerade_check(const char *tablename, 42masquerade_check(const char *tablename,
43 const void *e, 43 const void *e,
44 const struct xt_target *target,
44 void *targinfo, 45 void *targinfo,
45 unsigned int targinfosize, 46 unsigned int targinfosize,
46 unsigned int hook_mask) 47 unsigned int hook_mask)
47{ 48{
48 const struct ip_nat_multi_range_compat *mr = targinfo; 49 const struct ip_nat_multi_range_compat *mr = targinfo;
49 50
50 if (strcmp(tablename, "nat") != 0) {
51 DEBUGP("masquerade_check: bad table `%s'.\n", tablename);
52 return 0;
53 }
54 if (targinfosize != IPT_ALIGN(sizeof(*mr))) {
55 DEBUGP("masquerade_check: size %u != %u.\n",
56 targinfosize, sizeof(*mr));
57 return 0;
58 }
59 if (hook_mask & ~(1 << NF_IP_POST_ROUTING)) {
60 DEBUGP("masquerade_check: bad hooks %x.\n", hook_mask);
61 return 0;
62 }
63 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { 51 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
64 DEBUGP("masquerade_check: bad MAP_IPS.\n"); 52 DEBUGP("masquerade_check: bad MAP_IPS.\n");
65 return 0; 53 return 0;
@@ -76,6 +64,7 @@ masquerade_target(struct sk_buff **pskb,
76 const struct net_device *in, 64 const struct net_device *in,
77 const struct net_device *out, 65 const struct net_device *out,
78 unsigned int hooknum, 66 unsigned int hooknum,
67 const struct xt_target *target,
79 const void *targinfo, 68 const void *targinfo,
80 void *userinfo) 69 void *userinfo)
81{ 70{
@@ -179,6 +168,9 @@ static struct notifier_block masq_inet_notifier = {
179static struct ipt_target masquerade = { 168static struct ipt_target masquerade = {
180 .name = "MASQUERADE", 169 .name = "MASQUERADE",
181 .target = masquerade_target, 170 .target = masquerade_target,
171 .targetsize = sizeof(struct ip_nat_multi_range_compat),
172 .table = "nat",
173 .hooks = 1 << NF_IP_POST_ROUTING,
182 .checkentry = masquerade_check, 174 .checkentry = masquerade_check,
183 .me = THIS_MODULE, 175 .me = THIS_MODULE,
184}; 176};
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index b074467fe67b..fba181c2a426 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -32,25 +32,13 @@ MODULE_DESCRIPTION("iptables 1:1 NAT mapping of IP networks target");
32static int 32static int
33check(const char *tablename, 33check(const char *tablename,
34 const void *e, 34 const void *e,
35 const struct xt_target *target,
35 void *targinfo, 36 void *targinfo,
36 unsigned int targinfosize, 37 unsigned int targinfosize,
37 unsigned int hook_mask) 38 unsigned int hook_mask)
38{ 39{
39 const struct ip_nat_multi_range_compat *mr = targinfo; 40 const struct ip_nat_multi_range_compat *mr = targinfo;
40 41
41 if (strcmp(tablename, "nat") != 0) {
42 DEBUGP(MODULENAME":check: bad table `%s'.\n", tablename);
43 return 0;
44 }
45 if (targinfosize != IPT_ALIGN(sizeof(*mr))) {
46 DEBUGP(MODULENAME":check: size %u.\n", targinfosize);
47 return 0;
48 }
49 if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_POST_ROUTING) |
50 (1 << NF_IP_LOCAL_OUT))) {
51 DEBUGP(MODULENAME":check: bad hooks %x.\n", hook_mask);
52 return 0;
53 }
54 if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) { 42 if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) {
55 DEBUGP(MODULENAME":check: bad MAP_IPS.\n"); 43 DEBUGP(MODULENAME":check: bad MAP_IPS.\n");
56 return 0; 44 return 0;
@@ -67,6 +55,7 @@ target(struct sk_buff **pskb,
67 const struct net_device *in, 55 const struct net_device *in,
68 const struct net_device *out, 56 const struct net_device *out,
69 unsigned int hooknum, 57 unsigned int hooknum,
58 const struct xt_target *target,
70 const void *targinfo, 59 const void *targinfo,
71 void *userinfo) 60 void *userinfo)
72{ 61{
@@ -101,6 +90,10 @@ target(struct sk_buff **pskb,
101static struct ipt_target target_module = { 90static struct ipt_target target_module = {
102 .name = MODULENAME, 91 .name = MODULENAME,
103 .target = target, 92 .target = target,
93 .targetsize = sizeof(struct ip_nat_multi_range_compat),
94 .table = "nat",
95 .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_POST_ROUTING) |
96 (1 << NF_IP_LOCAL_OUT),
104 .checkentry = check, 97 .checkentry = check,
105 .me = THIS_MODULE 98 .me = THIS_MODULE
106}; 99};
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index 140be51f2f01..be3da7c4b871 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -34,24 +34,13 @@ MODULE_DESCRIPTION("iptables REDIRECT target module");
34static int 34static int
35redirect_check(const char *tablename, 35redirect_check(const char *tablename,
36 const void *e, 36 const void *e,
37 const struct xt_target *target,
37 void *targinfo, 38 void *targinfo,
38 unsigned int targinfosize, 39 unsigned int targinfosize,
39 unsigned int hook_mask) 40 unsigned int hook_mask)
40{ 41{
41 const struct ip_nat_multi_range_compat *mr = targinfo; 42 const struct ip_nat_multi_range_compat *mr = targinfo;
42 43
43 if (strcmp(tablename, "nat") != 0) {
44 DEBUGP("redirect_check: bad table `%s'.\n", table);
45 return 0;
46 }
47 if (targinfosize != IPT_ALIGN(sizeof(*mr))) {
48 DEBUGP("redirect_check: size %u.\n", targinfosize);
49 return 0;
50 }
51 if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))) {
52 DEBUGP("redirect_check: bad hooks %x.\n", hook_mask);
53 return 0;
54 }
55 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { 44 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
56 DEBUGP("redirect_check: bad MAP_IPS.\n"); 45 DEBUGP("redirect_check: bad MAP_IPS.\n");
57 return 0; 46 return 0;
@@ -68,6 +57,7 @@ redirect_target(struct sk_buff **pskb,
68 const struct net_device *in, 57 const struct net_device *in,
69 const struct net_device *out, 58 const struct net_device *out,
70 unsigned int hooknum, 59 unsigned int hooknum,
60 const struct xt_target *target,
71 const void *targinfo, 61 const void *targinfo,
72 void *userinfo) 62 void *userinfo)
73{ 63{
@@ -115,6 +105,9 @@ redirect_target(struct sk_buff **pskb,
115static struct ipt_target redirect_reg = { 105static struct ipt_target redirect_reg = {
116 .name = "REDIRECT", 106 .name = "REDIRECT",
117 .target = redirect_target, 107 .target = redirect_target,
108 .targetsize = sizeof(struct ip_nat_multi_range_compat),
109 .table = "nat",
110 .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT),
118 .checkentry = redirect_check, 111 .checkentry = redirect_check,
119 .me = THIS_MODULE, 112 .me = THIS_MODULE,
120}; 113};
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 3eb47aae78c5..9d3b3579f27c 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -154,10 +154,6 @@ static void send_reset(struct sk_buff *oldskb, int hook)
154 /* This packet will not be the same as the other: clear nf fields */ 154 /* This packet will not be the same as the other: clear nf fields */
155 nf_reset(nskb); 155 nf_reset(nskb);
156 nskb->nfmark = 0; 156 nskb->nfmark = 0;
157#ifdef CONFIG_BRIDGE_NETFILTER
158 nf_bridge_put(nskb->nf_bridge);
159 nskb->nf_bridge = NULL;
160#endif
161 157
162 tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl); 158 tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
163 159
@@ -236,6 +232,7 @@ static unsigned int reject(struct sk_buff **pskb,
236 const struct net_device *in, 232 const struct net_device *in,
237 const struct net_device *out, 233 const struct net_device *out,
238 unsigned int hooknum, 234 unsigned int hooknum,
235 const struct xt_target *target,
239 const void *targinfo, 236 const void *targinfo,
240 void *userinfo) 237 void *userinfo)
241{ 238{
@@ -283,6 +280,7 @@ static unsigned int reject(struct sk_buff **pskb,
283 280
284static int check(const char *tablename, 281static int check(const char *tablename,
285 const void *e_void, 282 const void *e_void,
283 const struct xt_target *target,
286 void *targinfo, 284 void *targinfo,
287 unsigned int targinfosize, 285 unsigned int targinfosize,
288 unsigned int hook_mask) 286 unsigned int hook_mask)
@@ -290,23 +288,6 @@ static int check(const char *tablename,
290 const struct ipt_reject_info *rejinfo = targinfo; 288 const struct ipt_reject_info *rejinfo = targinfo;
291 const struct ipt_entry *e = e_void; 289 const struct ipt_entry *e = e_void;
292 290
293 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_reject_info))) {
294 DEBUGP("REJECT: targinfosize %u != 0\n", targinfosize);
295 return 0;
296 }
297
298 /* Only allow these for packet filtering. */
299 if (strcmp(tablename, "filter") != 0) {
300 DEBUGP("REJECT: bad table `%s'.\n", tablename);
301 return 0;
302 }
303 if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
304 | (1 << NF_IP_FORWARD)
305 | (1 << NF_IP_LOCAL_OUT))) != 0) {
306 DEBUGP("REJECT: bad hook mask %X\n", hook_mask);
307 return 0;
308 }
309
310 if (rejinfo->with == IPT_ICMP_ECHOREPLY) { 291 if (rejinfo->with == IPT_ICMP_ECHOREPLY) {
311 printk("REJECT: ECHOREPLY no longer supported.\n"); 292 printk("REJECT: ECHOREPLY no longer supported.\n");
312 return 0; 293 return 0;
@@ -318,13 +299,16 @@ static int check(const char *tablename,
318 return 0; 299 return 0;
319 } 300 }
320 } 301 }
321
322 return 1; 302 return 1;
323} 303}
324 304
325static struct ipt_target ipt_reject_reg = { 305static struct ipt_target ipt_reject_reg = {
326 .name = "REJECT", 306 .name = "REJECT",
327 .target = reject, 307 .target = reject,
308 .targetsize = sizeof(struct ipt_reject_info),
309 .table = "filter",
310 .hooks = (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) |
311 (1 << NF_IP_LOCAL_OUT),
328 .checkentry = check, 312 .checkentry = check,
329 .me = THIS_MODULE, 313 .me = THIS_MODULE,
330}; 314};
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c
index a22de59bba0e..7e2ebc9d945e 100644
--- a/net/ipv4/netfilter/ipt_SAME.c
+++ b/net/ipv4/netfilter/ipt_SAME.c
@@ -50,6 +50,7 @@ MODULE_DESCRIPTION("iptables special SNAT module for consistent sourceip");
50static int 50static int
51same_check(const char *tablename, 51same_check(const char *tablename,
52 const void *e, 52 const void *e,
53 const struct xt_target *target,
53 void *targinfo, 54 void *targinfo,
54 unsigned int targinfosize, 55 unsigned int targinfosize,
55 unsigned int hook_mask) 56 unsigned int hook_mask)
@@ -59,18 +60,6 @@ same_check(const char *tablename,
59 60
60 mr->ipnum = 0; 61 mr->ipnum = 0;
61 62
62 if (strcmp(tablename, "nat") != 0) {
63 DEBUGP("same_check: bad table `%s'.\n", tablename);
64 return 0;
65 }
66 if (targinfosize != IPT_ALIGN(sizeof(*mr))) {
67 DEBUGP("same_check: size %u.\n", targinfosize);
68 return 0;
69 }
70 if (hook_mask & ~(1 << NF_IP_PRE_ROUTING | 1 << NF_IP_POST_ROUTING)) {
71 DEBUGP("same_check: bad hooks %x.\n", hook_mask);
72 return 0;
73 }
74 if (mr->rangesize < 1) { 63 if (mr->rangesize < 1) {
75 DEBUGP("same_check: need at least one dest range.\n"); 64 DEBUGP("same_check: need at least one dest range.\n");
76 return 0; 65 return 0;
@@ -127,7 +116,7 @@ same_check(const char *tablename,
127} 116}
128 117
129static void 118static void
130same_destroy(void *targinfo, 119same_destroy(const struct xt_target *target, void *targinfo,
131 unsigned int targinfosize) 120 unsigned int targinfosize)
132{ 121{
133 struct ipt_same_info *mr = targinfo; 122 struct ipt_same_info *mr = targinfo;
@@ -143,6 +132,7 @@ same_target(struct sk_buff **pskb,
143 const struct net_device *in, 132 const struct net_device *in,
144 const struct net_device *out, 133 const struct net_device *out,
145 unsigned int hooknum, 134 unsigned int hooknum,
135 const struct xt_target *target,
146 const void *targinfo, 136 const void *targinfo,
147 void *userinfo) 137 void *userinfo)
148{ 138{
@@ -191,6 +181,9 @@ same_target(struct sk_buff **pskb,
191static struct ipt_target same_reg = { 181static struct ipt_target same_reg = {
192 .name = "SAME", 182 .name = "SAME",
193 .target = same_target, 183 .target = same_target,
184 .targetsize = sizeof(struct ipt_same_info),
185 .table = "nat",
186 .hooks = (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_POST_ROUTING),
194 .checkentry = same_check, 187 .checkentry = same_check,
195 .destroy = same_destroy, 188 .destroy = same_destroy,
196 .me = THIS_MODULE, 189 .me = THIS_MODULE,
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c
index c122841e182c..c4fc50ec2ddb 100644
--- a/net/ipv4/netfilter/ipt_TCPMSS.c
+++ b/net/ipv4/netfilter/ipt_TCPMSS.c
@@ -48,6 +48,7 @@ ipt_tcpmss_target(struct sk_buff **pskb,
48 const struct net_device *in, 48 const struct net_device *in,
49 const struct net_device *out, 49 const struct net_device *out,
50 unsigned int hooknum, 50 unsigned int hooknum,
51 const struct xt_target *target,
51 const void *targinfo, 52 const void *targinfo,
52 void *userinfo) 53 void *userinfo)
53{ 54{
@@ -211,6 +212,7 @@ static inline int find_syn_match(const struct ipt_entry_match *m)
211static int 212static int
212ipt_tcpmss_checkentry(const char *tablename, 213ipt_tcpmss_checkentry(const char *tablename,
213 const void *e_void, 214 const void *e_void,
215 const struct xt_target *target,
214 void *targinfo, 216 void *targinfo,
215 unsigned int targinfosize, 217 unsigned int targinfosize,
216 unsigned int hook_mask) 218 unsigned int hook_mask)
@@ -218,13 +220,6 @@ ipt_tcpmss_checkentry(const char *tablename,
218 const struct ipt_tcpmss_info *tcpmssinfo = targinfo; 220 const struct ipt_tcpmss_info *tcpmssinfo = targinfo;
219 const struct ipt_entry *e = e_void; 221 const struct ipt_entry *e = e_void;
220 222
221 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tcpmss_info))) {
222 DEBUGP("ipt_tcpmss_checkentry: targinfosize %u != %u\n",
223 targinfosize, IPT_ALIGN(sizeof(struct ipt_tcpmss_info)));
224 return 0;
225 }
226
227
228 if((tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) && 223 if((tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) &&
229 ((hook_mask & ~((1 << NF_IP_FORWARD) 224 ((hook_mask & ~((1 << NF_IP_FORWARD)
230 | (1 << NF_IP_LOCAL_OUT) 225 | (1 << NF_IP_LOCAL_OUT)
@@ -233,11 +228,8 @@ ipt_tcpmss_checkentry(const char *tablename,
233 return 0; 228 return 0;
234 } 229 }
235 230
236 if (e->ip.proto == IPPROTO_TCP 231 if (IPT_MATCH_ITERATE(e, find_syn_match))
237 && !(e->ip.invflags & IPT_INV_PROTO)
238 && IPT_MATCH_ITERATE(e, find_syn_match))
239 return 1; 232 return 1;
240
241 printk("TCPMSS: Only works on TCP SYN packets\n"); 233 printk("TCPMSS: Only works on TCP SYN packets\n");
242 return 0; 234 return 0;
243} 235}
@@ -245,6 +237,8 @@ ipt_tcpmss_checkentry(const char *tablename,
245static struct ipt_target ipt_tcpmss_reg = { 237static struct ipt_target ipt_tcpmss_reg = {
246 .name = "TCPMSS", 238 .name = "TCPMSS",
247 .target = ipt_tcpmss_target, 239 .target = ipt_tcpmss_target,
240 .targetsize = sizeof(struct ipt_tcpmss_info),
241 .proto = IPPROTO_TCP,
248 .checkentry = ipt_tcpmss_checkentry, 242 .checkentry = ipt_tcpmss_checkentry,
249 .me = THIS_MODULE, 243 .me = THIS_MODULE,
250}; 244};
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index 3a44a56db239..9aa7817657f0 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -25,6 +25,7 @@ target(struct sk_buff **pskb,
25 const struct net_device *in, 25 const struct net_device *in,
26 const struct net_device *out, 26 const struct net_device *out,
27 unsigned int hooknum, 27 unsigned int hooknum,
28 const struct xt_target *target,
28 const void *targinfo, 29 const void *targinfo,
29 void *userinfo) 30 void *userinfo)
30{ 31{
@@ -53,24 +54,13 @@ target(struct sk_buff **pskb,
53static int 54static int
54checkentry(const char *tablename, 55checkentry(const char *tablename,
55 const void *e_void, 56 const void *e_void,
57 const struct xt_target *target,
56 void *targinfo, 58 void *targinfo,
57 unsigned int targinfosize, 59 unsigned int targinfosize,
58 unsigned int hook_mask) 60 unsigned int hook_mask)
59{ 61{
60 const u_int8_t tos = ((struct ipt_tos_target_info *)targinfo)->tos; 62 const u_int8_t tos = ((struct ipt_tos_target_info *)targinfo)->tos;
61 63
62 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tos_target_info))) {
63 printk(KERN_WARNING "TOS: targinfosize %u != %Zu\n",
64 targinfosize,
65 IPT_ALIGN(sizeof(struct ipt_tos_target_info)));
66 return 0;
67 }
68
69 if (strcmp(tablename, "mangle") != 0) {
70 printk(KERN_WARNING "TOS: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
71 return 0;
72 }
73
74 if (tos != IPTOS_LOWDELAY 64 if (tos != IPTOS_LOWDELAY
75 && tos != IPTOS_THROUGHPUT 65 && tos != IPTOS_THROUGHPUT
76 && tos != IPTOS_RELIABILITY 66 && tos != IPTOS_RELIABILITY
@@ -79,13 +69,14 @@ checkentry(const char *tablename,
79 printk(KERN_WARNING "TOS: bad tos value %#x\n", tos); 69 printk(KERN_WARNING "TOS: bad tos value %#x\n", tos);
80 return 0; 70 return 0;
81 } 71 }
82
83 return 1; 72 return 1;
84} 73}
85 74
86static struct ipt_target ipt_tos_reg = { 75static struct ipt_target ipt_tos_reg = {
87 .name = "TOS", 76 .name = "TOS",
88 .target = target, 77 .target = target,
78 .targetsize = sizeof(struct ipt_tos_target_info),
79 .table = "mangle",
89 .checkentry = checkentry, 80 .checkentry = checkentry,
90 .me = THIS_MODULE, 81 .me = THIS_MODULE,
91}; 82};
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index b769eb231970..5009a003d578 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -20,9 +20,10 @@ MODULE_DESCRIPTION("IP tables TTL modification module");
20MODULE_LICENSE("GPL"); 20MODULE_LICENSE("GPL");
21 21
22static unsigned int 22static unsigned int
23ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in, 23ipt_ttl_target(struct sk_buff **pskb,
24 const struct net_device *out, unsigned int hooknum, 24 const struct net_device *in, const struct net_device *out,
25 const void *targinfo, void *userinfo) 25 unsigned int hooknum, const struct xt_target *target,
26 const void *targinfo, void *userinfo)
26{ 27{
27 struct iphdr *iph; 28 struct iphdr *iph;
28 const struct ipt_TTL_info *info = targinfo; 29 const struct ipt_TTL_info *info = targinfo;
@@ -67,40 +68,28 @@ ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in,
67 68
68static int ipt_ttl_checkentry(const char *tablename, 69static int ipt_ttl_checkentry(const char *tablename,
69 const void *e, 70 const void *e,
71 const struct xt_target *target,
70 void *targinfo, 72 void *targinfo,
71 unsigned int targinfosize, 73 unsigned int targinfosize,
72 unsigned int hook_mask) 74 unsigned int hook_mask)
73{ 75{
74 struct ipt_TTL_info *info = targinfo; 76 struct ipt_TTL_info *info = targinfo;
75 77
76 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
77 printk(KERN_WARNING "ipt_TTL: targinfosize %u != %Zu\n",
78 targinfosize,
79 IPT_ALIGN(sizeof(struct ipt_TTL_info)));
80 return 0;
81 }
82
83 if (strcmp(tablename, "mangle")) {
84 printk(KERN_WARNING "ipt_TTL: can only be called from "
85 "\"mangle\" table, not \"%s\"\n", tablename);
86 return 0;
87 }
88
89 if (info->mode > IPT_TTL_MAXMODE) { 78 if (info->mode > IPT_TTL_MAXMODE) {
90 printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n", 79 printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n",
91 info->mode); 80 info->mode);
92 return 0; 81 return 0;
93 } 82 }
94
95 if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) 83 if ((info->mode != IPT_TTL_SET) && (info->ttl == 0))
96 return 0; 84 return 0;
97
98 return 1; 85 return 1;
99} 86}
100 87
101static struct ipt_target ipt_TTL = { 88static struct ipt_target ipt_TTL = {
102 .name = "TTL", 89 .name = "TTL",
103 .target = ipt_ttl_target, 90 .target = ipt_ttl_target,
91 .targetsize = sizeof(struct ipt_TTL_info),
92 .table = "mangle",
104 .checkentry = ipt_ttl_checkentry, 93 .checkentry = ipt_ttl_checkentry,
105 .me = THIS_MODULE, 94 .me = THIS_MODULE,
106}; 95};
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 180a9ea57b69..a82a32ed0e2f 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -303,6 +303,7 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb,
303 const struct net_device *in, 303 const struct net_device *in,
304 const struct net_device *out, 304 const struct net_device *out,
305 unsigned int hooknum, 305 unsigned int hooknum,
306 const struct xt_target *target,
306 const void *targinfo, void *userinfo) 307 const void *targinfo, void *userinfo)
307{ 308{
308 struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo; 309 struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
@@ -339,42 +340,37 @@ static void ipt_logfn(unsigned int pf,
339 340
340static int ipt_ulog_checkentry(const char *tablename, 341static int ipt_ulog_checkentry(const char *tablename,
341 const void *e, 342 const void *e,
343 const struct xt_target *target,
342 void *targinfo, 344 void *targinfo,
343 unsigned int targinfosize, 345 unsigned int targinfosize,
344 unsigned int hookmask) 346 unsigned int hookmask)
345{ 347{
346 struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo; 348 struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
347 349
348 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ulog_info))) {
349 DEBUGP("ipt_ULOG: targinfosize %u != 0\n", targinfosize);
350 return 0;
351 }
352
353 if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') { 350 if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') {
354 DEBUGP("ipt_ULOG: prefix term %i\n", 351 DEBUGP("ipt_ULOG: prefix term %i\n",
355 loginfo->prefix[sizeof(loginfo->prefix) - 1]); 352 loginfo->prefix[sizeof(loginfo->prefix) - 1]);
356 return 0; 353 return 0;
357 } 354 }
358
359 if (loginfo->qthreshold > ULOG_MAX_QLEN) { 355 if (loginfo->qthreshold > ULOG_MAX_QLEN) {
360 DEBUGP("ipt_ULOG: queue threshold %i > MAX_QLEN\n", 356 DEBUGP("ipt_ULOG: queue threshold %i > MAX_QLEN\n",
361 loginfo->qthreshold); 357 loginfo->qthreshold);
362 return 0; 358 return 0;
363 } 359 }
364
365 return 1; 360 return 1;
366} 361}
367 362
368static struct ipt_target ipt_ulog_reg = { 363static struct ipt_target ipt_ulog_reg = {
369 .name = "ULOG", 364 .name = "ULOG",
370 .target = ipt_ulog_target, 365 .target = ipt_ulog_target,
366 .targetsize = sizeof(struct ipt_ulog_info),
371 .checkentry = ipt_ulog_checkentry, 367 .checkentry = ipt_ulog_checkentry,
372 .me = THIS_MODULE, 368 .me = THIS_MODULE,
373}; 369};
374 370
375static struct nf_logger ipt_ulog_logger = { 371static struct nf_logger ipt_ulog_logger = {
376 .name = "ipt_ULOG", 372 .name = "ipt_ULOG",
377 .logfn = &ipt_logfn, 373 .logfn = ipt_logfn,
378 .me = THIS_MODULE, 374 .me = THIS_MODULE,
379}; 375};
380 376
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c
index d6b83a976518..5fdf85d0efcf 100644
--- a/net/ipv4/netfilter/ipt_addrtype.c
+++ b/net/ipv4/netfilter/ipt_addrtype.c
@@ -27,8 +27,9 @@ static inline int match_type(u_int32_t addr, u_int16_t mask)
27 return !!(mask & (1 << inet_addr_type(addr))); 27 return !!(mask & (1 << inet_addr_type(addr)));
28} 28}
29 29
30static int match(const struct sk_buff *skb, const struct net_device *in, 30static int match(const struct sk_buff *skb,
31 const struct net_device *out, const void *matchinfo, 31 const struct net_device *in, const struct net_device *out,
32 const struct xt_match *match, const void *matchinfo,
32 int offset, unsigned int protoff, int *hotdrop) 33 int offset, unsigned int protoff, int *hotdrop)
33{ 34{
34 const struct ipt_addrtype_info *info = matchinfo; 35 const struct ipt_addrtype_info *info = matchinfo;
@@ -43,23 +44,10 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
43 return ret; 44 return ret;
44} 45}
45 46
46static int checkentry(const char *tablename, const void *ip,
47 void *matchinfo, unsigned int matchsize,
48 unsigned int hook_mask)
49{
50 if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
51 printk(KERN_ERR "ipt_addrtype: invalid size (%u != %Zu)\n",
52 matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
53 return 0;
54 }
55
56 return 1;
57}
58
59static struct ipt_match addrtype_match = { 47static struct ipt_match addrtype_match = {
60 .name = "addrtype", 48 .name = "addrtype",
61 .match = match, 49 .match = match,
62 .checkentry = checkentry, 50 .matchsize = sizeof(struct ipt_addrtype_info),
63 .me = THIS_MODULE 51 .me = THIS_MODULE
64}; 52};
65 53
diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c
index 144adfec13cc..35a21fb1f8e0 100644
--- a/net/ipv4/netfilter/ipt_ah.c
+++ b/net/ipv4/netfilter/ipt_ah.c
@@ -39,6 +39,7 @@ static int
39match(const struct sk_buff *skb, 39match(const struct sk_buff *skb,
40 const struct net_device *in, 40 const struct net_device *in,
41 const struct net_device *out, 41 const struct net_device *out,
42 const struct xt_match *match,
42 const void *matchinfo, 43 const void *matchinfo,
43 int offset, 44 int offset,
44 unsigned int protoff, 45 unsigned int protoff,
@@ -71,37 +72,27 @@ match(const struct sk_buff *skb,
71static int 72static int
72checkentry(const char *tablename, 73checkentry(const char *tablename,
73 const void *ip_void, 74 const void *ip_void,
75 const struct xt_match *match,
74 void *matchinfo, 76 void *matchinfo,
75 unsigned int matchinfosize, 77 unsigned int matchinfosize,
76 unsigned int hook_mask) 78 unsigned int hook_mask)
77{ 79{
78 const struct ipt_ah *ahinfo = matchinfo; 80 const struct ipt_ah *ahinfo = matchinfo;
79 const struct ipt_ip *ip = ip_void;
80 81
81 /* Must specify proto == AH, and no unknown invflags */ 82 /* Must specify no unknown invflags */
82 if (ip->proto != IPPROTO_AH || (ip->invflags & IPT_INV_PROTO)) {
83 duprintf("ipt_ah: Protocol %u != %u\n", ip->proto,
84 IPPROTO_AH);
85 return 0;
86 }
87 if (matchinfosize != IPT_ALIGN(sizeof(struct ipt_ah))) {
88 duprintf("ipt_ah: matchsize %u != %u\n",
89 matchinfosize, IPT_ALIGN(sizeof(struct ipt_ah)));
90 return 0;
91 }
92 if (ahinfo->invflags & ~IPT_AH_INV_MASK) { 83 if (ahinfo->invflags & ~IPT_AH_INV_MASK) {
93 duprintf("ipt_ah: unknown flags %X\n", 84 duprintf("ipt_ah: unknown flags %X\n", ahinfo->invflags);
94 ahinfo->invflags);
95 return 0; 85 return 0;
96 } 86 }
97
98 return 1; 87 return 1;
99} 88}
100 89
101static struct ipt_match ah_match = { 90static struct ipt_match ah_match = {
102 .name = "ah", 91 .name = "ah",
103 .match = &match, 92 .match = match,
104 .checkentry = &checkentry, 93 .matchsize = sizeof(struct ipt_ah),
94 .proto = IPPROTO_AH,
95 .checkentry = checkentry,
105 .me = THIS_MODULE, 96 .me = THIS_MODULE,
106}; 97};
107 98
diff --git a/net/ipv4/netfilter/ipt_dscp.c b/net/ipv4/netfilter/ipt_dscp.c
index 92063b4f8602..11963c385dea 100644
--- a/net/ipv4/netfilter/ipt_dscp.c
+++ b/net/ipv4/netfilter/ipt_dscp.c
@@ -19,8 +19,9 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
19MODULE_DESCRIPTION("iptables DSCP matching module"); 19MODULE_DESCRIPTION("iptables DSCP matching module");
20MODULE_LICENSE("GPL"); 20MODULE_LICENSE("GPL");
21 21
22static int match(const struct sk_buff *skb, const struct net_device *in, 22static int match(const struct sk_buff *skb,
23 const struct net_device *out, const void *matchinfo, 23 const struct net_device *in, const struct net_device *out,
24 const struct xt_match *match, const void *matchinfo,
24 int offset, unsigned int protoff, int *hotdrop) 25 int offset, unsigned int protoff, int *hotdrop)
25{ 26{
26 const struct ipt_dscp_info *info = matchinfo; 27 const struct ipt_dscp_info *info = matchinfo;
@@ -31,20 +32,10 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
31 return ((iph->tos&IPT_DSCP_MASK) == sh_dscp) ^ info->invert; 32 return ((iph->tos&IPT_DSCP_MASK) == sh_dscp) ^ info->invert;
32} 33}
33 34
34static int checkentry(const char *tablename, const void *ip,
35 void *matchinfo, unsigned int matchsize,
36 unsigned int hook_mask)
37{
38 if (matchsize != IPT_ALIGN(sizeof(struct ipt_dscp_info)))
39 return 0;
40
41 return 1;
42}
43
44static struct ipt_match dscp_match = { 35static struct ipt_match dscp_match = {
45 .name = "dscp", 36 .name = "dscp",
46 .match = &match, 37 .match = match,
47 .checkentry = &checkentry, 38 .matchsize = sizeof(struct ipt_dscp_info),
48 .me = THIS_MODULE, 39 .me = THIS_MODULE,
49}; 40};
50 41
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c
index e68b0c7981f0..d7e29f6a38d8 100644
--- a/net/ipv4/netfilter/ipt_ecn.c
+++ b/net/ipv4/netfilter/ipt_ecn.c
@@ -65,8 +65,9 @@ static inline int match_tcp(const struct sk_buff *skb,
65 return 1; 65 return 1;
66} 66}
67 67
68static int match(const struct sk_buff *skb, const struct net_device *in, 68static int match(const struct sk_buff *skb,
69 const struct net_device *out, const void *matchinfo, 69 const struct net_device *in, const struct net_device *out,
70 const struct xt_match *match, const void *matchinfo,
70 int offset, unsigned int protoff, int *hotdrop) 71 int offset, unsigned int protoff, int *hotdrop)
71{ 72{
72 const struct ipt_ecn_info *info = matchinfo; 73 const struct ipt_ecn_info *info = matchinfo;
@@ -86,15 +87,13 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
86} 87}
87 88
88static int checkentry(const char *tablename, const void *ip_void, 89static int checkentry(const char *tablename, const void *ip_void,
90 const struct xt_match *match,
89 void *matchinfo, unsigned int matchsize, 91 void *matchinfo, unsigned int matchsize,
90 unsigned int hook_mask) 92 unsigned int hook_mask)
91{ 93{
92 const struct ipt_ecn_info *info = matchinfo; 94 const struct ipt_ecn_info *info = matchinfo;
93 const struct ipt_ip *ip = ip_void; 95 const struct ipt_ip *ip = ip_void;
94 96
95 if (matchsize != IPT_ALIGN(sizeof(struct ipt_ecn_info)))
96 return 0;
97
98 if (info->operation & IPT_ECN_OP_MATCH_MASK) 97 if (info->operation & IPT_ECN_OP_MATCH_MASK)
99 return 0; 98 return 0;
100 99
@@ -113,8 +112,9 @@ static int checkentry(const char *tablename, const void *ip_void,
113 112
114static struct ipt_match ecn_match = { 113static struct ipt_match ecn_match = {
115 .name = "ecn", 114 .name = "ecn",
116 .match = &match, 115 .match = match,
117 .checkentry = &checkentry, 116 .matchsize = sizeof(struct ipt_ecn_info),
117 .checkentry = checkentry,
118 .me = THIS_MODULE, 118 .me = THIS_MODULE,
119}; 119};
120 120
diff --git a/net/ipv4/netfilter/ipt_esp.c b/net/ipv4/netfilter/ipt_esp.c
index 9de191a8162d..af0d5ec79cb5 100644
--- a/net/ipv4/netfilter/ipt_esp.c
+++ b/net/ipv4/netfilter/ipt_esp.c
@@ -40,6 +40,7 @@ static int
40match(const struct sk_buff *skb, 40match(const struct sk_buff *skb,
41 const struct net_device *in, 41 const struct net_device *in,
42 const struct net_device *out, 42 const struct net_device *out,
43 const struct xt_match *match,
43 const void *matchinfo, 44 const void *matchinfo,
44 int offset, 45 int offset,
45 unsigned int protoff, 46 unsigned int protoff,
@@ -72,37 +73,27 @@ match(const struct sk_buff *skb,
72static int 73static int
73checkentry(const char *tablename, 74checkentry(const char *tablename,
74 const void *ip_void, 75 const void *ip_void,
76 const struct xt_match *match,
75 void *matchinfo, 77 void *matchinfo,
76 unsigned int matchinfosize, 78 unsigned int matchinfosize,
77 unsigned int hook_mask) 79 unsigned int hook_mask)
78{ 80{
79 const struct ipt_esp *espinfo = matchinfo; 81 const struct ipt_esp *espinfo = matchinfo;
80 const struct ipt_ip *ip = ip_void;
81 82
82 /* Must specify proto == ESP, and no unknown invflags */ 83 /* Must specify no unknown invflags */
83 if (ip->proto != IPPROTO_ESP || (ip->invflags & IPT_INV_PROTO)) {
84 duprintf("ipt_esp: Protocol %u != %u\n", ip->proto,
85 IPPROTO_ESP);
86 return 0;
87 }
88 if (matchinfosize != IPT_ALIGN(sizeof(struct ipt_esp))) {
89 duprintf("ipt_esp: matchsize %u != %u\n",
90 matchinfosize, IPT_ALIGN(sizeof(struct ipt_esp)));
91 return 0;
92 }
93 if (espinfo->invflags & ~IPT_ESP_INV_MASK) { 84 if (espinfo->invflags & ~IPT_ESP_INV_MASK) {
94 duprintf("ipt_esp: unknown flags %X\n", 85 duprintf("ipt_esp: unknown flags %X\n", espinfo->invflags);
95 espinfo->invflags);
96 return 0; 86 return 0;
97 } 87 }
98
99 return 1; 88 return 1;
100} 89}
101 90
102static struct ipt_match esp_match = { 91static struct ipt_match esp_match = {
103 .name = "esp", 92 .name = "esp",
104 .match = &match, 93 .match = match,
105 .checkentry = &checkentry, 94 .matchsize = sizeof(struct ipt_esp),
95 .proto = IPPROTO_ESP,
96 .checkentry = checkentry,
106 .me = THIS_MODULE, 97 .me = THIS_MODULE,
107}; 98};
108 99
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
index 4fe48c1bd5f3..dc1521c5aa81 100644
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ b/net/ipv4/netfilter/ipt_hashlimit.c
@@ -427,6 +427,7 @@ static int
427hashlimit_match(const struct sk_buff *skb, 427hashlimit_match(const struct sk_buff *skb,
428 const struct net_device *in, 428 const struct net_device *in,
429 const struct net_device *out, 429 const struct net_device *out,
430 const struct xt_match *match,
430 const void *matchinfo, 431 const void *matchinfo,
431 int offset, 432 int offset,
432 unsigned int protoff, 433 unsigned int protoff,
@@ -506,15 +507,13 @@ hashlimit_match(const struct sk_buff *skb,
506static int 507static int
507hashlimit_checkentry(const char *tablename, 508hashlimit_checkentry(const char *tablename,
508 const void *inf, 509 const void *inf,
510 const struct xt_match *match,
509 void *matchinfo, 511 void *matchinfo,
510 unsigned int matchsize, 512 unsigned int matchsize,
511 unsigned int hook_mask) 513 unsigned int hook_mask)
512{ 514{
513 struct ipt_hashlimit_info *r = matchinfo; 515 struct ipt_hashlimit_info *r = matchinfo;
514 516
515 if (matchsize != IPT_ALIGN(sizeof(struct ipt_hashlimit_info)))
516 return 0;
517
518 /* Check for overflow. */ 517 /* Check for overflow. */
519 if (r->cfg.burst == 0 518 if (r->cfg.burst == 0
520 || user2credits(r->cfg.avg * r->cfg.burst) < 519 || user2credits(r->cfg.avg * r->cfg.burst) <
@@ -558,19 +557,21 @@ hashlimit_checkentry(const char *tablename,
558} 557}
559 558
560static void 559static void
561hashlimit_destroy(void *matchinfo, unsigned int matchsize) 560hashlimit_destroy(const struct xt_match *match, void *matchinfo,
561 unsigned int matchsize)
562{ 562{
563 struct ipt_hashlimit_info *r = (struct ipt_hashlimit_info *) matchinfo; 563 struct ipt_hashlimit_info *r = (struct ipt_hashlimit_info *) matchinfo;
564 564
565 htable_put(r->hinfo); 565 htable_put(r->hinfo);
566} 566}
567 567
568static struct ipt_match ipt_hashlimit = { 568static struct ipt_match ipt_hashlimit = {
569 .name = "hashlimit", 569 .name = "hashlimit",
570 .match = hashlimit_match, 570 .match = hashlimit_match,
571 .checkentry = hashlimit_checkentry, 571 .matchsize = sizeof(struct ipt_hashlimit_info),
572 .destroy = hashlimit_destroy, 572 .checkentry = hashlimit_checkentry,
573 .me = THIS_MODULE 573 .destroy = hashlimit_destroy,
574 .me = THIS_MODULE
574}; 575};
575 576
576/* PROC stuff */ 577/* PROC stuff */
diff --git a/net/ipv4/netfilter/ipt_iprange.c b/net/ipv4/netfilter/ipt_iprange.c
index 13fb16fb7892..ae70112f5e06 100644
--- a/net/ipv4/netfilter/ipt_iprange.c
+++ b/net/ipv4/netfilter/ipt_iprange.c
@@ -27,6 +27,7 @@ static int
27match(const struct sk_buff *skb, 27match(const struct sk_buff *skb,
28 const struct net_device *in, 28 const struct net_device *in,
29 const struct net_device *out, 29 const struct net_device *out,
30 const struct xt_match *match,
30 const void *matchinfo, 31 const void *matchinfo,
31 int offset, unsigned int protoff, int *hotdrop) 32 int offset, unsigned int protoff, int *hotdrop)
32{ 33{
@@ -62,27 +63,12 @@ match(const struct sk_buff *skb,
62 return 1; 63 return 1;
63} 64}
64 65
65static int check(const char *tablename, 66static struct ipt_match iprange_match = {
66 const void *inf, 67 .name = "iprange",
67 void *matchinfo, 68 .match = match,
68 unsigned int matchsize, 69 .matchsize = sizeof(struct ipt_iprange_info),
69 unsigned int hook_mask) 70 .destroy = NULL,
70{ 71 .me = THIS_MODULE
71 /* verify size */
72 if (matchsize != IPT_ALIGN(sizeof(struct ipt_iprange_info)))
73 return 0;
74
75 return 1;
76}
77
78static struct ipt_match iprange_match =
79{
80 .list = { NULL, NULL },
81 .name = "iprange",
82 .match = &match,
83 .checkentry = &check,
84 .destroy = NULL,
85 .me = THIS_MODULE
86}; 72};
87 73
88static int __init init(void) 74static int __init init(void)
diff --git a/net/ipv4/netfilter/ipt_multiport.c b/net/ipv4/netfilter/ipt_multiport.c
index 2d52326553f1..bd07f7c53872 100644
--- a/net/ipv4/netfilter/ipt_multiport.c
+++ b/net/ipv4/netfilter/ipt_multiport.c
@@ -95,6 +95,7 @@ static int
95match(const struct sk_buff *skb, 95match(const struct sk_buff *skb,
96 const struct net_device *in, 96 const struct net_device *in,
97 const struct net_device *out, 97 const struct net_device *out,
98 const struct xt_match *match,
98 const void *matchinfo, 99 const void *matchinfo,
99 int offset, 100 int offset,
100 unsigned int protoff, 101 unsigned int protoff,
@@ -127,6 +128,7 @@ static int
127match_v1(const struct sk_buff *skb, 128match_v1(const struct sk_buff *skb,
128 const struct net_device *in, 129 const struct net_device *in,
129 const struct net_device *out, 130 const struct net_device *out,
131 const struct xt_match *match,
130 const void *matchinfo, 132 const void *matchinfo,
131 int offset, 133 int offset,
132 unsigned int protoff, 134 unsigned int protoff,
@@ -153,40 +155,19 @@ match_v1(const struct sk_buff *skb,
153 return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1])); 155 return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
154} 156}
155 157
156/* Called when user tries to insert an entry of this type. */
157static int
158checkentry(const char *tablename,
159 const void *ip,
160 void *matchinfo,
161 unsigned int matchsize,
162 unsigned int hook_mask)
163{
164 return (matchsize == IPT_ALIGN(sizeof(struct ipt_multiport)));
165}
166
167static int
168checkentry_v1(const char *tablename,
169 const void *ip,
170 void *matchinfo,
171 unsigned int matchsize,
172 unsigned int hook_mask)
173{
174 return (matchsize == IPT_ALIGN(sizeof(struct ipt_multiport_v1)));
175}
176
177static struct ipt_match multiport_match = { 158static struct ipt_match multiport_match = {
178 .name = "multiport", 159 .name = "multiport",
179 .revision = 0, 160 .revision = 0,
180 .match = &match, 161 .match = match,
181 .checkentry = &checkentry, 162 .matchsize = sizeof(struct ipt_multiport),
182 .me = THIS_MODULE, 163 .me = THIS_MODULE,
183}; 164};
184 165
185static struct ipt_match multiport_match_v1 = { 166static struct ipt_match multiport_match_v1 = {
186 .name = "multiport", 167 .name = "multiport",
187 .revision = 1, 168 .revision = 1,
188 .match = &match_v1, 169 .match = match_v1,
189 .checkentry = &checkentry_v1, 170 .matchsize = sizeof(struct ipt_multiport_v1),
190 .me = THIS_MODULE, 171 .me = THIS_MODULE,
191}; 172};
192 173
diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c
index 4843d0c9734f..3900428771f3 100644
--- a/net/ipv4/netfilter/ipt_owner.c
+++ b/net/ipv4/netfilter/ipt_owner.c
@@ -25,6 +25,7 @@ static int
25match(const struct sk_buff *skb, 25match(const struct sk_buff *skb,
26 const struct net_device *in, 26 const struct net_device *in,
27 const struct net_device *out, 27 const struct net_device *out,
28 const struct xt_match *match,
28 const void *matchinfo, 29 const void *matchinfo,
29 int offset, 30 int offset,
30 unsigned int protoff, 31 unsigned int protoff,
@@ -53,37 +54,27 @@ match(const struct sk_buff *skb,
53static int 54static int
54checkentry(const char *tablename, 55checkentry(const char *tablename,
55 const void *ip, 56 const void *ip,
57 const struct xt_match *match,
56 void *matchinfo, 58 void *matchinfo,
57 unsigned int matchsize, 59 unsigned int matchsize,
58 unsigned int hook_mask) 60 unsigned int hook_mask)
59{ 61{
60 const struct ipt_owner_info *info = matchinfo; 62 const struct ipt_owner_info *info = matchinfo;
61 63
62 if (hook_mask
63 & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
64 printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
65 return 0;
66 }
67
68 if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
69 printk("Matchsize %u != %Zu\n", matchsize,
70 IPT_ALIGN(sizeof(struct ipt_owner_info)));
71 return 0;
72 }
73
74 if (info->match & (IPT_OWNER_PID|IPT_OWNER_SID|IPT_OWNER_COMM)) { 64 if (info->match & (IPT_OWNER_PID|IPT_OWNER_SID|IPT_OWNER_COMM)) {
75 printk("ipt_owner: pid, sid and command matching " 65 printk("ipt_owner: pid, sid and command matching "
76 "not supported anymore\n"); 66 "not supported anymore\n");
77 return 0; 67 return 0;
78 } 68 }
79
80 return 1; 69 return 1;
81} 70}
82 71
83static struct ipt_match owner_match = { 72static struct ipt_match owner_match = {
84 .name = "owner", 73 .name = "owner",
85 .match = &match, 74 .match = match,
86 .checkentry = &checkentry, 75 .matchsize = sizeof(struct ipt_owner_info),
76 .hooks = (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING),
77 .checkentry = checkentry,
87 .me = THIS_MODULE, 78 .me = THIS_MODULE,
88}; 79};
89 80
diff --git a/net/ipv4/netfilter/ipt_policy.c b/net/ipv4/netfilter/ipt_policy.c
deleted file mode 100644
index 5a7a265280f9..000000000000
--- a/net/ipv4/netfilter/ipt_policy.c
+++ /dev/null
@@ -1,176 +0,0 @@
1/* IP tables module for matching IPsec policy
2 *
3 * Copyright (c) 2004,2005 Patrick McHardy, <kaber@trash.net>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/kernel.h>
11#include <linux/config.h>
12#include <linux/module.h>
13#include <linux/skbuff.h>
14#include <linux/init.h>
15#include <net/xfrm.h>
16
17#include <linux/netfilter_ipv4.h>
18#include <linux/netfilter_ipv4/ip_tables.h>
19#include <linux/netfilter_ipv4/ipt_policy.h>
20
21MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
22MODULE_DESCRIPTION("IPtables IPsec policy matching module");
23MODULE_LICENSE("GPL");
24
25
26static inline int
27match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
28{
29#define MATCH_ADDR(x,y,z) (!e->match.x || \
30 ((e->x.a4.s_addr == (e->y.a4.s_addr & (z))) \
31 ^ e->invert.x))
32#define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x))
33
34 return MATCH_ADDR(saddr, smask, x->props.saddr.a4) &&
35 MATCH_ADDR(daddr, dmask, x->id.daddr.a4) &&
36 MATCH(proto, x->id.proto) &&
37 MATCH(mode, x->props.mode) &&
38 MATCH(spi, x->id.spi) &&
39 MATCH(reqid, x->props.reqid);
40}
41
42static int
43match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
44{
45 const struct ipt_policy_elem *e;
46 struct sec_path *sp = skb->sp;
47 int strict = info->flags & IPT_POLICY_MATCH_STRICT;
48 int i, pos;
49
50 if (sp == NULL)
51 return -1;
52 if (strict && info->len != sp->len)
53 return 0;
54
55 for (i = sp->len - 1; i >= 0; i--) {
56 pos = strict ? i - sp->len + 1 : 0;
57 if (pos >= info->len)
58 return 0;
59 e = &info->pol[pos];
60
61 if (match_xfrm_state(sp->x[i].xvec, e)) {
62 if (!strict)
63 return 1;
64 } else if (strict)
65 return 0;
66 }
67
68 return strict ? 1 : 0;
69}
70
71static int
72match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
73{
74 const struct ipt_policy_elem *e;
75 struct dst_entry *dst = skb->dst;
76 int strict = info->flags & IPT_POLICY_MATCH_STRICT;
77 int i, pos;
78
79 if (dst->xfrm == NULL)
80 return -1;
81
82 for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
83 pos = strict ? i : 0;
84 if (pos >= info->len)
85 return 0;
86 e = &info->pol[pos];
87
88 if (match_xfrm_state(dst->xfrm, e)) {
89 if (!strict)
90 return 1;
91 } else if (strict)
92 return 0;
93 }
94
95 return strict ? i == info->len : 0;
96}
97
98static int match(const struct sk_buff *skb,
99 const struct net_device *in,
100 const struct net_device *out,
101 const void *matchinfo,
102 int offset,
103 unsigned int protoff,
104 int *hotdrop)
105{
106 const struct ipt_policy_info *info = matchinfo;
107 int ret;
108
109 if (info->flags & IPT_POLICY_MATCH_IN)
110 ret = match_policy_in(skb, info);
111 else
112 ret = match_policy_out(skb, info);
113
114 if (ret < 0)
115 ret = info->flags & IPT_POLICY_MATCH_NONE ? 1 : 0;
116 else if (info->flags & IPT_POLICY_MATCH_NONE)
117 ret = 0;
118
119 return ret;
120}
121
122static int checkentry(const char *tablename, const void *ip_void,
123 void *matchinfo, unsigned int matchsize,
124 unsigned int hook_mask)
125{
126 struct ipt_policy_info *info = matchinfo;
127
128 if (matchsize != IPT_ALIGN(sizeof(*info))) {
129 printk(KERN_ERR "ipt_policy: matchsize %u != %zu\n",
130 matchsize, IPT_ALIGN(sizeof(*info)));
131 return 0;
132 }
133 if (!(info->flags & (IPT_POLICY_MATCH_IN|IPT_POLICY_MATCH_OUT))) {
134 printk(KERN_ERR "ipt_policy: neither incoming nor "
135 "outgoing policy selected\n");
136 return 0;
137 }
138 if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
139 && info->flags & IPT_POLICY_MATCH_OUT) {
140 printk(KERN_ERR "ipt_policy: output policy not valid in "
141 "PRE_ROUTING and INPUT\n");
142 return 0;
143 }
144 if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
145 && info->flags & IPT_POLICY_MATCH_IN) {
146 printk(KERN_ERR "ipt_policy: input policy not valid in "
147 "POST_ROUTING and OUTPUT\n");
148 return 0;
149 }
150 if (info->len > IPT_POLICY_MAX_ELEM) {
151 printk(KERN_ERR "ipt_policy: too many policy elements\n");
152 return 0;
153 }
154
155 return 1;
156}
157
158static struct ipt_match policy_match = {
159 .name = "policy",
160 .match = match,
161 .checkentry = checkentry,
162 .me = THIS_MODULE,
163};
164
165static int __init init(void)
166{
167 return ipt_register_match(&policy_match);
168}
169
170static void __exit fini(void)
171{
172 ipt_unregister_match(&policy_match);
173}
174
175module_init(init);
176module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 44611d6d14f5..06792ead1da4 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -102,6 +102,7 @@ static int
102match(const struct sk_buff *skb, 102match(const struct sk_buff *skb,
103 const struct net_device *in, 103 const struct net_device *in,
104 const struct net_device *out, 104 const struct net_device *out,
105 const struct xt_match *match,
105 const void *matchinfo, 106 const void *matchinfo,
106 int offset, 107 int offset,
107 unsigned int protoff, 108 unsigned int protoff,
@@ -318,7 +319,7 @@ static int ip_recent_ctrl(struct file *file, const char __user *input, unsigned
318 skb->nh.iph->daddr = 0; 319 skb->nh.iph->daddr = 0;
319 /* Clear ttl since we have no way of knowing it */ 320 /* Clear ttl since we have no way of knowing it */
320 skb->nh.iph->ttl = 0; 321 skb->nh.iph->ttl = 0;
321 match(skb,NULL,NULL,info,0,0,NULL); 322 match(skb,NULL,NULL,NULL,info,0,0,NULL);
322 323
323 kfree(skb->nh.iph); 324 kfree(skb->nh.iph);
324out_free_skb: 325out_free_skb:
@@ -356,6 +357,7 @@ static int
356match(const struct sk_buff *skb, 357match(const struct sk_buff *skb,
357 const struct net_device *in, 358 const struct net_device *in,
358 const struct net_device *out, 359 const struct net_device *out,
360 const struct xt_match *match,
359 const void *matchinfo, 361 const void *matchinfo,
360 int offset, 362 int offset,
361 unsigned int protoff, 363 unsigned int protoff,
@@ -657,6 +659,7 @@ match(const struct sk_buff *skb,
657static int 659static int
658checkentry(const char *tablename, 660checkentry(const char *tablename,
659 const void *ip, 661 const void *ip,
662 const struct xt_match *match,
660 void *matchinfo, 663 void *matchinfo,
661 unsigned int matchsize, 664 unsigned int matchsize,
662 unsigned int hook_mask) 665 unsigned int hook_mask)
@@ -670,8 +673,6 @@ checkentry(const char *tablename,
670 if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() entered.\n"); 673 if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() entered.\n");
671#endif 674#endif
672 675
673 if (matchsize != IPT_ALIGN(sizeof(struct ipt_recent_info))) return 0;
674
675 /* seconds and hit_count only valid for CHECK/UPDATE */ 676 /* seconds and hit_count only valid for CHECK/UPDATE */
676 if(info->check_set & IPT_RECENT_SET) { flag++; if(info->seconds || info->hit_count) return 0; } 677 if(info->check_set & IPT_RECENT_SET) { flag++; if(info->seconds || info->hit_count) return 0; }
677 if(info->check_set & IPT_RECENT_REMOVE) { flag++; if(info->seconds || info->hit_count) return 0; } 678 if(info->check_set & IPT_RECENT_REMOVE) { flag++; if(info->seconds || info->hit_count) return 0; }
@@ -871,7 +872,7 @@ checkentry(const char *tablename,
871 * up its memory. 872 * up its memory.
872 */ 873 */
873static void 874static void
874destroy(void *matchinfo, unsigned int matchsize) 875destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
875{ 876{
876 const struct ipt_recent_info *info = matchinfo; 877 const struct ipt_recent_info *info = matchinfo;
877 struct recent_ip_tables *curr_table, *last_table; 878 struct recent_ip_tables *curr_table, *last_table;
@@ -951,12 +952,13 @@ destroy(void *matchinfo, unsigned int matchsize)
951/* This is the structure we pass to ipt_register to register our 952/* This is the structure we pass to ipt_register to register our
952 * module with iptables. 953 * module with iptables.
953 */ 954 */
954static struct ipt_match recent_match = { 955static struct ipt_match recent_match = {
955 .name = "recent", 956 .name = "recent",
956 .match = &match, 957 .match = match,
957 .checkentry = &checkentry, 958 .matchsize = sizeof(struct ipt_recent_info),
958 .destroy = &destroy, 959 .checkentry = checkentry,
959 .me = THIS_MODULE 960 .destroy = destroy,
961 .me = THIS_MODULE
960}; 962};
961 963
962/* Kernel module initialization. */ 964/* Kernel module initialization. */
diff --git a/net/ipv4/netfilter/ipt_tos.c b/net/ipv4/netfilter/ipt_tos.c
index 9ab765e126f2..e404e92ddd01 100644
--- a/net/ipv4/netfilter/ipt_tos.c
+++ b/net/ipv4/netfilter/ipt_tos.c
@@ -21,6 +21,7 @@ static int
21match(const struct sk_buff *skb, 21match(const struct sk_buff *skb,
22 const struct net_device *in, 22 const struct net_device *in,
23 const struct net_device *out, 23 const struct net_device *out,
24 const struct xt_match *match,
24 const void *matchinfo, 25 const void *matchinfo,
25 int offset, 26 int offset,
26 unsigned int protoff, 27 unsigned int protoff,
@@ -31,23 +32,10 @@ match(const struct sk_buff *skb,
31 return (skb->nh.iph->tos == info->tos) ^ info->invert; 32 return (skb->nh.iph->tos == info->tos) ^ info->invert;
32} 33}
33 34
34static int
35checkentry(const char *tablename,
36 const void *ip,
37 void *matchinfo,
38 unsigned int matchsize,
39 unsigned int hook_mask)
40{
41 if (matchsize != IPT_ALIGN(sizeof(struct ipt_tos_info)))
42 return 0;
43
44 return 1;
45}
46
47static struct ipt_match tos_match = { 35static struct ipt_match tos_match = {
48 .name = "tos", 36 .name = "tos",
49 .match = &match, 37 .match = match,
50 .checkentry = &checkentry, 38 .matchsize = sizeof(struct ipt_tos_info),
51 .me = THIS_MODULE, 39 .me = THIS_MODULE,
52}; 40};
53 41
diff --git a/net/ipv4/netfilter/ipt_ttl.c b/net/ipv4/netfilter/ipt_ttl.c
index 82da53f430ab..ae7ce4d8d90e 100644
--- a/net/ipv4/netfilter/ipt_ttl.c
+++ b/net/ipv4/netfilter/ipt_ttl.c
@@ -19,8 +19,9 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
19MODULE_DESCRIPTION("IP tables TTL matching module"); 19MODULE_DESCRIPTION("IP tables TTL matching module");
20MODULE_LICENSE("GPL"); 20MODULE_LICENSE("GPL");
21 21
22static int match(const struct sk_buff *skb, const struct net_device *in, 22static int match(const struct sk_buff *skb,
23 const struct net_device *out, const void *matchinfo, 23 const struct net_device *in, const struct net_device *out,
24 const struct xt_match *match, const void *matchinfo,
24 int offset, unsigned int protoff, int *hotdrop) 25 int offset, unsigned int protoff, int *hotdrop)
25{ 26{
26 const struct ipt_ttl_info *info = matchinfo; 27 const struct ipt_ttl_info *info = matchinfo;
@@ -47,20 +48,10 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
47 return 0; 48 return 0;
48} 49}
49 50
50static int checkentry(const char *tablename, const void *ip,
51 void *matchinfo, unsigned int matchsize,
52 unsigned int hook_mask)
53{
54 if (matchsize != IPT_ALIGN(sizeof(struct ipt_ttl_info)))
55 return 0;
56
57 return 1;
58}
59
60static struct ipt_match ttl_match = { 51static struct ipt_match ttl_match = {
61 .name = "ttl", 52 .name = "ttl",
62 .match = &match, 53 .match = match,
63 .checkentry = &checkentry, 54 .matchsize = sizeof(struct ipt_ttl_info),
64 .me = THIS_MODULE, 55 .me = THIS_MODULE,
65}; 56};
66 57
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 6c8624a54933..c8abc9d859b9 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -141,19 +141,21 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum,
141{ 141{
142 struct nf_conn *ct; 142 struct nf_conn *ct;
143 enum ip_conntrack_info ctinfo; 143 enum ip_conntrack_info ctinfo;
144 struct nf_conn_help *help;
144 145
145 /* This is where we call the helper: as the packet goes out. */ 146 /* This is where we call the helper: as the packet goes out. */
146 ct = nf_ct_get(*pskb, &ctinfo); 147 ct = nf_ct_get(*pskb, &ctinfo);
147 if (ct && ct->helper) { 148 if (!ct)
148 unsigned int ret; 149 return NF_ACCEPT;
149 ret = ct->helper->help(pskb, 150
150 (*pskb)->nh.raw - (*pskb)->data 151 help = nfct_help(ct);
151 + (*pskb)->nh.iph->ihl*4, 152 if (!help || !help->helper)
152 ct, ctinfo); 153 return NF_ACCEPT;
153 if (ret != NF_ACCEPT) 154
154 return ret; 155 return help->helper->help(pskb,
155 } 156 (*pskb)->nh.raw - (*pskb)->data
156 return NF_ACCEPT; 157 + (*pskb)->nh.iph->ihl*4,
158 ct, ctinfo);
157} 159}
158 160
159static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, 161static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
@@ -566,6 +568,7 @@ static int init_or_cleanup(int init)
566 return ret; 568 return ret;
567} 569}
568 570
571MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
569MODULE_LICENSE("GPL"); 572MODULE_LICENSE("GPL");
570 573
571static int __init init(void) 574static int __init init(void)
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index f29a12da5109..fc2562415555 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -660,12 +660,9 @@ static int raw_geticmpfilter(struct sock *sk, char __user *optval, int __user *o
660out: return ret; 660out: return ret;
661} 661}
662 662
663static int raw_setsockopt(struct sock *sk, int level, int optname, 663static int do_raw_setsockopt(struct sock *sk, int level, int optname,
664 char __user *optval, int optlen) 664 char __user *optval, int optlen)
665{ 665{
666 if (level != SOL_RAW)
667 return ip_setsockopt(sk, level, optname, optval, optlen);
668
669 if (optname == ICMP_FILTER) { 666 if (optname == ICMP_FILTER) {
670 if (inet_sk(sk)->num != IPPROTO_ICMP) 667 if (inet_sk(sk)->num != IPPROTO_ICMP)
671 return -EOPNOTSUPP; 668 return -EOPNOTSUPP;
@@ -675,12 +672,27 @@ static int raw_setsockopt(struct sock *sk, int level, int optname,
675 return -ENOPROTOOPT; 672 return -ENOPROTOOPT;
676} 673}
677 674
678static int raw_getsockopt(struct sock *sk, int level, int optname, 675static int raw_setsockopt(struct sock *sk, int level, int optname,
679 char __user *optval, int __user *optlen) 676 char __user *optval, int optlen)
680{ 677{
681 if (level != SOL_RAW) 678 if (level != SOL_RAW)
682 return ip_getsockopt(sk, level, optname, optval, optlen); 679 return ip_setsockopt(sk, level, optname, optval, optlen);
680 return do_raw_setsockopt(sk, level, optname, optval, optlen);
681}
683 682
683#ifdef CONFIG_COMPAT
684static int compat_raw_setsockopt(struct sock *sk, int level, int optname,
685 char __user *optval, int optlen)
686{
687 if (level != SOL_RAW)
688 return compat_ip_setsockopt(sk, level, optname, optval, optlen);
689 return do_raw_setsockopt(sk, level, optname, optval, optlen);
690}
691#endif
692
693static int do_raw_getsockopt(struct sock *sk, int level, int optname,
694 char __user *optval, int __user *optlen)
695{
684 if (optname == ICMP_FILTER) { 696 if (optname == ICMP_FILTER) {
685 if (inet_sk(sk)->num != IPPROTO_ICMP) 697 if (inet_sk(sk)->num != IPPROTO_ICMP)
686 return -EOPNOTSUPP; 698 return -EOPNOTSUPP;
@@ -690,6 +702,24 @@ static int raw_getsockopt(struct sock *sk, int level, int optname,
690 return -ENOPROTOOPT; 702 return -ENOPROTOOPT;
691} 703}
692 704
705static int raw_getsockopt(struct sock *sk, int level, int optname,
706 char __user *optval, int __user *optlen)
707{
708 if (level != SOL_RAW)
709 return ip_getsockopt(sk, level, optname, optval, optlen);
710 return do_raw_getsockopt(sk, level, optname, optval, optlen);
711}
712
713#ifdef CONFIG_COMPAT
714static int compat_raw_getsockopt(struct sock *sk, int level, int optname,
715 char __user *optval, int __user *optlen)
716{
717 if (level != SOL_RAW)
718 return compat_ip_getsockopt(sk, level, optname, optval, optlen);
719 return do_raw_getsockopt(sk, level, optname, optval, optlen);
720}
721#endif
722
693static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg) 723static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
694{ 724{
695 switch (cmd) { 725 switch (cmd) {
@@ -719,22 +749,26 @@ static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
719} 749}
720 750
721struct proto raw_prot = { 751struct proto raw_prot = {
722 .name = "RAW", 752 .name = "RAW",
723 .owner = THIS_MODULE, 753 .owner = THIS_MODULE,
724 .close = raw_close, 754 .close = raw_close,
725 .connect = ip4_datagram_connect, 755 .connect = ip4_datagram_connect,
726 .disconnect = udp_disconnect, 756 .disconnect = udp_disconnect,
727 .ioctl = raw_ioctl, 757 .ioctl = raw_ioctl,
728 .init = raw_init, 758 .init = raw_init,
729 .setsockopt = raw_setsockopt, 759 .setsockopt = raw_setsockopt,
730 .getsockopt = raw_getsockopt, 760 .getsockopt = raw_getsockopt,
731 .sendmsg = raw_sendmsg, 761 .sendmsg = raw_sendmsg,
732 .recvmsg = raw_recvmsg, 762 .recvmsg = raw_recvmsg,
733 .bind = raw_bind, 763 .bind = raw_bind,
734 .backlog_rcv = raw_rcv_skb, 764 .backlog_rcv = raw_rcv_skb,
735 .hash = raw_v4_hash, 765 .hash = raw_v4_hash,
736 .unhash = raw_v4_unhash, 766 .unhash = raw_v4_unhash,
737 .obj_size = sizeof(struct raw_sock), 767 .obj_size = sizeof(struct raw_sock),
768#ifdef CONFIG_COMPAT
769 .compat_setsockopt = compat_raw_setsockopt,
770 .compat_getsockopt = compat_raw_getsockopt,
771#endif
738}; 772};
739 773
740#ifdef CONFIG_PROC_FS 774#ifdef CONFIG_PROC_FS
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 16984d4a8a06..6b6c3adfcf00 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -664,7 +664,30 @@ ctl_table ipv4_table[] = {
664 .mode = 0644, 664 .mode = 0644,
665 .proc_handler = &proc_dointvec, 665 .proc_handler = &proc_dointvec,
666 }, 666 },
667 667 {
668 .ctl_name = NET_TCP_MTU_PROBING,
669 .procname = "tcp_mtu_probing",
670 .data = &sysctl_tcp_mtu_probing,
671 .maxlen = sizeof(int),
672 .mode = 0644,
673 .proc_handler = &proc_dointvec,
674 },
675 {
676 .ctl_name = NET_TCP_BASE_MSS,
677 .procname = "tcp_base_mss",
678 .data = &sysctl_tcp_base_mss,
679 .maxlen = sizeof(int),
680 .mode = 0644,
681 .proc_handler = &proc_dointvec,
682 },
683 {
684 .ctl_name = NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS,
685 .procname = "tcp_workaround_signed_windows",
686 .data = &sysctl_tcp_workaround_signed_windows,
687 .maxlen = sizeof(int),
688 .mode = 0644,
689 .proc_handler = &proc_dointvec
690 },
668 { .ctl_name = 0 } 691 { .ctl_name = 0 }
669}; 692};
670 693
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 00aa80e93243..4b0272c92d66 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1687,18 +1687,14 @@ int tcp_disconnect(struct sock *sk, int flags)
1687/* 1687/*
1688 * Socket option code for TCP. 1688 * Socket option code for TCP.
1689 */ 1689 */
1690int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, 1690static int do_tcp_setsockopt(struct sock *sk, int level,
1691 int optlen) 1691 int optname, char __user *optval, int optlen)
1692{ 1692{
1693 struct tcp_sock *tp = tcp_sk(sk); 1693 struct tcp_sock *tp = tcp_sk(sk);
1694 struct inet_connection_sock *icsk = inet_csk(sk); 1694 struct inet_connection_sock *icsk = inet_csk(sk);
1695 int val; 1695 int val;
1696 int err = 0; 1696 int err = 0;
1697 1697
1698 if (level != SOL_TCP)
1699 return icsk->icsk_af_ops->setsockopt(sk, level, optname,
1700 optval, optlen);
1701
1702 /* This is a string value all the others are int's */ 1698 /* This is a string value all the others are int's */
1703 if (optname == TCP_CONGESTION) { 1699 if (optname == TCP_CONGESTION) {
1704 char name[TCP_CA_NAME_MAX]; 1700 char name[TCP_CA_NAME_MAX];
@@ -1871,6 +1867,30 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
1871 return err; 1867 return err;
1872} 1868}
1873 1869
1870int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
1871 int optlen)
1872{
1873 struct inet_connection_sock *icsk = inet_csk(sk);
1874
1875 if (level != SOL_TCP)
1876 return icsk->icsk_af_ops->setsockopt(sk, level, optname,
1877 optval, optlen);
1878 return do_tcp_setsockopt(sk, level, optname, optval, optlen);
1879}
1880
1881#ifdef CONFIG_COMPAT
1882int compat_tcp_setsockopt(struct sock *sk, int level, int optname,
1883 char __user *optval, int optlen)
1884{
1885 if (level != SOL_TCP)
1886 return inet_csk_compat_setsockopt(sk, level, optname,
1887 optval, optlen);
1888 return do_tcp_setsockopt(sk, level, optname, optval, optlen);
1889}
1890
1891EXPORT_SYMBOL(compat_tcp_setsockopt);
1892#endif
1893
1874/* Return information about state of tcp endpoint in API format. */ 1894/* Return information about state of tcp endpoint in API format. */
1875void tcp_get_info(struct sock *sk, struct tcp_info *info) 1895void tcp_get_info(struct sock *sk, struct tcp_info *info)
1876{ 1896{
@@ -1931,17 +1951,13 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
1931 1951
1932EXPORT_SYMBOL_GPL(tcp_get_info); 1952EXPORT_SYMBOL_GPL(tcp_get_info);
1933 1953
1934int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, 1954static int do_tcp_getsockopt(struct sock *sk, int level,
1935 int __user *optlen) 1955 int optname, char __user *optval, int __user *optlen)
1936{ 1956{
1937 struct inet_connection_sock *icsk = inet_csk(sk); 1957 struct inet_connection_sock *icsk = inet_csk(sk);
1938 struct tcp_sock *tp = tcp_sk(sk); 1958 struct tcp_sock *tp = tcp_sk(sk);
1939 int val, len; 1959 int val, len;
1940 1960
1941 if (level != SOL_TCP)
1942 return icsk->icsk_af_ops->getsockopt(sk, level, optname,
1943 optval, optlen);
1944
1945 if (get_user(len, optlen)) 1961 if (get_user(len, optlen))
1946 return -EFAULT; 1962 return -EFAULT;
1947 1963
@@ -2025,6 +2041,29 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
2025 return 0; 2041 return 0;
2026} 2042}
2027 2043
2044int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
2045 int __user *optlen)
2046{
2047 struct inet_connection_sock *icsk = inet_csk(sk);
2048
2049 if (level != SOL_TCP)
2050 return icsk->icsk_af_ops->getsockopt(sk, level, optname,
2051 optval, optlen);
2052 return do_tcp_getsockopt(sk, level, optname, optval, optlen);
2053}
2054
2055#ifdef CONFIG_COMPAT
2056int compat_tcp_getsockopt(struct sock *sk, int level, int optname,
2057 char __user *optval, int __user *optlen)
2058{
2059 if (level != SOL_TCP)
2060 return inet_csk_compat_getsockopt(sk, level, optname,
2061 optval, optlen);
2062 return do_tcp_getsockopt(sk, level, optname, optval, optlen);
2063}
2064
2065EXPORT_SYMBOL(compat_tcp_getsockopt);
2066#endif
2028 2067
2029extern void __skb_cb_too_small_for_tcp(int, int); 2068extern void __skb_cb_too_small_for_tcp(int, int);
2030extern struct tcp_congestion_ops tcp_reno; 2069extern struct tcp_congestion_ops tcp_reno;
diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c
index 128de4d7c0b7..1b2ff53f98ed 100644
--- a/net/ipv4/tcp_htcp.c
+++ b/net/ipv4/tcp_htcp.c
@@ -27,12 +27,12 @@ struct htcp {
27 u16 alpha; /* Fixed point arith, << 7 */ 27 u16 alpha; /* Fixed point arith, << 7 */
28 u8 beta; /* Fixed point arith, << 7 */ 28 u8 beta; /* Fixed point arith, << 7 */
29 u8 modeswitch; /* Delay modeswitch until we had at least one congestion event */ 29 u8 modeswitch; /* Delay modeswitch until we had at least one congestion event */
30 u8 ccount; /* Number of RTTs since last congestion event */ 30 u32 last_cong; /* Time since last congestion event end */
31 u8 undo_ccount; 31 u32 undo_last_cong;
32 u16 packetcount; 32 u16 pkts_acked;
33 u32 packetcount;
33 u32 minRTT; 34 u32 minRTT;
34 u32 maxRTT; 35 u32 maxRTT;
35 u32 snd_cwnd_cnt2;
36 36
37 u32 undo_maxRTT; 37 u32 undo_maxRTT;
38 u32 undo_old_maxB; 38 u32 undo_old_maxB;
@@ -45,21 +45,30 @@ struct htcp {
45 u32 lasttime; 45 u32 lasttime;
46}; 46};
47 47
48static inline u32 htcp_cong_time(struct htcp *ca)
49{
50 return jiffies - ca->last_cong;
51}
52
53static inline u32 htcp_ccount(struct htcp *ca)
54{
55 return htcp_cong_time(ca)/ca->minRTT;
56}
57
48static inline void htcp_reset(struct htcp *ca) 58static inline void htcp_reset(struct htcp *ca)
49{ 59{
50 ca->undo_ccount = ca->ccount; 60 ca->undo_last_cong = ca->last_cong;
51 ca->undo_maxRTT = ca->maxRTT; 61 ca->undo_maxRTT = ca->maxRTT;
52 ca->undo_old_maxB = ca->old_maxB; 62 ca->undo_old_maxB = ca->old_maxB;
53 63
54 ca->ccount = 0; 64 ca->last_cong = jiffies;
55 ca->snd_cwnd_cnt2 = 0;
56} 65}
57 66
58static u32 htcp_cwnd_undo(struct sock *sk) 67static u32 htcp_cwnd_undo(struct sock *sk)
59{ 68{
60 const struct tcp_sock *tp = tcp_sk(sk); 69 const struct tcp_sock *tp = tcp_sk(sk);
61 struct htcp *ca = inet_csk_ca(sk); 70 struct htcp *ca = inet_csk_ca(sk);
62 ca->ccount = ca->undo_ccount; 71 ca->last_cong = ca->undo_last_cong;
63 ca->maxRTT = ca->undo_maxRTT; 72 ca->maxRTT = ca->undo_maxRTT;
64 ca->old_maxB = ca->undo_old_maxB; 73 ca->old_maxB = ca->undo_old_maxB;
65 return max(tp->snd_cwnd, (tp->snd_ssthresh<<7)/ca->beta); 74 return max(tp->snd_cwnd, (tp->snd_ssthresh<<7)/ca->beta);
@@ -77,10 +86,10 @@ static inline void measure_rtt(struct sock *sk)
77 ca->minRTT = srtt; 86 ca->minRTT = srtt;
78 87
79 /* max RTT */ 88 /* max RTT */
80 if (icsk->icsk_ca_state == TCP_CA_Open && tp->snd_ssthresh < 0xFFFF && ca->ccount > 3) { 89 if (icsk->icsk_ca_state == TCP_CA_Open && tp->snd_ssthresh < 0xFFFF && htcp_ccount(ca) > 3) {
81 if (ca->maxRTT < ca->minRTT) 90 if (ca->maxRTT < ca->minRTT)
82 ca->maxRTT = ca->minRTT; 91 ca->maxRTT = ca->minRTT;
83 if (ca->maxRTT < srtt && srtt <= ca->maxRTT+HZ/50) 92 if (ca->maxRTT < srtt && srtt <= ca->maxRTT+msecs_to_jiffies(20))
84 ca->maxRTT = srtt; 93 ca->maxRTT = srtt;
85 } 94 }
86} 95}
@@ -92,6 +101,12 @@ static void measure_achieved_throughput(struct sock *sk, u32 pkts_acked)
92 struct htcp *ca = inet_csk_ca(sk); 101 struct htcp *ca = inet_csk_ca(sk);
93 u32 now = tcp_time_stamp; 102 u32 now = tcp_time_stamp;
94 103
104 if (icsk->icsk_ca_state == TCP_CA_Open)
105 ca->pkts_acked = pkts_acked;
106
107 if (!use_bandwidth_switch)
108 return;
109
95 /* achieved throughput calculations */ 110 /* achieved throughput calculations */
96 if (icsk->icsk_ca_state != TCP_CA_Open && 111 if (icsk->icsk_ca_state != TCP_CA_Open &&
97 icsk->icsk_ca_state != TCP_CA_Disorder) { 112 icsk->icsk_ca_state != TCP_CA_Disorder) {
@@ -106,7 +121,7 @@ static void measure_achieved_throughput(struct sock *sk, u32 pkts_acked)
106 && now - ca->lasttime >= ca->minRTT 121 && now - ca->lasttime >= ca->minRTT
107 && ca->minRTT > 0) { 122 && ca->minRTT > 0) {
108 __u32 cur_Bi = ca->packetcount*HZ/(now - ca->lasttime); 123 __u32 cur_Bi = ca->packetcount*HZ/(now - ca->lasttime);
109 if (ca->ccount <= 3) { 124 if (htcp_ccount(ca) <= 3) {
110 /* just after backoff */ 125 /* just after backoff */
111 ca->minB = ca->maxB = ca->Bi = cur_Bi; 126 ca->minB = ca->maxB = ca->Bi = cur_Bi;
112 } else { 127 } else {
@@ -135,7 +150,7 @@ static inline void htcp_beta_update(struct htcp *ca, u32 minRTT, u32 maxRTT)
135 } 150 }
136 } 151 }
137 152
138 if (ca->modeswitch && minRTT > max(HZ/100, 1) && maxRTT) { 153 if (ca->modeswitch && minRTT > msecs_to_jiffies(10) && maxRTT) {
139 ca->beta = (minRTT<<7)/maxRTT; 154 ca->beta = (minRTT<<7)/maxRTT;
140 if (ca->beta < BETA_MIN) 155 if (ca->beta < BETA_MIN)
141 ca->beta = BETA_MIN; 156 ca->beta = BETA_MIN;
@@ -151,7 +166,7 @@ static inline void htcp_alpha_update(struct htcp *ca)
151{ 166{
152 u32 minRTT = ca->minRTT; 167 u32 minRTT = ca->minRTT;
153 u32 factor = 1; 168 u32 factor = 1;
154 u32 diff = ca->ccount * minRTT; /* time since last backoff */ 169 u32 diff = htcp_cong_time(ca);
155 170
156 if (diff > HZ) { 171 if (diff > HZ) {
157 diff -= HZ; 172 diff -= HZ;
@@ -216,21 +231,18 @@ static void htcp_cong_avoid(struct sock *sk, u32 ack, u32 rtt,
216 231
217 measure_rtt(sk); 232 measure_rtt(sk);
218 233
219 /* keep track of number of round-trip times since last backoff event */
220 if (ca->snd_cwnd_cnt2++ > tp->snd_cwnd) {
221 ca->ccount++;
222 ca->snd_cwnd_cnt2 = 0;
223 htcp_alpha_update(ca);
224 }
225
226 /* In dangerous area, increase slowly. 234 /* In dangerous area, increase slowly.
227 * In theory this is tp->snd_cwnd += alpha / tp->snd_cwnd 235 * In theory this is tp->snd_cwnd += alpha / tp->snd_cwnd
228 */ 236 */
229 if ((tp->snd_cwnd_cnt++ * ca->alpha)>>7 >= tp->snd_cwnd) { 237 if ((tp->snd_cwnd_cnt * ca->alpha)>>7 >= tp->snd_cwnd) {
230 if (tp->snd_cwnd < tp->snd_cwnd_clamp) 238 if (tp->snd_cwnd < tp->snd_cwnd_clamp)
231 tp->snd_cwnd++; 239 tp->snd_cwnd++;
232 tp->snd_cwnd_cnt = 0; 240 tp->snd_cwnd_cnt = 0;
233 } 241 htcp_alpha_update(ca);
242 } else
243 tp->snd_cwnd_cnt += ca->pkts_acked;
244
245 ca->pkts_acked = 1;
234 } 246 }
235} 247}
236 248
@@ -249,11 +261,19 @@ static void htcp_init(struct sock *sk)
249 memset(ca, 0, sizeof(struct htcp)); 261 memset(ca, 0, sizeof(struct htcp));
250 ca->alpha = ALPHA_BASE; 262 ca->alpha = ALPHA_BASE;
251 ca->beta = BETA_MIN; 263 ca->beta = BETA_MIN;
264 ca->pkts_acked = 1;
265 ca->last_cong = jiffies;
252} 266}
253 267
254static void htcp_state(struct sock *sk, u8 new_state) 268static void htcp_state(struct sock *sk, u8 new_state)
255{ 269{
256 switch (new_state) { 270 switch (new_state) {
271 case TCP_CA_Open:
272 {
273 struct htcp *ca = inet_csk_ca(sk);
274 ca->last_cong = jiffies;
275 }
276 break;
257 case TCP_CA_CWR: 277 case TCP_CA_CWR:
258 case TCP_CA_Recovery: 278 case TCP_CA_Recovery:
259 case TCP_CA_Loss: 279 case TCP_CA_Loss:
@@ -278,8 +298,6 @@ static int __init htcp_register(void)
278{ 298{
279 BUG_ON(sizeof(struct htcp) > ICSK_CA_PRIV_SIZE); 299 BUG_ON(sizeof(struct htcp) > ICSK_CA_PRIV_SIZE);
280 BUILD_BUG_ON(BETA_MIN >= BETA_MAX); 300 BUILD_BUG_ON(BETA_MIN >= BETA_MAX);
281 if (!use_bandwidth_switch)
282 htcp.pkts_acked = NULL;
283 return tcp_register_congestion_control(&htcp); 301 return tcp_register_congestion_control(&htcp);
284} 302}
285 303
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index e9a54ae7d690..195d83584558 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1891,6 +1891,34 @@ static void tcp_try_to_open(struct sock *sk, struct tcp_sock *tp, int flag)
1891 } 1891 }
1892} 1892}
1893 1893
1894static void tcp_mtup_probe_failed(struct sock *sk)
1895{
1896 struct inet_connection_sock *icsk = inet_csk(sk);
1897
1898 icsk->icsk_mtup.search_high = icsk->icsk_mtup.probe_size - 1;
1899 icsk->icsk_mtup.probe_size = 0;
1900}
1901
1902static void tcp_mtup_probe_success(struct sock *sk, struct sk_buff *skb)
1903{
1904 struct tcp_sock *tp = tcp_sk(sk);
1905 struct inet_connection_sock *icsk = inet_csk(sk);
1906
1907 /* FIXME: breaks with very large cwnd */
1908 tp->prior_ssthresh = tcp_current_ssthresh(sk);
1909 tp->snd_cwnd = tp->snd_cwnd *
1910 tcp_mss_to_mtu(sk, tp->mss_cache) /
1911 icsk->icsk_mtup.probe_size;
1912 tp->snd_cwnd_cnt = 0;
1913 tp->snd_cwnd_stamp = tcp_time_stamp;
1914 tp->rcv_ssthresh = tcp_current_ssthresh(sk);
1915
1916 icsk->icsk_mtup.search_low = icsk->icsk_mtup.probe_size;
1917 icsk->icsk_mtup.probe_size = 0;
1918 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
1919}
1920
1921
1894/* Process an event, which can update packets-in-flight not trivially. 1922/* Process an event, which can update packets-in-flight not trivially.
1895 * Main goal of this function is to calculate new estimate for left_out, 1923 * Main goal of this function is to calculate new estimate for left_out,
1896 * taking into account both packets sitting in receiver's buffer and 1924 * taking into account both packets sitting in receiver's buffer and
@@ -2023,6 +2051,17 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
2023 return; 2051 return;
2024 } 2052 }
2025 2053
2054 /* MTU probe failure: don't reduce cwnd */
2055 if (icsk->icsk_ca_state < TCP_CA_CWR &&
2056 icsk->icsk_mtup.probe_size &&
2057 tp->snd_una == tp->mtu_probe.probe_seq_start) {
2058 tcp_mtup_probe_failed(sk);
2059 /* Restores the reduction we did in tcp_mtup_probe() */
2060 tp->snd_cwnd++;
2061 tcp_simple_retransmit(sk);
2062 return;
2063 }
2064
2026 /* Otherwise enter Recovery state */ 2065 /* Otherwise enter Recovery state */
2027 2066
2028 if (IsReno(tp)) 2067 if (IsReno(tp))
@@ -2243,6 +2282,13 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
2243 tp->retrans_stamp = 0; 2282 tp->retrans_stamp = 0;
2244 } 2283 }
2245 2284
2285 /* MTU probing checks */
2286 if (icsk->icsk_mtup.probe_size) {
2287 if (!after(tp->mtu_probe.probe_seq_end, TCP_SKB_CB(skb)->end_seq)) {
2288 tcp_mtup_probe_success(sk, skb);
2289 }
2290 }
2291
2246 if (sacked) { 2292 if (sacked) {
2247 if (sacked & TCPCB_RETRANS) { 2293 if (sacked & TCPCB_RETRANS) {
2248 if(sacked & TCPCB_SACKED_RETRANS) 2294 if(sacked & TCPCB_SACKED_RETRANS)
@@ -4101,6 +4147,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
4101 if (tp->rx_opt.sack_ok && sysctl_tcp_fack) 4147 if (tp->rx_opt.sack_ok && sysctl_tcp_fack)
4102 tp->rx_opt.sack_ok |= 2; 4148 tp->rx_opt.sack_ok |= 2;
4103 4149
4150 tcp_mtup_init(sk);
4104 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); 4151 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
4105 tcp_initialize_rcv_mss(sk); 4152 tcp_initialize_rcv_mss(sk);
4106 4153
@@ -4211,6 +4258,7 @@ discard:
4211 if (tp->ecn_flags&TCP_ECN_OK) 4258 if (tp->ecn_flags&TCP_ECN_OK)
4212 sock_set_flag(sk, SOCK_NO_LARGESEND); 4259 sock_set_flag(sk, SOCK_NO_LARGESEND);
4213 4260
4261 tcp_mtup_init(sk);
4214 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); 4262 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
4215 tcp_initialize_rcv_mss(sk); 4263 tcp_initialize_rcv_mss(sk);
4216 4264
@@ -4399,6 +4447,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
4399 */ 4447 */
4400 tp->lsndtime = tcp_time_stamp; 4448 tp->lsndtime = tcp_time_stamp;
4401 4449
4450 tcp_mtup_init(sk);
4402 tcp_initialize_rcv_mss(sk); 4451 tcp_initialize_rcv_mss(sk);
4403 tcp_init_buffer_space(sk); 4452 tcp_init_buffer_space(sk);
4404 tcp_fast_path_on(tp); 4453 tcp_fast_path_on(tp);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 233bdf259965..9e85c0416109 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -900,6 +900,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
900 inet_csk(newsk)->icsk_ext_hdr_len = newinet->opt->optlen; 900 inet_csk(newsk)->icsk_ext_hdr_len = newinet->opt->optlen;
901 newinet->id = newtp->write_seq ^ jiffies; 901 newinet->id = newtp->write_seq ^ jiffies;
902 902
903 tcp_mtup_init(newsk);
903 tcp_sync_mss(newsk, dst_mtu(dst)); 904 tcp_sync_mss(newsk, dst_mtu(dst));
904 newtp->advmss = dst_metric(dst, RTAX_ADVMSS); 905 newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
905 tcp_initialize_rcv_mss(newsk); 906 tcp_initialize_rcv_mss(newsk);
@@ -1216,17 +1217,21 @@ int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw)
1216} 1217}
1217 1218
1218struct inet_connection_sock_af_ops ipv4_specific = { 1219struct inet_connection_sock_af_ops ipv4_specific = {
1219 .queue_xmit = ip_queue_xmit, 1220 .queue_xmit = ip_queue_xmit,
1220 .send_check = tcp_v4_send_check, 1221 .send_check = tcp_v4_send_check,
1221 .rebuild_header = inet_sk_rebuild_header, 1222 .rebuild_header = inet_sk_rebuild_header,
1222 .conn_request = tcp_v4_conn_request, 1223 .conn_request = tcp_v4_conn_request,
1223 .syn_recv_sock = tcp_v4_syn_recv_sock, 1224 .syn_recv_sock = tcp_v4_syn_recv_sock,
1224 .remember_stamp = tcp_v4_remember_stamp, 1225 .remember_stamp = tcp_v4_remember_stamp,
1225 .net_header_len = sizeof(struct iphdr), 1226 .net_header_len = sizeof(struct iphdr),
1226 .setsockopt = ip_setsockopt, 1227 .setsockopt = ip_setsockopt,
1227 .getsockopt = ip_getsockopt, 1228 .getsockopt = ip_getsockopt,
1228 .addr2sockaddr = inet_csk_addr2sockaddr, 1229 .addr2sockaddr = inet_csk_addr2sockaddr,
1229 .sockaddr_len = sizeof(struct sockaddr_in), 1230 .sockaddr_len = sizeof(struct sockaddr_in),
1231#ifdef CONFIG_COMPAT
1232 .compat_setsockopt = compat_ip_setsockopt,
1233 .compat_getsockopt = compat_ip_getsockopt,
1234#endif
1230}; 1235};
1231 1236
1232/* NOTE: A lot of things set to zero explicitly by call to 1237/* NOTE: A lot of things set to zero explicitly by call to
@@ -1825,23 +1830,16 @@ struct proto tcp_prot = {
1825 .obj_size = sizeof(struct tcp_sock), 1830 .obj_size = sizeof(struct tcp_sock),
1826 .twsk_prot = &tcp_timewait_sock_ops, 1831 .twsk_prot = &tcp_timewait_sock_ops,
1827 .rsk_prot = &tcp_request_sock_ops, 1832 .rsk_prot = &tcp_request_sock_ops,
1833#ifdef CONFIG_COMPAT
1834 .compat_setsockopt = compat_tcp_setsockopt,
1835 .compat_getsockopt = compat_tcp_getsockopt,
1836#endif
1828}; 1837};
1829 1838
1830
1831
1832void __init tcp_v4_init(struct net_proto_family *ops) 1839void __init tcp_v4_init(struct net_proto_family *ops)
1833{ 1840{
1834 int err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_TCP, &tcp_socket); 1841 if (inet_csk_ctl_sock_create(&tcp_socket, PF_INET, SOCK_RAW, IPPROTO_TCP) < 0)
1835 if (err < 0)
1836 panic("Failed to create the TCP control socket.\n"); 1842 panic("Failed to create the TCP control socket.\n");
1837 tcp_socket->sk->sk_allocation = GFP_ATOMIC;
1838 inet_sk(tcp_socket->sk)->uc_ttl = -1;
1839
1840 /* Unhash it so that IP input processing does not even
1841 * see it, we do not wish this socket to see incoming
1842 * packets.
1843 */
1844 tcp_socket->sk->sk_prot->unhash(tcp_socket->sk);
1845} 1843}
1846 1844
1847EXPORT_SYMBOL(ipv4_specific); 1845EXPORT_SYMBOL(ipv4_specific);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 9f498a6c8895..9d79546d384e 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -45,12 +45,23 @@
45/* People can turn this off for buggy TCP's found in printers etc. */ 45/* People can turn this off for buggy TCP's found in printers etc. */
46int sysctl_tcp_retrans_collapse = 1; 46int sysctl_tcp_retrans_collapse = 1;
47 47
48/* People can turn this on to work with those rare, broken TCPs that
49 * interpret the window field as a signed quantity.
50 */
51int sysctl_tcp_workaround_signed_windows = 0;
52
48/* This limits the percentage of the congestion window which we 53/* This limits the percentage of the congestion window which we
49 * will allow a single TSO frame to consume. Building TSO frames 54 * will allow a single TSO frame to consume. Building TSO frames
50 * which are too large can cause TCP streams to be bursty. 55 * which are too large can cause TCP streams to be bursty.
51 */ 56 */
52int sysctl_tcp_tso_win_divisor = 3; 57int sysctl_tcp_tso_win_divisor = 3;
53 58
59int sysctl_tcp_mtu_probing = 0;
60int sysctl_tcp_base_mss = 512;
61
62EXPORT_SYMBOL(sysctl_tcp_mtu_probing);
63EXPORT_SYMBOL(sysctl_tcp_base_mss);
64
54static void update_send_head(struct sock *sk, struct tcp_sock *tp, 65static void update_send_head(struct sock *sk, struct tcp_sock *tp,
55 struct sk_buff *skb) 66 struct sk_buff *skb)
56{ 67{
@@ -171,12 +182,18 @@ void tcp_select_initial_window(int __space, __u32 mss,
171 space = (space / mss) * mss; 182 space = (space / mss) * mss;
172 183
173 /* NOTE: offering an initial window larger than 32767 184 /* NOTE: offering an initial window larger than 32767
174 * will break some buggy TCP stacks. We try to be nice. 185 * will break some buggy TCP stacks. If the admin tells us
175 * If we are not window scaling, then this truncates 186 * it is likely we could be speaking with such a buggy stack
176 * our initial window offering to 32k. There should also 187 * we will truncate our initial window offering to 32K-1
177 * be a sysctl option to stop being nice. 188 * unless the remote has sent us a window scaling option,
189 * which we interpret as a sign the remote TCP is not
190 * misinterpreting the window field as a signed quantity.
178 */ 191 */
179 (*rcv_wnd) = min(space, MAX_TCP_WINDOW); 192 if (sysctl_tcp_workaround_signed_windows)
193 (*rcv_wnd) = min(space, MAX_TCP_WINDOW);
194 else
195 (*rcv_wnd) = space;
196
180 (*rcv_wscale) = 0; 197 (*rcv_wscale) = 0;
181 if (wscale_ok) { 198 if (wscale_ok) {
182 /* Set window scaling on max possible window 199 /* Set window scaling on max possible window
@@ -235,7 +252,7 @@ static u16 tcp_select_window(struct sock *sk)
235 /* Make sure we do not exceed the maximum possible 252 /* Make sure we do not exceed the maximum possible
236 * scaled window. 253 * scaled window.
237 */ 254 */
238 if (!tp->rx_opt.rcv_wscale) 255 if (!tp->rx_opt.rcv_wscale && sysctl_tcp_workaround_signed_windows)
239 new_win = min(new_win, MAX_TCP_WINDOW); 256 new_win = min(new_win, MAX_TCP_WINDOW);
240 else 257 else
241 new_win = min(new_win, (65535U << tp->rx_opt.rcv_wscale)); 258 new_win = min(new_win, (65535U << tp->rx_opt.rcv_wscale));
@@ -681,6 +698,62 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
681 return 0; 698 return 0;
682} 699}
683 700
701/* Not accounting for SACKs here. */
702int tcp_mtu_to_mss(struct sock *sk, int pmtu)
703{
704 struct tcp_sock *tp = tcp_sk(sk);
705 struct inet_connection_sock *icsk = inet_csk(sk);
706 int mss_now;
707
708 /* Calculate base mss without TCP options:
709 It is MMS_S - sizeof(tcphdr) of rfc1122
710 */
711 mss_now = pmtu - icsk->icsk_af_ops->net_header_len - sizeof(struct tcphdr);
712
713 /* Clamp it (mss_clamp does not include tcp options) */
714 if (mss_now > tp->rx_opt.mss_clamp)
715 mss_now = tp->rx_opt.mss_clamp;
716
717 /* Now subtract optional transport overhead */
718 mss_now -= icsk->icsk_ext_hdr_len;
719
720 /* Then reserve room for full set of TCP options and 8 bytes of data */
721 if (mss_now < 48)
722 mss_now = 48;
723
724 /* Now subtract TCP options size, not including SACKs */
725 mss_now -= tp->tcp_header_len - sizeof(struct tcphdr);
726
727 return mss_now;
728}
729
730/* Inverse of above */
731int tcp_mss_to_mtu(struct sock *sk, int mss)
732{
733 struct tcp_sock *tp = tcp_sk(sk);
734 struct inet_connection_sock *icsk = inet_csk(sk);
735 int mtu;
736
737 mtu = mss +
738 tp->tcp_header_len +
739 icsk->icsk_ext_hdr_len +
740 icsk->icsk_af_ops->net_header_len;
741
742 return mtu;
743}
744
745void tcp_mtup_init(struct sock *sk)
746{
747 struct tcp_sock *tp = tcp_sk(sk);
748 struct inet_connection_sock *icsk = inet_csk(sk);
749
750 icsk->icsk_mtup.enabled = sysctl_tcp_mtu_probing > 1;
751 icsk->icsk_mtup.search_high = tp->rx_opt.mss_clamp + sizeof(struct tcphdr) +
752 icsk->icsk_af_ops->net_header_len;
753 icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, sysctl_tcp_base_mss);
754 icsk->icsk_mtup.probe_size = 0;
755}
756
684/* This function synchronize snd mss to current pmtu/exthdr set. 757/* This function synchronize snd mss to current pmtu/exthdr set.
685 758
686 tp->rx_opt.user_mss is mss set by user by TCP_MAXSEG. It does NOT counts 759 tp->rx_opt.user_mss is mss set by user by TCP_MAXSEG. It does NOT counts
@@ -708,25 +781,12 @@ unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu)
708{ 781{
709 struct tcp_sock *tp = tcp_sk(sk); 782 struct tcp_sock *tp = tcp_sk(sk);
710 struct inet_connection_sock *icsk = inet_csk(sk); 783 struct inet_connection_sock *icsk = inet_csk(sk);
711 /* Calculate base mss without TCP options: 784 int mss_now;
712 It is MMS_S - sizeof(tcphdr) of rfc1122
713 */
714 int mss_now = (pmtu - icsk->icsk_af_ops->net_header_len -
715 sizeof(struct tcphdr));
716
717 /* Clamp it (mss_clamp does not include tcp options) */
718 if (mss_now > tp->rx_opt.mss_clamp)
719 mss_now = tp->rx_opt.mss_clamp;
720
721 /* Now subtract optional transport overhead */
722 mss_now -= icsk->icsk_ext_hdr_len;
723 785
724 /* Then reserve room for full set of TCP options and 8 bytes of data */ 786 if (icsk->icsk_mtup.search_high > pmtu)
725 if (mss_now < 48) 787 icsk->icsk_mtup.search_high = pmtu;
726 mss_now = 48;
727 788
728 /* Now subtract TCP options size, not including SACKs */ 789 mss_now = tcp_mtu_to_mss(sk, pmtu);
729 mss_now -= tp->tcp_header_len - sizeof(struct tcphdr);
730 790
731 /* Bound mss with half of window */ 791 /* Bound mss with half of window */
732 if (tp->max_window && mss_now > (tp->max_window>>1)) 792 if (tp->max_window && mss_now > (tp->max_window>>1))
@@ -734,6 +794,8 @@ unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu)
734 794
735 /* And store cached results */ 795 /* And store cached results */
736 icsk->icsk_pmtu_cookie = pmtu; 796 icsk->icsk_pmtu_cookie = pmtu;
797 if (icsk->icsk_mtup.enabled)
798 mss_now = min(mss_now, tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low));
737 tp->mss_cache = mss_now; 799 tp->mss_cache = mss_now;
738 800
739 return mss_now; 801 return mss_now;
@@ -1063,6 +1125,140 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
1063 return 1; 1125 return 1;
1064} 1126}
1065 1127
1128/* Create a new MTU probe if we are ready.
1129 * Returns 0 if we should wait to probe (no cwnd available),
1130 * 1 if a probe was sent,
1131 * -1 otherwise */
1132static int tcp_mtu_probe(struct sock *sk)
1133{
1134 struct tcp_sock *tp = tcp_sk(sk);
1135 struct inet_connection_sock *icsk = inet_csk(sk);
1136 struct sk_buff *skb, *nskb, *next;
1137 int len;
1138 int probe_size;
1139 unsigned int pif;
1140 int copy;
1141 int mss_now;
1142
1143 /* Not currently probing/verifying,
1144 * not in recovery,
1145 * have enough cwnd, and
1146 * not SACKing (the variable headers throw things off) */
1147 if (!icsk->icsk_mtup.enabled ||
1148 icsk->icsk_mtup.probe_size ||
1149 inet_csk(sk)->icsk_ca_state != TCP_CA_Open ||
1150 tp->snd_cwnd < 11 ||
1151 tp->rx_opt.eff_sacks)
1152 return -1;
1153
1154 /* Very simple search strategy: just double the MSS. */
1155 mss_now = tcp_current_mss(sk, 0);
1156 probe_size = 2*tp->mss_cache;
1157 if (probe_size > tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_high)) {
1158 /* TODO: set timer for probe_converge_event */
1159 return -1;
1160 }
1161
1162 /* Have enough data in the send queue to probe? */
1163 len = 0;
1164 if ((skb = sk->sk_send_head) == NULL)
1165 return -1;
1166 while ((len += skb->len) < probe_size && !tcp_skb_is_last(sk, skb))
1167 skb = skb->next;
1168 if (len < probe_size)
1169 return -1;
1170
1171 /* Receive window check. */
1172 if (after(TCP_SKB_CB(skb)->seq + probe_size, tp->snd_una + tp->snd_wnd)) {
1173 if (tp->snd_wnd < probe_size)
1174 return -1;
1175 else
1176 return 0;
1177 }
1178
1179 /* Do we need to wait to drain cwnd? */
1180 pif = tcp_packets_in_flight(tp);
1181 if (pif + 2 > tp->snd_cwnd) {
1182 /* With no packets in flight, don't stall. */
1183 if (pif == 0)
1184 return -1;
1185 else
1186 return 0;
1187 }
1188
1189 /* We're allowed to probe. Build it now. */
1190 if ((nskb = sk_stream_alloc_skb(sk, probe_size, GFP_ATOMIC)) == NULL)
1191 return -1;
1192 sk_charge_skb(sk, nskb);
1193
1194 skb = sk->sk_send_head;
1195 __skb_insert(nskb, skb->prev, skb, &sk->sk_write_queue);
1196 sk->sk_send_head = nskb;
1197
1198 TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(skb)->seq;
1199 TCP_SKB_CB(nskb)->end_seq = TCP_SKB_CB(skb)->seq + probe_size;
1200 TCP_SKB_CB(nskb)->flags = TCPCB_FLAG_ACK;
1201 TCP_SKB_CB(nskb)->sacked = 0;
1202 nskb->csum = 0;
1203 if (skb->ip_summed == CHECKSUM_HW)
1204 nskb->ip_summed = CHECKSUM_HW;
1205
1206 len = 0;
1207 while (len < probe_size) {
1208 next = skb->next;
1209
1210 copy = min_t(int, skb->len, probe_size - len);
1211 if (nskb->ip_summed)
1212 skb_copy_bits(skb, 0, skb_put(nskb, copy), copy);
1213 else
1214 nskb->csum = skb_copy_and_csum_bits(skb, 0,
1215 skb_put(nskb, copy), copy, nskb->csum);
1216
1217 if (skb->len <= copy) {
1218 /* We've eaten all the data from this skb.
1219 * Throw it away. */
1220 TCP_SKB_CB(nskb)->flags |= TCP_SKB_CB(skb)->flags;
1221 __skb_unlink(skb, &sk->sk_write_queue);
1222 sk_stream_free_skb(sk, skb);
1223 } else {
1224 TCP_SKB_CB(nskb)->flags |= TCP_SKB_CB(skb)->flags &
1225 ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH);
1226 if (!skb_shinfo(skb)->nr_frags) {
1227 skb_pull(skb, copy);
1228 if (skb->ip_summed != CHECKSUM_HW)
1229 skb->csum = csum_partial(skb->data, skb->len, 0);
1230 } else {
1231 __pskb_trim_head(skb, copy);
1232 tcp_set_skb_tso_segs(sk, skb, mss_now);
1233 }
1234 TCP_SKB_CB(skb)->seq += copy;
1235 }
1236
1237 len += copy;
1238 skb = next;
1239 }
1240 tcp_init_tso_segs(sk, nskb, nskb->len);
1241
1242 /* We're ready to send. If this fails, the probe will
1243 * be resegmented into mss-sized pieces by tcp_write_xmit(). */
1244 TCP_SKB_CB(nskb)->when = tcp_time_stamp;
1245 if (!tcp_transmit_skb(sk, nskb, 1, GFP_ATOMIC)) {
1246 /* Decrement cwnd here because we are sending
1247 * effectively two packets. */
1248 tp->snd_cwnd--;
1249 update_send_head(sk, tp, nskb);
1250
1251 icsk->icsk_mtup.probe_size = tcp_mss_to_mtu(sk, nskb->len);
1252 tp->mtu_probe.probe_seq_start = TCP_SKB_CB(nskb)->seq;
1253 tp->mtu_probe.probe_seq_end = TCP_SKB_CB(nskb)->end_seq;
1254
1255 return 1;
1256 }
1257
1258 return -1;
1259}
1260
1261
1066/* This routine writes packets to the network. It advances the 1262/* This routine writes packets to the network. It advances the
1067 * send_head. This happens as incoming acks open up the remote 1263 * send_head. This happens as incoming acks open up the remote
1068 * window for us. 1264 * window for us.
@@ -1076,6 +1272,7 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle)
1076 struct sk_buff *skb; 1272 struct sk_buff *skb;
1077 unsigned int tso_segs, sent_pkts; 1273 unsigned int tso_segs, sent_pkts;
1078 int cwnd_quota; 1274 int cwnd_quota;
1275 int result;
1079 1276
1080 /* If we are closed, the bytes will have to remain here. 1277 /* If we are closed, the bytes will have to remain here.
1081 * In time closedown will finish, we empty the write queue and all 1278 * In time closedown will finish, we empty the write queue and all
@@ -1085,6 +1282,14 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle)
1085 return 0; 1282 return 0;
1086 1283
1087 sent_pkts = 0; 1284 sent_pkts = 0;
1285
1286 /* Do MTU probing. */
1287 if ((result = tcp_mtu_probe(sk)) == 0) {
1288 return 0;
1289 } else if (result > 0) {
1290 sent_pkts = 1;
1291 }
1292
1088 while ((skb = sk->sk_send_head)) { 1293 while ((skb = sk->sk_send_head)) {
1089 unsigned int limit; 1294 unsigned int limit;
1090 1295
@@ -1455,9 +1660,15 @@ void tcp_simple_retransmit(struct sock *sk)
1455int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) 1660int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
1456{ 1661{
1457 struct tcp_sock *tp = tcp_sk(sk); 1662 struct tcp_sock *tp = tcp_sk(sk);
1663 struct inet_connection_sock *icsk = inet_csk(sk);
1458 unsigned int cur_mss = tcp_current_mss(sk, 0); 1664 unsigned int cur_mss = tcp_current_mss(sk, 0);
1459 int err; 1665 int err;
1460 1666
1667 /* Inconslusive MTU probe */
1668 if (icsk->icsk_mtup.probe_size) {
1669 icsk->icsk_mtup.probe_size = 0;
1670 }
1671
1461 /* Do not sent more than we queued. 1/4 is reserved for possible 1672 /* Do not sent more than we queued. 1/4 is reserved for possible
1462 * copying overhead: fragmentation, tunneling, mangling etc. 1673 * copying overhead: fragmentation, tunneling, mangling etc.
1463 */ 1674 */
@@ -1883,6 +2094,7 @@ static void tcp_connect_init(struct sock *sk)
1883 if (tp->rx_opt.user_mss) 2094 if (tp->rx_opt.user_mss)
1884 tp->rx_opt.mss_clamp = tp->rx_opt.user_mss; 2095 tp->rx_opt.mss_clamp = tp->rx_opt.user_mss;
1885 tp->max_window = 0; 2096 tp->max_window = 0;
2097 tcp_mtup_init(sk);
1886 tcp_sync_mss(sk, dst_mtu(dst)); 2098 tcp_sync_mss(sk, dst_mtu(dst));
1887 2099
1888 if (!tp->window_clamp) 2100 if (!tp->window_clamp)
@@ -2180,3 +2392,4 @@ EXPORT_SYMBOL(tcp_make_synack);
2180EXPORT_SYMBOL(tcp_simple_retransmit); 2392EXPORT_SYMBOL(tcp_simple_retransmit);
2181EXPORT_SYMBOL(tcp_sync_mss); 2393EXPORT_SYMBOL(tcp_sync_mss);
2182EXPORT_SYMBOL(sysctl_tcp_tso_win_divisor); 2394EXPORT_SYMBOL(sysctl_tcp_tso_win_divisor);
2395EXPORT_SYMBOL(tcp_mtup_init);
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index e1880959614a..7c1bde3cd6cb 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -119,8 +119,10 @@ static int tcp_orphan_retries(struct sock *sk, int alive)
119/* A write timeout has occurred. Process the after effects. */ 119/* A write timeout has occurred. Process the after effects. */
120static int tcp_write_timeout(struct sock *sk) 120static int tcp_write_timeout(struct sock *sk)
121{ 121{
122 const struct inet_connection_sock *icsk = inet_csk(sk); 122 struct inet_connection_sock *icsk = inet_csk(sk);
123 struct tcp_sock *tp = tcp_sk(sk);
123 int retry_until; 124 int retry_until;
125 int mss;
124 126
125 if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { 127 if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {
126 if (icsk->icsk_retransmits) 128 if (icsk->icsk_retransmits)
@@ -128,25 +130,19 @@ static int tcp_write_timeout(struct sock *sk)
128 retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries; 130 retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries;
129 } else { 131 } else {
130 if (icsk->icsk_retransmits >= sysctl_tcp_retries1) { 132 if (icsk->icsk_retransmits >= sysctl_tcp_retries1) {
131 /* NOTE. draft-ietf-tcpimpl-pmtud-01.txt requires pmtu black 133 /* Black hole detection */
132 hole detection. :-( 134 if (sysctl_tcp_mtu_probing) {
133 135 if (!icsk->icsk_mtup.enabled) {
134 It is place to make it. It is not made. I do not want 136 icsk->icsk_mtup.enabled = 1;
135 to make it. It is disgusting. It does not work in any 137 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
136 case. Let me to cite the same draft, which requires for 138 } else {
137 us to implement this: 139 mss = min(sysctl_tcp_base_mss,
138 140 tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low)/2);
139 "The one security concern raised by this memo is that ICMP black holes 141 mss = max(mss, 68 - tp->tcp_header_len);
140 are often caused by over-zealous security administrators who block 142 icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, mss);
141 all ICMP messages. It is vitally important that those who design and 143 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
142 deploy security systems understand the impact of strict filtering on 144 }
143 upper-layer protocols. The safest web site in the world is worthless 145 }
144 if most TCP implementations cannot transfer data from it. It would
145 be far nicer to have all of the black holes fixed rather than fixing
146 all of the TCP implementations."
147
148 Golden words :-).
149 */
150 146
151 dst_negative_advice(&sk->sk_dst_cache); 147 dst_negative_advice(&sk->sk_dst_cache);
152 } 148 }
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 00840474a449..3f93292b0ad8 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1207,16 +1207,13 @@ static int udp_destroy_sock(struct sock *sk)
1207/* 1207/*
1208 * Socket option code for UDP 1208 * Socket option code for UDP
1209 */ 1209 */
1210static int udp_setsockopt(struct sock *sk, int level, int optname, 1210static int do_udp_setsockopt(struct sock *sk, int level, int optname,
1211 char __user *optval, int optlen) 1211 char __user *optval, int optlen)
1212{ 1212{
1213 struct udp_sock *up = udp_sk(sk); 1213 struct udp_sock *up = udp_sk(sk);
1214 int val; 1214 int val;
1215 int err = 0; 1215 int err = 0;
1216 1216
1217 if (level != SOL_UDP)
1218 return ip_setsockopt(sk, level, optname, optval, optlen);
1219
1220 if(optlen<sizeof(int)) 1217 if(optlen<sizeof(int))
1221 return -EINVAL; 1218 return -EINVAL;
1222 1219
@@ -1256,15 +1253,30 @@ static int udp_setsockopt(struct sock *sk, int level, int optname,
1256 return err; 1253 return err;
1257} 1254}
1258 1255
1259static int udp_getsockopt(struct sock *sk, int level, int optname, 1256static int udp_setsockopt(struct sock *sk, int level, int optname,
1257 char __user *optval, int optlen)
1258{
1259 if (level != SOL_UDP)
1260 return ip_setsockopt(sk, level, optname, optval, optlen);
1261 return do_udp_setsockopt(sk, level, optname, optval, optlen);
1262}
1263
1264#ifdef CONFIG_COMPAT
1265static int compat_udp_setsockopt(struct sock *sk, int level, int optname,
1266 char __user *optval, int optlen)
1267{
1268 if (level != SOL_UDP)
1269 return compat_ip_setsockopt(sk, level, optname, optval, optlen);
1270 return do_udp_setsockopt(sk, level, optname, optval, optlen);
1271}
1272#endif
1273
1274static int do_udp_getsockopt(struct sock *sk, int level, int optname,
1260 char __user *optval, int __user *optlen) 1275 char __user *optval, int __user *optlen)
1261{ 1276{
1262 struct udp_sock *up = udp_sk(sk); 1277 struct udp_sock *up = udp_sk(sk);
1263 int val, len; 1278 int val, len;
1264 1279
1265 if (level != SOL_UDP)
1266 return ip_getsockopt(sk, level, optname, optval, optlen);
1267
1268 if(get_user(len,optlen)) 1280 if(get_user(len,optlen))
1269 return -EFAULT; 1281 return -EFAULT;
1270 1282
@@ -1293,6 +1305,23 @@ static int udp_getsockopt(struct sock *sk, int level, int optname,
1293 return 0; 1305 return 0;
1294} 1306}
1295 1307
1308static int udp_getsockopt(struct sock *sk, int level, int optname,
1309 char __user *optval, int __user *optlen)
1310{
1311 if (level != SOL_UDP)
1312 return ip_getsockopt(sk, level, optname, optval, optlen);
1313 return do_udp_getsockopt(sk, level, optname, optval, optlen);
1314}
1315
1316#ifdef CONFIG_COMPAT
1317static int compat_udp_getsockopt(struct sock *sk, int level, int optname,
1318 char __user *optval, int __user *optlen)
1319{
1320 if (level != SOL_UDP)
1321 return compat_ip_getsockopt(sk, level, optname, optval, optlen);
1322 return do_udp_getsockopt(sk, level, optname, optval, optlen);
1323}
1324#endif
1296/** 1325/**
1297 * udp_poll - wait for a UDP event. 1326 * udp_poll - wait for a UDP event.
1298 * @file - file struct 1327 * @file - file struct
@@ -1341,23 +1370,27 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
1341} 1370}
1342 1371
1343struct proto udp_prot = { 1372struct proto udp_prot = {
1344 .name = "UDP", 1373 .name = "UDP",
1345 .owner = THIS_MODULE, 1374 .owner = THIS_MODULE,
1346 .close = udp_close, 1375 .close = udp_close,
1347 .connect = ip4_datagram_connect, 1376 .connect = ip4_datagram_connect,
1348 .disconnect = udp_disconnect, 1377 .disconnect = udp_disconnect,
1349 .ioctl = udp_ioctl, 1378 .ioctl = udp_ioctl,
1350 .destroy = udp_destroy_sock, 1379 .destroy = udp_destroy_sock,
1351 .setsockopt = udp_setsockopt, 1380 .setsockopt = udp_setsockopt,
1352 .getsockopt = udp_getsockopt, 1381 .getsockopt = udp_getsockopt,
1353 .sendmsg = udp_sendmsg, 1382 .sendmsg = udp_sendmsg,
1354 .recvmsg = udp_recvmsg, 1383 .recvmsg = udp_recvmsg,
1355 .sendpage = udp_sendpage, 1384 .sendpage = udp_sendpage,
1356 .backlog_rcv = udp_queue_rcv_skb, 1385 .backlog_rcv = udp_queue_rcv_skb,
1357 .hash = udp_v4_hash, 1386 .hash = udp_v4_hash,
1358 .unhash = udp_v4_unhash, 1387 .unhash = udp_v4_unhash,
1359 .get_port = udp_v4_get_port, 1388 .get_port = udp_v4_get_port,
1360 .obj_size = sizeof(struct udp_sock), 1389 .obj_size = sizeof(struct udp_sock),
1390#ifdef CONFIG_COMPAT
1391 .compat_setsockopt = compat_udp_setsockopt,
1392 .compat_getsockopt = compat_udp_getsockopt,
1393#endif
1361}; 1394};
1362 1395
1363/* ------------------------------------------------------------------------ */ 1396/* ------------------------------------------------------------------------ */
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index afbb0d4cc305..b08d56b117f8 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -5,6 +5,7 @@
5 5
6#include <linux/skbuff.h> 6#include <linux/skbuff.h>
7#include <linux/module.h> 7#include <linux/module.h>
8#include <linux/mutex.h>
8#include <net/xfrm.h> 9#include <net/xfrm.h>
9#include <net/ip.h> 10#include <net/ip.h>
10#include <net/protocol.h> 11#include <net/protocol.h>
@@ -26,19 +27,19 @@ static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, s
26} 27}
27 28
28static struct xfrm_tunnel *ipip_handler; 29static struct xfrm_tunnel *ipip_handler;
29static DECLARE_MUTEX(xfrm4_tunnel_sem); 30static DEFINE_MUTEX(xfrm4_tunnel_mutex);
30 31
31int xfrm4_tunnel_register(struct xfrm_tunnel *handler) 32int xfrm4_tunnel_register(struct xfrm_tunnel *handler)
32{ 33{
33 int ret; 34 int ret;
34 35
35 down(&xfrm4_tunnel_sem); 36 mutex_lock(&xfrm4_tunnel_mutex);
36 ret = 0; 37 ret = 0;
37 if (ipip_handler != NULL) 38 if (ipip_handler != NULL)
38 ret = -EINVAL; 39 ret = -EINVAL;
39 if (!ret) 40 if (!ret)
40 ipip_handler = handler; 41 ipip_handler = handler;
41 up(&xfrm4_tunnel_sem); 42 mutex_unlock(&xfrm4_tunnel_mutex);
42 43
43 return ret; 44 return ret;
44} 45}
@@ -49,13 +50,13 @@ int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)
49{ 50{
50 int ret; 51 int ret;
51 52
52 down(&xfrm4_tunnel_sem); 53 mutex_lock(&xfrm4_tunnel_mutex);
53 ret = 0; 54 ret = 0;
54 if (ipip_handler != handler) 55 if (ipip_handler != handler)
55 ret = -EINVAL; 56 ret = -EINVAL;
56 if (!ret) 57 if (!ret)
57 ipip_handler = NULL; 58 ipip_handler = NULL;
58 up(&xfrm4_tunnel_sem); 59 mutex_unlock(&xfrm4_tunnel_mutex);
59 60
60 synchronize_net(); 61 synchronize_net();
61 62
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index ab7a9124f985..e6f83b6a2b76 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -6,8 +6,6 @@
6config IPV6 6config IPV6
7 tristate "The IPv6 protocol" 7 tristate "The IPv6 protocol"
8 default m 8 default m
9 select CRYPTO if IPV6_PRIVACY
10 select CRYPTO_MD5 if IPV6_PRIVACY
11 ---help--- 9 ---help---
12 This is complemental support for the IP version 6. 10 This is complemental support for the IP version 6.
13 You will still be able to do traditional IPv4 networking as well. 11 You will still be able to do traditional IPv4 networking as well.
@@ -22,7 +20,7 @@ config IPV6
22 module will be called ipv6. 20 module will be called ipv6.
23 21
24config IPV6_PRIVACY 22config IPV6_PRIVACY
25 bool "IPv6: Privacy Extensions (RFC 3041) support" 23 bool "IPv6: Privacy Extensions support"
26 depends on IPV6 24 depends on IPV6
27 ---help--- 25 ---help---
28 Privacy Extensions for Stateless Address Autoconfiguration in IPv6 26 Privacy Extensions for Stateless Address Autoconfiguration in IPv6
@@ -30,6 +28,9 @@ config IPV6_PRIVACY
30 pseudo-random global-scope unicast address(es) will assigned to 28 pseudo-random global-scope unicast address(es) will assigned to
31 your interface(s). 29 your interface(s).
32 30
31 We use our standard pseudo random algorithm to generate randomized
32 interface identifier, instead of one described in RFC 3041.
33
33 By default, kernel do not generate temporary addresses. 34 By default, kernel do not generate temporary addresses.
34 To use temporary addresses, do 35 To use temporary addresses, do
35 36
@@ -37,6 +38,25 @@ config IPV6_PRIVACY
37 38
38 See <file:Documentation/networking/ip-sysctl.txt> for details. 39 See <file:Documentation/networking/ip-sysctl.txt> for details.
39 40
41config IPV6_ROUTER_PREF
42 bool "IPv6: Router Preference (RFC 4191) support"
43 depends on IPV6
44 ---help---
45 Router Preference is an optional extension to the Router
46 Advertisement message to improve the ability of hosts
47 to pick more appropriate router, especially when the hosts
48 is placed in a multi-homed network.
49
50 If unsure, say N.
51
52config IPV6_ROUTE_INFO
53 bool "IPv6: Route Information (RFC 4191) support (EXPERIMENTAL)"
54 depends on IPV6_ROUTER_PREF && EXPERIMENTAL
55 ---help---
56 This is experimental support of Route Information.
57
58 If unsure, say N.
59
40config INET6_AH 60config INET6_AH
41 tristate "IPv6: AH transformation" 61 tristate "IPv6: AH transformation"
42 depends on IPV6 62 depends on IPV6
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 19727d941962..01c62a0d3742 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -78,8 +78,6 @@
78 78
79#ifdef CONFIG_IPV6_PRIVACY 79#ifdef CONFIG_IPV6_PRIVACY
80#include <linux/random.h> 80#include <linux/random.h>
81#include <linux/crypto.h>
82#include <linux/scatterlist.h>
83#endif 81#endif
84 82
85#include <asm/uaccess.h> 83#include <asm/uaccess.h>
@@ -110,8 +108,6 @@ static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpad
110static void ipv6_regen_rndid(unsigned long data); 108static void ipv6_regen_rndid(unsigned long data);
111 109
112static int desync_factor = MAX_DESYNC_FACTOR * HZ; 110static int desync_factor = MAX_DESYNC_FACTOR * HZ;
113static struct crypto_tfm *md5_tfm;
114static DEFINE_SPINLOCK(md5_tfm_lock);
115#endif 111#endif
116 112
117static int ipv6_count_addresses(struct inet6_dev *idev); 113static int ipv6_count_addresses(struct inet6_dev *idev);
@@ -169,6 +165,15 @@ struct ipv6_devconf ipv6_devconf = {
169 .max_desync_factor = MAX_DESYNC_FACTOR, 165 .max_desync_factor = MAX_DESYNC_FACTOR,
170#endif 166#endif
171 .max_addresses = IPV6_MAX_ADDRESSES, 167 .max_addresses = IPV6_MAX_ADDRESSES,
168 .accept_ra_defrtr = 1,
169 .accept_ra_pinfo = 1,
170#ifdef CONFIG_IPV6_ROUTER_PREF
171 .accept_ra_rtr_pref = 1,
172 .rtr_probe_interval = 60 * HZ,
173#ifdef CONFIG_IPV6_ROUTE_INFO
174 .accept_ra_rt_info_max_plen = 0,
175#endif
176#endif
172}; 177};
173 178
174static struct ipv6_devconf ipv6_devconf_dflt = { 179static struct ipv6_devconf ipv6_devconf_dflt = {
@@ -190,6 +195,15 @@ static struct ipv6_devconf ipv6_devconf_dflt = {
190 .max_desync_factor = MAX_DESYNC_FACTOR, 195 .max_desync_factor = MAX_DESYNC_FACTOR,
191#endif 196#endif
192 .max_addresses = IPV6_MAX_ADDRESSES, 197 .max_addresses = IPV6_MAX_ADDRESSES,
198 .accept_ra_defrtr = 1,
199 .accept_ra_pinfo = 1,
200#ifdef CONFIG_IPV6_ROUTER_PREF
201 .accept_ra_rtr_pref = 1,
202 .rtr_probe_interval = 60 * HZ,
203#ifdef CONFIG_IPV6_ROUTE_INFO
204 .accept_ra_rt_info_max_plen = 0,
205#endif
206#endif
193}; 207};
194 208
195/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ 209/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
@@ -327,86 +341,83 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
327 if (dev->mtu < IPV6_MIN_MTU) 341 if (dev->mtu < IPV6_MIN_MTU)
328 return NULL; 342 return NULL;
329 343
330 ndev = kmalloc(sizeof(struct inet6_dev), GFP_KERNEL); 344 ndev = kzalloc(sizeof(struct inet6_dev), GFP_KERNEL);
331 345
332 if (ndev) { 346 if (ndev == NULL)
333 memset(ndev, 0, sizeof(struct inet6_dev)); 347 return NULL;
334 348
335 rwlock_init(&ndev->lock); 349 rwlock_init(&ndev->lock);
336 ndev->dev = dev; 350 ndev->dev = dev;
337 memcpy(&ndev->cnf, &ipv6_devconf_dflt, sizeof(ndev->cnf)); 351 memcpy(&ndev->cnf, &ipv6_devconf_dflt, sizeof(ndev->cnf));
338 ndev->cnf.mtu6 = dev->mtu; 352 ndev->cnf.mtu6 = dev->mtu;
339 ndev->cnf.sysctl = NULL; 353 ndev->cnf.sysctl = NULL;
340 ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl); 354 ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl);
341 if (ndev->nd_parms == NULL) { 355 if (ndev->nd_parms == NULL) {
342 kfree(ndev); 356 kfree(ndev);
343 return NULL; 357 return NULL;
344 } 358 }
345 /* We refer to the device */ 359 /* We refer to the device */
346 dev_hold(dev); 360 dev_hold(dev);
347
348 if (snmp6_alloc_dev(ndev) < 0) {
349 ADBG((KERN_WARNING
350 "%s(): cannot allocate memory for statistics; dev=%s.\n",
351 __FUNCTION__, dev->name));
352 neigh_parms_release(&nd_tbl, ndev->nd_parms);
353 ndev->dead = 1;
354 in6_dev_finish_destroy(ndev);
355 return NULL;
356 }
357 361
358 if (snmp6_register_dev(ndev) < 0) { 362 if (snmp6_alloc_dev(ndev) < 0) {
359 ADBG((KERN_WARNING 363 ADBG((KERN_WARNING
360 "%s(): cannot create /proc/net/dev_snmp6/%s\n", 364 "%s(): cannot allocate memory for statistics; dev=%s.\n",
361 __FUNCTION__, dev->name)); 365 __FUNCTION__, dev->name));
362 neigh_parms_release(&nd_tbl, ndev->nd_parms); 366 neigh_parms_release(&nd_tbl, ndev->nd_parms);
363 ndev->dead = 1; 367 ndev->dead = 1;
364 in6_dev_finish_destroy(ndev); 368 in6_dev_finish_destroy(ndev);
365 return NULL; 369 return NULL;
366 } 370 }
367 371
368 /* One reference from device. We must do this before 372 if (snmp6_register_dev(ndev) < 0) {
369 * we invoke __ipv6_regen_rndid(). 373 ADBG((KERN_WARNING
370 */ 374 "%s(): cannot create /proc/net/dev_snmp6/%s\n",
371 in6_dev_hold(ndev); 375 __FUNCTION__, dev->name));
376 neigh_parms_release(&nd_tbl, ndev->nd_parms);
377 ndev->dead = 1;
378 in6_dev_finish_destroy(ndev);
379 return NULL;
380 }
381
382 /* One reference from device. We must do this before
383 * we invoke __ipv6_regen_rndid().
384 */
385 in6_dev_hold(ndev);
372 386
373#ifdef CONFIG_IPV6_PRIVACY 387#ifdef CONFIG_IPV6_PRIVACY
374 get_random_bytes(ndev->rndid, sizeof(ndev->rndid)); 388 init_timer(&ndev->regen_timer);
375 get_random_bytes(ndev->entropy, sizeof(ndev->entropy)); 389 ndev->regen_timer.function = ipv6_regen_rndid;
376 init_timer(&ndev->regen_timer); 390 ndev->regen_timer.data = (unsigned long) ndev;
377 ndev->regen_timer.function = ipv6_regen_rndid; 391 if ((dev->flags&IFF_LOOPBACK) ||
378 ndev->regen_timer.data = (unsigned long) ndev; 392 dev->type == ARPHRD_TUNNEL ||
379 if ((dev->flags&IFF_LOOPBACK) || 393 dev->type == ARPHRD_NONE ||
380 dev->type == ARPHRD_TUNNEL || 394 dev->type == ARPHRD_SIT) {
381 dev->type == ARPHRD_NONE || 395 printk(KERN_INFO
382 dev->type == ARPHRD_SIT) { 396 "%s: Disabled Privacy Extensions\n",
383 printk(KERN_INFO 397 dev->name);
384 "%s: Disabled Privacy Extensions\n", 398 ndev->cnf.use_tempaddr = -1;
385 dev->name); 399 } else {
386 ndev->cnf.use_tempaddr = -1; 400 in6_dev_hold(ndev);
387 } else { 401 ipv6_regen_rndid((unsigned long) ndev);
388 in6_dev_hold(ndev); 402 }
389 ipv6_regen_rndid((unsigned long) ndev);
390 }
391#endif 403#endif
392 404
393 if (netif_carrier_ok(dev)) 405 if (netif_carrier_ok(dev))
394 ndev->if_flags |= IF_READY; 406 ndev->if_flags |= IF_READY;
395 407
396 write_lock_bh(&addrconf_lock); 408 write_lock_bh(&addrconf_lock);
397 dev->ip6_ptr = ndev; 409 dev->ip6_ptr = ndev;
398 write_unlock_bh(&addrconf_lock); 410 write_unlock_bh(&addrconf_lock);
399 411
400 ipv6_mc_init_dev(ndev); 412 ipv6_mc_init_dev(ndev);
401 ndev->tstamp = jiffies; 413 ndev->tstamp = jiffies;
402#ifdef CONFIG_SYSCTL 414#ifdef CONFIG_SYSCTL
403 neigh_sysctl_register(dev, ndev->nd_parms, NET_IPV6, 415 neigh_sysctl_register(dev, ndev->nd_parms, NET_IPV6,
404 NET_IPV6_NEIGH, "ipv6", 416 NET_IPV6_NEIGH, "ipv6",
405 &ndisc_ifinfo_sysctl_change, 417 &ndisc_ifinfo_sysctl_change,
406 NULL); 418 NULL);
407 addrconf_sysctl_register(ndev, &ndev->cnf); 419 addrconf_sysctl_register(ndev, &ndev->cnf);
408#endif 420#endif
409 }
410 return ndev; 421 return ndev;
411} 422}
412 423
@@ -524,7 +535,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
524 goto out; 535 goto out;
525 } 536 }
526 537
527 ifa = kmalloc(sizeof(struct inet6_ifaddr), GFP_ATOMIC); 538 ifa = kzalloc(sizeof(struct inet6_ifaddr), GFP_ATOMIC);
528 539
529 if (ifa == NULL) { 540 if (ifa == NULL) {
530 ADBG(("ipv6_add_addr: malloc failed\n")); 541 ADBG(("ipv6_add_addr: malloc failed\n"));
@@ -538,7 +549,6 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
538 goto out; 549 goto out;
539 } 550 }
540 551
541 memset(ifa, 0, sizeof(struct inet6_ifaddr));
542 ipv6_addr_copy(&ifa->addr, addr); 552 ipv6_addr_copy(&ifa->addr, addr);
543 553
544 spin_lock_init(&ifa->lock); 554 spin_lock_init(&ifa->lock);
@@ -1305,52 +1315,67 @@ static void addrconf_leave_anycast(struct inet6_ifaddr *ifp)
1305 __ipv6_dev_ac_dec(ifp->idev, &addr); 1315 __ipv6_dev_ac_dec(ifp->idev, &addr);
1306} 1316}
1307 1317
1318static int addrconf_ifid_eui48(u8 *eui, struct net_device *dev)
1319{
1320 if (dev->addr_len != ETH_ALEN)
1321 return -1;
1322 memcpy(eui, dev->dev_addr, 3);
1323 memcpy(eui + 5, dev->dev_addr + 3, 3);
1324
1325 /*
1326 * The zSeries OSA network cards can be shared among various
1327 * OS instances, but the OSA cards have only one MAC address.
1328 * This leads to duplicate address conflicts in conjunction
1329 * with IPv6 if more than one instance uses the same card.
1330 *
1331 * The driver for these cards can deliver a unique 16-bit
1332 * identifier for each instance sharing the same card. It is
1333 * placed instead of 0xFFFE in the interface identifier. The
1334 * "u" bit of the interface identifier is not inverted in this
1335 * case. Hence the resulting interface identifier has local
1336 * scope according to RFC2373.
1337 */
1338 if (dev->dev_id) {
1339 eui[3] = (dev->dev_id >> 8) & 0xFF;
1340 eui[4] = dev->dev_id & 0xFF;
1341 } else {
1342 eui[3] = 0xFF;
1343 eui[4] = 0xFE;
1344 eui[0] ^= 2;
1345 }
1346 return 0;
1347}
1348
1349static int addrconf_ifid_arcnet(u8 *eui, struct net_device *dev)
1350{
1351 /* XXX: inherit EUI-64 from other interface -- yoshfuji */
1352 if (dev->addr_len != ARCNET_ALEN)
1353 return -1;
1354 memset(eui, 0, 7);
1355 eui[7] = *(u8*)dev->dev_addr;
1356 return 0;
1357}
1358
1359static int addrconf_ifid_infiniband(u8 *eui, struct net_device *dev)
1360{
1361 if (dev->addr_len != INFINIBAND_ALEN)
1362 return -1;
1363 memcpy(eui, dev->dev_addr + 12, 8);
1364 eui[0] |= 2;
1365 return 0;
1366}
1367
1308static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) 1368static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
1309{ 1369{
1310 switch (dev->type) { 1370 switch (dev->type) {
1311 case ARPHRD_ETHER: 1371 case ARPHRD_ETHER:
1312 case ARPHRD_FDDI: 1372 case ARPHRD_FDDI:
1313 case ARPHRD_IEEE802_TR: 1373 case ARPHRD_IEEE802_TR:
1314 if (dev->addr_len != ETH_ALEN) 1374 return addrconf_ifid_eui48(eui, dev);
1315 return -1;
1316 memcpy(eui, dev->dev_addr, 3);
1317 memcpy(eui + 5, dev->dev_addr + 3, 3);
1318
1319 /*
1320 * The zSeries OSA network cards can be shared among various
1321 * OS instances, but the OSA cards have only one MAC address.
1322 * This leads to duplicate address conflicts in conjunction
1323 * with IPv6 if more than one instance uses the same card.
1324 *
1325 * The driver for these cards can deliver a unique 16-bit
1326 * identifier for each instance sharing the same card. It is
1327 * placed instead of 0xFFFE in the interface identifier. The
1328 * "u" bit of the interface identifier is not inverted in this
1329 * case. Hence the resulting interface identifier has local
1330 * scope according to RFC2373.
1331 */
1332 if (dev->dev_id) {
1333 eui[3] = (dev->dev_id >> 8) & 0xFF;
1334 eui[4] = dev->dev_id & 0xFF;
1335 } else {
1336 eui[3] = 0xFF;
1337 eui[4] = 0xFE;
1338 eui[0] ^= 2;
1339 }
1340 return 0;
1341 case ARPHRD_ARCNET: 1375 case ARPHRD_ARCNET:
1342 /* XXX: inherit EUI-64 from other interface -- yoshfuji */ 1376 return addrconf_ifid_arcnet(eui, dev);
1343 if (dev->addr_len != ARCNET_ALEN)
1344 return -1;
1345 memset(eui, 0, 7);
1346 eui[7] = *(u8*)dev->dev_addr;
1347 return 0;
1348 case ARPHRD_INFINIBAND: 1377 case ARPHRD_INFINIBAND:
1349 if (dev->addr_len != INFINIBAND_ALEN) 1378 return addrconf_ifid_infiniband(eui, dev);
1350 return -1;
1351 memcpy(eui, dev->dev_addr + 12, 8);
1352 eui[0] |= 2;
1353 return 0;
1354 } 1379 }
1355 return -1; 1380 return -1;
1356} 1381}
@@ -1376,34 +1401,9 @@ static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev)
1376/* (re)generation of randomized interface identifier (RFC 3041 3.2, 3.5) */ 1401/* (re)generation of randomized interface identifier (RFC 3041 3.2, 3.5) */
1377static int __ipv6_regen_rndid(struct inet6_dev *idev) 1402static int __ipv6_regen_rndid(struct inet6_dev *idev)
1378{ 1403{
1379 struct net_device *dev;
1380 struct scatterlist sg[2];
1381
1382 sg_set_buf(&sg[0], idev->entropy, 8);
1383 sg_set_buf(&sg[1], idev->work_eui64, 8);
1384
1385 dev = idev->dev;
1386
1387 if (ipv6_generate_eui64(idev->work_eui64, dev)) {
1388 printk(KERN_INFO
1389 "__ipv6_regen_rndid(idev=%p): cannot get EUI64 identifier; use random bytes.\n",
1390 idev);
1391 get_random_bytes(idev->work_eui64, sizeof(idev->work_eui64));
1392 }
1393regen: 1404regen:
1394 spin_lock(&md5_tfm_lock); 1405 get_random_bytes(idev->rndid, sizeof(idev->rndid));
1395 if (unlikely(md5_tfm == NULL)) {
1396 spin_unlock(&md5_tfm_lock);
1397 return -1;
1398 }
1399 crypto_digest_init(md5_tfm);
1400 crypto_digest_update(md5_tfm, sg, 2);
1401 crypto_digest_final(md5_tfm, idev->work_digest);
1402 spin_unlock(&md5_tfm_lock);
1403
1404 memcpy(idev->rndid, &idev->work_digest[0], 8);
1405 idev->rndid[0] &= ~0x02; 1406 idev->rndid[0] &= ~0x02;
1406 memcpy(idev->entropy, &idev->work_digest[8], 8);
1407 1407
1408 /* 1408 /*
1409 * <draft-ietf-ipngwg-temp-addresses-v2-00.txt>: 1409 * <draft-ietf-ipngwg-temp-addresses-v2-00.txt>:
@@ -2143,7 +2143,6 @@ static void addrconf_ip6_tnl_config(struct net_device *dev)
2143 return; 2143 return;
2144 } 2144 }
2145 ip6_tnl_add_linklocal(idev); 2145 ip6_tnl_add_linklocal(idev);
2146 addrconf_add_mroute(dev);
2147} 2146}
2148 2147
2149static int addrconf_notify(struct notifier_block *this, unsigned long event, 2148static int addrconf_notify(struct notifier_block *this, unsigned long event,
@@ -2668,11 +2667,10 @@ static int if6_seq_open(struct inode *inode, struct file *file)
2668{ 2667{
2669 struct seq_file *seq; 2668 struct seq_file *seq;
2670 int rc = -ENOMEM; 2669 int rc = -ENOMEM;
2671 struct if6_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL); 2670 struct if6_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
2672 2671
2673 if (!s) 2672 if (!s)
2674 goto out; 2673 goto out;
2675 memset(s, 0, sizeof(*s));
2676 2674
2677 rc = seq_open(file, &if6_seq_ops); 2675 rc = seq_open(file, &if6_seq_ops);
2678 if (rc) 2676 if (rc)
@@ -3133,6 +3131,15 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf,
3133 array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor; 3131 array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor;
3134#endif 3132#endif
3135 array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses; 3133 array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses;
3134 array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr;
3135 array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo;
3136#ifdef CONFIG_IPV6_ROUTER_PREF
3137 array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref;
3138 array[DEVCONF_RTR_PROBE_INTERVAL] = cnf->rtr_probe_interval;
3139#ifdef CONFIV_IPV6_ROUTE_INFO
3140 array[DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN] = cnf->accept_ra_rt_info_max_plen;
3141#endif
3142#endif
3136} 3143}
3137 3144
3138static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, 3145static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
@@ -3586,6 +3593,51 @@ static struct addrconf_sysctl_table
3586 .proc_handler = &proc_dointvec, 3593 .proc_handler = &proc_dointvec,
3587 }, 3594 },
3588 { 3595 {
3596 .ctl_name = NET_IPV6_ACCEPT_RA_DEFRTR,
3597 .procname = "accept_ra_defrtr",
3598 .data = &ipv6_devconf.accept_ra_defrtr,
3599 .maxlen = sizeof(int),
3600 .mode = 0644,
3601 .proc_handler = &proc_dointvec,
3602 },
3603 {
3604 .ctl_name = NET_IPV6_ACCEPT_RA_PINFO,
3605 .procname = "accept_ra_pinfo",
3606 .data = &ipv6_devconf.accept_ra_pinfo,
3607 .maxlen = sizeof(int),
3608 .mode = 0644,
3609 .proc_handler = &proc_dointvec,
3610 },
3611#ifdef CONFIG_IPV6_ROUTER_PREF
3612 {
3613 .ctl_name = NET_IPV6_ACCEPT_RA_RTR_PREF,
3614 .procname = "accept_ra_rtr_pref",
3615 .data = &ipv6_devconf.accept_ra_rtr_pref,
3616 .maxlen = sizeof(int),
3617 .mode = 0644,
3618 .proc_handler = &proc_dointvec,
3619 },
3620 {
3621 .ctl_name = NET_IPV6_RTR_PROBE_INTERVAL,
3622 .procname = "router_probe_interval",
3623 .data = &ipv6_devconf.rtr_probe_interval,
3624 .maxlen = sizeof(int),
3625 .mode = 0644,
3626 .proc_handler = &proc_dointvec_jiffies,
3627 .strategy = &sysctl_jiffies,
3628 },
3629#ifdef CONFIV_IPV6_ROUTE_INFO
3630 {
3631 .ctl_name = NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN,
3632 .procname = "accept_ra_rt_info_max_plen",
3633 .data = &ipv6_devconf.accept_ra_rt_info_max_plen,
3634 .maxlen = sizeof(int),
3635 .mode = 0644,
3636 .proc_handler = &proc_dointvec,
3637 },
3638#endif
3639#endif
3640 {
3589 .ctl_name = 0, /* sentinel */ 3641 .ctl_name = 0, /* sentinel */
3590 } 3642 }
3591 }, 3643 },
@@ -3760,13 +3812,6 @@ int __init addrconf_init(void)
3760 3812
3761 register_netdevice_notifier(&ipv6_dev_notf); 3813 register_netdevice_notifier(&ipv6_dev_notf);
3762 3814
3763#ifdef CONFIG_IPV6_PRIVACY
3764 md5_tfm = crypto_alloc_tfm("md5", 0);
3765 if (unlikely(md5_tfm == NULL))
3766 printk(KERN_WARNING
3767 "failed to load transform for md5\n");
3768#endif
3769
3770 addrconf_verify(0); 3815 addrconf_verify(0);
3771 rtnetlink_links[PF_INET6] = inet6_rtnetlink_table; 3816 rtnetlink_links[PF_INET6] = inet6_rtnetlink_table;
3772#ifdef CONFIG_SYSCTL 3817#ifdef CONFIG_SYSCTL
@@ -3829,11 +3874,6 @@ void __exit addrconf_cleanup(void)
3829 3874
3830 rtnl_unlock(); 3875 rtnl_unlock();
3831 3876
3832#ifdef CONFIG_IPV6_PRIVACY
3833 crypto_free_tfm(md5_tfm);
3834 md5_tfm = NULL;
3835#endif
3836
3837#ifdef CONFIG_PROC_FS 3877#ifdef CONFIG_PROC_FS
3838 proc_net_remove("if_inet6"); 3878 proc_net_remove("if_inet6");
3839#endif 3879#endif
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 6c9711ac1c03..e19457fe4f6e 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -456,45 +456,53 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
456} 456}
457 457
458const struct proto_ops inet6_stream_ops = { 458const struct proto_ops inet6_stream_ops = {
459 .family = PF_INET6, 459 .family = PF_INET6,
460 .owner = THIS_MODULE, 460 .owner = THIS_MODULE,
461 .release = inet6_release, 461 .release = inet6_release,
462 .bind = inet6_bind, 462 .bind = inet6_bind,
463 .connect = inet_stream_connect, /* ok */ 463 .connect = inet_stream_connect, /* ok */
464 .socketpair = sock_no_socketpair, /* a do nothing */ 464 .socketpair = sock_no_socketpair, /* a do nothing */
465 .accept = inet_accept, /* ok */ 465 .accept = inet_accept, /* ok */
466 .getname = inet6_getname, 466 .getname = inet6_getname,
467 .poll = tcp_poll, /* ok */ 467 .poll = tcp_poll, /* ok */
468 .ioctl = inet6_ioctl, /* must change */ 468 .ioctl = inet6_ioctl, /* must change */
469 .listen = inet_listen, /* ok */ 469 .listen = inet_listen, /* ok */
470 .shutdown = inet_shutdown, /* ok */ 470 .shutdown = inet_shutdown, /* ok */
471 .setsockopt = sock_common_setsockopt, /* ok */ 471 .setsockopt = sock_common_setsockopt, /* ok */
472 .getsockopt = sock_common_getsockopt, /* ok */ 472 .getsockopt = sock_common_getsockopt, /* ok */
473 .sendmsg = inet_sendmsg, /* ok */ 473 .sendmsg = inet_sendmsg, /* ok */
474 .recvmsg = sock_common_recvmsg, /* ok */ 474 .recvmsg = sock_common_recvmsg, /* ok */
475 .mmap = sock_no_mmap, 475 .mmap = sock_no_mmap,
476 .sendpage = tcp_sendpage 476 .sendpage = tcp_sendpage,
477#ifdef CONFIG_COMPAT
478 .compat_setsockopt = compat_sock_common_setsockopt,
479 .compat_getsockopt = compat_sock_common_getsockopt,
480#endif
477}; 481};
478 482
479const struct proto_ops inet6_dgram_ops = { 483const struct proto_ops inet6_dgram_ops = {
480 .family = PF_INET6, 484 .family = PF_INET6,
481 .owner = THIS_MODULE, 485 .owner = THIS_MODULE,
482 .release = inet6_release, 486 .release = inet6_release,
483 .bind = inet6_bind, 487 .bind = inet6_bind,
484 .connect = inet_dgram_connect, /* ok */ 488 .connect = inet_dgram_connect, /* ok */
485 .socketpair = sock_no_socketpair, /* a do nothing */ 489 .socketpair = sock_no_socketpair, /* a do nothing */
486 .accept = sock_no_accept, /* a do nothing */ 490 .accept = sock_no_accept, /* a do nothing */
487 .getname = inet6_getname, 491 .getname = inet6_getname,
488 .poll = udp_poll, /* ok */ 492 .poll = udp_poll, /* ok */
489 .ioctl = inet6_ioctl, /* must change */ 493 .ioctl = inet6_ioctl, /* must change */
490 .listen = sock_no_listen, /* ok */ 494 .listen = sock_no_listen, /* ok */
491 .shutdown = inet_shutdown, /* ok */ 495 .shutdown = inet_shutdown, /* ok */
492 .setsockopt = sock_common_setsockopt, /* ok */ 496 .setsockopt = sock_common_setsockopt, /* ok */
493 .getsockopt = sock_common_getsockopt, /* ok */ 497 .getsockopt = sock_common_getsockopt, /* ok */
494 .sendmsg = inet_sendmsg, /* ok */ 498 .sendmsg = inet_sendmsg, /* ok */
495 .recvmsg = sock_common_recvmsg, /* ok */ 499 .recvmsg = sock_common_recvmsg, /* ok */
496 .mmap = sock_no_mmap, 500 .mmap = sock_no_mmap,
497 .sendpage = sock_no_sendpage, 501 .sendpage = sock_no_sendpage,
502#ifdef CONFIG_COMPAT
503 .compat_setsockopt = compat_sock_common_setsockopt,
504 .compat_getsockopt = compat_sock_common_getsockopt,
505#endif
498}; 506};
499 507
500static struct net_proto_family inet6_family_ops = { 508static struct net_proto_family inet6_family_ops = {
@@ -505,24 +513,28 @@ static struct net_proto_family inet6_family_ops = {
505 513
506/* Same as inet6_dgram_ops, sans udp_poll. */ 514/* Same as inet6_dgram_ops, sans udp_poll. */
507static const struct proto_ops inet6_sockraw_ops = { 515static const struct proto_ops inet6_sockraw_ops = {
508 .family = PF_INET6, 516 .family = PF_INET6,
509 .owner = THIS_MODULE, 517 .owner = THIS_MODULE,
510 .release = inet6_release, 518 .release = inet6_release,
511 .bind = inet6_bind, 519 .bind = inet6_bind,
512 .connect = inet_dgram_connect, /* ok */ 520 .connect = inet_dgram_connect, /* ok */
513 .socketpair = sock_no_socketpair, /* a do nothing */ 521 .socketpair = sock_no_socketpair, /* a do nothing */
514 .accept = sock_no_accept, /* a do nothing */ 522 .accept = sock_no_accept, /* a do nothing */
515 .getname = inet6_getname, 523 .getname = inet6_getname,
516 .poll = datagram_poll, /* ok */ 524 .poll = datagram_poll, /* ok */
517 .ioctl = inet6_ioctl, /* must change */ 525 .ioctl = inet6_ioctl, /* must change */
518 .listen = sock_no_listen, /* ok */ 526 .listen = sock_no_listen, /* ok */
519 .shutdown = inet_shutdown, /* ok */ 527 .shutdown = inet_shutdown, /* ok */
520 .setsockopt = sock_common_setsockopt, /* ok */ 528 .setsockopt = sock_common_setsockopt, /* ok */
521 .getsockopt = sock_common_getsockopt, /* ok */ 529 .getsockopt = sock_common_getsockopt, /* ok */
522 .sendmsg = inet_sendmsg, /* ok */ 530 .sendmsg = inet_sendmsg, /* ok */
523 .recvmsg = sock_common_recvmsg, /* ok */ 531 .recvmsg = sock_common_recvmsg, /* ok */
524 .mmap = sock_no_mmap, 532 .mmap = sock_no_mmap,
525 .sendpage = sock_no_sendpage, 533 .sendpage = sock_no_sendpage,
534#ifdef CONFIG_COMPAT
535 .compat_setsockopt = compat_sock_common_setsockopt,
536 .compat_getsockopt = compat_sock_common_getsockopt,
537#endif
526}; 538};
527 539
528static struct inet_protosw rawv6_protosw = { 540static struct inet_protosw rawv6_protosw = {
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 84963749ab77..cf58251df4b3 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -213,6 +213,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
213 ah->reserved = 0; 213 ah->reserved = 0;
214 ah->spi = x->id.spi; 214 ah->spi = x->id.spi;
215 ah->seq_no = htonl(++x->replay.oseq); 215 ah->seq_no = htonl(++x->replay.oseq);
216 xfrm_aevent_doreplay(x);
216 ahp->icv(ahp, skb, ah->auth_data); 217 ahp->icv(ahp, skb, ah->auth_data);
217 218
218 err = 0; 219 err = 0;
@@ -353,12 +354,10 @@ static int ah6_init_state(struct xfrm_state *x)
353 if (x->encap) 354 if (x->encap)
354 goto error; 355 goto error;
355 356
356 ahp = kmalloc(sizeof(*ahp), GFP_KERNEL); 357 ahp = kzalloc(sizeof(*ahp), GFP_KERNEL);
357 if (ahp == NULL) 358 if (ahp == NULL)
358 return -ENOMEM; 359 return -ENOMEM;
359 360
360 memset(ahp, 0, sizeof(*ahp));
361
362 ahp->key = x->aalg->alg_key; 361 ahp->key = x->aalg->alg_key;
363 ahp->key_len = (x->aalg->alg_key_len+7)/8; 362 ahp->key_len = (x->aalg->alg_key_len+7)/8;
364 ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); 363 ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, 0);
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 840a33d33296..39ec528923f6 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -308,7 +308,7 @@ int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr)
308 * not found: create a new one. 308 * not found: create a new one.
309 */ 309 */
310 310
311 aca = kmalloc(sizeof(struct ifacaddr6), GFP_ATOMIC); 311 aca = kzalloc(sizeof(struct ifacaddr6), GFP_ATOMIC);
312 312
313 if (aca == NULL) { 313 if (aca == NULL) {
314 err = -ENOMEM; 314 err = -ENOMEM;
@@ -322,8 +322,6 @@ int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr)
322 goto out; 322 goto out;
323 } 323 }
324 324
325 memset(aca, 0, sizeof(struct ifacaddr6));
326
327 ipv6_addr_copy(&aca->aca_addr, addr); 325 ipv6_addr_copy(&aca->aca_addr, addr);
328 aca->aca_idev = idev; 326 aca->aca_idev = idev;
329 aca->aca_rt = rt; 327 aca->aca_rt = rt;
@@ -550,7 +548,7 @@ static int ac6_seq_open(struct inode *inode, struct file *file)
550{ 548{
551 struct seq_file *seq; 549 struct seq_file *seq;
552 int rc = -ENOMEM; 550 int rc = -ENOMEM;
553 struct ac6_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL); 551 struct ac6_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
554 552
555 if (!s) 553 if (!s)
556 goto out; 554 goto out;
@@ -561,7 +559,6 @@ static int ac6_seq_open(struct inode *inode, struct file *file)
561 559
562 seq = file->private_data; 560 seq = file->private_data;
563 seq->private = s; 561 seq->private = s;
564 memset(s, 0, sizeof(*s));
565out: 562out:
566 return rc; 563 return rc;
567out_kfree: 564out_kfree:
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 7b5b94f13902..3dcaac7a0972 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -94,6 +94,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
94 94
95 esph->spi = x->id.spi; 95 esph->spi = x->id.spi;
96 esph->seq_no = htonl(++x->replay.oseq); 96 esph->seq_no = htonl(++x->replay.oseq);
97 xfrm_aevent_doreplay(x);
97 98
98 if (esp->conf.ivlen) 99 if (esp->conf.ivlen)
99 crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); 100 crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
@@ -304,12 +305,10 @@ static int esp6_init_state(struct xfrm_state *x)
304 if (x->encap) 305 if (x->encap)
305 goto error; 306 goto error;
306 307
307 esp = kmalloc(sizeof(*esp), GFP_KERNEL); 308 esp = kzalloc(sizeof(*esp), GFP_KERNEL);
308 if (esp == NULL) 309 if (esp == NULL)
309 return -ENOMEM; 310 return -ENOMEM;
310 311
311 memset(esp, 0, sizeof(*esp));
312
313 if (x->aalg) { 312 if (x->aalg) {
314 struct xfrm_algo_desc *aalg_desc; 313 struct xfrm_algo_desc *aalg_desc;
315 314
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 1bf6d9a769e6..2cb6149349bf 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -1105,7 +1105,6 @@ static int fib6_age(struct rt6_info *rt, void *arg)
1105 if (rt->rt6i_flags&RTF_EXPIRES && rt->rt6i_expires) { 1105 if (rt->rt6i_flags&RTF_EXPIRES && rt->rt6i_expires) {
1106 if (time_after(now, rt->rt6i_expires)) { 1106 if (time_after(now, rt->rt6i_expires)) {
1107 RT6_TRACE("expiring %p\n", rt); 1107 RT6_TRACE("expiring %p\n", rt);
1108 rt6_reset_dflt_pointer(rt);
1109 return -1; 1108 return -1;
1110 } 1109 }
1111 gc_args.more++; 1110 gc_args.more++;
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 69cbe8a66d02..f9ca63912fbf 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -287,10 +287,9 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int *
287 int err; 287 int err;
288 288
289 err = -ENOMEM; 289 err = -ENOMEM;
290 fl = kmalloc(sizeof(*fl), GFP_KERNEL); 290 fl = kzalloc(sizeof(*fl), GFP_KERNEL);
291 if (fl == NULL) 291 if (fl == NULL)
292 goto done; 292 goto done;
293 memset(fl, 0, sizeof(*fl));
294 293
295 olen = optlen - CMSG_ALIGN(sizeof(*freq)); 294 olen = optlen - CMSG_ALIGN(sizeof(*freq));
296 if (olen > 0) { 295 if (olen > 0) {
@@ -663,7 +662,7 @@ static int ip6fl_seq_open(struct inode *inode, struct file *file)
663{ 662{
664 struct seq_file *seq; 663 struct seq_file *seq;
665 int rc = -ENOMEM; 664 int rc = -ENOMEM;
666 struct ip6fl_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL); 665 struct ip6fl_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
667 666
668 if (!s) 667 if (!s)
669 goto out; 668 goto out;
@@ -674,7 +673,6 @@ static int ip6fl_seq_open(struct inode *inode, struct file *file)
674 673
675 seq = file->private_data; 674 seq = file->private_data;
676 seq->private = s; 675 seq->private = s;
677 memset(s, 0, sizeof(*s));
678out: 676out:
679 return rc; 677 return rc;
680out_kfree: 678out_kfree:
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 5bf70b1442ea..e46048974f37 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -161,7 +161,7 @@ int ip6_output(struct sk_buff *skb)
161int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, 161int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
162 struct ipv6_txoptions *opt, int ipfragok) 162 struct ipv6_txoptions *opt, int ipfragok)
163{ 163{
164 struct ipv6_pinfo *np = sk ? inet6_sk(sk) : NULL; 164 struct ipv6_pinfo *np = inet6_sk(sk);
165 struct in6_addr *first_hop = &fl->fl6_dst; 165 struct in6_addr *first_hop = &fl->fl6_dst;
166 struct dst_entry *dst = skb->dst; 166 struct dst_entry *dst = skb->dst;
167 struct ipv6hdr *hdr; 167 struct ipv6hdr *hdr;
@@ -733,28 +733,29 @@ int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl)
733 if (*dst) { 733 if (*dst) {
734 struct rt6_info *rt = (struct rt6_info*)*dst; 734 struct rt6_info *rt = (struct rt6_info*)*dst;
735 735
736 /* Yes, checking route validity in not connected 736 /* Yes, checking route validity in not connected
737 case is not very simple. Take into account, 737 * case is not very simple. Take into account,
738 that we do not support routing by source, TOS, 738 * that we do not support routing by source, TOS,
739 and MSG_DONTROUTE --ANK (980726) 739 * and MSG_DONTROUTE --ANK (980726)
740 740 *
741 1. If route was host route, check that 741 * 1. If route was host route, check that
742 cached destination is current. 742 * cached destination is current.
743 If it is network route, we still may 743 * If it is network route, we still may
744 check its validity using saved pointer 744 * check its validity using saved pointer
745 to the last used address: daddr_cache. 745 * to the last used address: daddr_cache.
746 We do not want to save whole address now, 746 * We do not want to save whole address now,
747 (because main consumer of this service 747 * (because main consumer of this service
748 is tcp, which has not this problem), 748 * is tcp, which has not this problem),
749 so that the last trick works only on connected 749 * so that the last trick works only on connected
750 sockets. 750 * sockets.
751 2. oif also should be the same. 751 * 2. oif also should be the same.
752 */ 752 */
753
754 if (((rt->rt6i_dst.plen != 128 || 753 if (((rt->rt6i_dst.plen != 128 ||
755 !ipv6_addr_equal(&fl->fl6_dst, &rt->rt6i_dst.addr)) 754 !ipv6_addr_equal(&fl->fl6_dst,
755 &rt->rt6i_dst.addr))
756 && (np->daddr_cache == NULL || 756 && (np->daddr_cache == NULL ||
757 !ipv6_addr_equal(&fl->fl6_dst, np->daddr_cache))) 757 !ipv6_addr_equal(&fl->fl6_dst,
758 np->daddr_cache)))
758 || (fl->oif && fl->oif != (*dst)->dev->ifindex)) { 759 || (fl->oif && fl->oif != (*dst)->dev->ifindex)) {
759 dst_release(*dst); 760 dst_release(*dst);
760 *dst = NULL; 761 *dst = NULL;
@@ -889,7 +890,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
889 np->cork.hop_limit = hlimit; 890 np->cork.hop_limit = hlimit;
890 np->cork.tclass = tclass; 891 np->cork.tclass = tclass;
891 mtu = dst_mtu(rt->u.dst.path); 892 mtu = dst_mtu(rt->u.dst.path);
892 if (np && np->frag_size < mtu) { 893 if (np->frag_size < mtu) {
893 if (np->frag_size) 894 if (np->frag_size)
894 mtu = np->frag_size; 895 mtu = np->frag_size;
895 } 896 }
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index d511a884dad0..028b636687ec 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -50,6 +50,7 @@
50#include <net/protocol.h> 50#include <net/protocol.h>
51#include <linux/ipv6.h> 51#include <linux/ipv6.h>
52#include <linux/icmpv6.h> 52#include <linux/icmpv6.h>
53#include <linux/mutex.h>
53 54
54struct ipcomp6_tfms { 55struct ipcomp6_tfms {
55 struct list_head list; 56 struct list_head list;
@@ -57,7 +58,7 @@ struct ipcomp6_tfms {
57 int users; 58 int users;
58}; 59};
59 60
60static DECLARE_MUTEX(ipcomp6_resource_sem); 61static DEFINE_MUTEX(ipcomp6_resource_mutex);
61static void **ipcomp6_scratches; 62static void **ipcomp6_scratches;
62static int ipcomp6_scratch_users; 63static int ipcomp6_scratch_users;
63static LIST_HEAD(ipcomp6_tfms_list); 64static LIST_HEAD(ipcomp6_tfms_list);
@@ -286,8 +287,8 @@ static void ipcomp6_free_scratches(void)
286 287
287 for_each_cpu(i) { 288 for_each_cpu(i) {
288 void *scratch = *per_cpu_ptr(scratches, i); 289 void *scratch = *per_cpu_ptr(scratches, i);
289 if (scratch) 290
290 vfree(scratch); 291 vfree(scratch);
291 } 292 }
292 293
293 free_percpu(scratches); 294 free_percpu(scratches);
@@ -405,9 +406,9 @@ static void ipcomp6_destroy(struct xfrm_state *x)
405 if (!ipcd) 406 if (!ipcd)
406 return; 407 return;
407 xfrm_state_delete_tunnel(x); 408 xfrm_state_delete_tunnel(x);
408 down(&ipcomp6_resource_sem); 409 mutex_lock(&ipcomp6_resource_mutex);
409 ipcomp6_free_data(ipcd); 410 ipcomp6_free_data(ipcd);
410 up(&ipcomp6_resource_sem); 411 mutex_unlock(&ipcomp6_resource_mutex);
411 kfree(ipcd); 412 kfree(ipcd);
412 413
413 xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr); 414 xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr);
@@ -427,23 +428,22 @@ static int ipcomp6_init_state(struct xfrm_state *x)
427 goto out; 428 goto out;
428 429
429 err = -ENOMEM; 430 err = -ENOMEM;
430 ipcd = kmalloc(sizeof(*ipcd), GFP_KERNEL); 431 ipcd = kzalloc(sizeof(*ipcd), GFP_KERNEL);
431 if (!ipcd) 432 if (!ipcd)
432 goto out; 433 goto out;
433 434
434 memset(ipcd, 0, sizeof(*ipcd));
435 x->props.header_len = 0; 435 x->props.header_len = 0;
436 if (x->props.mode) 436 if (x->props.mode)
437 x->props.header_len += sizeof(struct ipv6hdr); 437 x->props.header_len += sizeof(struct ipv6hdr);
438 438
439 down(&ipcomp6_resource_sem); 439 mutex_lock(&ipcomp6_resource_mutex);
440 if (!ipcomp6_alloc_scratches()) 440 if (!ipcomp6_alloc_scratches())
441 goto error; 441 goto error;
442 442
443 ipcd->tfms = ipcomp6_alloc_tfms(x->calg->alg_name); 443 ipcd->tfms = ipcomp6_alloc_tfms(x->calg->alg_name);
444 if (!ipcd->tfms) 444 if (!ipcd->tfms)
445 goto error; 445 goto error;
446 up(&ipcomp6_resource_sem); 446 mutex_unlock(&ipcomp6_resource_mutex);
447 447
448 if (x->props.mode) { 448 if (x->props.mode) {
449 err = ipcomp6_tunnel_attach(x); 449 err = ipcomp6_tunnel_attach(x);
@@ -459,10 +459,10 @@ static int ipcomp6_init_state(struct xfrm_state *x)
459out: 459out:
460 return err; 460 return err;
461error_tunnel: 461error_tunnel:
462 down(&ipcomp6_resource_sem); 462 mutex_lock(&ipcomp6_resource_mutex);
463error: 463error:
464 ipcomp6_free_data(ipcd); 464 ipcomp6_free_data(ipcd);
465 up(&ipcomp6_resource_sem); 465 mutex_unlock(&ipcomp6_resource_mutex);
466 kfree(ipcd); 466 kfree(ipcd);
467 467
468 goto out; 468 goto out;
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index f7142ba519ab..4c20eeb3d568 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -109,19 +109,13 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *))
109 return 0; 109 return 0;
110} 110}
111 111
112int ipv6_setsockopt(struct sock *sk, int level, int optname, 112static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
113 char __user *optval, int optlen) 113 char __user *optval, int optlen)
114{ 114{
115 struct ipv6_pinfo *np = inet6_sk(sk); 115 struct ipv6_pinfo *np = inet6_sk(sk);
116 int val, valbool; 116 int val, valbool;
117 int retv = -ENOPROTOOPT; 117 int retv = -ENOPROTOOPT;
118 118
119 if (level == SOL_IP && sk->sk_type != SOCK_RAW)
120 return udp_prot.setsockopt(sk, level, optname, optval, optlen);
121
122 if(level!=SOL_IPV6)
123 goto out;
124
125 if (optval == NULL) 119 if (optval == NULL)
126 val=0; 120 val=0;
127 else if (get_user(val, (int __user *) optval)) 121 else if (get_user(val, (int __user *) optval))
@@ -613,17 +607,9 @@ done:
613 retv = xfrm_user_policy(sk, optname, optval, optlen); 607 retv = xfrm_user_policy(sk, optname, optval, optlen);
614 break; 608 break;
615 609
616#ifdef CONFIG_NETFILTER
617 default:
618 retv = nf_setsockopt(sk, PF_INET6, optname, optval,
619 optlen);
620 break;
621#endif
622
623 } 610 }
624 release_sock(sk); 611 release_sock(sk);
625 612
626out:
627 return retv; 613 return retv;
628 614
629e_inval: 615e_inval:
@@ -631,6 +617,65 @@ e_inval:
631 return -EINVAL; 617 return -EINVAL;
632} 618}
633 619
620int ipv6_setsockopt(struct sock *sk, int level, int optname,
621 char __user *optval, int optlen)
622{
623 int err;
624
625 if (level == SOL_IP && sk->sk_type != SOCK_RAW)
626 return udp_prot.setsockopt(sk, level, optname, optval, optlen);
627
628 if (level != SOL_IPV6)
629 return -ENOPROTOOPT;
630
631 err = do_ipv6_setsockopt(sk, level, optname, optval, optlen);
632#ifdef CONFIG_NETFILTER
633 /* we need to exclude all possible ENOPROTOOPTs except default case */
634 if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY &&
635 optname != IPV6_XFRM_POLICY) {
636 lock_sock(sk);
637 err = nf_setsockopt(sk, PF_INET6, optname, optval,
638 optlen);
639 release_sock(sk);
640 }
641#endif
642 return err;
643}
644
645
646#ifdef CONFIG_COMPAT
647int compat_ipv6_setsockopt(struct sock *sk, int level, int optname,
648 char __user *optval, int optlen)
649{
650 int err;
651
652 if (level == SOL_IP && sk->sk_type != SOCK_RAW) {
653 if (udp_prot.compat_setsockopt != NULL)
654 return udp_prot.compat_setsockopt(sk, level, optname,
655 optval, optlen);
656 return udp_prot.setsockopt(sk, level, optname, optval, optlen);
657 }
658
659 if (level != SOL_IPV6)
660 return -ENOPROTOOPT;
661
662 err = do_ipv6_setsockopt(sk, level, optname, optval, optlen);
663#ifdef CONFIG_NETFILTER
664 /* we need to exclude all possible ENOPROTOOPTs except default case */
665 if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY &&
666 optname != IPV6_XFRM_POLICY) {
667 lock_sock(sk);
668 err = compat_nf_setsockopt(sk, PF_INET6, optname,
669 optval, optlen);
670 release_sock(sk);
671 }
672#endif
673 return err;
674}
675
676EXPORT_SYMBOL(compat_ipv6_setsockopt);
677#endif
678
634static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr, 679static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr,
635 char __user *optval, int len) 680 char __user *optval, int len)
636{ 681{
@@ -642,17 +687,13 @@ static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr,
642 return len; 687 return len;
643} 688}
644 689
645int ipv6_getsockopt(struct sock *sk, int level, int optname, 690static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
646 char __user *optval, int __user *optlen) 691 char __user *optval, int __user *optlen)
647{ 692{
648 struct ipv6_pinfo *np = inet6_sk(sk); 693 struct ipv6_pinfo *np = inet6_sk(sk);
649 int len; 694 int len;
650 int val; 695 int val;
651 696
652 if (level == SOL_IP && sk->sk_type != SOCK_RAW)
653 return udp_prot.getsockopt(sk, level, optname, optval, optlen);
654 if(level!=SOL_IPV6)
655 return -ENOPROTOOPT;
656 if (get_user(len, optlen)) 697 if (get_user(len, optlen))
657 return -EFAULT; 698 return -EFAULT;
658 switch (optname) { 699 switch (optname) {
@@ -842,17 +883,7 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
842 break; 883 break;
843 884
844 default: 885 default:
845#ifdef CONFIG_NETFILTER
846 lock_sock(sk);
847 val = nf_getsockopt(sk, PF_INET6, optname, optval,
848 &len);
849 release_sock(sk);
850 if (val >= 0)
851 val = put_user(len, optlen);
852 return val;
853#else
854 return -EINVAL; 886 return -EINVAL;
855#endif
856 } 887 }
857 len = min_t(unsigned int, sizeof(int), len); 888 len = min_t(unsigned int, sizeof(int), len);
858 if(put_user(len, optlen)) 889 if(put_user(len, optlen))
@@ -862,6 +893,78 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
862 return 0; 893 return 0;
863} 894}
864 895
896int ipv6_getsockopt(struct sock *sk, int level, int optname,
897 char __user *optval, int __user *optlen)
898{
899 int err;
900
901 if (level == SOL_IP && sk->sk_type != SOCK_RAW)
902 return udp_prot.getsockopt(sk, level, optname, optval, optlen);
903
904 if(level != SOL_IPV6)
905 return -ENOPROTOOPT;
906
907 err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
908#ifdef CONFIG_NETFILTER
909 /* we need to exclude all possible EINVALs except default case */
910 if (err == -EINVAL && optname != IPV6_ADDRFORM &&
911 optname != MCAST_MSFILTER) {
912 int len;
913
914 if (get_user(len, optlen))
915 return -EFAULT;
916
917 lock_sock(sk);
918 err = nf_getsockopt(sk, PF_INET6, optname, optval,
919 &len);
920 release_sock(sk);
921 if (err >= 0)
922 err = put_user(len, optlen);
923 }
924#endif
925 return err;
926}
927
928#ifdef CONFIG_COMPAT
929int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
930 char __user *optval, int __user *optlen)
931{
932 int err;
933
934 if (level == SOL_IP && sk->sk_type != SOCK_RAW) {
935 if (udp_prot.compat_getsockopt != NULL)
936 return udp_prot.compat_getsockopt(sk, level, optname,
937 optval, optlen);
938 return udp_prot.getsockopt(sk, level, optname, optval, optlen);
939 }
940
941 if (level != SOL_IPV6)
942 return -ENOPROTOOPT;
943
944 err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
945#ifdef CONFIG_NETFILTER
946 /* we need to exclude all possible EINVALs except default case */
947 if (err == -EINVAL && optname != IPV6_ADDRFORM &&
948 optname != MCAST_MSFILTER) {
949 int len;
950
951 if (get_user(len, optlen))
952 return -EFAULT;
953
954 lock_sock(sk);
955 err = compat_nf_getsockopt(sk, PF_INET6,
956 optname, optval, &len);
957 release_sock(sk);
958 if (err >= 0)
959 err = put_user(len, optlen);
960 }
961#endif
962 return err;
963}
964
965EXPORT_SYMBOL(compat_ipv6_getsockopt);
966#endif
967
865void __init ipv6_packet_init(void) 968void __init ipv6_packet_init(void)
866{ 969{
867 dev_add_pack(&ipv6_packet_type); 970 dev_add_pack(&ipv6_packet_type);
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 807c021d64a2..6e871afbb2c7 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -767,10 +767,10 @@ static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
767 * for deleted items allows change reports to use common code with 767 * for deleted items allows change reports to use common code with
768 * non-deleted or query-response MCA's. 768 * non-deleted or query-response MCA's.
769 */ 769 */
770 pmc = kmalloc(sizeof(*pmc), GFP_ATOMIC); 770 pmc = kzalloc(sizeof(*pmc), GFP_ATOMIC);
771 if (!pmc) 771 if (!pmc)
772 return; 772 return;
773 memset(pmc, 0, sizeof(*pmc)); 773
774 spin_lock_bh(&im->mca_lock); 774 spin_lock_bh(&im->mca_lock);
775 spin_lock_init(&pmc->mca_lock); 775 spin_lock_init(&pmc->mca_lock);
776 pmc->idev = im->idev; 776 pmc->idev = im->idev;
@@ -893,7 +893,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
893 * not found: create a new one. 893 * not found: create a new one.
894 */ 894 */
895 895
896 mc = kmalloc(sizeof(struct ifmcaddr6), GFP_ATOMIC); 896 mc = kzalloc(sizeof(struct ifmcaddr6), GFP_ATOMIC);
897 897
898 if (mc == NULL) { 898 if (mc == NULL) {
899 write_unlock_bh(&idev->lock); 899 write_unlock_bh(&idev->lock);
@@ -901,7 +901,6 @@ int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
901 return -ENOMEM; 901 return -ENOMEM;
902 } 902 }
903 903
904 memset(mc, 0, sizeof(struct ifmcaddr6));
905 init_timer(&mc->mca_timer); 904 init_timer(&mc->mca_timer);
906 mc->mca_timer.function = igmp6_timer_handler; 905 mc->mca_timer.function = igmp6_timer_handler;
907 mc->mca_timer.data = (unsigned long) mc; 906 mc->mca_timer.data = (unsigned long) mc;
@@ -1934,10 +1933,10 @@ static int ip6_mc_add1_src(struct ifmcaddr6 *pmc, int sfmode,
1934 psf_prev = psf; 1933 psf_prev = psf;
1935 } 1934 }
1936 if (!psf) { 1935 if (!psf) {
1937 psf = kmalloc(sizeof(*psf), GFP_ATOMIC); 1936 psf = kzalloc(sizeof(*psf), GFP_ATOMIC);
1938 if (!psf) 1937 if (!psf)
1939 return -ENOBUFS; 1938 return -ENOBUFS;
1940 memset(psf, 0, sizeof(*psf)); 1939
1941 psf->sf_addr = *psfsrc; 1940 psf->sf_addr = *psfsrc;
1942 if (psf_prev) { 1941 if (psf_prev) {
1943 psf_prev->sf_next = psf; 1942 psf_prev->sf_next = psf;
@@ -2431,7 +2430,7 @@ static int igmp6_mc_seq_open(struct inode *inode, struct file *file)
2431{ 2430{
2432 struct seq_file *seq; 2431 struct seq_file *seq;
2433 int rc = -ENOMEM; 2432 int rc = -ENOMEM;
2434 struct igmp6_mc_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL); 2433 struct igmp6_mc_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
2435 2434
2436 if (!s) 2435 if (!s)
2437 goto out; 2436 goto out;
@@ -2442,7 +2441,6 @@ static int igmp6_mc_seq_open(struct inode *inode, struct file *file)
2442 2441
2443 seq = file->private_data; 2442 seq = file->private_data;
2444 seq->private = s; 2443 seq->private = s;
2445 memset(s, 0, sizeof(*s));
2446out: 2444out:
2447 return rc; 2445 return rc;
2448out_kfree: 2446out_kfree:
@@ -2606,7 +2604,7 @@ static int igmp6_mcf_seq_open(struct inode *inode, struct file *file)
2606{ 2604{
2607 struct seq_file *seq; 2605 struct seq_file *seq;
2608 int rc = -ENOMEM; 2606 int rc = -ENOMEM;
2609 struct igmp6_mcf_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL); 2607 struct igmp6_mcf_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
2610 2608
2611 if (!s) 2609 if (!s)
2612 goto out; 2610 goto out;
@@ -2617,7 +2615,6 @@ static int igmp6_mcf_seq_open(struct inode *inode, struct file *file)
2617 2615
2618 seq = file->private_data; 2616 seq = file->private_data;
2619 seq->private = s; 2617 seq->private = s;
2620 memset(s, 0, sizeof(*s));
2621out: 2618out:
2622 return rc; 2619 return rc;
2623out_kfree: 2620out_kfree:
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index cb8856b1d951..dfa20d3be9b6 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -156,7 +156,11 @@ struct neigh_table nd_tbl = {
156 156
157/* ND options */ 157/* ND options */
158struct ndisc_options { 158struct ndisc_options {
159 struct nd_opt_hdr *nd_opt_array[__ND_OPT_MAX]; 159 struct nd_opt_hdr *nd_opt_array[__ND_OPT_ARRAY_MAX];
160#ifdef CONFIG_IPV6_ROUTE_INFO
161 struct nd_opt_hdr *nd_opts_ri;
162 struct nd_opt_hdr *nd_opts_ri_end;
163#endif
160}; 164};
161 165
162#define nd_opts_src_lladdr nd_opt_array[ND_OPT_SOURCE_LL_ADDR] 166#define nd_opts_src_lladdr nd_opt_array[ND_OPT_SOURCE_LL_ADDR]
@@ -255,6 +259,13 @@ static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
255 if (ndopts->nd_opt_array[nd_opt->nd_opt_type] == 0) 259 if (ndopts->nd_opt_array[nd_opt->nd_opt_type] == 0)
256 ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt; 260 ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
257 break; 261 break;
262#ifdef CONFIG_IPV6_ROUTE_INFO
263 case ND_OPT_ROUTE_INFO:
264 ndopts->nd_opts_ri_end = nd_opt;
265 if (!ndopts->nd_opts_ri)
266 ndopts->nd_opts_ri = nd_opt;
267 break;
268#endif
258 default: 269 default:
259 /* 270 /*
260 * Unknown options must be silently ignored, 271 * Unknown options must be silently ignored,
@@ -1019,10 +1030,11 @@ static void ndisc_router_discovery(struct sk_buff *skb)
1019 struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw; 1030 struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw;
1020 struct neighbour *neigh = NULL; 1031 struct neighbour *neigh = NULL;
1021 struct inet6_dev *in6_dev; 1032 struct inet6_dev *in6_dev;
1022 struct rt6_info *rt; 1033 struct rt6_info *rt = NULL;
1023 int lifetime; 1034 int lifetime;
1024 struct ndisc_options ndopts; 1035 struct ndisc_options ndopts;
1025 int optlen; 1036 int optlen;
1037 unsigned int pref = 0;
1026 1038
1027 __u8 * opt = (__u8 *)(ra_msg + 1); 1039 __u8 * opt = (__u8 *)(ra_msg + 1);
1028 1040
@@ -1081,8 +1093,19 @@ static void ndisc_router_discovery(struct sk_buff *skb)
1081 (ra_msg->icmph.icmp6_addrconf_other ? 1093 (ra_msg->icmph.icmp6_addrconf_other ?
1082 IF_RA_OTHERCONF : 0); 1094 IF_RA_OTHERCONF : 0);
1083 1095
1096 if (!in6_dev->cnf.accept_ra_defrtr)
1097 goto skip_defrtr;
1098
1084 lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime); 1099 lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);
1085 1100
1101#ifdef CONFIG_IPV6_ROUTER_PREF
1102 pref = ra_msg->icmph.icmp6_router_pref;
1103 /* 10b is handled as if it were 00b (medium) */
1104 if (pref == ICMPV6_ROUTER_PREF_INVALID ||
1105 in6_dev->cnf.accept_ra_rtr_pref)
1106 pref = ICMPV6_ROUTER_PREF_MEDIUM;
1107#endif
1108
1086 rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev); 1109 rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
1087 1110
1088 if (rt) 1111 if (rt)
@@ -1098,7 +1121,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
1098 ND_PRINTK3(KERN_DEBUG 1121 ND_PRINTK3(KERN_DEBUG
1099 "ICMPv6 RA: adding default router.\n"); 1122 "ICMPv6 RA: adding default router.\n");
1100 1123
1101 rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev); 1124 rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev, pref);
1102 if (rt == NULL) { 1125 if (rt == NULL) {
1103 ND_PRINTK0(KERN_ERR 1126 ND_PRINTK0(KERN_ERR
1104 "ICMPv6 RA: %s() failed to add default route.\n", 1127 "ICMPv6 RA: %s() failed to add default route.\n",
@@ -1117,6 +1140,8 @@ static void ndisc_router_discovery(struct sk_buff *skb)
1117 return; 1140 return;
1118 } 1141 }
1119 neigh->flags |= NTF_ROUTER; 1142 neigh->flags |= NTF_ROUTER;
1143 } else if (rt) {
1144 rt->rt6i_flags |= (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
1120 } 1145 }
1121 1146
1122 if (rt) 1147 if (rt)
@@ -1128,6 +1153,8 @@ static void ndisc_router_discovery(struct sk_buff *skb)
1128 rt->u.dst.metrics[RTAX_HOPLIMIT-1] = ra_msg->icmph.icmp6_hop_limit; 1153 rt->u.dst.metrics[RTAX_HOPLIMIT-1] = ra_msg->icmph.icmp6_hop_limit;
1129 } 1154 }
1130 1155
1156skip_defrtr:
1157
1131 /* 1158 /*
1132 * Update Reachable Time and Retrans Timer 1159 * Update Reachable Time and Retrans Timer
1133 */ 1160 */
@@ -1186,7 +1213,21 @@ static void ndisc_router_discovery(struct sk_buff *skb)
1186 NEIGH_UPDATE_F_ISROUTER); 1213 NEIGH_UPDATE_F_ISROUTER);
1187 } 1214 }
1188 1215
1189 if (ndopts.nd_opts_pi) { 1216#ifdef CONFIG_IPV6_ROUTE_INFO
1217 if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) {
1218 struct nd_opt_hdr *p;
1219 for (p = ndopts.nd_opts_ri;
1220 p;
1221 p = ndisc_next_option(p, ndopts.nd_opts_ri_end)) {
1222 if (((struct route_info *)p)->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen)
1223 continue;
1224 rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3,
1225 &skb->nh.ipv6h->saddr);
1226 }
1227 }
1228#endif
1229
1230 if (in6_dev->cnf.accept_ra_pinfo && ndopts.nd_opts_pi) {
1190 struct nd_opt_hdr *p; 1231 struct nd_opt_hdr *p;
1191 for (p = ndopts.nd_opts_pi; 1232 for (p = ndopts.nd_opts_pi;
1192 p; 1233 p;
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 2d6f8ecbc27b..98f78759f1ab 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -133,16 +133,6 @@ config IP6_NF_MATCH_EUI64
133 133
134 To compile it as a module, choose M here. If unsure, say N. 134 To compile it as a module, choose M here. If unsure, say N.
135 135
136config IP6_NF_MATCH_POLICY
137 tristate "IPsec policy match support"
138 depends on IP6_NF_IPTABLES && XFRM
139 help
140 Policy matching allows you to match packets based on the
141 IPsec policy that was used during decapsulation/will
142 be used during encapsulation.
143
144 To compile it as a module, choose M here. If unsure, say N.
145
146# The targets 136# The targets
147config IP6_NF_FILTER 137config IP6_NF_FILTER
148 tristate "Packet filtering" 138 tristate "Packet filtering"
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index db6073c94163..8436a1a1731f 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -9,7 +9,6 @@ obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
9obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o 9obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
10obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o 10obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
11obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o 11obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o
12obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o
13obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o 12obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
14obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o 13obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
15obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o 14obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index af0635084df8..344eab3b5da8 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -35,6 +35,7 @@
35#include <linux/spinlock.h> 35#include <linux/spinlock.h>
36#include <linux/sysctl.h> 36#include <linux/sysctl.h>
37#include <linux/proc_fs.h> 37#include <linux/proc_fs.h>
38#include <linux/mutex.h>
38#include <net/sock.h> 39#include <net/sock.h>
39#include <net/ipv6.h> 40#include <net/ipv6.h>
40#include <net/ip6_route.h> 41#include <net/ip6_route.h>
@@ -65,7 +66,7 @@ static unsigned int queue_dropped = 0;
65static unsigned int queue_user_dropped = 0; 66static unsigned int queue_user_dropped = 0;
66static struct sock *ipqnl; 67static struct sock *ipqnl;
67static LIST_HEAD(queue_list); 68static LIST_HEAD(queue_list);
68static DECLARE_MUTEX(ipqnl_sem); 69static DEFINE_MUTEX(ipqnl_mutex);
69 70
70static void 71static void
71ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict) 72ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict)
@@ -537,7 +538,7 @@ ipq_rcv_sk(struct sock *sk, int len)
537 struct sk_buff *skb; 538 struct sk_buff *skb;
538 unsigned int qlen; 539 unsigned int qlen;
539 540
540 down(&ipqnl_sem); 541 mutex_lock(&ipqnl_mutex);
541 542
542 for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) { 543 for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
543 skb = skb_dequeue(&sk->sk_receive_queue); 544 skb = skb_dequeue(&sk->sk_receive_queue);
@@ -545,7 +546,7 @@ ipq_rcv_sk(struct sock *sk, int len)
545 kfree_skb(skb); 546 kfree_skb(skb);
546 } 547 }
547 548
548 up(&ipqnl_sem); 549 mutex_unlock(&ipqnl_mutex);
549} 550}
550 551
551static int 552static int
@@ -704,8 +705,8 @@ cleanup_sysctl:
704 705
705cleanup_ipqnl: 706cleanup_ipqnl:
706 sock_release(ipqnl->sk_socket); 707 sock_release(ipqnl->sk_socket);
707 down(&ipqnl_sem); 708 mutex_lock(&ipqnl_mutex);
708 up(&ipqnl_sem); 709 mutex_unlock(&ipqnl_mutex);
709 710
710cleanup_netlink_notifier: 711cleanup_netlink_notifier:
711 netlink_unregister_notifier(&ipq_nl_notifier); 712 netlink_unregister_notifier(&ipq_nl_notifier);
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 74ff56c322f4..db3c9ae98e95 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -29,7 +29,7 @@
29#include <linux/icmpv6.h> 29#include <linux/icmpv6.h>
30#include <net/ipv6.h> 30#include <net/ipv6.h>
31#include <asm/uaccess.h> 31#include <asm/uaccess.h>
32#include <asm/semaphore.h> 32#include <linux/mutex.h>
33#include <linux/proc_fs.h> 33#include <linux/proc_fs.h>
34#include <linux/cpumask.h> 34#include <linux/cpumask.h>
35 35
@@ -94,19 +94,6 @@ do { \
94#define up(x) do { printk("UP:%u:" #x "\n", __LINE__); up(x); } while(0) 94#define up(x) do { printk("UP:%u:" #x "\n", __LINE__); up(x); } while(0)
95#endif 95#endif
96 96
97int
98ip6_masked_addrcmp(const struct in6_addr *addr1, const struct in6_addr *mask,
99 const struct in6_addr *addr2)
100{
101 int i;
102 for( i = 0; i < 16; i++){
103 if((addr1->s6_addr[i] & mask->s6_addr[i]) !=
104 (addr2->s6_addr[i] & mask->s6_addr[i]))
105 return 1;
106 }
107 return 0;
108}
109
110/* Check for an extension */ 97/* Check for an extension */
111int 98int
112ip6t_ext_hdr(u8 nexthdr) 99ip6t_ext_hdr(u8 nexthdr)
@@ -135,10 +122,10 @@ ip6_packet_match(const struct sk_buff *skb,
135 122
136#define FWINV(bool,invflg) ((bool) ^ !!(ip6info->invflags & invflg)) 123#define FWINV(bool,invflg) ((bool) ^ !!(ip6info->invflags & invflg))
137 124
138 if (FWINV(ip6_masked_addrcmp(&ipv6->saddr, &ip6info->smsk, 125 if (FWINV(ipv6_masked_addr_cmp(&ipv6->saddr, &ip6info->smsk,
139 &ip6info->src), IP6T_INV_SRCIP) 126 &ip6info->src), IP6T_INV_SRCIP)
140 || FWINV(ip6_masked_addrcmp(&ipv6->daddr, &ip6info->dmsk, 127 || FWINV(ipv6_masked_addr_cmp(&ipv6->daddr, &ip6info->dmsk,
141 &ip6info->dst), IP6T_INV_DSTIP)) { 128 &ip6info->dst), IP6T_INV_DSTIP)) {
142 dprintf("Source or dest mismatch.\n"); 129 dprintf("Source or dest mismatch.\n");
143/* 130/*
144 dprintf("SRC: %u. Mask: %u. Target: %u.%s\n", ip->saddr, 131 dprintf("SRC: %u. Mask: %u. Target: %u.%s\n", ip->saddr,
@@ -232,6 +219,7 @@ ip6t_error(struct sk_buff **pskb,
232 const struct net_device *in, 219 const struct net_device *in,
233 const struct net_device *out, 220 const struct net_device *out,
234 unsigned int hooknum, 221 unsigned int hooknum,
222 const struct xt_target *target,
235 const void *targinfo, 223 const void *targinfo,
236 void *userinfo) 224 void *userinfo)
237{ 225{
@@ -251,7 +239,7 @@ int do_match(struct ip6t_entry_match *m,
251 int *hotdrop) 239 int *hotdrop)
252{ 240{
253 /* Stop iteration if it doesn't match */ 241 /* Stop iteration if it doesn't match */
254 if (!m->u.kernel.match->match(skb, in, out, m->data, 242 if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data,
255 offset, protoff, hotdrop)) 243 offset, protoff, hotdrop))
256 return 1; 244 return 1;
257 else 245 else
@@ -373,6 +361,7 @@ ip6t_do_table(struct sk_buff **pskb,
373 verdict = t->u.kernel.target->target(pskb, 361 verdict = t->u.kernel.target->target(pskb,
374 in, out, 362 in, out,
375 hook, 363 hook,
364 t->u.kernel.target,
376 t->data, 365 t->data,
377 userdata); 366 userdata);
378 367
@@ -531,7 +520,7 @@ cleanup_match(struct ip6t_entry_match *m, unsigned int *i)
531 return 1; 520 return 1;
532 521
533 if (m->u.kernel.match->destroy) 522 if (m->u.kernel.match->destroy)
534 m->u.kernel.match->destroy(m->data, 523 m->u.kernel.match->destroy(m->u.kernel.match, m->data,
535 m->u.match_size - sizeof(*m)); 524 m->u.match_size - sizeof(*m));
536 module_put(m->u.kernel.match->me); 525 module_put(m->u.kernel.match->me);
537 return 0; 526 return 0;
@@ -544,21 +533,12 @@ standard_check(const struct ip6t_entry_target *t,
544 struct ip6t_standard_target *targ = (void *)t; 533 struct ip6t_standard_target *targ = (void *)t;
545 534
546 /* Check standard info. */ 535 /* Check standard info. */
547 if (t->u.target_size
548 != IP6T_ALIGN(sizeof(struct ip6t_standard_target))) {
549 duprintf("standard_check: target size %u != %u\n",
550 t->u.target_size,
551 IP6T_ALIGN(sizeof(struct ip6t_standard_target)));
552 return 0;
553 }
554
555 if (targ->verdict >= 0 536 if (targ->verdict >= 0
556 && targ->verdict > max_offset - sizeof(struct ip6t_entry)) { 537 && targ->verdict > max_offset - sizeof(struct ip6t_entry)) {
557 duprintf("ip6t_standard_check: bad verdict (%i)\n", 538 duprintf("ip6t_standard_check: bad verdict (%i)\n",
558 targ->verdict); 539 targ->verdict);
559 return 0; 540 return 0;
560 } 541 }
561
562 if (targ->verdict < -NF_MAX_VERDICT - 1) { 542 if (targ->verdict < -NF_MAX_VERDICT - 1) {
563 duprintf("ip6t_standard_check: bad negative verdict (%i)\n", 543 duprintf("ip6t_standard_check: bad negative verdict (%i)\n",
564 targ->verdict); 544 targ->verdict);
@@ -575,6 +555,7 @@ check_match(struct ip6t_entry_match *m,
575 unsigned int *i) 555 unsigned int *i)
576{ 556{
577 struct ip6t_match *match; 557 struct ip6t_match *match;
558 int ret;
578 559
579 match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name, 560 match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name,
580 m->u.user.revision), 561 m->u.user.revision),
@@ -585,18 +566,27 @@ check_match(struct ip6t_entry_match *m,
585 } 566 }
586 m->u.kernel.match = match; 567 m->u.kernel.match = match;
587 568
569 ret = xt_check_match(match, AF_INET6, m->u.match_size - sizeof(*m),
570 name, hookmask, ipv6->proto,
571 ipv6->invflags & IP6T_INV_PROTO);
572 if (ret)
573 goto err;
574
588 if (m->u.kernel.match->checkentry 575 if (m->u.kernel.match->checkentry
589 && !m->u.kernel.match->checkentry(name, ipv6, m->data, 576 && !m->u.kernel.match->checkentry(name, ipv6, match, m->data,
590 m->u.match_size - sizeof(*m), 577 m->u.match_size - sizeof(*m),
591 hookmask)) { 578 hookmask)) {
592 module_put(m->u.kernel.match->me);
593 duprintf("ip_tables: check failed for `%s'.\n", 579 duprintf("ip_tables: check failed for `%s'.\n",
594 m->u.kernel.match->name); 580 m->u.kernel.match->name);
595 return -EINVAL; 581 ret = -EINVAL;
582 goto err;
596 } 583 }
597 584
598 (*i)++; 585 (*i)++;
599 return 0; 586 return 0;
587err:
588 module_put(m->u.kernel.match->me);
589 return ret;
600} 590}
601 591
602static struct ip6t_target ip6t_standard_target; 592static struct ip6t_target ip6t_standard_target;
@@ -632,26 +622,32 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
632 } 622 }
633 t->u.kernel.target = target; 623 t->u.kernel.target = target;
634 624
625 ret = xt_check_target(target, AF_INET6, t->u.target_size - sizeof(*t),
626 name, e->comefrom, e->ipv6.proto,
627 e->ipv6.invflags & IP6T_INV_PROTO);
628 if (ret)
629 goto err;
630
635 if (t->u.kernel.target == &ip6t_standard_target) { 631 if (t->u.kernel.target == &ip6t_standard_target) {
636 if (!standard_check(t, size)) { 632 if (!standard_check(t, size)) {
637 ret = -EINVAL; 633 ret = -EINVAL;
638 goto cleanup_matches; 634 goto cleanup_matches;
639 } 635 }
640 } else if (t->u.kernel.target->checkentry 636 } else if (t->u.kernel.target->checkentry
641 && !t->u.kernel.target->checkentry(name, e, t->data, 637 && !t->u.kernel.target->checkentry(name, e, target, t->data,
642 t->u.target_size 638 t->u.target_size
643 - sizeof(*t), 639 - sizeof(*t),
644 e->comefrom)) { 640 e->comefrom)) {
645 module_put(t->u.kernel.target->me);
646 duprintf("ip_tables: check failed for `%s'.\n", 641 duprintf("ip_tables: check failed for `%s'.\n",
647 t->u.kernel.target->name); 642 t->u.kernel.target->name);
648 ret = -EINVAL; 643 ret = -EINVAL;
649 goto cleanup_matches; 644 goto err;
650 } 645 }
651 646
652 (*i)++; 647 (*i)++;
653 return 0; 648 return 0;
654 649 err:
650 module_put(t->u.kernel.target->me);
655 cleanup_matches: 651 cleanup_matches:
656 IP6T_MATCH_ITERATE(e, cleanup_match, &j); 652 IP6T_MATCH_ITERATE(e, cleanup_match, &j);
657 return ret; 653 return ret;
@@ -712,7 +708,7 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i)
712 IP6T_MATCH_ITERATE(e, cleanup_match, NULL); 708 IP6T_MATCH_ITERATE(e, cleanup_match, NULL);
713 t = ip6t_get_target(e); 709 t = ip6t_get_target(e);
714 if (t->u.kernel.target->destroy) 710 if (t->u.kernel.target->destroy)
715 t->u.kernel.target->destroy(t->data, 711 t->u.kernel.target->destroy(t->u.kernel.target, t->data,
716 t->u.target_size - sizeof(*t)); 712 t->u.target_size - sizeof(*t));
717 module_put(t->u.kernel.target->me); 713 module_put(t->u.kernel.target->me);
718 return 0; 714 return 0;
@@ -1333,6 +1329,7 @@ static int
1333icmp6_match(const struct sk_buff *skb, 1329icmp6_match(const struct sk_buff *skb,
1334 const struct net_device *in, 1330 const struct net_device *in,
1335 const struct net_device *out, 1331 const struct net_device *out,
1332 const struct xt_match *match,
1336 const void *matchinfo, 1333 const void *matchinfo,
1337 int offset, 1334 int offset,
1338 unsigned int protoff, 1335 unsigned int protoff,
@@ -1365,28 +1362,29 @@ icmp6_match(const struct sk_buff *skb,
1365static int 1362static int
1366icmp6_checkentry(const char *tablename, 1363icmp6_checkentry(const char *tablename,
1367 const void *entry, 1364 const void *entry,
1365 const struct xt_match *match,
1368 void *matchinfo, 1366 void *matchinfo,
1369 unsigned int matchsize, 1367 unsigned int matchsize,
1370 unsigned int hook_mask) 1368 unsigned int hook_mask)
1371{ 1369{
1372 const struct ip6t_ip6 *ipv6 = entry;
1373 const struct ip6t_icmp *icmpinfo = matchinfo; 1370 const struct ip6t_icmp *icmpinfo = matchinfo;
1374 1371
1375 /* Must specify proto == ICMP, and no unknown invflags */ 1372 /* Must specify no unknown invflags */
1376 return ipv6->proto == IPPROTO_ICMPV6 1373 return !(icmpinfo->invflags & ~IP6T_ICMP_INV);
1377 && !(ipv6->invflags & IP6T_INV_PROTO)
1378 && matchsize == IP6T_ALIGN(sizeof(struct ip6t_icmp))
1379 && !(icmpinfo->invflags & ~IP6T_ICMP_INV);
1380} 1374}
1381 1375
1382/* The built-in targets: standard (NULL) and error. */ 1376/* The built-in targets: standard (NULL) and error. */
1383static struct ip6t_target ip6t_standard_target = { 1377static struct ip6t_target ip6t_standard_target = {
1384 .name = IP6T_STANDARD_TARGET, 1378 .name = IP6T_STANDARD_TARGET,
1379 .targetsize = sizeof(int),
1380 .family = AF_INET6,
1385}; 1381};
1386 1382
1387static struct ip6t_target ip6t_error_target = { 1383static struct ip6t_target ip6t_error_target = {
1388 .name = IP6T_ERROR_TARGET, 1384 .name = IP6T_ERROR_TARGET,
1389 .target = ip6t_error, 1385 .target = ip6t_error,
1386 .targetsize = IP6T_FUNCTION_MAXNAMELEN,
1387 .family = AF_INET6,
1390}; 1388};
1391 1389
1392static struct nf_sockopt_ops ip6t_sockopts = { 1390static struct nf_sockopt_ops ip6t_sockopts = {
@@ -1402,7 +1400,10 @@ static struct nf_sockopt_ops ip6t_sockopts = {
1402static struct ip6t_match icmp6_matchstruct = { 1400static struct ip6t_match icmp6_matchstruct = {
1403 .name = "icmp6", 1401 .name = "icmp6",
1404 .match = &icmp6_match, 1402 .match = &icmp6_match,
1405 .checkentry = &icmp6_checkentry, 1403 .matchsize = sizeof(struct ip6t_icmp),
1404 .checkentry = icmp6_checkentry,
1405 .proto = IPPROTO_ICMPV6,
1406 .family = AF_INET6,
1406}; 1407};
1407 1408
1408static int __init init(void) 1409static int __init init(void)
@@ -1412,9 +1413,9 @@ static int __init init(void)
1412 xt_proto_init(AF_INET6); 1413 xt_proto_init(AF_INET6);
1413 1414
1414 /* Noone else will be downing sem now, so we won't sleep */ 1415 /* Noone else will be downing sem now, so we won't sleep */
1415 xt_register_target(AF_INET6, &ip6t_standard_target); 1416 xt_register_target(&ip6t_standard_target);
1416 xt_register_target(AF_INET6, &ip6t_error_target); 1417 xt_register_target(&ip6t_error_target);
1417 xt_register_match(AF_INET6, &icmp6_matchstruct); 1418 xt_register_match(&icmp6_matchstruct);
1418 1419
1419 /* Register setsockopt */ 1420 /* Register setsockopt */
1420 ret = nf_register_sockopt(&ip6t_sockopts); 1421 ret = nf_register_sockopt(&ip6t_sockopts);
@@ -1431,9 +1432,9 @@ static int __init init(void)
1431static void __exit fini(void) 1432static void __exit fini(void)
1432{ 1433{
1433 nf_unregister_sockopt(&ip6t_sockopts); 1434 nf_unregister_sockopt(&ip6t_sockopts);
1434 xt_unregister_match(AF_INET6, &icmp6_matchstruct); 1435 xt_unregister_match(&icmp6_matchstruct);
1435 xt_unregister_target(AF_INET6, &ip6t_error_target); 1436 xt_unregister_target(&ip6t_error_target);
1436 xt_unregister_target(AF_INET6, &ip6t_standard_target); 1437 xt_unregister_target(&ip6t_standard_target);
1437 xt_proto_fini(AF_INET6); 1438 xt_proto_fini(AF_INET6);
1438} 1439}
1439 1440
@@ -1515,7 +1516,6 @@ EXPORT_SYMBOL(ip6t_unregister_table);
1515EXPORT_SYMBOL(ip6t_do_table); 1516EXPORT_SYMBOL(ip6t_do_table);
1516EXPORT_SYMBOL(ip6t_ext_hdr); 1517EXPORT_SYMBOL(ip6t_ext_hdr);
1517EXPORT_SYMBOL(ipv6_find_hdr); 1518EXPORT_SYMBOL(ipv6_find_hdr);
1518EXPORT_SYMBOL(ip6_masked_addrcmp);
1519 1519
1520module_init(init); 1520module_init(init);
1521module_exit(fini); 1521module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c
index 306200c35057..da14c6d86bcc 100644
--- a/net/ipv6/netfilter/ip6t_HL.c
+++ b/net/ipv6/netfilter/ip6t_HL.c
@@ -21,6 +21,7 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb,
21 const struct net_device *in, 21 const struct net_device *in,
22 const struct net_device *out, 22 const struct net_device *out,
23 unsigned int hooknum, 23 unsigned int hooknum,
24 const struct xt_target *target,
24 const void *targinfo, void *userinfo) 25 const void *targinfo, void *userinfo)
25{ 26{
26 struct ipv6hdr *ip6h; 27 struct ipv6hdr *ip6h;
@@ -63,43 +64,31 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb,
63 64
64static int ip6t_hl_checkentry(const char *tablename, 65static int ip6t_hl_checkentry(const char *tablename,
65 const void *entry, 66 const void *entry,
67 const struct xt_target *target,
66 void *targinfo, 68 void *targinfo,
67 unsigned int targinfosize, 69 unsigned int targinfosize,
68 unsigned int hook_mask) 70 unsigned int hook_mask)
69{ 71{
70 struct ip6t_HL_info *info = targinfo; 72 struct ip6t_HL_info *info = targinfo;
71 73
72 if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
73 printk(KERN_WARNING "ip6t_HL: targinfosize %u != %Zu\n",
74 targinfosize,
75 IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
76 return 0;
77 }
78
79 if (strcmp(tablename, "mangle")) {
80 printk(KERN_WARNING "ip6t_HL: can only be called from "
81 "\"mangle\" table, not \"%s\"\n", tablename);
82 return 0;
83 }
84
85 if (info->mode > IP6T_HL_MAXMODE) { 74 if (info->mode > IP6T_HL_MAXMODE) {
86 printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n", 75 printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n",
87 info->mode); 76 info->mode);
88 return 0; 77 return 0;
89 } 78 }
90
91 if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) { 79 if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
92 printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't " 80 printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't "
93 "make sense with value 0\n"); 81 "make sense with value 0\n");
94 return 0; 82 return 0;
95 } 83 }
96
97 return 1; 84 return 1;
98} 85}
99 86
100static struct ip6t_target ip6t_HL = { 87static struct ip6t_target ip6t_HL = {
101 .name = "HL", 88 .name = "HL",
102 .target = ip6t_hl_target, 89 .target = ip6t_hl_target,
90 .targetsize = sizeof(struct ip6t_HL_info),
91 .table = "mangle",
103 .checkentry = ip6t_hl_checkentry, 92 .checkentry = ip6t_hl_checkentry,
104 .me = THIS_MODULE 93 .me = THIS_MODULE
105}; 94};
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 6b930efa9fb9..07c6bcbe4c5f 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -426,6 +426,7 @@ ip6t_log_target(struct sk_buff **pskb,
426 const struct net_device *in, 426 const struct net_device *in,
427 const struct net_device *out, 427 const struct net_device *out,
428 unsigned int hooknum, 428 unsigned int hooknum,
429 const struct xt_target *target,
429 const void *targinfo, 430 const void *targinfo,
430 void *userinfo) 431 void *userinfo)
431{ 432{
@@ -449,35 +450,29 @@ ip6t_log_target(struct sk_buff **pskb,
449 450
450static int ip6t_log_checkentry(const char *tablename, 451static int ip6t_log_checkentry(const char *tablename,
451 const void *entry, 452 const void *entry,
453 const struct xt_target *target,
452 void *targinfo, 454 void *targinfo,
453 unsigned int targinfosize, 455 unsigned int targinfosize,
454 unsigned int hook_mask) 456 unsigned int hook_mask)
455{ 457{
456 const struct ip6t_log_info *loginfo = targinfo; 458 const struct ip6t_log_info *loginfo = targinfo;
457 459
458 if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_log_info))) {
459 DEBUGP("LOG: targinfosize %u != %u\n",
460 targinfosize, IP6T_ALIGN(sizeof(struct ip6t_log_info)));
461 return 0;
462 }
463
464 if (loginfo->level >= 8) { 460 if (loginfo->level >= 8) {
465 DEBUGP("LOG: level %u >= 8\n", loginfo->level); 461 DEBUGP("LOG: level %u >= 8\n", loginfo->level);
466 return 0; 462 return 0;
467 } 463 }
468
469 if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') { 464 if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
470 DEBUGP("LOG: prefix term %i\n", 465 DEBUGP("LOG: prefix term %i\n",
471 loginfo->prefix[sizeof(loginfo->prefix)-1]); 466 loginfo->prefix[sizeof(loginfo->prefix)-1]);
472 return 0; 467 return 0;
473 } 468 }
474
475 return 1; 469 return 1;
476} 470}
477 471
478static struct ip6t_target ip6t_log_reg = { 472static struct ip6t_target ip6t_log_reg = {
479 .name = "LOG", 473 .name = "LOG",
480 .target = ip6t_log_target, 474 .target = ip6t_log_target,
475 .targetsize = sizeof(struct ip6t_log_info),
481 .checkentry = ip6t_log_checkentry, 476 .checkentry = ip6t_log_checkentry,
482 .me = THIS_MODULE, 477 .me = THIS_MODULE,
483}; 478};
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index 0e6d1d4bbd5c..ddfa38575fe2 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -179,6 +179,7 @@ static unsigned int reject6_target(struct sk_buff **pskb,
179 const struct net_device *in, 179 const struct net_device *in,
180 const struct net_device *out, 180 const struct net_device *out,
181 unsigned int hooknum, 181 unsigned int hooknum,
182 const struct xt_target *target,
182 const void *targinfo, 183 const void *targinfo,
183 void *userinfo) 184 void *userinfo)
184{ 185{
@@ -221,6 +222,7 @@ static unsigned int reject6_target(struct sk_buff **pskb,
221 222
222static int check(const char *tablename, 223static int check(const char *tablename,
223 const void *entry, 224 const void *entry,
225 const struct xt_target *target,
224 void *targinfo, 226 void *targinfo,
225 unsigned int targinfosize, 227 unsigned int targinfosize,
226 unsigned int hook_mask) 228 unsigned int hook_mask)
@@ -228,24 +230,6 @@ static int check(const char *tablename,
228 const struct ip6t_reject_info *rejinfo = targinfo; 230 const struct ip6t_reject_info *rejinfo = targinfo;
229 const struct ip6t_entry *e = entry; 231 const struct ip6t_entry *e = entry;
230 232
231 if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
232 DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize);
233 return 0;
234 }
235
236 /* Only allow these for packet filtering. */
237 if (strcmp(tablename, "filter") != 0) {
238 DEBUGP("ip6t_REJECT: bad table `%s'.\n", tablename);
239 return 0;
240 }
241
242 if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
243 | (1 << NF_IP6_FORWARD)
244 | (1 << NF_IP6_LOCAL_OUT))) != 0) {
245 DEBUGP("ip6t_REJECT: bad hook mask %X\n", hook_mask);
246 return 0;
247 }
248
249 if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) { 233 if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
250 printk("ip6t_REJECT: ECHOREPLY is not supported.\n"); 234 printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
251 return 0; 235 return 0;
@@ -257,13 +241,16 @@ static int check(const char *tablename,
257 return 0; 241 return 0;
258 } 242 }
259 } 243 }
260
261 return 1; 244 return 1;
262} 245}
263 246
264static struct ip6t_target ip6t_reject_reg = { 247static struct ip6t_target ip6t_reject_reg = {
265 .name = "REJECT", 248 .name = "REJECT",
266 .target = reject6_target, 249 .target = reject6_target,
250 .targetsize = sizeof(struct ip6t_reject_info),
251 .table = "filter",
252 .hooks = (1 << NF_IP6_LOCAL_IN) | (1 << NF_IP6_FORWARD) |
253 (1 << NF_IP6_LOCAL_OUT),
267 .checkentry = check, 254 .checkentry = check,
268 .me = THIS_MODULE 255 .me = THIS_MODULE
269}; 256};
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index 219a30365dff..178f6fb1e53d 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -44,6 +44,7 @@ static int
44match(const struct sk_buff *skb, 44match(const struct sk_buff *skb,
45 const struct net_device *in, 45 const struct net_device *in,
46 const struct net_device *out, 46 const struct net_device *out,
47 const struct xt_match *match,
47 const void *matchinfo, 48 const void *matchinfo,
48 int offset, 49 int offset,
49 unsigned int protoff, 50 unsigned int protoff,
@@ -99,17 +100,13 @@ match(const struct sk_buff *skb,
99static int 100static int
100checkentry(const char *tablename, 101checkentry(const char *tablename,
101 const void *entry, 102 const void *entry,
103 const struct xt_match *match,
102 void *matchinfo, 104 void *matchinfo,
103 unsigned int matchinfosize, 105 unsigned int matchinfosize,
104 unsigned int hook_mask) 106 unsigned int hook_mask)
105{ 107{
106 const struct ip6t_ah *ahinfo = matchinfo; 108 const struct ip6t_ah *ahinfo = matchinfo;
107 109
108 if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_ah))) {
109 DEBUGP("ip6t_ah: matchsize %u != %u\n",
110 matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_ah)));
111 return 0;
112 }
113 if (ahinfo->invflags & ~IP6T_AH_INV_MASK) { 110 if (ahinfo->invflags & ~IP6T_AH_INV_MASK) {
114 DEBUGP("ip6t_ah: unknown flags %X\n", ahinfo->invflags); 111 DEBUGP("ip6t_ah: unknown flags %X\n", ahinfo->invflags);
115 return 0; 112 return 0;
@@ -119,8 +116,9 @@ checkentry(const char *tablename,
119 116
120static struct ip6t_match ah_match = { 117static struct ip6t_match ah_match = {
121 .name = "ah", 118 .name = "ah",
122 .match = &match, 119 .match = match,
123 .checkentry = &checkentry, 120 .matchsize = sizeof(struct ip6t_ah),
121 .checkentry = checkentry,
124 .me = THIS_MODULE, 122 .me = THIS_MODULE,
125}; 123};
126 124
diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c
index b4c153a53500..e97a70226987 100644
--- a/net/ipv6/netfilter/ip6t_dst.c
+++ b/net/ipv6/netfilter/ip6t_dst.c
@@ -55,6 +55,7 @@ static int
55match(const struct sk_buff *skb, 55match(const struct sk_buff *skb,
56 const struct net_device *in, 56 const struct net_device *in,
57 const struct net_device *out, 57 const struct net_device *out,
58 const struct xt_match *match,
58 const void *matchinfo, 59 const void *matchinfo,
59 int offset, 60 int offset,
60 unsigned int protoff, 61 unsigned int protoff,
@@ -179,22 +180,17 @@ match(const struct sk_buff *skb,
179static int 180static int
180checkentry(const char *tablename, 181checkentry(const char *tablename,
181 const void *info, 182 const void *info,
183 const struct xt_match *match,
182 void *matchinfo, 184 void *matchinfo,
183 unsigned int matchinfosize, 185 unsigned int matchinfosize,
184 unsigned int hook_mask) 186 unsigned int hook_mask)
185{ 187{
186 const struct ip6t_opts *optsinfo = matchinfo; 188 const struct ip6t_opts *optsinfo = matchinfo;
187 189
188 if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_opts))) {
189 DEBUGP("ip6t_opts: matchsize %u != %u\n",
190 matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_opts)));
191 return 0;
192 }
193 if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) { 190 if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) {
194 DEBUGP("ip6t_opts: unknown flags %X\n", optsinfo->invflags); 191 DEBUGP("ip6t_opts: unknown flags %X\n", optsinfo->invflags);
195 return 0; 192 return 0;
196 } 193 }
197
198 return 1; 194 return 1;
199} 195}
200 196
@@ -204,8 +200,9 @@ static struct ip6t_match opts_match = {
204#else 200#else
205 .name = "dst", 201 .name = "dst",
206#endif 202#endif
207 .match = &match, 203 .match = match,
208 .checkentry = &checkentry, 204 .matchsize = sizeof(struct ip6t_opts),
205 .checkentry = checkentry,
209 .me = THIS_MODULE, 206 .me = THIS_MODULE,
210}; 207};
211 208
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c
index 724285df8711..540b8bfd5055 100644
--- a/net/ipv6/netfilter/ip6t_esp.c
+++ b/net/ipv6/netfilter/ip6t_esp.c
@@ -44,6 +44,7 @@ static int
44match(const struct sk_buff *skb, 44match(const struct sk_buff *skb,
45 const struct net_device *in, 45 const struct net_device *in,
46 const struct net_device *out, 46 const struct net_device *out,
47 const struct xt_match *match,
47 const void *matchinfo, 48 const void *matchinfo,
48 int offset, 49 int offset,
49 unsigned int protoff, 50 unsigned int protoff,
@@ -77,17 +78,13 @@ match(const struct sk_buff *skb,
77static int 78static int
78checkentry(const char *tablename, 79checkentry(const char *tablename,
79 const void *ip, 80 const void *ip,
81 const struct xt_match *match,
80 void *matchinfo, 82 void *matchinfo,
81 unsigned int matchinfosize, 83 unsigned int matchinfosize,
82 unsigned int hook_mask) 84 unsigned int hook_mask)
83{ 85{
84 const struct ip6t_esp *espinfo = matchinfo; 86 const struct ip6t_esp *espinfo = matchinfo;
85 87
86 if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_esp))) {
87 DEBUGP("ip6t_esp: matchsize %u != %u\n",
88 matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_esp)));
89 return 0;
90 }
91 if (espinfo->invflags & ~IP6T_ESP_INV_MASK) { 88 if (espinfo->invflags & ~IP6T_ESP_INV_MASK) {
92 DEBUGP("ip6t_esp: unknown flags %X\n", 89 DEBUGP("ip6t_esp: unknown flags %X\n",
93 espinfo->invflags); 90 espinfo->invflags);
@@ -98,8 +95,9 @@ checkentry(const char *tablename,
98 95
99static struct ip6t_match esp_match = { 96static struct ip6t_match esp_match = {
100 .name = "esp", 97 .name = "esp",
101 .match = &match, 98 .match = match,
102 .checkentry = &checkentry, 99 .matchsize = sizeof(struct ip6t_esp),
100 .checkentry = checkentry,
103 .me = THIS_MODULE, 101 .me = THIS_MODULE,
104}; 102};
105 103
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
index 27396ac0b9ed..d4b0bad52830 100644
--- a/net/ipv6/netfilter/ip6t_eui64.c
+++ b/net/ipv6/netfilter/ip6t_eui64.c
@@ -22,6 +22,7 @@ static int
22match(const struct sk_buff *skb, 22match(const struct sk_buff *skb,
23 const struct net_device *in, 23 const struct net_device *in,
24 const struct net_device *out, 24 const struct net_device *out,
25 const struct xt_match *match,
25 const void *matchinfo, 26 const void *matchinfo,
26 int offset, 27 int offset,
27 unsigned int protoff, 28 unsigned int protoff,
@@ -60,30 +61,12 @@ match(const struct sk_buff *skb,
60 return 0; 61 return 0;
61} 62}
62 63
63static int
64ip6t_eui64_checkentry(const char *tablename,
65 const void *ip,
66 void *matchinfo,
67 unsigned int matchsize,
68 unsigned int hook_mask)
69{
70 if (hook_mask
71 & ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN) |
72 (1 << NF_IP6_FORWARD))) {
73 printk("ip6t_eui64: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n");
74 return 0;
75 }
76
77 if (matchsize != IP6T_ALIGN(sizeof(int)))
78 return 0;
79
80 return 1;
81}
82
83static struct ip6t_match eui64_match = { 64static struct ip6t_match eui64_match = {
84 .name = "eui64", 65 .name = "eui64",
85 .match = &match, 66 .match = match,
86 .checkentry = &ip6t_eui64_checkentry, 67 .matchsize = sizeof(int),
68 .hooks = (1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN) |
69 (1 << NF_IP6_FORWARD),
87 .me = THIS_MODULE, 70 .me = THIS_MODULE,
88}; 71};
89 72
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index 4c14125a0e26..4c41e14823d5 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -43,6 +43,7 @@ static int
43match(const struct sk_buff *skb, 43match(const struct sk_buff *skb,
44 const struct net_device *in, 44 const struct net_device *in,
45 const struct net_device *out, 45 const struct net_device *out,
46 const struct xt_match *match,
46 const void *matchinfo, 47 const void *matchinfo,
47 int offset, 48 int offset,
48 unsigned int protoff, 49 unsigned int protoff,
@@ -116,29 +117,25 @@ match(const struct sk_buff *skb,
116static int 117static int
117checkentry(const char *tablename, 118checkentry(const char *tablename,
118 const void *ip, 119 const void *ip,
120 const struct xt_match *match,
119 void *matchinfo, 121 void *matchinfo,
120 unsigned int matchinfosize, 122 unsigned int matchinfosize,
121 unsigned int hook_mask) 123 unsigned int hook_mask)
122{ 124{
123 const struct ip6t_frag *fraginfo = matchinfo; 125 const struct ip6t_frag *fraginfo = matchinfo;
124 126
125 if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_frag))) {
126 DEBUGP("ip6t_frag: matchsize %u != %u\n",
127 matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_frag)));
128 return 0;
129 }
130 if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) { 127 if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) {
131 DEBUGP("ip6t_frag: unknown flags %X\n", fraginfo->invflags); 128 DEBUGP("ip6t_frag: unknown flags %X\n", fraginfo->invflags);
132 return 0; 129 return 0;
133 } 130 }
134
135 return 1; 131 return 1;
136} 132}
137 133
138static struct ip6t_match frag_match = { 134static struct ip6t_match frag_match = {
139 .name = "frag", 135 .name = "frag",
140 .match = &match, 136 .match = match,
141 .checkentry = &checkentry, 137 .matchsize = sizeof(struct ip6t_frag),
138 .checkentry = checkentry,
142 .me = THIS_MODULE, 139 .me = THIS_MODULE,
143}; 140};
144 141
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index 37a8474a7e0c..b4a1fdfe6abc 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -55,6 +55,7 @@ static int
55match(const struct sk_buff *skb, 55match(const struct sk_buff *skb,
56 const struct net_device *in, 56 const struct net_device *in,
57 const struct net_device *out, 57 const struct net_device *out,
58 const struct xt_match *match,
58 const void *matchinfo, 59 const void *matchinfo,
59 int offset, 60 int offset,
60 unsigned int protoff, 61 unsigned int protoff,
@@ -179,22 +180,17 @@ match(const struct sk_buff *skb,
179static int 180static int
180checkentry(const char *tablename, 181checkentry(const char *tablename,
181 const void *entry, 182 const void *entry,
183 const struct xt_match *match,
182 void *matchinfo, 184 void *matchinfo,
183 unsigned int matchinfosize, 185 unsigned int matchinfosize,
184 unsigned int hook_mask) 186 unsigned int hook_mask)
185{ 187{
186 const struct ip6t_opts *optsinfo = matchinfo; 188 const struct ip6t_opts *optsinfo = matchinfo;
187 189
188 if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_opts))) {
189 DEBUGP("ip6t_opts: matchsize %u != %u\n",
190 matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_opts)));
191 return 0;
192 }
193 if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) { 190 if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) {
194 DEBUGP("ip6t_opts: unknown flags %X\n", optsinfo->invflags); 191 DEBUGP("ip6t_opts: unknown flags %X\n", optsinfo->invflags);
195 return 0; 192 return 0;
196 } 193 }
197
198 return 1; 194 return 1;
199} 195}
200 196
@@ -204,8 +200,9 @@ static struct ip6t_match opts_match = {
204#else 200#else
205 .name = "dst", 201 .name = "dst",
206#endif 202#endif
207 .match = &match, 203 .match = match,
208 .checkentry = &checkentry, 204 .matchsize = sizeof(struct ip6t_opts),
205 .checkentry = checkentry,
209 .me = THIS_MODULE, 206 .me = THIS_MODULE,
210}; 207};
211 208
diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c
index c5d9079f2d9d..374055733b26 100644
--- a/net/ipv6/netfilter/ip6t_hl.c
+++ b/net/ipv6/netfilter/ip6t_hl.c
@@ -18,10 +18,10 @@ MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
18MODULE_DESCRIPTION("IP tables Hop Limit matching module"); 18MODULE_DESCRIPTION("IP tables Hop Limit matching module");
19MODULE_LICENSE("GPL"); 19MODULE_LICENSE("GPL");
20 20
21static int match(const struct sk_buff *skb, const struct net_device *in, 21static int match(const struct sk_buff *skb,
22 const struct net_device *out, const void *matchinfo, 22 const struct net_device *in, const struct net_device *out,
23 int offset, unsigned int protoff, 23 const struct xt_match *match, const void *matchinfo,
24 int *hotdrop) 24 int offset, unsigned int protoff, int *hotdrop)
25{ 25{
26 const struct ip6t_hl_info *info = matchinfo; 26 const struct ip6t_hl_info *info = matchinfo;
27 const struct ipv6hdr *ip6h = skb->nh.ipv6h; 27 const struct ipv6hdr *ip6h = skb->nh.ipv6h;
@@ -48,20 +48,10 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
48 return 0; 48 return 0;
49} 49}
50 50
51static int checkentry(const char *tablename, const void *entry,
52 void *matchinfo, unsigned int matchsize,
53 unsigned int hook_mask)
54{
55 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_hl_info)))
56 return 0;
57
58 return 1;
59}
60
61static struct ip6t_match hl_match = { 51static struct ip6t_match hl_match = {
62 .name = "hl", 52 .name = "hl",
63 .match = &match, 53 .match = match,
64 .checkentry = &checkentry, 54 .matchsize = sizeof(struct ip6t_hl_info),
65 .me = THIS_MODULE, 55 .me = THIS_MODULE,
66}; 56};
67 57
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c
index 83ad6b272f7e..9375eeb1369f 100644
--- a/net/ipv6/netfilter/ip6t_ipv6header.c
+++ b/net/ipv6/netfilter/ip6t_ipv6header.c
@@ -29,6 +29,7 @@ static int
29ipv6header_match(const struct sk_buff *skb, 29ipv6header_match(const struct sk_buff *skb,
30 const struct net_device *in, 30 const struct net_device *in,
31 const struct net_device *out, 31 const struct net_device *out,
32 const struct xt_match *match,
32 const void *matchinfo, 33 const void *matchinfo,
33 int offset, 34 int offset,
34 unsigned int protoff, 35 unsigned int protoff,
@@ -125,17 +126,13 @@ ipv6header_match(const struct sk_buff *skb,
125static int 126static int
126ipv6header_checkentry(const char *tablename, 127ipv6header_checkentry(const char *tablename,
127 const void *ip, 128 const void *ip,
129 const struct xt_match *match,
128 void *matchinfo, 130 void *matchinfo,
129 unsigned int matchsize, 131 unsigned int matchsize,
130 unsigned int hook_mask) 132 unsigned int hook_mask)
131{ 133{
132 const struct ip6t_ipv6header_info *info = matchinfo; 134 const struct ip6t_ipv6header_info *info = matchinfo;
133 135
134 /* Check for obvious errors */
135 /* This match is valid in all hooks! */
136 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_ipv6header_info)))
137 return 0;
138
139 /* invflags is 0 or 0xff in hard mode */ 136 /* invflags is 0 or 0xff in hard mode */
140 if ((!info->modeflag) && info->invflags != 0x00 && 137 if ((!info->modeflag) && info->invflags != 0x00 &&
141 info->invflags != 0xFF) 138 info->invflags != 0xFF)
@@ -147,6 +144,7 @@ ipv6header_checkentry(const char *tablename,
147static struct ip6t_match ip6t_ipv6header_match = { 144static struct ip6t_match ip6t_ipv6header_match = {
148 .name = "ipv6header", 145 .name = "ipv6header",
149 .match = &ipv6header_match, 146 .match = &ipv6header_match,
147 .matchsize = sizeof(struct ip6t_ipv6header_info),
150 .checkentry = &ipv6header_checkentry, 148 .checkentry = &ipv6header_checkentry,
151 .destroy = NULL, 149 .destroy = NULL,
152 .me = THIS_MODULE, 150 .me = THIS_MODULE,
diff --git a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c
index 49f7829dfbc2..752b65d21c72 100644
--- a/net/ipv6/netfilter/ip6t_multiport.c
+++ b/net/ipv6/netfilter/ip6t_multiport.c
@@ -51,6 +51,7 @@ static int
51match(const struct sk_buff *skb, 51match(const struct sk_buff *skb,
52 const struct net_device *in, 52 const struct net_device *in,
53 const struct net_device *out, 53 const struct net_device *out,
54 const struct xt_match *match,
54 const void *matchinfo, 55 const void *matchinfo,
55 int offset, 56 int offset,
56 unsigned int protoff, 57 unsigned int protoff,
@@ -85,6 +86,7 @@ match(const struct sk_buff *skb,
85static int 86static int
86checkentry(const char *tablename, 87checkentry(const char *tablename,
87 const void *info, 88 const void *info,
89 const struct xt_match *match,
88 void *matchinfo, 90 void *matchinfo,
89 unsigned int matchsize, 91 unsigned int matchsize,
90 unsigned int hook_mask) 92 unsigned int hook_mask)
@@ -92,13 +94,9 @@ checkentry(const char *tablename,
92 const struct ip6t_ip6 *ip = info; 94 const struct ip6t_ip6 *ip = info;
93 const struct ip6t_multiport *multiinfo = matchinfo; 95 const struct ip6t_multiport *multiinfo = matchinfo;
94 96
95 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_multiport)))
96 return 0;
97
98 /* Must specify proto == TCP/UDP, no unknown flags or bad count */ 97 /* Must specify proto == TCP/UDP, no unknown flags or bad count */
99 return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP) 98 return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
100 && !(ip->invflags & IP6T_INV_PROTO) 99 && !(ip->invflags & IP6T_INV_PROTO)
101 && matchsize == IP6T_ALIGN(sizeof(struct ip6t_multiport))
102 && (multiinfo->flags == IP6T_MULTIPORT_SOURCE 100 && (multiinfo->flags == IP6T_MULTIPORT_SOURCE
103 || multiinfo->flags == IP6T_MULTIPORT_DESTINATION 101 || multiinfo->flags == IP6T_MULTIPORT_DESTINATION
104 || multiinfo->flags == IP6T_MULTIPORT_EITHER) 102 || multiinfo->flags == IP6T_MULTIPORT_EITHER)
@@ -107,8 +105,9 @@ checkentry(const char *tablename,
107 105
108static struct ip6t_match multiport_match = { 106static struct ip6t_match multiport_match = {
109 .name = "multiport", 107 .name = "multiport",
110 .match = &match, 108 .match = match,
111 .checkentry = &checkentry, 109 .matchsize = sizeof(struct ip6t_multiport),
110 .checkentry = checkentry,
112 .me = THIS_MODULE, 111 .me = THIS_MODULE,
113}; 112};
114 113
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c
index 8c8a4c7ec934..e2cee3bcdef9 100644
--- a/net/ipv6/netfilter/ip6t_owner.c
+++ b/net/ipv6/netfilter/ip6t_owner.c
@@ -26,6 +26,7 @@ static int
26match(const struct sk_buff *skb, 26match(const struct sk_buff *skb,
27 const struct net_device *in, 27 const struct net_device *in,
28 const struct net_device *out, 28 const struct net_device *out,
29 const struct xt_match *match,
29 const void *matchinfo, 30 const void *matchinfo,
30 int offset, 31 int offset,
31 unsigned int protoff, 32 unsigned int protoff,
@@ -54,34 +55,27 @@ match(const struct sk_buff *skb,
54static int 55static int
55checkentry(const char *tablename, 56checkentry(const char *tablename,
56 const void *ip, 57 const void *ip,
58 const struct xt_match *match,
57 void *matchinfo, 59 void *matchinfo,
58 unsigned int matchsize, 60 unsigned int matchsize,
59 unsigned int hook_mask) 61 unsigned int hook_mask)
60{ 62{
61 const struct ip6t_owner_info *info = matchinfo; 63 const struct ip6t_owner_info *info = matchinfo;
62 64
63 if (hook_mask
64 & ~((1 << NF_IP6_LOCAL_OUT) | (1 << NF_IP6_POST_ROUTING))) {
65 printk("ip6t_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
66 return 0;
67 }
68
69 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_owner_info)))
70 return 0;
71
72 if (info->match & (IP6T_OWNER_PID | IP6T_OWNER_SID)) { 65 if (info->match & (IP6T_OWNER_PID | IP6T_OWNER_SID)) {
73 printk("ipt_owner: pid and sid matching " 66 printk("ipt_owner: pid and sid matching "
74 "not supported anymore\n"); 67 "not supported anymore\n");
75 return 0; 68 return 0;
76 } 69 }
77
78 return 1; 70 return 1;
79} 71}
80 72
81static struct ip6t_match owner_match = { 73static struct ip6t_match owner_match = {
82 .name = "owner", 74 .name = "owner",
83 .match = &match, 75 .match = match,
84 .checkentry = &checkentry, 76 .matchsize = sizeof(struct ip6t_owner_info),
77 .hooks = (1 << NF_IP6_LOCAL_OUT) | (1 << NF_IP6_POST_ROUTING),
78 .checkentry = checkentry,
85 .me = THIS_MODULE, 79 .me = THIS_MODULE,
86}; 80};
87 81
diff --git a/net/ipv6/netfilter/ip6t_policy.c b/net/ipv6/netfilter/ip6t_policy.c
deleted file mode 100644
index 3d39ec924041..000000000000
--- a/net/ipv6/netfilter/ip6t_policy.c
+++ /dev/null
@@ -1,176 +0,0 @@
1/* IP tables module for matching IPsec policy
2 *
3 * Copyright (c) 2004,2005 Patrick McHardy, <kaber@trash.net>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/kernel.h>
11#include <linux/config.h>
12#include <linux/module.h>
13#include <linux/skbuff.h>
14#include <linux/init.h>
15#include <net/xfrm.h>
16
17#include <linux/netfilter_ipv6.h>
18#include <linux/netfilter_ipv6/ip6_tables.h>
19#include <linux/netfilter_ipv6/ip6t_policy.h>
20
21MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
22MODULE_DESCRIPTION("IPtables IPsec policy matching module");
23MODULE_LICENSE("GPL");
24
25
26static inline int
27match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e)
28{
29#define MATCH_ADDR(x,y,z) (!e->match.x || \
30 ((!ip6_masked_addrcmp(&e->x.a6, &e->y.a6, z)) \
31 ^ e->invert.x))
32#define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x))
33
34 return MATCH_ADDR(saddr, smask, (struct in6_addr *)&x->props.saddr.a6) &&
35 MATCH_ADDR(daddr, dmask, (struct in6_addr *)&x->id.daddr.a6) &&
36 MATCH(proto, x->id.proto) &&
37 MATCH(mode, x->props.mode) &&
38 MATCH(spi, x->id.spi) &&
39 MATCH(reqid, x->props.reqid);
40}
41
42static int
43match_policy_in(const struct sk_buff *skb, const struct ip6t_policy_info *info)
44{
45 const struct ip6t_policy_elem *e;
46 struct sec_path *sp = skb->sp;
47 int strict = info->flags & IP6T_POLICY_MATCH_STRICT;
48 int i, pos;
49
50 if (sp == NULL)
51 return -1;
52 if (strict && info->len != sp->len)
53 return 0;
54
55 for (i = sp->len - 1; i >= 0; i--) {
56 pos = strict ? i - sp->len + 1 : 0;
57 if (pos >= info->len)
58 return 0;
59 e = &info->pol[pos];
60
61 if (match_xfrm_state(sp->x[i].xvec, e)) {
62 if (!strict)
63 return 1;
64 } else if (strict)
65 return 0;
66 }
67
68 return strict ? 1 : 0;
69}
70
71static int
72match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info)
73{
74 const struct ip6t_policy_elem *e;
75 struct dst_entry *dst = skb->dst;
76 int strict = info->flags & IP6T_POLICY_MATCH_STRICT;
77 int i, pos;
78
79 if (dst->xfrm == NULL)
80 return -1;
81
82 for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
83 pos = strict ? i : 0;
84 if (pos >= info->len)
85 return 0;
86 e = &info->pol[pos];
87
88 if (match_xfrm_state(dst->xfrm, e)) {
89 if (!strict)
90 return 1;
91 } else if (strict)
92 return 0;
93 }
94
95 return strict ? i == info->len : 0;
96}
97
98static int match(const struct sk_buff *skb,
99 const struct net_device *in,
100 const struct net_device *out,
101 const void *matchinfo,
102 int offset,
103 unsigned int protoff,
104 int *hotdrop)
105{
106 const struct ip6t_policy_info *info = matchinfo;
107 int ret;
108
109 if (info->flags & IP6T_POLICY_MATCH_IN)
110 ret = match_policy_in(skb, info);
111 else
112 ret = match_policy_out(skb, info);
113
114 if (ret < 0)
115 ret = info->flags & IP6T_POLICY_MATCH_NONE ? 1 : 0;
116 else if (info->flags & IP6T_POLICY_MATCH_NONE)
117 ret = 0;
118
119 return ret;
120}
121
122static int checkentry(const char *tablename, const void *ip_void,
123 void *matchinfo, unsigned int matchsize,
124 unsigned int hook_mask)
125{
126 struct ip6t_policy_info *info = matchinfo;
127
128 if (matchsize != IP6T_ALIGN(sizeof(*info))) {
129 printk(KERN_ERR "ip6t_policy: matchsize %u != %zu\n",
130 matchsize, IP6T_ALIGN(sizeof(*info)));
131 return 0;
132 }
133 if (!(info->flags & (IP6T_POLICY_MATCH_IN|IP6T_POLICY_MATCH_OUT))) {
134 printk(KERN_ERR "ip6t_policy: neither incoming nor "
135 "outgoing policy selected\n");
136 return 0;
137 }
138 if (hook_mask & (1 << NF_IP6_PRE_ROUTING | 1 << NF_IP6_LOCAL_IN)
139 && info->flags & IP6T_POLICY_MATCH_OUT) {
140 printk(KERN_ERR "ip6t_policy: output policy not valid in "
141 "PRE_ROUTING and INPUT\n");
142 return 0;
143 }
144 if (hook_mask & (1 << NF_IP6_POST_ROUTING | 1 << NF_IP6_LOCAL_OUT)
145 && info->flags & IP6T_POLICY_MATCH_IN) {
146 printk(KERN_ERR "ip6t_policy: input policy not valid in "
147 "POST_ROUTING and OUTPUT\n");
148 return 0;
149 }
150 if (info->len > IP6T_POLICY_MAX_ELEM) {
151 printk(KERN_ERR "ip6t_policy: too many policy elements\n");
152 return 0;
153 }
154
155 return 1;
156}
157
158static struct ip6t_match policy_match = {
159 .name = "policy",
160 .match = match,
161 .checkentry = checkentry,
162 .me = THIS_MODULE,
163};
164
165static int __init init(void)
166{
167 return ip6t_register_match(&policy_match);
168}
169
170static void __exit fini(void)
171{
172 ip6t_unregister_match(&policy_match);
173}
174
175module_init(init);
176module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index 8f82476dc89e..4c6b55bb225b 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -45,6 +45,7 @@ static int
45match(const struct sk_buff *skb, 45match(const struct sk_buff *skb,
46 const struct net_device *in, 46 const struct net_device *in,
47 const struct net_device *out, 47 const struct net_device *out,
48 const struct xt_match *match,
48 const void *matchinfo, 49 const void *matchinfo,
49 int offset, 50 int offset,
50 unsigned int protoff, 51 unsigned int protoff,
@@ -194,17 +195,13 @@ match(const struct sk_buff *skb,
194static int 195static int
195checkentry(const char *tablename, 196checkentry(const char *tablename,
196 const void *entry, 197 const void *entry,
198 const struct xt_match *match,
197 void *matchinfo, 199 void *matchinfo,
198 unsigned int matchinfosize, 200 unsigned int matchinfosize,
199 unsigned int hook_mask) 201 unsigned int hook_mask)
200{ 202{
201 const struct ip6t_rt *rtinfo = matchinfo; 203 const struct ip6t_rt *rtinfo = matchinfo;
202 204
203 if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_rt))) {
204 DEBUGP("ip6t_rt: matchsize %u != %u\n",
205 matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_rt)));
206 return 0;
207 }
208 if (rtinfo->invflags & ~IP6T_RT_INV_MASK) { 205 if (rtinfo->invflags & ~IP6T_RT_INV_MASK) {
209 DEBUGP("ip6t_rt: unknown flags %X\n", rtinfo->invflags); 206 DEBUGP("ip6t_rt: unknown flags %X\n", rtinfo->invflags);
210 return 0; 207 return 0;
@@ -222,8 +219,9 @@ checkentry(const char *tablename,
222 219
223static struct ip6t_match rt_match = { 220static struct ip6t_match rt_match = {
224 .name = "rt", 221 .name = "rt",
225 .match = &match, 222 .match = match,
226 .checkentry = &checkentry, 223 .matchsize = sizeof(struct ip6t_rt),
224 .checkentry = checkentry,
227 .me = THIS_MODULE, 225 .me = THIS_MODULE,
228}; 226};
229 227
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index ac702a29dd16..c16f62934bd9 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -179,31 +179,36 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
179 int (*okfn)(struct sk_buff *)) 179 int (*okfn)(struct sk_buff *))
180{ 180{
181 struct nf_conn *ct; 181 struct nf_conn *ct;
182 struct nf_conn_help *help;
182 enum ip_conntrack_info ctinfo; 183 enum ip_conntrack_info ctinfo;
184 unsigned int ret, protoff;
185 unsigned int extoff = (u8*)((*pskb)->nh.ipv6h + 1)
186 - (*pskb)->data;
187 unsigned char pnum = (*pskb)->nh.ipv6h->nexthdr;
188
183 189
184 /* This is where we call the helper: as the packet goes out. */ 190 /* This is where we call the helper: as the packet goes out. */
185 ct = nf_ct_get(*pskb, &ctinfo); 191 ct = nf_ct_get(*pskb, &ctinfo);
186 if (ct && ct->helper) { 192 if (!ct)
187 unsigned int ret, protoff; 193 goto out;
188 unsigned int extoff = (u8*)((*pskb)->nh.ipv6h + 1)
189 - (*pskb)->data;
190 unsigned char pnum = (*pskb)->nh.ipv6h->nexthdr;
191
192 protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum,
193 (*pskb)->len - extoff);
194 if (protoff < 0 || protoff > (*pskb)->len ||
195 pnum == NEXTHDR_FRAGMENT) {
196 DEBUGP("proto header not found\n");
197 return NF_ACCEPT;
198 }
199 194
200 ret = ct->helper->help(pskb, protoff, ct, ctinfo); 195 help = nfct_help(ct);
201 if (ret != NF_ACCEPT) 196 if (!help || !help->helper)
202 return ret; 197 goto out;
198
199 protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum,
200 (*pskb)->len - extoff);
201 if (protoff < 0 || protoff > (*pskb)->len ||
202 pnum == NEXTHDR_FRAGMENT) {
203 DEBUGP("proto header not found\n");
204 return NF_ACCEPT;
203 } 205 }
204 206
207 ret = help->helper->help(pskb, protoff, ct, ctinfo);
208 if (ret != NF_ACCEPT)
209 return ret;
210out:
205 /* We've seen it coming out the other side: confirm it */ 211 /* We've seen it coming out the other side: confirm it */
206
207 return nf_conntrack_confirm(pskb); 212 return nf_conntrack_confirm(pskb);
208} 213}
209 214
@@ -579,6 +584,7 @@ static int init_or_cleanup(int init)
579 return ret; 584 return ret;
580} 585}
581 586
587MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
582MODULE_LICENSE("GPL"); 588MODULE_LICENSE("GPL");
583MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); 589MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
584 590
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 84ef9a13108d..3e319035f82d 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -313,8 +313,8 @@ static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash,
313#ifdef CONFIG_SMP 313#ifdef CONFIG_SMP
314 hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) { 314 hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) {
315 if (fq->id == fq_in->id && 315 if (fq->id == fq_in->id &&
316 !ipv6_addr_cmp(&fq_in->saddr, &fq->saddr) && 316 ipv6_addr_equal(&fq_in->saddr, &fq->saddr) &&
317 !ipv6_addr_cmp(&fq_in->daddr, &fq->daddr)) { 317 ipv6_addr_equal(&fq_in->daddr, &fq->daddr)) {
318 atomic_inc(&fq->refcnt); 318 atomic_inc(&fq->refcnt);
319 write_unlock(&nf_ct_frag6_lock); 319 write_unlock(&nf_ct_frag6_lock);
320 fq_in->last_in |= COMPLETE; 320 fq_in->last_in |= COMPLETE;
@@ -376,8 +376,8 @@ fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst)
376 read_lock(&nf_ct_frag6_lock); 376 read_lock(&nf_ct_frag6_lock);
377 hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) { 377 hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) {
378 if (fq->id == id && 378 if (fq->id == id &&
379 !ipv6_addr_cmp(src, &fq->saddr) && 379 ipv6_addr_equal(src, &fq->saddr) &&
380 !ipv6_addr_cmp(dst, &fq->daddr)) { 380 ipv6_addr_equal(dst, &fq->daddr)) {
381 atomic_inc(&fq->refcnt); 381 atomic_inc(&fq->refcnt);
382 read_unlock(&nf_ct_frag6_lock); 382 read_unlock(&nf_ct_frag6_lock);
383 return fq; 383 return fq;
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index ae20a0ec9bd8..fa1ce0ae123e 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -859,29 +859,12 @@ static int rawv6_geticmpfilter(struct sock *sk, int level, int optname,
859} 859}
860 860
861 861
862static int rawv6_setsockopt(struct sock *sk, int level, int optname, 862static int do_rawv6_setsockopt(struct sock *sk, int level, int optname,
863 char __user *optval, int optlen) 863 char __user *optval, int optlen)
864{ 864{
865 struct raw6_sock *rp = raw6_sk(sk); 865 struct raw6_sock *rp = raw6_sk(sk);
866 int val; 866 int val;
867 867
868 switch(level) {
869 case SOL_RAW:
870 break;
871
872 case SOL_ICMPV6:
873 if (inet_sk(sk)->num != IPPROTO_ICMPV6)
874 return -EOPNOTSUPP;
875 return rawv6_seticmpfilter(sk, level, optname, optval,
876 optlen);
877 case SOL_IPV6:
878 if (optname == IPV6_CHECKSUM)
879 break;
880 default:
881 return ipv6_setsockopt(sk, level, optname, optval,
882 optlen);
883 };
884
885 if (get_user(val, (int __user *)optval)) 868 if (get_user(val, (int __user *)optval))
886 return -EFAULT; 869 return -EFAULT;
887 870
@@ -906,12 +889,9 @@ static int rawv6_setsockopt(struct sock *sk, int level, int optname,
906 } 889 }
907} 890}
908 891
909static int rawv6_getsockopt(struct sock *sk, int level, int optname, 892static int rawv6_setsockopt(struct sock *sk, int level, int optname,
910 char __user *optval, int __user *optlen) 893 char __user *optval, int optlen)
911{ 894{
912 struct raw6_sock *rp = raw6_sk(sk);
913 int val, len;
914
915 switch(level) { 895 switch(level) {
916 case SOL_RAW: 896 case SOL_RAW:
917 break; 897 break;
@@ -919,15 +899,45 @@ static int rawv6_getsockopt(struct sock *sk, int level, int optname,
919 case SOL_ICMPV6: 899 case SOL_ICMPV6:
920 if (inet_sk(sk)->num != IPPROTO_ICMPV6) 900 if (inet_sk(sk)->num != IPPROTO_ICMPV6)
921 return -EOPNOTSUPP; 901 return -EOPNOTSUPP;
922 return rawv6_geticmpfilter(sk, level, optname, optval, 902 return rawv6_seticmpfilter(sk, level, optname, optval,
923 optlen); 903 optlen);
924 case SOL_IPV6: 904 case SOL_IPV6:
925 if (optname == IPV6_CHECKSUM) 905 if (optname == IPV6_CHECKSUM)
926 break; 906 break;
927 default: 907 default:
928 return ipv6_getsockopt(sk, level, optname, optval, 908 return ipv6_setsockopt(sk, level, optname, optval,
929 optlen); 909 optlen);
930 }; 910 };
911 return do_rawv6_setsockopt(sk, level, optname, optval, optlen);
912}
913
914#ifdef CONFIG_COMPAT
915static int compat_rawv6_setsockopt(struct sock *sk, int level, int optname,
916 char __user *optval, int optlen)
917{
918 switch (level) {
919 case SOL_RAW:
920 break;
921 case SOL_ICMPV6:
922 if (inet_sk(sk)->num != IPPROTO_ICMPV6)
923 return -EOPNOTSUPP;
924 return rawv6_seticmpfilter(sk, level, optname, optval, optlen);
925 case SOL_IPV6:
926 if (optname == IPV6_CHECKSUM)
927 break;
928 default:
929 return compat_ipv6_setsockopt(sk, level, optname,
930 optval, optlen);
931 };
932 return do_rawv6_setsockopt(sk, level, optname, optval, optlen);
933}
934#endif
935
936static int do_rawv6_getsockopt(struct sock *sk, int level, int optname,
937 char __user *optval, int __user *optlen)
938{
939 struct raw6_sock *rp = raw6_sk(sk);
940 int val, len;
931 941
932 if (get_user(len,optlen)) 942 if (get_user(len,optlen))
933 return -EFAULT; 943 return -EFAULT;
@@ -953,6 +963,50 @@ static int rawv6_getsockopt(struct sock *sk, int level, int optname,
953 return 0; 963 return 0;
954} 964}
955 965
966static int rawv6_getsockopt(struct sock *sk, int level, int optname,
967 char __user *optval, int __user *optlen)
968{
969 switch(level) {
970 case SOL_RAW:
971 break;
972
973 case SOL_ICMPV6:
974 if (inet_sk(sk)->num != IPPROTO_ICMPV6)
975 return -EOPNOTSUPP;
976 return rawv6_geticmpfilter(sk, level, optname, optval,
977 optlen);
978 case SOL_IPV6:
979 if (optname == IPV6_CHECKSUM)
980 break;
981 default:
982 return ipv6_getsockopt(sk, level, optname, optval,
983 optlen);
984 };
985 return do_rawv6_getsockopt(sk, level, optname, optval, optlen);
986}
987
988#ifdef CONFIG_COMPAT
989static int compat_rawv6_getsockopt(struct sock *sk, int level, int optname,
990 char __user *optval, int __user *optlen)
991{
992 switch (level) {
993 case SOL_RAW:
994 break;
995 case SOL_ICMPV6:
996 if (inet_sk(sk)->num != IPPROTO_ICMPV6)
997 return -EOPNOTSUPP;
998 return rawv6_geticmpfilter(sk, level, optname, optval, optlen);
999 case SOL_IPV6:
1000 if (optname == IPV6_CHECKSUM)
1001 break;
1002 default:
1003 return compat_ipv6_getsockopt(sk, level, optname,
1004 optval, optlen);
1005 };
1006 return do_rawv6_getsockopt(sk, level, optname, optval, optlen);
1007}
1008#endif
1009
956static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) 1010static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
957{ 1011{
958 switch(cmd) { 1012 switch(cmd) {
@@ -998,23 +1052,27 @@ static int rawv6_init_sk(struct sock *sk)
998} 1052}
999 1053
1000struct proto rawv6_prot = { 1054struct proto rawv6_prot = {
1001 .name = "RAWv6", 1055 .name = "RAWv6",
1002 .owner = THIS_MODULE, 1056 .owner = THIS_MODULE,
1003 .close = rawv6_close, 1057 .close = rawv6_close,
1004 .connect = ip6_datagram_connect, 1058 .connect = ip6_datagram_connect,
1005 .disconnect = udp_disconnect, 1059 .disconnect = udp_disconnect,
1006 .ioctl = rawv6_ioctl, 1060 .ioctl = rawv6_ioctl,
1007 .init = rawv6_init_sk, 1061 .init = rawv6_init_sk,
1008 .destroy = inet6_destroy_sock, 1062 .destroy = inet6_destroy_sock,
1009 .setsockopt = rawv6_setsockopt, 1063 .setsockopt = rawv6_setsockopt,
1010 .getsockopt = rawv6_getsockopt, 1064 .getsockopt = rawv6_getsockopt,
1011 .sendmsg = rawv6_sendmsg, 1065 .sendmsg = rawv6_sendmsg,
1012 .recvmsg = rawv6_recvmsg, 1066 .recvmsg = rawv6_recvmsg,
1013 .bind = rawv6_bind, 1067 .bind = rawv6_bind,
1014 .backlog_rcv = rawv6_rcv_skb, 1068 .backlog_rcv = rawv6_rcv_skb,
1015 .hash = raw_v6_hash, 1069 .hash = raw_v6_hash,
1016 .unhash = raw_v6_unhash, 1070 .unhash = raw_v6_unhash,
1017 .obj_size = sizeof(struct raw6_sock), 1071 .obj_size = sizeof(struct raw6_sock),
1072#ifdef CONFIG_COMPAT
1073 .compat_setsockopt = compat_rawv6_setsockopt,
1074 .compat_getsockopt = compat_rawv6_getsockopt,
1075#endif
1018}; 1076};
1019 1077
1020#ifdef CONFIG_PROC_FS 1078#ifdef CONFIG_PROC_FS
@@ -1140,7 +1198,7 @@ static int raw6_seq_open(struct inode *inode, struct file *file)
1140{ 1198{
1141 struct seq_file *seq; 1199 struct seq_file *seq;
1142 int rc = -ENOMEM; 1200 int rc = -ENOMEM;
1143 struct raw6_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL); 1201 struct raw6_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
1144 if (!s) 1202 if (!s)
1145 goto out; 1203 goto out;
1146 rc = seq_open(file, &raw6_seq_ops); 1204 rc = seq_open(file, &raw6_seq_ops);
@@ -1148,7 +1206,6 @@ static int raw6_seq_open(struct inode *inode, struct file *file)
1148 goto out_kfree; 1206 goto out_kfree;
1149 seq = file->private_data; 1207 seq = file->private_data;
1150 seq->private = s; 1208 seq->private = s;
1151 memset(s, 0, sizeof(*s));
1152out: 1209out:
1153 return rc; 1210 return rc;
1154out_kfree: 1211out_kfree:
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 15e1456b3f18..b67a45fb93e9 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -203,7 +203,7 @@ static inline void frag_free_queue(struct frag_queue *fq, int *work)
203 203
204static inline struct frag_queue *frag_alloc_queue(void) 204static inline struct frag_queue *frag_alloc_queue(void)
205{ 205{
206 struct frag_queue *fq = kmalloc(sizeof(struct frag_queue), GFP_ATOMIC); 206 struct frag_queue *fq = kzalloc(sizeof(struct frag_queue), GFP_ATOMIC);
207 207
208 if(!fq) 208 if(!fq)
209 return NULL; 209 return NULL;
@@ -288,6 +288,7 @@ static void ip6_evictor(void)
288static void ip6_frag_expire(unsigned long data) 288static void ip6_frag_expire(unsigned long data)
289{ 289{
290 struct frag_queue *fq = (struct frag_queue *) data; 290 struct frag_queue *fq = (struct frag_queue *) data;
291 struct net_device *dev;
291 292
292 spin_lock(&fq->lock); 293 spin_lock(&fq->lock);
293 294
@@ -299,22 +300,22 @@ static void ip6_frag_expire(unsigned long data)
299 IP6_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT); 300 IP6_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT);
300 IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); 301 IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
301 302
302 /* Send error only if the first segment arrived. */ 303 /* Don't send error if the first segment did not arrive. */
303 if (fq->last_in&FIRST_IN && fq->fragments) { 304 if (!(fq->last_in&FIRST_IN) || !fq->fragments)
304 struct net_device *dev = dev_get_by_index(fq->iif); 305 goto out;
305 306
306 /* 307 dev = dev_get_by_index(fq->iif);
307 But use as source device on which LAST ARRIVED 308 if (!dev)
308 segment was received. And do not use fq->dev 309 goto out;
309 pointer directly, device might already disappeared. 310
310 */ 311 /*
311 if (dev) { 312 But use as source device on which LAST ARRIVED
312 fq->fragments->dev = dev; 313 segment was received. And do not use fq->dev
313 icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, 314 pointer directly, device might already disappeared.
314 dev); 315 */
315 dev_put(dev); 316 fq->fragments->dev = dev;
316 } 317 icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev);
317 } 318 dev_put(dev);
318out: 319out:
319 spin_unlock(&fq->lock); 320 spin_unlock(&fq->lock);
320 fq_put(fq, NULL); 321 fq_put(fq, NULL);
@@ -368,8 +369,6 @@ ip6_frag_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr
368 if ((fq = frag_alloc_queue()) == NULL) 369 if ((fq = frag_alloc_queue()) == NULL)
369 goto oom; 370 goto oom;
370 371
371 memset(fq, 0, sizeof(struct frag_queue));
372
373 fq->id = id; 372 fq->id = id;
374 ipv6_addr_copy(&fq->saddr, src); 373 ipv6_addr_copy(&fq->saddr, src);
375 ipv6_addr_copy(&fq->daddr, dst); 374 ipv6_addr_copy(&fq->daddr, dst);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index e0d3ad02ffb5..79078747a646 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -72,6 +72,10 @@
72#define RT6_TRACE(x...) do { ; } while (0) 72#define RT6_TRACE(x...) do { ; } while (0)
73#endif 73#endif
74 74
75#define CLONE_OFFLINK_ROUTE 0
76
77#define RT6_SELECT_F_IFACE 0x1
78#define RT6_SELECT_F_REACHABLE 0x2
75 79
76static int ip6_rt_max_size = 4096; 80static int ip6_rt_max_size = 4096;
77static int ip6_rt_gc_min_interval = HZ / 2; 81static int ip6_rt_gc_min_interval = HZ / 2;
@@ -94,6 +98,14 @@ static int ip6_pkt_discard_out(struct sk_buff *skb);
94static void ip6_link_failure(struct sk_buff *skb); 98static void ip6_link_failure(struct sk_buff *skb);
95static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu); 99static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
96 100
101#ifdef CONFIG_IPV6_ROUTE_INFO
102static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixlen,
103 struct in6_addr *gwaddr, int ifindex,
104 unsigned pref);
105static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixlen,
106 struct in6_addr *gwaddr, int ifindex);
107#endif
108
97static struct dst_ops ip6_dst_ops = { 109static struct dst_ops ip6_dst_ops = {
98 .family = AF_INET6, 110 .family = AF_INET6,
99 .protocol = __constant_htons(ETH_P_IPV6), 111 .protocol = __constant_htons(ETH_P_IPV6),
@@ -214,150 +226,211 @@ static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt,
214 return rt; 226 return rt;
215} 227}
216 228
229#ifdef CONFIG_IPV6_ROUTER_PREF
230static void rt6_probe(struct rt6_info *rt)
231{
232 struct neighbour *neigh = rt ? rt->rt6i_nexthop : NULL;
233 /*
234 * Okay, this does not seem to be appropriate
235 * for now, however, we need to check if it
236 * is really so; aka Router Reachability Probing.
237 *
238 * Router Reachability Probe MUST be rate-limited
239 * to no more than one per minute.
240 */
241 if (!neigh || (neigh->nud_state & NUD_VALID))
242 return;
243 read_lock_bh(&neigh->lock);
244 if (!(neigh->nud_state & NUD_VALID) &&
245 time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) {
246 struct in6_addr mcaddr;
247 struct in6_addr *target;
248
249 neigh->updated = jiffies;
250 read_unlock_bh(&neigh->lock);
251
252 target = (struct in6_addr *)&neigh->primary_key;
253 addrconf_addr_solict_mult(target, &mcaddr);
254 ndisc_send_ns(rt->rt6i_dev, NULL, target, &mcaddr, NULL);
255 } else
256 read_unlock_bh(&neigh->lock);
257}
258#else
259static inline void rt6_probe(struct rt6_info *rt)
260{
261 return;
262}
263#endif
264
217/* 265/*
218 * pointer to the last default router chosen. BH is disabled locally. 266 * Default Router Selection (RFC 2461 6.3.6)
219 */ 267 */
220static struct rt6_info *rt6_dflt_pointer; 268static int inline rt6_check_dev(struct rt6_info *rt, int oif)
221static DEFINE_SPINLOCK(rt6_dflt_lock); 269{
270 struct net_device *dev = rt->rt6i_dev;
271 if (!oif || dev->ifindex == oif)
272 return 2;
273 if ((dev->flags & IFF_LOOPBACK) &&
274 rt->rt6i_idev && rt->rt6i_idev->dev->ifindex == oif)
275 return 1;
276 return 0;
277}
222 278
223void rt6_reset_dflt_pointer(struct rt6_info *rt) 279static int inline rt6_check_neigh(struct rt6_info *rt)
224{ 280{
225 spin_lock_bh(&rt6_dflt_lock); 281 struct neighbour *neigh = rt->rt6i_nexthop;
226 if (rt == NULL || rt == rt6_dflt_pointer) { 282 int m = 0;
227 RT6_TRACE("reset default router: %p->NULL\n", rt6_dflt_pointer); 283 if (neigh) {
228 rt6_dflt_pointer = NULL; 284 read_lock_bh(&neigh->lock);
285 if (neigh->nud_state & NUD_VALID)
286 m = 1;
287 read_unlock_bh(&neigh->lock);
229 } 288 }
230 spin_unlock_bh(&rt6_dflt_lock); 289 return m;
231} 290}
232 291
233/* Default Router Selection (RFC 2461 6.3.6) */ 292static int rt6_score_route(struct rt6_info *rt, int oif,
234static struct rt6_info *rt6_best_dflt(struct rt6_info *rt, int oif) 293 int strict)
235{ 294{
236 struct rt6_info *match = NULL; 295 int m = rt6_check_dev(rt, oif);
237 struct rt6_info *sprt; 296 if (!m && (strict & RT6_SELECT_F_IFACE))
238 int mpri = 0; 297 return -1;
239 298#ifdef CONFIG_IPV6_ROUTER_PREF
240 for (sprt = rt; sprt; sprt = sprt->u.next) { 299 m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2;
241 struct neighbour *neigh; 300#endif
242 int m = 0; 301 if (rt6_check_neigh(rt))
243 302 m |= 16;
244 if (!oif || 303 else if (strict & RT6_SELECT_F_REACHABLE)
245 (sprt->rt6i_dev && 304 return -1;
246 sprt->rt6i_dev->ifindex == oif)) 305 return m;
247 m += 8; 306}
248 307
249 if (rt6_check_expired(sprt)) 308static struct rt6_info *rt6_select(struct rt6_info **head, int oif,
250 continue; 309 int strict)
310{
311 struct rt6_info *match = NULL, *last = NULL;
312 struct rt6_info *rt, *rt0 = *head;
313 u32 metric;
314 int mpri = -1;
251 315
252 if (sprt == rt6_dflt_pointer) 316 RT6_TRACE("%s(head=%p(*head=%p), oif=%d)\n",
253 m += 4; 317 __FUNCTION__, head, head ? *head : NULL, oif);
254 318
255 if ((neigh = sprt->rt6i_nexthop) != NULL) { 319 for (rt = rt0, metric = rt0->rt6i_metric;
256 read_lock_bh(&neigh->lock); 320 rt && rt->rt6i_metric == metric;
257 switch (neigh->nud_state) { 321 rt = rt->u.next) {
258 case NUD_REACHABLE: 322 int m;
259 m += 3;
260 break;
261 323
262 case NUD_STALE: 324 if (rt6_check_expired(rt))
263 case NUD_DELAY: 325 continue;
264 case NUD_PROBE:
265 m += 2;
266 break;
267 326
268 case NUD_NOARP: 327 last = rt;
269 case NUD_PERMANENT:
270 m += 1;
271 break;
272 328
273 case NUD_INCOMPLETE: 329 m = rt6_score_route(rt, oif, strict);
274 default: 330 if (m < 0)
275 read_unlock_bh(&neigh->lock);
276 continue;
277 }
278 read_unlock_bh(&neigh->lock);
279 } else {
280 continue; 331 continue;
281 }
282 332
283 if (m > mpri || m >= 12) { 333 if (m > mpri) {
284 match = sprt; 334 rt6_probe(match);
335 match = rt;
285 mpri = m; 336 mpri = m;
286 if (m >= 12) { 337 } else {
287 /* we choose the last default router if it 338 rt6_probe(rt);
288 * is in (probably) reachable state.
289 * If route changed, we should do pmtu
290 * discovery. --yoshfuji
291 */
292 break;
293 }
294 } 339 }
295 } 340 }
296 341
297 spin_lock(&rt6_dflt_lock); 342 if (!match &&
298 if (!match) { 343 (strict & RT6_SELECT_F_REACHABLE) &&
299 /* 344 last && last != rt0) {
300 * No default routers are known to be reachable. 345 /* no entries matched; do round-robin */
301 * SHOULD round robin 346 *head = rt0->u.next;
302 */ 347 rt0->u.next = last->u.next;
303 if (rt6_dflt_pointer) { 348 last->u.next = rt0;
304 for (sprt = rt6_dflt_pointer->u.next;
305 sprt; sprt = sprt->u.next) {
306 if (sprt->u.dst.obsolete <= 0 &&
307 sprt->u.dst.error == 0 &&
308 !rt6_check_expired(sprt)) {
309 match = sprt;
310 break;
311 }
312 }
313 for (sprt = rt;
314 !match && sprt;
315 sprt = sprt->u.next) {
316 if (sprt->u.dst.obsolete <= 0 &&
317 sprt->u.dst.error == 0 &&
318 !rt6_check_expired(sprt)) {
319 match = sprt;
320 break;
321 }
322 if (sprt == rt6_dflt_pointer)
323 break;
324 }
325 }
326 } 349 }
327 350
328 if (match) { 351 RT6_TRACE("%s() => %p, score=%d\n",
329 if (rt6_dflt_pointer != match) 352 __FUNCTION__, match, mpri);
330 RT6_TRACE("changed default router: %p->%p\n", 353
331 rt6_dflt_pointer, match); 354 return (match ? match : &ip6_null_entry);
332 rt6_dflt_pointer = match; 355}
356
357#ifdef CONFIG_IPV6_ROUTE_INFO
358int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
359 struct in6_addr *gwaddr)
360{
361 struct route_info *rinfo = (struct route_info *) opt;
362 struct in6_addr prefix_buf, *prefix;
363 unsigned int pref;
364 u32 lifetime;
365 struct rt6_info *rt;
366
367 if (len < sizeof(struct route_info)) {
368 return -EINVAL;
333 } 369 }
334 spin_unlock(&rt6_dflt_lock);
335 370
336 if (!match) { 371 /* Sanity check for prefix_len and length */
337 /* 372 if (rinfo->length > 3) {
338 * Last Resort: if no default routers found, 373 return -EINVAL;
339 * use addrconf default route. 374 } else if (rinfo->prefix_len > 128) {
340 * We don't record this route. 375 return -EINVAL;
341 */ 376 } else if (rinfo->prefix_len > 64) {
342 for (sprt = ip6_routing_table.leaf; 377 if (rinfo->length < 2) {
343 sprt; sprt = sprt->u.next) { 378 return -EINVAL;
344 if (!rt6_check_expired(sprt) &&
345 (sprt->rt6i_flags & RTF_DEFAULT) &&
346 (!oif ||
347 (sprt->rt6i_dev &&
348 sprt->rt6i_dev->ifindex == oif))) {
349 match = sprt;
350 break;
351 }
352 } 379 }
353 if (!match) { 380 } else if (rinfo->prefix_len > 0) {
354 /* no default route. give up. */ 381 if (rinfo->length < 1) {
355 match = &ip6_null_entry; 382 return -EINVAL;
356 } 383 }
357 } 384 }
358 385
359 return match; 386 pref = rinfo->route_pref;
387 if (pref == ICMPV6_ROUTER_PREF_INVALID)
388 pref = ICMPV6_ROUTER_PREF_MEDIUM;
389
390 lifetime = htonl(rinfo->lifetime);
391 if (lifetime == 0xffffffff) {
392 /* infinity */
393 } else if (lifetime > 0x7fffffff/HZ) {
394 /* Avoid arithmetic overflow */
395 lifetime = 0x7fffffff/HZ - 1;
396 }
397
398 if (rinfo->length == 3)
399 prefix = (struct in6_addr *)rinfo->prefix;
400 else {
401 /* this function is safe */
402 ipv6_addr_prefix(&prefix_buf,
403 (struct in6_addr *)rinfo->prefix,
404 rinfo->prefix_len);
405 prefix = &prefix_buf;
406 }
407
408 rt = rt6_get_route_info(prefix, rinfo->prefix_len, gwaddr, dev->ifindex);
409
410 if (rt && !lifetime) {
411 ip6_del_rt(rt, NULL, NULL, NULL);
412 rt = NULL;
413 }
414
415 if (!rt && lifetime)
416 rt = rt6_add_route_info(prefix, rinfo->prefix_len, gwaddr, dev->ifindex,
417 pref);
418 else if (rt)
419 rt->rt6i_flags = RTF_ROUTEINFO |
420 (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
421
422 if (rt) {
423 if (lifetime == 0xffffffff) {
424 rt->rt6i_flags &= ~RTF_EXPIRES;
425 } else {
426 rt->rt6i_expires = jiffies + HZ * lifetime;
427 rt->rt6i_flags |= RTF_EXPIRES;
428 }
429 dst_release(&rt->u.dst);
430 }
431 return 0;
360} 432}
433#endif
361 434
362struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, 435struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr,
363 int oif, int strict) 436 int oif, int strict)
@@ -397,14 +470,9 @@ int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh,
397 return err; 470 return err;
398} 471}
399 472
400/* No rt6_lock! If COW failed, the function returns dead route entry 473static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *daddr,
401 with dst->error set to errno value. 474 struct in6_addr *saddr)
402 */
403
404static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr,
405 struct in6_addr *saddr, struct netlink_skb_parms *req)
406{ 475{
407 int err;
408 struct rt6_info *rt; 476 struct rt6_info *rt;
409 477
410 /* 478 /*
@@ -435,25 +503,30 @@ static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr,
435 503
436 rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); 504 rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
437 505
438 dst_hold(&rt->u.dst); 506 }
439
440 err = ip6_ins_rt(rt, NULL, NULL, req);
441 if (err == 0)
442 return rt;
443 507
444 rt->u.dst.error = err; 508 return rt;
509}
445 510
446 return rt; 511static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *daddr)
512{
513 struct rt6_info *rt = ip6_rt_copy(ort);
514 if (rt) {
515 ipv6_addr_copy(&rt->rt6i_dst.addr, daddr);
516 rt->rt6i_dst.plen = 128;
517 rt->rt6i_flags |= RTF_CACHE;
518 if (rt->rt6i_flags & RTF_REJECT)
519 rt->u.dst.error = ort->u.dst.error;
520 rt->u.dst.flags |= DST_HOST;
521 rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop);
447 } 522 }
448 dst_hold(&ip6_null_entry.u.dst); 523 return rt;
449 return &ip6_null_entry;
450} 524}
451 525
452#define BACKTRACK() \ 526#define BACKTRACK() \
453if (rt == &ip6_null_entry && strict) { \ 527if (rt == &ip6_null_entry) { \
454 while ((fn = fn->parent) != NULL) { \ 528 while ((fn = fn->parent) != NULL) { \
455 if (fn->fn_flags & RTN_ROOT) { \ 529 if (fn->fn_flags & RTN_ROOT) { \
456 dst_hold(&rt->u.dst); \
457 goto out; \ 530 goto out; \
458 } \ 531 } \
459 if (fn->fn_flags & RTN_RTINFO) \ 532 if (fn->fn_flags & RTN_RTINFO) \
@@ -465,115 +538,138 @@ if (rt == &ip6_null_entry && strict) { \
465void ip6_route_input(struct sk_buff *skb) 538void ip6_route_input(struct sk_buff *skb)
466{ 539{
467 struct fib6_node *fn; 540 struct fib6_node *fn;
468 struct rt6_info *rt; 541 struct rt6_info *rt, *nrt;
469 int strict; 542 int strict;
470 int attempts = 3; 543 int attempts = 3;
544 int err;
545 int reachable = RT6_SELECT_F_REACHABLE;
471 546
472 strict = ipv6_addr_type(&skb->nh.ipv6h->daddr) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL); 547 strict = ipv6_addr_type(&skb->nh.ipv6h->daddr) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL) ? RT6_SELECT_F_IFACE : 0;
473 548
474relookup: 549relookup:
475 read_lock_bh(&rt6_lock); 550 read_lock_bh(&rt6_lock);
476 551
552restart_2:
477 fn = fib6_lookup(&ip6_routing_table, &skb->nh.ipv6h->daddr, 553 fn = fib6_lookup(&ip6_routing_table, &skb->nh.ipv6h->daddr,
478 &skb->nh.ipv6h->saddr); 554 &skb->nh.ipv6h->saddr);
479 555
480restart: 556restart:
481 rt = fn->leaf; 557 rt = rt6_select(&fn->leaf, skb->dev->ifindex, strict | reachable);
482
483 if ((rt->rt6i_flags & RTF_CACHE)) {
484 rt = rt6_device_match(rt, skb->dev->ifindex, strict);
485 BACKTRACK();
486 dst_hold(&rt->u.dst);
487 goto out;
488 }
489
490 rt = rt6_device_match(rt, skb->dev->ifindex, strict);
491 BACKTRACK(); 558 BACKTRACK();
559 if (rt == &ip6_null_entry ||
560 rt->rt6i_flags & RTF_CACHE)
561 goto out;
492 562
493 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { 563 dst_hold(&rt->u.dst);
494 struct rt6_info *nrt; 564 read_unlock_bh(&rt6_lock);
495 dst_hold(&rt->u.dst);
496 read_unlock_bh(&rt6_lock);
497 565
498 nrt = rt6_cow(rt, &skb->nh.ipv6h->daddr, 566 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
499 &skb->nh.ipv6h->saddr, 567 nrt = rt6_alloc_cow(rt, &skb->nh.ipv6h->daddr, &skb->nh.ipv6h->saddr);
500 &NETLINK_CB(skb)); 568 else {
569#if CLONE_OFFLINK_ROUTE
570 nrt = rt6_alloc_clone(rt, &skb->nh.ipv6h->daddr);
571#else
572 goto out2;
573#endif
574 }
501 575
502 dst_release(&rt->u.dst); 576 dst_release(&rt->u.dst);
503 rt = nrt; 577 rt = nrt ? : &ip6_null_entry;
504 578
505 if (rt->u.dst.error != -EEXIST || --attempts <= 0) 579 dst_hold(&rt->u.dst);
580 if (nrt) {
581 err = ip6_ins_rt(nrt, NULL, NULL, &NETLINK_CB(skb));
582 if (!err)
506 goto out2; 583 goto out2;
507
508 /* Race condition! In the gap, when rt6_lock was
509 released someone could insert this route. Relookup.
510 */
511 dst_release(&rt->u.dst);
512 goto relookup;
513 } 584 }
514 dst_hold(&rt->u.dst); 585
586 if (--attempts <= 0)
587 goto out2;
588
589 /*
590 * Race condition! In the gap, when rt6_lock was
591 * released someone could insert this route. Relookup.
592 */
593 dst_release(&rt->u.dst);
594 goto relookup;
515 595
516out: 596out:
597 if (reachable) {
598 reachable = 0;
599 goto restart_2;
600 }
601 dst_hold(&rt->u.dst);
517 read_unlock_bh(&rt6_lock); 602 read_unlock_bh(&rt6_lock);
518out2: 603out2:
519 rt->u.dst.lastuse = jiffies; 604 rt->u.dst.lastuse = jiffies;
520 rt->u.dst.__use++; 605 rt->u.dst.__use++;
521 skb->dst = (struct dst_entry *) rt; 606 skb->dst = (struct dst_entry *) rt;
607 return;
522} 608}
523 609
524struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) 610struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
525{ 611{
526 struct fib6_node *fn; 612 struct fib6_node *fn;
527 struct rt6_info *rt; 613 struct rt6_info *rt, *nrt;
528 int strict; 614 int strict;
529 int attempts = 3; 615 int attempts = 3;
616 int err;
617 int reachable = RT6_SELECT_F_REACHABLE;
530 618
531 strict = ipv6_addr_type(&fl->fl6_dst) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL); 619 strict = ipv6_addr_type(&fl->fl6_dst) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL) ? RT6_SELECT_F_IFACE : 0;
532 620
533relookup: 621relookup:
534 read_lock_bh(&rt6_lock); 622 read_lock_bh(&rt6_lock);
535 623
624restart_2:
536 fn = fib6_lookup(&ip6_routing_table, &fl->fl6_dst, &fl->fl6_src); 625 fn = fib6_lookup(&ip6_routing_table, &fl->fl6_dst, &fl->fl6_src);
537 626
538restart: 627restart:
539 rt = fn->leaf; 628 rt = rt6_select(&fn->leaf, fl->oif, strict | reachable);
540 629 BACKTRACK();
541 if ((rt->rt6i_flags & RTF_CACHE)) { 630 if (rt == &ip6_null_entry ||
542 rt = rt6_device_match(rt, fl->oif, strict); 631 rt->rt6i_flags & RTF_CACHE)
543 BACKTRACK();
544 dst_hold(&rt->u.dst);
545 goto out; 632 goto out;
546 }
547 if (rt->rt6i_flags & RTF_DEFAULT) {
548 if (rt->rt6i_metric >= IP6_RT_PRIO_ADDRCONF)
549 rt = rt6_best_dflt(rt, fl->oif);
550 } else {
551 rt = rt6_device_match(rt, fl->oif, strict);
552 BACKTRACK();
553 }
554 633
555 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { 634 dst_hold(&rt->u.dst);
556 struct rt6_info *nrt; 635 read_unlock_bh(&rt6_lock);
557 dst_hold(&rt->u.dst);
558 read_unlock_bh(&rt6_lock);
559 636
560 nrt = rt6_cow(rt, &fl->fl6_dst, &fl->fl6_src, NULL); 637 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
638 nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src);
639 else {
640#if CLONE_OFFLINK_ROUTE
641 nrt = rt6_alloc_clone(rt, &fl->fl6_dst);
642#else
643 goto out2;
644#endif
645 }
561 646
562 dst_release(&rt->u.dst); 647 dst_release(&rt->u.dst);
563 rt = nrt; 648 rt = nrt ? : &ip6_null_entry;
564 649
565 if (rt->u.dst.error != -EEXIST || --attempts <= 0) 650 dst_hold(&rt->u.dst);
651 if (nrt) {
652 err = ip6_ins_rt(nrt, NULL, NULL, NULL);
653 if (!err)
566 goto out2; 654 goto out2;
567
568 /* Race condition! In the gap, when rt6_lock was
569 released someone could insert this route. Relookup.
570 */
571 dst_release(&rt->u.dst);
572 goto relookup;
573 } 655 }
574 dst_hold(&rt->u.dst); 656
657 if (--attempts <= 0)
658 goto out2;
659
660 /*
661 * Race condition! In the gap, when rt6_lock was
662 * released someone could insert this route. Relookup.
663 */
664 dst_release(&rt->u.dst);
665 goto relookup;
575 666
576out: 667out:
668 if (reachable) {
669 reachable = 0;
670 goto restart_2;
671 }
672 dst_hold(&rt->u.dst);
577 read_unlock_bh(&rt6_lock); 673 read_unlock_bh(&rt6_lock);
578out2: 674out2:
579 rt->u.dst.lastuse = jiffies; 675 rt->u.dst.lastuse = jiffies;
@@ -999,8 +1095,6 @@ int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct
999 1095
1000 write_lock_bh(&rt6_lock); 1096 write_lock_bh(&rt6_lock);
1001 1097
1002 rt6_reset_dflt_pointer(NULL);
1003
1004 err = fib6_del(rt, nlh, _rtattr, req); 1098 err = fib6_del(rt, nlh, _rtattr, req);
1005 dst_release(&rt->u.dst); 1099 dst_release(&rt->u.dst);
1006 1100
@@ -1050,59 +1144,63 @@ static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_r
1050void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr, 1144void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr,
1051 struct neighbour *neigh, u8 *lladdr, int on_link) 1145 struct neighbour *neigh, u8 *lladdr, int on_link)
1052{ 1146{
1053 struct rt6_info *rt, *nrt; 1147 struct rt6_info *rt, *nrt = NULL;
1054 1148 int strict;
1055 /* Locate old route to this destination. */ 1149 struct fib6_node *fn;
1056 rt = rt6_lookup(dest, NULL, neigh->dev->ifindex, 1);
1057
1058 if (rt == NULL)
1059 return;
1060
1061 if (neigh->dev != rt->rt6i_dev)
1062 goto out;
1063 1150
1064 /* 1151 /*
1065 * Current route is on-link; redirect is always invalid. 1152 * Get the "current" route for this destination and
1066 * 1153 * check if the redirect has come from approriate router.
1067 * Seems, previous statement is not true. It could 1154 *
1068 * be node, which looks for us as on-link (f.e. proxy ndisc) 1155 * RFC 2461 specifies that redirects should only be
1069 * But then router serving it might decide, that we should 1156 * accepted if they come from the nexthop to the target.
1070 * know truth 8)8) --ANK (980726). 1157 * Due to the way the routes are chosen, this notion
1158 * is a bit fuzzy and one might need to check all possible
1159 * routes.
1071 */ 1160 */
1072 if (!(rt->rt6i_flags&RTF_GATEWAY)) 1161 strict = ipv6_addr_type(dest) & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL);
1073 goto out;
1074 1162
1075 /* 1163 read_lock_bh(&rt6_lock);
1076 * RFC 2461 specifies that redirects should only be 1164 fn = fib6_lookup(&ip6_routing_table, dest, NULL);
1077 * accepted if they come from the nexthop to the target. 1165restart:
1078 * Due to the way default routers are chosen, this notion 1166 for (rt = fn->leaf; rt; rt = rt->u.next) {
1079 * is a bit fuzzy and one might need to check all default 1167 /*
1080 * routers. 1168 * Current route is on-link; redirect is always invalid.
1081 */ 1169 *
1082 if (!ipv6_addr_equal(saddr, &rt->rt6i_gateway)) { 1170 * Seems, previous statement is not true. It could
1083 if (rt->rt6i_flags & RTF_DEFAULT) { 1171 * be node, which looks for us as on-link (f.e. proxy ndisc)
1084 struct rt6_info *rt1; 1172 * But then router serving it might decide, that we should
1085 1173 * know truth 8)8) --ANK (980726).
1086 read_lock(&rt6_lock); 1174 */
1087 for (rt1 = ip6_routing_table.leaf; rt1; rt1 = rt1->u.next) { 1175 if (rt6_check_expired(rt))
1088 if (ipv6_addr_equal(saddr, &rt1->rt6i_gateway)) { 1176 continue;
1089 dst_hold(&rt1->u.dst); 1177 if (!(rt->rt6i_flags & RTF_GATEWAY))
1090 dst_release(&rt->u.dst); 1178 continue;
1091 read_unlock(&rt6_lock); 1179 if (neigh->dev != rt->rt6i_dev)
1092 rt = rt1; 1180 continue;
1093 goto source_ok; 1181 if (!ipv6_addr_equal(saddr, &rt->rt6i_gateway))
1094 } 1182 continue;
1095 } 1183 break;
1096 read_unlock(&rt6_lock); 1184 }
1185 if (rt)
1186 dst_hold(&rt->u.dst);
1187 else if (strict) {
1188 while ((fn = fn->parent) != NULL) {
1189 if (fn->fn_flags & RTN_ROOT)
1190 break;
1191 if (fn->fn_flags & RTN_RTINFO)
1192 goto restart;
1097 } 1193 }
1194 }
1195 read_unlock_bh(&rt6_lock);
1196
1197 if (!rt) {
1098 if (net_ratelimit()) 1198 if (net_ratelimit())
1099 printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop " 1199 printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop "
1100 "for redirect target\n"); 1200 "for redirect target\n");
1101 goto out; 1201 return;
1102 } 1202 }
1103 1203
1104source_ok:
1105
1106 /* 1204 /*
1107 * We have finally decided to accept it. 1205 * We have finally decided to accept it.
1108 */ 1206 */
@@ -1210,38 +1308,27 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
1210 1. It is connected route. Action: COW 1308 1. It is connected route. Action: COW
1211 2. It is gatewayed route or NONEXTHOP route. Action: clone it. 1309 2. It is gatewayed route or NONEXTHOP route. Action: clone it.
1212 */ 1310 */
1213 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { 1311 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
1214 nrt = rt6_cow(rt, daddr, saddr, NULL); 1312 nrt = rt6_alloc_cow(rt, daddr, saddr);
1215 if (!nrt->u.dst.error) { 1313 else
1216 nrt->u.dst.metrics[RTAX_MTU-1] = pmtu; 1314 nrt = rt6_alloc_clone(rt, daddr);
1217 if (allfrag) 1315
1218 nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; 1316 if (nrt) {
1219 /* According to RFC 1981, detecting PMTU increase shouldn't be
1220 happened within 5 mins, the recommended timer is 10 mins.
1221 Here this route expiration time is set to ip6_rt_mtu_expires
1222 which is 10 mins. After 10 mins the decreased pmtu is expired
1223 and detecting PMTU increase will be automatically happened.
1224 */
1225 dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires);
1226 nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES;
1227 }
1228 dst_release(&nrt->u.dst);
1229 } else {
1230 nrt = ip6_rt_copy(rt);
1231 if (nrt == NULL)
1232 goto out;
1233 ipv6_addr_copy(&nrt->rt6i_dst.addr, daddr);
1234 nrt->rt6i_dst.plen = 128;
1235 nrt->u.dst.flags |= DST_HOST;
1236 nrt->rt6i_nexthop = neigh_clone(rt->rt6i_nexthop);
1237 dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires);
1238 nrt->rt6i_flags |= RTF_DYNAMIC|RTF_CACHE|RTF_EXPIRES;
1239 nrt->u.dst.metrics[RTAX_MTU-1] = pmtu; 1317 nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
1240 if (allfrag) 1318 if (allfrag)
1241 nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; 1319 nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
1320
1321 /* According to RFC 1981, detecting PMTU increase shouldn't be
1322 * happened within 5 mins, the recommended timer is 10 mins.
1323 * Here this route expiration time is set to ip6_rt_mtu_expires
1324 * which is 10 mins. After 10 mins the decreased pmtu is expired
1325 * and detecting PMTU increase will be automatically happened.
1326 */
1327 dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires);
1328 nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES;
1329
1242 ip6_ins_rt(nrt, NULL, NULL, NULL); 1330 ip6_ins_rt(nrt, NULL, NULL, NULL);
1243 } 1331 }
1244
1245out: 1332out:
1246 dst_release(&rt->u.dst); 1333 dst_release(&rt->u.dst);
1247} 1334}
@@ -1280,6 +1367,57 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
1280 return rt; 1367 return rt;
1281} 1368}
1282 1369
1370#ifdef CONFIG_IPV6_ROUTE_INFO
1371static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixlen,
1372 struct in6_addr *gwaddr, int ifindex)
1373{
1374 struct fib6_node *fn;
1375 struct rt6_info *rt = NULL;
1376
1377 write_lock_bh(&rt6_lock);
1378 fn = fib6_locate(&ip6_routing_table, prefix ,prefixlen, NULL, 0);
1379 if (!fn)
1380 goto out;
1381
1382 for (rt = fn->leaf; rt; rt = rt->u.next) {
1383 if (rt->rt6i_dev->ifindex != ifindex)
1384 continue;
1385 if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY))
1386 continue;
1387 if (!ipv6_addr_equal(&rt->rt6i_gateway, gwaddr))
1388 continue;
1389 dst_hold(&rt->u.dst);
1390 break;
1391 }
1392out:
1393 write_unlock_bh(&rt6_lock);
1394 return rt;
1395}
1396
1397static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixlen,
1398 struct in6_addr *gwaddr, int ifindex,
1399 unsigned pref)
1400{
1401 struct in6_rtmsg rtmsg;
1402
1403 memset(&rtmsg, 0, sizeof(rtmsg));
1404 rtmsg.rtmsg_type = RTMSG_NEWROUTE;
1405 ipv6_addr_copy(&rtmsg.rtmsg_dst, prefix);
1406 rtmsg.rtmsg_dst_len = prefixlen;
1407 ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr);
1408 rtmsg.rtmsg_metric = 1024;
1409 rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO | RTF_UP | RTF_PREF(pref);
1410 /* We should treat it as a default route if prefix length is 0. */
1411 if (!prefixlen)
1412 rtmsg.rtmsg_flags |= RTF_DEFAULT;
1413 rtmsg.rtmsg_ifindex = ifindex;
1414
1415 ip6_route_add(&rtmsg, NULL, NULL, NULL);
1416
1417 return rt6_get_route_info(prefix, prefixlen, gwaddr, ifindex);
1418}
1419#endif
1420
1283struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *dev) 1421struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *dev)
1284{ 1422{
1285 struct rt6_info *rt; 1423 struct rt6_info *rt;
@@ -1290,6 +1428,7 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d
1290 write_lock_bh(&rt6_lock); 1428 write_lock_bh(&rt6_lock);
1291 for (rt = fn->leaf; rt; rt=rt->u.next) { 1429 for (rt = fn->leaf; rt; rt=rt->u.next) {
1292 if (dev == rt->rt6i_dev && 1430 if (dev == rt->rt6i_dev &&
1431 ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) &&
1293 ipv6_addr_equal(&rt->rt6i_gateway, addr)) 1432 ipv6_addr_equal(&rt->rt6i_gateway, addr))
1294 break; 1433 break;
1295 } 1434 }
@@ -1300,7 +1439,8 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d
1300} 1439}
1301 1440
1302struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, 1441struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
1303 struct net_device *dev) 1442 struct net_device *dev,
1443 unsigned int pref)
1304{ 1444{
1305 struct in6_rtmsg rtmsg; 1445 struct in6_rtmsg rtmsg;
1306 1446
@@ -1308,7 +1448,8 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
1308 rtmsg.rtmsg_type = RTMSG_NEWROUTE; 1448 rtmsg.rtmsg_type = RTMSG_NEWROUTE;
1309 ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr); 1449 ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr);
1310 rtmsg.rtmsg_metric = 1024; 1450 rtmsg.rtmsg_metric = 1024;
1311 rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | RTF_UP | RTF_EXPIRES; 1451 rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | RTF_UP | RTF_EXPIRES |
1452 RTF_PREF(pref);
1312 1453
1313 rtmsg.rtmsg_ifindex = dev->ifindex; 1454 rtmsg.rtmsg_ifindex = dev->ifindex;
1314 1455
@@ -1326,8 +1467,6 @@ restart:
1326 if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) { 1467 if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) {
1327 dst_hold(&rt->u.dst); 1468 dst_hold(&rt->u.dst);
1328 1469
1329 rt6_reset_dflt_pointer(NULL);
1330
1331 read_unlock_bh(&rt6_lock); 1470 read_unlock_bh(&rt6_lock);
1332 1471
1333 ip6_del_rt(rt, NULL, NULL, NULL); 1472 ip6_del_rt(rt, NULL, NULL, NULL);
@@ -1738,11 +1877,10 @@ int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
1738 /* 1877 /*
1739 * 2. allocate and initialize walker. 1878 * 2. allocate and initialize walker.
1740 */ 1879 */
1741 w = kmalloc(sizeof(*w), GFP_ATOMIC); 1880 w = kzalloc(sizeof(*w), GFP_ATOMIC);
1742 if (w == NULL) 1881 if (w == NULL)
1743 return -ENOMEM; 1882 return -ENOMEM;
1744 RT6_TRACE("dump<%p", w); 1883 RT6_TRACE("dump<%p", w);
1745 memset(w, 0, sizeof(*w));
1746 w->root = &ip6_routing_table; 1884 w->root = &ip6_routing_table;
1747 w->func = fib6_dump_node; 1885 w->func = fib6_dump_node;
1748 w->args = &arg; 1886 w->args = &arg;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index ca9cf6853755..301eee726b0f 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -987,6 +987,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
987 inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen + 987 inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen +
988 newnp->opt->opt_flen); 988 newnp->opt->opt_flen);
989 989
990 tcp_mtup_init(newsk);
990 tcp_sync_mss(newsk, dst_mtu(dst)); 991 tcp_sync_mss(newsk, dst_mtu(dst));
991 newtp->advmss = dst_metric(dst, RTAX_ADVMSS); 992 newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
992 tcp_initialize_rcv_mss(newsk); 993 tcp_initialize_rcv_mss(newsk);
@@ -1297,18 +1298,21 @@ static int tcp_v6_remember_stamp(struct sock *sk)
1297} 1298}
1298 1299
1299static struct inet_connection_sock_af_ops ipv6_specific = { 1300static struct inet_connection_sock_af_ops ipv6_specific = {
1300 .queue_xmit = inet6_csk_xmit, 1301 .queue_xmit = inet6_csk_xmit,
1301 .send_check = tcp_v6_send_check, 1302 .send_check = tcp_v6_send_check,
1302 .rebuild_header = inet6_sk_rebuild_header, 1303 .rebuild_header = inet6_sk_rebuild_header,
1303 .conn_request = tcp_v6_conn_request, 1304 .conn_request = tcp_v6_conn_request,
1304 .syn_recv_sock = tcp_v6_syn_recv_sock, 1305 .syn_recv_sock = tcp_v6_syn_recv_sock,
1305 .remember_stamp = tcp_v6_remember_stamp, 1306 .remember_stamp = tcp_v6_remember_stamp,
1306 .net_header_len = sizeof(struct ipv6hdr), 1307 .net_header_len = sizeof(struct ipv6hdr),
1307 1308 .setsockopt = ipv6_setsockopt,
1308 .setsockopt = ipv6_setsockopt, 1309 .getsockopt = ipv6_getsockopt,
1309 .getsockopt = ipv6_getsockopt, 1310 .addr2sockaddr = inet6_csk_addr2sockaddr,
1310 .addr2sockaddr = inet6_csk_addr2sockaddr, 1311 .sockaddr_len = sizeof(struct sockaddr_in6),
1311 .sockaddr_len = sizeof(struct sockaddr_in6) 1312#ifdef CONFIG_COMPAT
1313 .compat_setsockopt = compat_ipv6_setsockopt,
1314 .compat_getsockopt = compat_ipv6_getsockopt,
1315#endif
1312}; 1316};
1313 1317
1314/* 1318/*
@@ -1316,22 +1320,23 @@ static struct inet_connection_sock_af_ops ipv6_specific = {
1316 */ 1320 */
1317 1321
1318static struct inet_connection_sock_af_ops ipv6_mapped = { 1322static struct inet_connection_sock_af_ops ipv6_mapped = {
1319 .queue_xmit = ip_queue_xmit, 1323 .queue_xmit = ip_queue_xmit,
1320 .send_check = tcp_v4_send_check, 1324 .send_check = tcp_v4_send_check,
1321 .rebuild_header = inet_sk_rebuild_header, 1325 .rebuild_header = inet_sk_rebuild_header,
1322 .conn_request = tcp_v6_conn_request, 1326 .conn_request = tcp_v6_conn_request,
1323 .syn_recv_sock = tcp_v6_syn_recv_sock, 1327 .syn_recv_sock = tcp_v6_syn_recv_sock,
1324 .remember_stamp = tcp_v4_remember_stamp, 1328 .remember_stamp = tcp_v4_remember_stamp,
1325 .net_header_len = sizeof(struct iphdr), 1329 .net_header_len = sizeof(struct iphdr),
1326 1330 .setsockopt = ipv6_setsockopt,
1327 .setsockopt = ipv6_setsockopt, 1331 .getsockopt = ipv6_getsockopt,
1328 .getsockopt = ipv6_getsockopt, 1332 .addr2sockaddr = inet6_csk_addr2sockaddr,
1329 .addr2sockaddr = inet6_csk_addr2sockaddr, 1333 .sockaddr_len = sizeof(struct sockaddr_in6),
1330 .sockaddr_len = sizeof(struct sockaddr_in6) 1334#ifdef CONFIG_COMPAT
1335 .compat_setsockopt = compat_ipv6_setsockopt,
1336 .compat_getsockopt = compat_ipv6_getsockopt,
1337#endif
1331}; 1338};
1332 1339
1333
1334
1335/* NOTE: A lot of things set to zero explicitly by call to 1340/* NOTE: A lot of things set to zero explicitly by call to
1336 * sk_alloc() so need not be done here. 1341 * sk_alloc() so need not be done here.
1337 */ 1342 */
@@ -1583,6 +1588,10 @@ struct proto tcpv6_prot = {
1583 .obj_size = sizeof(struct tcp6_sock), 1588 .obj_size = sizeof(struct tcp6_sock),
1584 .twsk_prot = &tcp6_timewait_sock_ops, 1589 .twsk_prot = &tcp6_timewait_sock_ops,
1585 .rsk_prot = &tcp6_request_sock_ops, 1590 .rsk_prot = &tcp6_request_sock_ops,
1591#ifdef CONFIG_COMPAT
1592 .compat_setsockopt = compat_tcp_setsockopt,
1593 .compat_getsockopt = compat_tcp_getsockopt,
1594#endif
1586}; 1595};
1587 1596
1588static struct inet6_protocol tcpv6_protocol = { 1597static struct inet6_protocol tcpv6_protocol = {
@@ -1604,21 +1613,12 @@ static struct inet_protosw tcpv6_protosw = {
1604 1613
1605void __init tcpv6_init(void) 1614void __init tcpv6_init(void)
1606{ 1615{
1607 int err;
1608
1609 /* register inet6 protocol */ 1616 /* register inet6 protocol */
1610 if (inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP) < 0) 1617 if (inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP) < 0)
1611 printk(KERN_ERR "tcpv6_init: Could not register protocol\n"); 1618 printk(KERN_ERR "tcpv6_init: Could not register protocol\n");
1612 inet6_register_protosw(&tcpv6_protosw); 1619 inet6_register_protosw(&tcpv6_protosw);
1613 1620
1614 err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_TCP, &tcp6_socket); 1621 if (inet_csk_ctl_sock_create(&tcp6_socket, PF_INET6, SOCK_RAW,
1615 if (err < 0) 1622 IPPROTO_TCP) < 0)
1616 panic("Failed to create the TCPv6 control socket.\n"); 1623 panic("Failed to create the TCPv6 control socket.\n");
1617 tcp6_socket->sk->sk_allocation = GFP_ATOMIC;
1618
1619 /* Unhash it so that IP input processing does not even
1620 * see it, we do not wish this socket to see incoming
1621 * packets.
1622 */
1623 tcp6_socket->sk->sk_prot->unhash(tcp6_socket->sk);
1624} 1624}
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index c47648892c04..8d3432a70f3a 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -880,16 +880,13 @@ static int udpv6_destroy_sock(struct sock *sk)
880/* 880/*
881 * Socket option code for UDP 881 * Socket option code for UDP
882 */ 882 */
883static int udpv6_setsockopt(struct sock *sk, int level, int optname, 883static int do_udpv6_setsockopt(struct sock *sk, int level, int optname,
884 char __user *optval, int optlen) 884 char __user *optval, int optlen)
885{ 885{
886 struct udp_sock *up = udp_sk(sk); 886 struct udp_sock *up = udp_sk(sk);
887 int val; 887 int val;
888 int err = 0; 888 int err = 0;
889 889
890 if (level != SOL_UDP)
891 return ipv6_setsockopt(sk, level, optname, optval, optlen);
892
893 if(optlen<sizeof(int)) 890 if(optlen<sizeof(int))
894 return -EINVAL; 891 return -EINVAL;
895 892
@@ -927,15 +924,31 @@ static int udpv6_setsockopt(struct sock *sk, int level, int optname,
927 return err; 924 return err;
928} 925}
929 926
930static int udpv6_getsockopt(struct sock *sk, int level, int optname, 927static int udpv6_setsockopt(struct sock *sk, int level, int optname,
928 char __user *optval, int optlen)
929{
930 if (level != SOL_UDP)
931 return ipv6_setsockopt(sk, level, optname, optval, optlen);
932 return do_udpv6_setsockopt(sk, level, optname, optval, optlen);
933}
934
935#ifdef CONFIG_COMPAT
936static int compat_udpv6_setsockopt(struct sock *sk, int level, int optname,
937 char __user *optval, int optlen)
938{
939 if (level != SOL_UDP)
940 return compat_ipv6_setsockopt(sk, level, optname,
941 optval, optlen);
942 return do_udpv6_setsockopt(sk, level, optname, optval, optlen);
943}
944#endif
945
946static int do_udpv6_getsockopt(struct sock *sk, int level, int optname,
931 char __user *optval, int __user *optlen) 947 char __user *optval, int __user *optlen)
932{ 948{
933 struct udp_sock *up = udp_sk(sk); 949 struct udp_sock *up = udp_sk(sk);
934 int val, len; 950 int val, len;
935 951
936 if (level != SOL_UDP)
937 return ipv6_getsockopt(sk, level, optname, optval, optlen);
938
939 if(get_user(len,optlen)) 952 if(get_user(len,optlen))
940 return -EFAULT; 953 return -EFAULT;
941 954
@@ -964,6 +977,25 @@ static int udpv6_getsockopt(struct sock *sk, int level, int optname,
964 return 0; 977 return 0;
965} 978}
966 979
980static int udpv6_getsockopt(struct sock *sk, int level, int optname,
981 char __user *optval, int __user *optlen)
982{
983 if (level != SOL_UDP)
984 return ipv6_getsockopt(sk, level, optname, optval, optlen);
985 return do_udpv6_getsockopt(sk, level, optname, optval, optlen);
986}
987
988#ifdef CONFIG_COMPAT
989static int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,
990 char __user *optval, int __user *optlen)
991{
992 if (level != SOL_UDP)
993 return compat_ipv6_getsockopt(sk, level, optname,
994 optval, optlen);
995 return do_udpv6_getsockopt(sk, level, optname, optval, optlen);
996}
997#endif
998
967static struct inet6_protocol udpv6_protocol = { 999static struct inet6_protocol udpv6_protocol = {
968 .handler = udpv6_rcv, 1000 .handler = udpv6_rcv,
969 .err_handler = udpv6_err, 1001 .err_handler = udpv6_err,
@@ -1037,22 +1069,26 @@ void udp6_proc_exit(void) {
1037/* ------------------------------------------------------------------------ */ 1069/* ------------------------------------------------------------------------ */
1038 1070
1039struct proto udpv6_prot = { 1071struct proto udpv6_prot = {
1040 .name = "UDPv6", 1072 .name = "UDPv6",
1041 .owner = THIS_MODULE, 1073 .owner = THIS_MODULE,
1042 .close = udpv6_close, 1074 .close = udpv6_close,
1043 .connect = ip6_datagram_connect, 1075 .connect = ip6_datagram_connect,
1044 .disconnect = udp_disconnect, 1076 .disconnect = udp_disconnect,
1045 .ioctl = udp_ioctl, 1077 .ioctl = udp_ioctl,
1046 .destroy = udpv6_destroy_sock, 1078 .destroy = udpv6_destroy_sock,
1047 .setsockopt = udpv6_setsockopt, 1079 .setsockopt = udpv6_setsockopt,
1048 .getsockopt = udpv6_getsockopt, 1080 .getsockopt = udpv6_getsockopt,
1049 .sendmsg = udpv6_sendmsg, 1081 .sendmsg = udpv6_sendmsg,
1050 .recvmsg = udpv6_recvmsg, 1082 .recvmsg = udpv6_recvmsg,
1051 .backlog_rcv = udpv6_queue_rcv_skb, 1083 .backlog_rcv = udpv6_queue_rcv_skb,
1052 .hash = udp_v6_hash, 1084 .hash = udp_v6_hash,
1053 .unhash = udp_v6_unhash, 1085 .unhash = udp_v6_unhash,
1054 .get_port = udp_v6_get_port, 1086 .get_port = udp_v6_get_port,
1055 .obj_size = sizeof(struct udp6_sock), 1087 .obj_size = sizeof(struct udp6_sock),
1088#ifdef CONFIG_COMPAT
1089 .compat_setsockopt = compat_udpv6_setsockopt,
1090 .compat_getsockopt = compat_udpv6_getsockopt,
1091#endif
1056}; 1092};
1057 1093
1058static struct inet_protosw udpv6_protosw = { 1094static struct inet_protosw udpv6_protosw = {
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 8cfc58b96fc2..08f9abbdf1d7 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -31,6 +31,7 @@
31#include <net/protocol.h> 31#include <net/protocol.h>
32#include <linux/ipv6.h> 32#include <linux/ipv6.h>
33#include <linux/icmpv6.h> 33#include <linux/icmpv6.h>
34#include <linux/mutex.h>
34 35
35#ifdef CONFIG_IPV6_XFRM6_TUNNEL_DEBUG 36#ifdef CONFIG_IPV6_XFRM6_TUNNEL_DEBUG
36# define X6TDEBUG 3 37# define X6TDEBUG 3
@@ -357,19 +358,19 @@ static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *dec
357} 358}
358 359
359static struct xfrm6_tunnel *xfrm6_tunnel_handler; 360static struct xfrm6_tunnel *xfrm6_tunnel_handler;
360static DECLARE_MUTEX(xfrm6_tunnel_sem); 361static DEFINE_MUTEX(xfrm6_tunnel_mutex);
361 362
362int xfrm6_tunnel_register(struct xfrm6_tunnel *handler) 363int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)
363{ 364{
364 int ret; 365 int ret;
365 366
366 down(&xfrm6_tunnel_sem); 367 mutex_lock(&xfrm6_tunnel_mutex);
367 ret = 0; 368 ret = 0;
368 if (xfrm6_tunnel_handler != NULL) 369 if (xfrm6_tunnel_handler != NULL)
369 ret = -EINVAL; 370 ret = -EINVAL;
370 if (!ret) 371 if (!ret)
371 xfrm6_tunnel_handler = handler; 372 xfrm6_tunnel_handler = handler;
372 up(&xfrm6_tunnel_sem); 373 mutex_unlock(&xfrm6_tunnel_mutex);
373 374
374 return ret; 375 return ret;
375} 376}
@@ -380,13 +381,13 @@ int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler)
380{ 381{
381 int ret; 382 int ret;
382 383
383 down(&xfrm6_tunnel_sem); 384 mutex_lock(&xfrm6_tunnel_mutex);
384 ret = 0; 385 ret = 0;
385 if (xfrm6_tunnel_handler != handler) 386 if (xfrm6_tunnel_handler != handler)
386 ret = -EINVAL; 387 ret = -EINVAL;
387 if (!ret) 388 if (!ret)
388 xfrm6_tunnel_handler = NULL; 389 xfrm6_tunnel_handler = NULL;
389 up(&xfrm6_tunnel_sem); 390 mutex_unlock(&xfrm6_tunnel_mutex);
390 391
391 synchronize_net(); 392 synchronize_net();
392 393
diff --git a/net/key/af_key.c b/net/key/af_key.c
index b2d4d1dd2116..859582275cab 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -2651,6 +2651,8 @@ static int pfkey_send_notify(struct xfrm_state *x, struct km_event *c)
2651 return key_notify_sa(x, c); 2651 return key_notify_sa(x, c);
2652 case XFRM_MSG_FLUSHSA: 2652 case XFRM_MSG_FLUSHSA:
2653 return key_notify_sa_flush(c); 2653 return key_notify_sa_flush(c);
2654 case XFRM_MSG_NEWAE: /* not yet supported */
2655 break;
2654 default: 2656 default:
2655 printk("pfkey: Unknown SA event %d\n", c->event); 2657 printk("pfkey: Unknown SA event %d\n", c->event);
2656 break; 2658 break;
@@ -3078,9 +3080,9 @@ static int pfkey_sendmsg(struct kiocb *kiocb,
3078 if (!hdr) 3080 if (!hdr)
3079 goto out; 3081 goto out;
3080 3082
3081 down(&xfrm_cfg_sem); 3083 mutex_lock(&xfrm_cfg_mutex);
3082 err = pfkey_process(sk, skb, hdr); 3084 err = pfkey_process(sk, skb, hdr);
3083 up(&xfrm_cfg_sem); 3085 mutex_unlock(&xfrm_cfg_mutex);
3084 3086
3085out: 3087out:
3086 if (err && hdr && pfkey_error(hdr, err, sk) == 0) 3088 if (err && hdr && pfkey_error(hdr, err, sk) == 0)
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index 8171c53bc0ed..5a04db745c8d 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -54,7 +54,7 @@ static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout);
54 * 54 *
55 * Return the next unused link number for a given sap. 55 * Return the next unused link number for a given sap.
56 */ 56 */
57static __inline__ u16 llc_ui_next_link_no(int sap) 57static inline u16 llc_ui_next_link_no(int sap)
58{ 58{
59 return llc_ui_sap_link_no_max[sap]++; 59 return llc_ui_sap_link_no_max[sap]++;
60} 60}
@@ -65,7 +65,7 @@ static __inline__ u16 llc_ui_next_link_no(int sap)
65 * 65 *
66 * Given an ARP header type return the corresponding ethernet protocol. 66 * Given an ARP header type return the corresponding ethernet protocol.
67 */ 67 */
68static __inline__ u16 llc_proto_type(u16 arphrd) 68static inline u16 llc_proto_type(u16 arphrd)
69{ 69{
70 return arphrd == ARPHRD_IEEE802_TR ? 70 return arphrd == ARPHRD_IEEE802_TR ?
71 htons(ETH_P_TR_802_2) : htons(ETH_P_802_2); 71 htons(ETH_P_TR_802_2) : htons(ETH_P_802_2);
@@ -75,7 +75,7 @@ static __inline__ u16 llc_proto_type(u16 arphrd)
75 * llc_ui_addr_null - determines if a address structure is null 75 * llc_ui_addr_null - determines if a address structure is null
76 * @addr: Address to test if null. 76 * @addr: Address to test if null.
77 */ 77 */
78static __inline__ u8 llc_ui_addr_null(struct sockaddr_llc *addr) 78static inline u8 llc_ui_addr_null(struct sockaddr_llc *addr)
79{ 79{
80 return !memcmp(addr, &llc_ui_addrnull, sizeof(*addr)); 80 return !memcmp(addr, &llc_ui_addrnull, sizeof(*addr));
81} 81}
@@ -89,8 +89,7 @@ static __inline__ u8 llc_ui_addr_null(struct sockaddr_llc *addr)
89 * operation the user would like to perform and the type of socket. 89 * operation the user would like to perform and the type of socket.
90 * Returns the correct llc header length. 90 * Returns the correct llc header length.
91 */ 91 */
92static __inline__ u8 llc_ui_header_len(struct sock *sk, 92static inline u8 llc_ui_header_len(struct sock *sk, struct sockaddr_llc *addr)
93 struct sockaddr_llc *addr)
94{ 93{
95 u8 rc = LLC_PDU_LEN_U; 94 u8 rc = LLC_PDU_LEN_U;
96 95
@@ -138,7 +137,7 @@ static void llc_ui_sk_init(struct socket *sock, struct sock *sk)
138} 137}
139 138
140static struct proto llc_proto = { 139static struct proto llc_proto = {
141 .name = "DDP", 140 .name = "LLC",
142 .owner = THIS_MODULE, 141 .owner = THIS_MODULE,
143 .obj_size = sizeof(struct llc_sock), 142 .obj_size = sizeof(struct llc_sock),
144}; 143};
@@ -188,8 +187,10 @@ static int llc_ui_release(struct socket *sock)
188 llc->laddr.lsap, llc->daddr.lsap); 187 llc->laddr.lsap, llc->daddr.lsap);
189 if (!llc_send_disc(sk)) 188 if (!llc_send_disc(sk))
190 llc_ui_wait_for_disc(sk, sk->sk_rcvtimeo); 189 llc_ui_wait_for_disc(sk, sk->sk_rcvtimeo);
191 if (!sock_flag(sk, SOCK_ZAPPED)) 190 if (!sock_flag(sk, SOCK_ZAPPED)) {
191 llc_sap_put(llc->sap);
192 llc_sap_remove_socket(llc->sap, sk); 192 llc_sap_remove_socket(llc->sap, sk);
193 }
193 release_sock(sk); 194 release_sock(sk);
194 if (llc->dev) 195 if (llc->dev)
195 dev_put(llc->dev); 196 dev_put(llc->dev);
diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c
index 8169f24ed33e..860140caa6e0 100644
--- a/net/llc/llc_c_ac.c
+++ b/net/llc/llc_c_ac.c
@@ -27,7 +27,6 @@
27#include <net/llc_pdu.h> 27#include <net/llc_pdu.h>
28#include <net/llc.h> 28#include <net/llc.h>
29 29
30#include "llc_output.h"
31 30
32static int llc_conn_ac_inc_vs_by_1(struct sock *sk, struct sk_buff *skb); 31static int llc_conn_ac_inc_vs_by_1(struct sock *sk, struct sk_buff *skb);
33static void llc_process_tmr_ev(struct sock *sk, struct sk_buff *skb); 32static void llc_process_tmr_ev(struct sock *sk, struct sk_buff *skb);
diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c
index ab0fcd32fd84..bd242a49514a 100644
--- a/net/llc/llc_core.c
+++ b/net/llc/llc_core.c
@@ -127,7 +127,6 @@ struct llc_sap *llc_sap_open(unsigned char lsap,
127 goto out; 127 goto out;
128 sap->laddr.lsap = lsap; 128 sap->laddr.lsap = lsap;
129 sap->rcv_func = func; 129 sap->rcv_func = func;
130 llc_sap_hold(sap);
131 llc_add_sap(sap); 130 llc_add_sap(sap);
132out: 131out:
133 write_unlock_bh(&llc_sap_list_lock); 132 write_unlock_bh(&llc_sap_list_lock);
diff --git a/net/llc/llc_output.c b/net/llc/llc_output.c
index b4d55b6abb67..b4e668e0e12c 100644
--- a/net/llc/llc_output.c
+++ b/net/llc/llc_output.c
@@ -30,7 +30,8 @@
30 * Fills MAC header fields, depending on MAC type. Returns 0, If MAC type 30 * Fills MAC header fields, depending on MAC type. Returns 0, If MAC type
31 * is a valid type and initialization completes correctly 1, otherwise. 31 * is a valid type and initialization completes correctly 1, otherwise.
32 */ 32 */
33int llc_mac_hdr_init(struct sk_buff *skb, unsigned char *sa, unsigned char *da) 33int llc_mac_hdr_init(struct sk_buff *skb,
34 const unsigned char *sa, const unsigned char *da)
34{ 35{
35 int rc = 0; 36 int rc = 0;
36 37
diff --git a/net/llc/llc_output.h b/net/llc/llc_output.h
deleted file mode 100644
index 179edf753f00..000000000000
--- a/net/llc/llc_output.h
+++ /dev/null
@@ -1,20 +0,0 @@
1#ifndef LLC_OUTPUT_H
2#define LLC_OUTPUT_H
3/*
4 * Copyright (c) 1997 by Procom Technology, Inc.
5 * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
6 *
7 * This program can be redistributed or modified under the terms of the
8 * GNU General Public License version 2 as published by the Free Software
9 * Foundation.
10 * This program is distributed without any warranty or implied warranty
11 * of merchantability or fitness for a particular purpose.
12 *
13 * See the GNU General Public License version 2 for more details.
14 */
15
16struct sk_buff;
17
18int llc_mac_hdr_init(struct sk_buff *skb, unsigned char *sa, unsigned char *da);
19
20#endif /* LLC_OUTPUT_H */
diff --git a/net/llc/llc_s_ac.c b/net/llc/llc_s_ac.c
index bb3580fb8cfe..ac3d93b210d2 100644
--- a/net/llc/llc_s_ac.c
+++ b/net/llc/llc_s_ac.c
@@ -24,7 +24,7 @@
24#include <net/llc_s_ac.h> 24#include <net/llc_s_ac.h>
25#include <net/llc_s_ev.h> 25#include <net/llc_s_ev.h>
26#include <net/llc_sap.h> 26#include <net/llc_sap.h>
27#include "llc_output.h" 27
28 28
29/** 29/**
30 * llc_sap_action_unit_data_ind - forward UI PDU to network layer 30 * llc_sap_action_unit_data_ind - forward UI PDU to network layer
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index a8e5544da93e..332acb37b385 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -11,7 +11,7 @@ config NETFILTER_NETLINK_QUEUE
11 tristate "Netfilter NFQUEUE over NFNETLINK interface" 11 tristate "Netfilter NFQUEUE over NFNETLINK interface"
12 depends on NETFILTER_NETLINK 12 depends on NETFILTER_NETLINK
13 help 13 help
14 If this option isenabled, the kernel will include support 14 If this option is enabled, the kernel will include support
15 for queueing packets via NFNETLINK. 15 for queueing packets via NFNETLINK.
16 16
17config NETFILTER_NETLINK_LOG 17config NETFILTER_NETLINK_LOG
@@ -66,7 +66,7 @@ config NF_CONNTRACK_EVENTS
66 help 66 help
67 If this option is enabled, the connection tracking code will 67 If this option is enabled, the connection tracking code will
68 provide a notifier chain that can be used by other kernel code 68 provide a notifier chain that can be used by other kernel code
69 to get notified aboutchanges in the connection tracking state. 69 to get notified about changes in the connection tracking state.
70 70
71 If unsure, say `N'. 71 If unsure, say `N'.
72 72
@@ -153,7 +153,7 @@ config NETFILTER_XT_TARGET_NFQUEUE
153 tristate '"NFQUEUE" target Support' 153 tristate '"NFQUEUE" target Support'
154 depends on NETFILTER_XTABLES 154 depends on NETFILTER_XTABLES
155 help 155 help
156 This Target replaced the old obsolete QUEUE target. 156 This target replaced the old obsolete QUEUE target.
157 157
158 As opposed to QUEUE, it supports 65535 different queues, 158 As opposed to QUEUE, it supports 65535 different queues,
159 not just one. 159 not just one.
@@ -279,6 +279,16 @@ config NETFILTER_XT_MATCH_MARK
279 279
280 To compile it as a module, choose M here. If unsure, say N. 280 To compile it as a module, choose M here. If unsure, say N.
281 281
282config NETFILTER_XT_MATCH_POLICY
283 tristate 'IPsec "policy" match support'
284 depends on NETFILTER_XTABLES && XFRM
285 help
286 Policy matching allows you to match packets based on the
287 IPsec policy that was used during decapsulation/will
288 be used during encapsulation.
289
290 To compile it as a module, choose M here. If unsure, say N.
291
282config NETFILTER_XT_MATCH_PHYSDEV 292config NETFILTER_XT_MATCH_PHYSDEV
283 tristate '"physdev" match support' 293 tristate '"physdev" match support'
284 depends on NETFILTER_XTABLES && BRIDGE_NETFILTER 294 depends on NETFILTER_XTABLES && BRIDGE_NETFILTER
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 746172ebc91b..9558727f5e79 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o
40obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o 40obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o
41obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o 41obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o
42obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o 42obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o
43obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o
43obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o 44obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o
44obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o 45obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
45obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o 46obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index d622ddf08bb0..0ae281d9bfc3 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -3,7 +3,7 @@
3 extension. */ 3 extension. */
4 4
5/* (C) 1999-2001 Paul `Rusty' Russell 5/* (C) 1999-2001 Paul `Rusty' Russell
6 * (C) 2002-2005 Netfilter Core Team <coreteam@netfilter.org> 6 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
7 * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org> 7 * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,11 @@
20 * - generalize L3 protocol denendent part. 20 * - generalize L3 protocol denendent part.
21 * 23 Mar 2004: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp> 21 * 23 Mar 2004: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
22 * - add support various size of conntrack structures. 22 * - add support various size of conntrack structures.
23 * 26 Jan 2006: Harald Welte <laforge@netfilter.org>
24 * - restructure nf_conn (introduce nf_conn_help)
25 * - redesign 'features' how they were originally intended
26 * 26 Feb 2006: Pablo Neira Ayuso <pablo@eurodev.net>
27 * - add support for L3 protocol module load on demand.
23 * 28 *
24 * Derived from net/ipv4/netfilter/ip_conntrack_core.c 29 * Derived from net/ipv4/netfilter/ip_conntrack_core.c
25 */ 30 */
@@ -55,7 +60,7 @@
55#include <net/netfilter/nf_conntrack_core.h> 60#include <net/netfilter/nf_conntrack_core.h>
56#include <linux/netfilter_ipv4/listhelp.h> 61#include <linux/netfilter_ipv4/listhelp.h>
57 62
58#define NF_CONNTRACK_VERSION "0.4.1" 63#define NF_CONNTRACK_VERSION "0.5.0"
59 64
60#if 0 65#if 0
61#define DEBUGP printk 66#define DEBUGP printk
@@ -82,8 +87,8 @@ unsigned int nf_ct_log_invalid;
82static LIST_HEAD(unconfirmed); 87static LIST_HEAD(unconfirmed);
83static int nf_conntrack_vmalloc; 88static int nf_conntrack_vmalloc;
84 89
85static unsigned int nf_conntrack_next_id = 1; 90static unsigned int nf_conntrack_next_id;
86static unsigned int nf_conntrack_expect_next_id = 1; 91static unsigned int nf_conntrack_expect_next_id;
87#ifdef CONFIG_NF_CONNTRACK_EVENTS 92#ifdef CONFIG_NF_CONNTRACK_EVENTS
88struct notifier_block *nf_conntrack_chain; 93struct notifier_block *nf_conntrack_chain;
89struct notifier_block *nf_conntrack_expect_chain; 94struct notifier_block *nf_conntrack_expect_chain;
@@ -182,7 +187,7 @@ static struct {
182DEFINE_RWLOCK(nf_ct_cache_lock); 187DEFINE_RWLOCK(nf_ct_cache_lock);
183 188
184/* This avoids calling kmem_cache_create() with same name simultaneously */ 189/* This avoids calling kmem_cache_create() with same name simultaneously */
185DECLARE_MUTEX(nf_ct_cache_mutex); 190static DEFINE_MUTEX(nf_ct_cache_mutex);
186 191
187extern struct nf_conntrack_protocol nf_conntrack_generic_protocol; 192extern struct nf_conntrack_protocol nf_conntrack_generic_protocol;
188struct nf_conntrack_protocol * 193struct nf_conntrack_protocol *
@@ -238,6 +243,35 @@ void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p)
238 module_put(p->me); 243 module_put(p->me);
239} 244}
240 245
246int
247nf_ct_l3proto_try_module_get(unsigned short l3proto)
248{
249 int ret;
250 struct nf_conntrack_l3proto *p;
251
252retry: p = nf_ct_l3proto_find_get(l3proto);
253 if (p == &nf_conntrack_generic_l3proto) {
254 ret = request_module("nf_conntrack-%d", l3proto);
255 if (!ret)
256 goto retry;
257
258 return -EPROTOTYPE;
259 }
260
261 return 0;
262}
263
264void nf_ct_l3proto_module_put(unsigned short l3proto)
265{
266 struct nf_conntrack_l3proto *p;
267
268 preempt_disable();
269 p = __nf_ct_l3proto_find(l3proto);
270 preempt_enable();
271
272 module_put(p->me);
273}
274
241static int nf_conntrack_hash_rnd_initted; 275static int nf_conntrack_hash_rnd_initted;
242static unsigned int nf_conntrack_hash_rnd; 276static unsigned int nf_conntrack_hash_rnd;
243 277
@@ -259,21 +293,8 @@ static inline u_int32_t hash_conntrack(const struct nf_conntrack_tuple *tuple)
259 nf_conntrack_hash_rnd); 293 nf_conntrack_hash_rnd);
260} 294}
261 295
262/* Initialize "struct nf_conn" which has spaces for helper */
263static int
264init_conntrack_for_helper(struct nf_conn *conntrack, u_int32_t features)
265{
266
267 conntrack->help = (union nf_conntrack_help *)
268 (((unsigned long)conntrack->data
269 + (__alignof__(union nf_conntrack_help) - 1))
270 & (~((unsigned long)(__alignof__(union nf_conntrack_help) -1))));
271 return 0;
272}
273
274int nf_conntrack_register_cache(u_int32_t features, const char *name, 296int nf_conntrack_register_cache(u_int32_t features, const char *name,
275 size_t size, 297 size_t size)
276 int (*init)(struct nf_conn *, u_int32_t))
277{ 298{
278 int ret = 0; 299 int ret = 0;
279 char *cache_name; 300 char *cache_name;
@@ -288,7 +309,7 @@ int nf_conntrack_register_cache(u_int32_t features, const char *name,
288 return -EINVAL; 309 return -EINVAL;
289 } 310 }
290 311
291 down(&nf_ct_cache_mutex); 312 mutex_lock(&nf_ct_cache_mutex);
292 313
293 write_lock_bh(&nf_ct_cache_lock); 314 write_lock_bh(&nf_ct_cache_lock);
294 /* e.g: multiple helpers are loaded */ 315 /* e.g: multiple helpers are loaded */
@@ -296,8 +317,7 @@ int nf_conntrack_register_cache(u_int32_t features, const char *name,
296 DEBUGP("nf_conntrack_register_cache: already resisterd.\n"); 317 DEBUGP("nf_conntrack_register_cache: already resisterd.\n");
297 if ((!strncmp(nf_ct_cache[features].name, name, 318 if ((!strncmp(nf_ct_cache[features].name, name,
298 NF_CT_FEATURES_NAMELEN)) 319 NF_CT_FEATURES_NAMELEN))
299 && nf_ct_cache[features].size == size 320 && nf_ct_cache[features].size == size) {
300 && nf_ct_cache[features].init_conntrack == init) {
301 DEBUGP("nf_conntrack_register_cache: reusing.\n"); 321 DEBUGP("nf_conntrack_register_cache: reusing.\n");
302 nf_ct_cache[features].use++; 322 nf_ct_cache[features].use++;
303 ret = 0; 323 ret = 0;
@@ -305,7 +325,7 @@ int nf_conntrack_register_cache(u_int32_t features, const char *name,
305 ret = -EBUSY; 325 ret = -EBUSY;
306 326
307 write_unlock_bh(&nf_ct_cache_lock); 327 write_unlock_bh(&nf_ct_cache_lock);
308 up(&nf_ct_cache_mutex); 328 mutex_unlock(&nf_ct_cache_mutex);
309 return ret; 329 return ret;
310 } 330 }
311 write_unlock_bh(&nf_ct_cache_lock); 331 write_unlock_bh(&nf_ct_cache_lock);
@@ -340,7 +360,6 @@ int nf_conntrack_register_cache(u_int32_t features, const char *name,
340 write_lock_bh(&nf_ct_cache_lock); 360 write_lock_bh(&nf_ct_cache_lock);
341 nf_ct_cache[features].use = 1; 361 nf_ct_cache[features].use = 1;
342 nf_ct_cache[features].size = size; 362 nf_ct_cache[features].size = size;
343 nf_ct_cache[features].init_conntrack = init;
344 nf_ct_cache[features].cachep = cachep; 363 nf_ct_cache[features].cachep = cachep;
345 nf_ct_cache[features].name = cache_name; 364 nf_ct_cache[features].name = cache_name;
346 write_unlock_bh(&nf_ct_cache_lock); 365 write_unlock_bh(&nf_ct_cache_lock);
@@ -350,7 +369,7 @@ int nf_conntrack_register_cache(u_int32_t features, const char *name,
350out_free_name: 369out_free_name:
351 kfree(cache_name); 370 kfree(cache_name);
352out_up_mutex: 371out_up_mutex:
353 up(&nf_ct_cache_mutex); 372 mutex_unlock(&nf_ct_cache_mutex);
354 return ret; 373 return ret;
355} 374}
356 375
@@ -365,19 +384,18 @@ void nf_conntrack_unregister_cache(u_int32_t features)
365 * slab cache. 384 * slab cache.
366 */ 385 */
367 DEBUGP("nf_conntrack_unregister_cache: 0x%04x\n", features); 386 DEBUGP("nf_conntrack_unregister_cache: 0x%04x\n", features);
368 down(&nf_ct_cache_mutex); 387 mutex_lock(&nf_ct_cache_mutex);
369 388
370 write_lock_bh(&nf_ct_cache_lock); 389 write_lock_bh(&nf_ct_cache_lock);
371 if (--nf_ct_cache[features].use > 0) { 390 if (--nf_ct_cache[features].use > 0) {
372 write_unlock_bh(&nf_ct_cache_lock); 391 write_unlock_bh(&nf_ct_cache_lock);
373 up(&nf_ct_cache_mutex); 392 mutex_unlock(&nf_ct_cache_mutex);
374 return; 393 return;
375 } 394 }
376 cachep = nf_ct_cache[features].cachep; 395 cachep = nf_ct_cache[features].cachep;
377 name = nf_ct_cache[features].name; 396 name = nf_ct_cache[features].name;
378 nf_ct_cache[features].cachep = NULL; 397 nf_ct_cache[features].cachep = NULL;
379 nf_ct_cache[features].name = NULL; 398 nf_ct_cache[features].name = NULL;
380 nf_ct_cache[features].init_conntrack = NULL;
381 nf_ct_cache[features].size = 0; 399 nf_ct_cache[features].size = 0;
382 write_unlock_bh(&nf_ct_cache_lock); 400 write_unlock_bh(&nf_ct_cache_lock);
383 401
@@ -386,7 +404,7 @@ void nf_conntrack_unregister_cache(u_int32_t features)
386 kmem_cache_destroy(cachep); 404 kmem_cache_destroy(cachep);
387 kfree(name); 405 kfree(name);
388 406
389 up(&nf_ct_cache_mutex); 407 mutex_unlock(&nf_ct_cache_mutex);
390} 408}
391 409
392int 410int
@@ -432,11 +450,15 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
432/* nf_conntrack_expect helper functions */ 450/* nf_conntrack_expect helper functions */
433void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) 451void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
434{ 452{
453 struct nf_conn_help *master_help = nfct_help(exp->master);
454
455 NF_CT_ASSERT(master_help);
435 ASSERT_WRITE_LOCK(&nf_conntrack_lock); 456 ASSERT_WRITE_LOCK(&nf_conntrack_lock);
436 NF_CT_ASSERT(!timer_pending(&exp->timeout)); 457 NF_CT_ASSERT(!timer_pending(&exp->timeout));
458
437 list_del(&exp->list); 459 list_del(&exp->list);
438 NF_CT_STAT_INC(expect_delete); 460 NF_CT_STAT_INC(expect_delete);
439 exp->master->expecting--; 461 master_help->expecting--;
440 nf_conntrack_expect_put(exp); 462 nf_conntrack_expect_put(exp);
441} 463}
442 464
@@ -508,9 +530,10 @@ find_expectation(const struct nf_conntrack_tuple *tuple)
508void nf_ct_remove_expectations(struct nf_conn *ct) 530void nf_ct_remove_expectations(struct nf_conn *ct)
509{ 531{
510 struct nf_conntrack_expect *i, *tmp; 532 struct nf_conntrack_expect *i, *tmp;
533 struct nf_conn_help *help = nfct_help(ct);
511 534
512 /* Optimization: most connection never expect any others. */ 535 /* Optimization: most connection never expect any others. */
513 if (ct->expecting == 0) 536 if (!help || help->expecting == 0)
514 return; 537 return;
515 538
516 list_for_each_entry_safe(i, tmp, &nf_conntrack_expect_list, list) { 539 list_for_each_entry_safe(i, tmp, &nf_conntrack_expect_list, list) {
@@ -713,6 +736,7 @@ __nf_conntrack_confirm(struct sk_buff **pskb)
713 conntrack_tuple_cmp, 736 conntrack_tuple_cmp,
714 struct nf_conntrack_tuple_hash *, 737 struct nf_conntrack_tuple_hash *,
715 &ct->tuplehash[IP_CT_DIR_REPLY].tuple, NULL)) { 738 &ct->tuplehash[IP_CT_DIR_REPLY].tuple, NULL)) {
739 struct nf_conn_help *help;
716 /* Remove from unconfirmed list */ 740 /* Remove from unconfirmed list */
717 list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); 741 list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
718 742
@@ -726,7 +750,8 @@ __nf_conntrack_confirm(struct sk_buff **pskb)
726 set_bit(IPS_CONFIRMED_BIT, &ct->status); 750 set_bit(IPS_CONFIRMED_BIT, &ct->status);
727 NF_CT_STAT_INC(insert); 751 NF_CT_STAT_INC(insert);
728 write_unlock_bh(&nf_conntrack_lock); 752 write_unlock_bh(&nf_conntrack_lock);
729 if (ct->helper) 753 help = nfct_help(ct);
754 if (help && help->helper)
730 nf_conntrack_event_cache(IPCT_HELPER, *pskb); 755 nf_conntrack_event_cache(IPCT_HELPER, *pskb);
731#ifdef CONFIG_NF_NAT_NEEDED 756#ifdef CONFIG_NF_NAT_NEEDED
732 if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) || 757 if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) ||
@@ -842,8 +867,9 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
842{ 867{
843 struct nf_conn *conntrack = NULL; 868 struct nf_conn *conntrack = NULL;
844 u_int32_t features = 0; 869 u_int32_t features = 0;
870 struct nf_conntrack_helper *helper;
845 871
846 if (!nf_conntrack_hash_rnd_initted) { 872 if (unlikely(!nf_conntrack_hash_rnd_initted)) {
847 get_random_bytes(&nf_conntrack_hash_rnd, 4); 873 get_random_bytes(&nf_conntrack_hash_rnd, 4);
848 nf_conntrack_hash_rnd_initted = 1; 874 nf_conntrack_hash_rnd_initted = 1;
849 } 875 }
@@ -863,8 +889,11 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
863 889
864 /* find features needed by this conntrack. */ 890 /* find features needed by this conntrack. */
865 features = l3proto->get_features(orig); 891 features = l3proto->get_features(orig);
892
893 /* FIXME: protect helper list per RCU */
866 read_lock_bh(&nf_conntrack_lock); 894 read_lock_bh(&nf_conntrack_lock);
867 if (__nf_ct_helper_find(repl) != NULL) 895 helper = __nf_ct_helper_find(repl);
896 if (helper)
868 features |= NF_CT_F_HELP; 897 features |= NF_CT_F_HELP;
869 read_unlock_bh(&nf_conntrack_lock); 898 read_unlock_bh(&nf_conntrack_lock);
870 899
@@ -872,7 +901,7 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
872 901
873 read_lock_bh(&nf_ct_cache_lock); 902 read_lock_bh(&nf_ct_cache_lock);
874 903
875 if (!nf_ct_cache[features].use) { 904 if (unlikely(!nf_ct_cache[features].use)) {
876 DEBUGP("nf_conntrack_alloc: not supported features = 0x%x\n", 905 DEBUGP("nf_conntrack_alloc: not supported features = 0x%x\n",
877 features); 906 features);
878 goto out; 907 goto out;
@@ -886,12 +915,10 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
886 915
887 memset(conntrack, 0, nf_ct_cache[features].size); 916 memset(conntrack, 0, nf_ct_cache[features].size);
888 conntrack->features = features; 917 conntrack->features = features;
889 if (nf_ct_cache[features].init_conntrack && 918 if (helper) {
890 nf_ct_cache[features].init_conntrack(conntrack, features) < 0) { 919 struct nf_conn_help *help = nfct_help(conntrack);
891 DEBUGP("nf_conntrack_alloc: failed to init\n"); 920 NF_CT_ASSERT(help);
892 kmem_cache_free(nf_ct_cache[features].cachep, conntrack); 921 help->helper = helper;
893 conntrack = NULL;
894 goto out;
895 } 922 }
896 923
897 atomic_set(&conntrack->ct_general.use, 1); 924 atomic_set(&conntrack->ct_general.use, 1);
@@ -972,11 +999,8 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
972#endif 999#endif
973 nf_conntrack_get(&conntrack->master->ct_general); 1000 nf_conntrack_get(&conntrack->master->ct_general);
974 NF_CT_STAT_INC(expect_new); 1001 NF_CT_STAT_INC(expect_new);
975 } else { 1002 } else
976 conntrack->helper = __nf_ct_helper_find(&repl_tuple);
977
978 NF_CT_STAT_INC(new); 1003 NF_CT_STAT_INC(new);
979 }
980 1004
981 /* Overload tuple linked list to put us in unconfirmed list. */ 1005 /* Overload tuple linked list to put us in unconfirmed list. */
982 list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed); 1006 list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed);
@@ -1206,14 +1230,16 @@ void nf_conntrack_expect_put(struct nf_conntrack_expect *exp)
1206 1230
1207static void nf_conntrack_expect_insert(struct nf_conntrack_expect *exp) 1231static void nf_conntrack_expect_insert(struct nf_conntrack_expect *exp)
1208{ 1232{
1233 struct nf_conn_help *master_help = nfct_help(exp->master);
1234
1209 atomic_inc(&exp->use); 1235 atomic_inc(&exp->use);
1210 exp->master->expecting++; 1236 master_help->expecting++;
1211 list_add(&exp->list, &nf_conntrack_expect_list); 1237 list_add(&exp->list, &nf_conntrack_expect_list);
1212 1238
1213 init_timer(&exp->timeout); 1239 init_timer(&exp->timeout);
1214 exp->timeout.data = (unsigned long)exp; 1240 exp->timeout.data = (unsigned long)exp;
1215 exp->timeout.function = expectation_timed_out; 1241 exp->timeout.function = expectation_timed_out;
1216 exp->timeout.expires = jiffies + exp->master->helper->timeout * HZ; 1242 exp->timeout.expires = jiffies + master_help->helper->timeout * HZ;
1217 add_timer(&exp->timeout); 1243 add_timer(&exp->timeout);
1218 1244
1219 exp->id = ++nf_conntrack_expect_next_id; 1245 exp->id = ++nf_conntrack_expect_next_id;
@@ -1239,10 +1265,12 @@ static void evict_oldest_expect(struct nf_conn *master)
1239 1265
1240static inline int refresh_timer(struct nf_conntrack_expect *i) 1266static inline int refresh_timer(struct nf_conntrack_expect *i)
1241{ 1267{
1268 struct nf_conn_help *master_help = nfct_help(i->master);
1269
1242 if (!del_timer(&i->timeout)) 1270 if (!del_timer(&i->timeout))
1243 return 0; 1271 return 0;
1244 1272
1245 i->timeout.expires = jiffies + i->master->helper->timeout*HZ; 1273 i->timeout.expires = jiffies + master_help->helper->timeout*HZ;
1246 add_timer(&i->timeout); 1274 add_timer(&i->timeout);
1247 return 1; 1275 return 1;
1248} 1276}
@@ -1251,8 +1279,11 @@ int nf_conntrack_expect_related(struct nf_conntrack_expect *expect)
1251{ 1279{
1252 struct nf_conntrack_expect *i; 1280 struct nf_conntrack_expect *i;
1253 struct nf_conn *master = expect->master; 1281 struct nf_conn *master = expect->master;
1282 struct nf_conn_help *master_help = nfct_help(master);
1254 int ret; 1283 int ret;
1255 1284
1285 NF_CT_ASSERT(master_help);
1286
1256 DEBUGP("nf_conntrack_expect_related %p\n", related_to); 1287 DEBUGP("nf_conntrack_expect_related %p\n", related_to);
1257 DEBUGP("tuple: "); NF_CT_DUMP_TUPLE(&expect->tuple); 1288 DEBUGP("tuple: "); NF_CT_DUMP_TUPLE(&expect->tuple);
1258 DEBUGP("mask: "); NF_CT_DUMP_TUPLE(&expect->mask); 1289 DEBUGP("mask: "); NF_CT_DUMP_TUPLE(&expect->mask);
@@ -1271,8 +1302,8 @@ int nf_conntrack_expect_related(struct nf_conntrack_expect *expect)
1271 } 1302 }
1272 } 1303 }
1273 /* Will be over limit? */ 1304 /* Will be over limit? */
1274 if (master->helper->max_expected && 1305 if (master_help->helper->max_expected &&
1275 master->expecting >= master->helper->max_expected) 1306 master_help->expecting >= master_help->helper->max_expected)
1276 evict_oldest_expect(master); 1307 evict_oldest_expect(master);
1277 1308
1278 nf_conntrack_expect_insert(expect); 1309 nf_conntrack_expect_insert(expect);
@@ -1283,24 +1314,6 @@ out:
1283 return ret; 1314 return ret;
1284} 1315}
1285 1316
1286/* Alter reply tuple (maybe alter helper). This is for NAT, and is
1287 implicitly racy: see __nf_conntrack_confirm */
1288void nf_conntrack_alter_reply(struct nf_conn *conntrack,
1289 const struct nf_conntrack_tuple *newreply)
1290{
1291 write_lock_bh(&nf_conntrack_lock);
1292 /* Should be unconfirmed, so not in hash table yet */
1293 NF_CT_ASSERT(!nf_ct_is_confirmed(conntrack));
1294
1295 DEBUGP("Altering reply tuple of %p to ", conntrack);
1296 NF_CT_DUMP_TUPLE(newreply);
1297
1298 conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
1299 if (!conntrack->master && conntrack->expecting == 0)
1300 conntrack->helper = __nf_ct_helper_find(newreply);
1301 write_unlock_bh(&nf_conntrack_lock);
1302}
1303
1304int nf_conntrack_helper_register(struct nf_conntrack_helper *me) 1317int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
1305{ 1318{
1306 int ret; 1319 int ret;
@@ -1308,9 +1321,8 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
1308 1321
1309 ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help", 1322 ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help",
1310 sizeof(struct nf_conn) 1323 sizeof(struct nf_conn)
1311 + sizeof(union nf_conntrack_help) 1324 + sizeof(struct nf_conn_help)
1312 + __alignof__(union nf_conntrack_help), 1325 + __alignof__(struct nf_conn_help));
1313 init_conntrack_for_helper);
1314 if (ret < 0) { 1326 if (ret < 0) {
1315 printk(KERN_ERR "nf_conntrack_helper_reigster: Unable to create slab cache for conntracks\n"); 1327 printk(KERN_ERR "nf_conntrack_helper_reigster: Unable to create slab cache for conntracks\n");
1316 return ret; 1328 return ret;
@@ -1338,9 +1350,12 @@ __nf_conntrack_helper_find_byname(const char *name)
1338static inline int unhelp(struct nf_conntrack_tuple_hash *i, 1350static inline int unhelp(struct nf_conntrack_tuple_hash *i,
1339 const struct nf_conntrack_helper *me) 1351 const struct nf_conntrack_helper *me)
1340{ 1352{
1341 if (nf_ct_tuplehash_to_ctrack(i)->helper == me) { 1353 struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i);
1342 nf_conntrack_event(IPCT_HELPER, nf_ct_tuplehash_to_ctrack(i)); 1354 struct nf_conn_help *help = nfct_help(ct);
1343 nf_ct_tuplehash_to_ctrack(i)->helper = NULL; 1355
1356 if (help && help->helper == me) {
1357 nf_conntrack_event(IPCT_HELPER, ct);
1358 help->helper = NULL;
1344 } 1359 }
1345 return 0; 1360 return 0;
1346} 1361}
@@ -1356,7 +1371,8 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
1356 1371
1357 /* Get rid of expectations */ 1372 /* Get rid of expectations */
1358 list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) { 1373 list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) {
1359 if (exp->master->helper == me && del_timer(&exp->timeout)) { 1374 struct nf_conn_help *help = nfct_help(exp->master);
1375 if (help->helper == me && del_timer(&exp->timeout)) {
1360 nf_ct_unlink_expect(exp); 1376 nf_ct_unlink_expect(exp);
1361 nf_conntrack_expect_put(exp); 1377 nf_conntrack_expect_put(exp);
1362 } 1378 }
@@ -1423,6 +1439,8 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
1423 1439
1424#include <linux/netfilter/nfnetlink.h> 1440#include <linux/netfilter/nfnetlink.h>
1425#include <linux/netfilter/nfnetlink_conntrack.h> 1441#include <linux/netfilter/nfnetlink_conntrack.h>
1442#include <linux/mutex.h>
1443
1426 1444
1427/* Generic function for tcp/udp/sctp/dccp and alike. This needs to be 1445/* Generic function for tcp/udp/sctp/dccp and alike. This needs to be
1428 * in ip_conntrack_core, since we don't want the protocols to autoload 1446 * in ip_conntrack_core, since we don't want the protocols to autoload
@@ -1697,7 +1715,7 @@ int __init nf_conntrack_init(void)
1697 } 1715 }
1698 1716
1699 ret = nf_conntrack_register_cache(NF_CT_F_BASIC, "nf_conntrack:basic", 1717 ret = nf_conntrack_register_cache(NF_CT_F_BASIC, "nf_conntrack:basic",
1700 sizeof(struct nf_conn), NULL); 1718 sizeof(struct nf_conn));
1701 if (ret < 0) { 1719 if (ret < 0) {
1702 printk(KERN_ERR "Unable to create nf_conn slab cache\n"); 1720 printk(KERN_ERR "Unable to create nf_conn slab cache\n");
1703 goto err_free_hash; 1721 goto err_free_hash;
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 6f210f399762..cd191b0d4ac7 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -440,7 +440,7 @@ static int help(struct sk_buff **pskb,
440 u32 seq; 440 u32 seq;
441 int dir = CTINFO2DIR(ctinfo); 441 int dir = CTINFO2DIR(ctinfo);
442 unsigned int matchlen, matchoff; 442 unsigned int matchlen, matchoff;
443 struct ip_ct_ftp_master *ct_ftp_info = &ct->help->ct_ftp_info; 443 struct ip_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info;
444 struct nf_conntrack_expect *exp; 444 struct nf_conntrack_expect *exp;
445 struct nf_conntrack_man cmd = {}; 445 struct nf_conntrack_man cmd = {};
446 446
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 9ff3463037e1..0e0e9d7b34c8 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -2,9 +2,9 @@
2 * protocol helpers and general trouble making from userspace. 2 * protocol helpers and general trouble making from userspace.
3 * 3 *
4 * (C) 2001 by Jay Schulist <jschlst@samba.org> 4 * (C) 2001 by Jay Schulist <jschlst@samba.org>
5 * (C) 2002-2005 by Harald Welte <laforge@gnumonks.org> 5 * (C) 2002-2006 by Harald Welte <laforge@gnumonks.org>
6 * (C) 2003 by Patrick Mchardy <kaber@trash.net> 6 * (C) 2003 by Patrick Mchardy <kaber@trash.net>
7 * (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net> 7 * (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net>
8 * 8 *
9 * I've reworked this stuff to use attributes instead of conntrack 9 * I've reworked this stuff to use attributes instead of conntrack
10 * structures. 5.44 am. I need more tea. --pablo 05/07/11. 10 * structures. 5.44 am. I need more tea. --pablo 05/07/11.
@@ -44,7 +44,7 @@
44 44
45MODULE_LICENSE("GPL"); 45MODULE_LICENSE("GPL");
46 46
47static char __initdata version[] = "0.92"; 47static char __initdata version[] = "0.93";
48 48
49#if 0 49#if 0
50#define DEBUGP printk 50#define DEBUGP printk
@@ -55,20 +55,18 @@ static char __initdata version[] = "0.92";
55 55
56static inline int 56static inline int
57ctnetlink_dump_tuples_proto(struct sk_buff *skb, 57ctnetlink_dump_tuples_proto(struct sk_buff *skb,
58 const struct nf_conntrack_tuple *tuple) 58 const struct nf_conntrack_tuple *tuple,
59 struct nf_conntrack_protocol *proto)
59{ 60{
60 struct nf_conntrack_protocol *proto;
61 int ret = 0; 61 int ret = 0;
62 struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
62 63
63 NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum); 64 NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
64 65
65 /* If no protocol helper is found, this function will return the
66 * generic protocol helper, so proto won't *ever* be NULL */
67 proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
68 if (likely(proto->tuple_to_nfattr)) 66 if (likely(proto->tuple_to_nfattr))
69 ret = proto->tuple_to_nfattr(skb, tuple); 67 ret = proto->tuple_to_nfattr(skb, tuple);
70 68
71 nf_ct_proto_put(proto); 69 NFA_NEST_END(skb, nest_parms);
72 70
73 return ret; 71 return ret;
74 72
@@ -77,33 +75,44 @@ nfattr_failure:
77} 75}
78 76
79static inline int 77static inline int
80ctnetlink_dump_tuples(struct sk_buff *skb, 78ctnetlink_dump_tuples_ip(struct sk_buff *skb,
81 const struct nf_conntrack_tuple *tuple) 79 const struct nf_conntrack_tuple *tuple,
80 struct nf_conntrack_l3proto *l3proto)
82{ 81{
83 struct nfattr *nest_parms;
84 struct nf_conntrack_l3proto *l3proto;
85 int ret = 0; 82 int ret = 0;
86 83 struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
87 l3proto = nf_ct_l3proto_find_get(tuple->src.l3num); 84
88
89 nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
90 if (likely(l3proto->tuple_to_nfattr)) 85 if (likely(l3proto->tuple_to_nfattr))
91 ret = l3proto->tuple_to_nfattr(skb, tuple); 86 ret = l3proto->tuple_to_nfattr(skb, tuple);
87
92 NFA_NEST_END(skb, nest_parms); 88 NFA_NEST_END(skb, nest_parms);
93 89
90 return ret;
91
92nfattr_failure:
93 return -1;
94}
95
96static inline int
97ctnetlink_dump_tuples(struct sk_buff *skb,
98 const struct nf_conntrack_tuple *tuple)
99{
100 int ret;
101 struct nf_conntrack_l3proto *l3proto;
102 struct nf_conntrack_protocol *proto;
103
104 l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
105 ret = ctnetlink_dump_tuples_ip(skb, tuple, l3proto);
94 nf_ct_l3proto_put(l3proto); 106 nf_ct_l3proto_put(l3proto);
95 107
96 if (unlikely(ret < 0)) 108 if (unlikely(ret < 0))
97 return ret; 109 return ret;
98 110
99 nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO); 111 proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
100 ret = ctnetlink_dump_tuples_proto(skb, tuple); 112 ret = ctnetlink_dump_tuples_proto(skb, tuple, proto);
101 NFA_NEST_END(skb, nest_parms); 113 nf_ct_proto_put(proto);
102 114
103 return ret; 115 return ret;
104
105nfattr_failure:
106 return -1;
107} 116}
108 117
109static inline int 118static inline int
@@ -165,15 +174,16 @@ static inline int
165ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct) 174ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct)
166{ 175{
167 struct nfattr *nest_helper; 176 struct nfattr *nest_helper;
177 const struct nf_conn_help *help = nfct_help(ct);
168 178
169 if (!ct->helper) 179 if (!help || !help->helper)
170 return 0; 180 return 0;
171 181
172 nest_helper = NFA_NEST(skb, CTA_HELP); 182 nest_helper = NFA_NEST(skb, CTA_HELP);
173 NFA_PUT(skb, CTA_HELP_NAME, strlen(ct->helper->name), ct->helper->name); 183 NFA_PUT(skb, CTA_HELP_NAME, strlen(help->helper->name), help->helper->name);
174 184
175 if (ct->helper->to_nfattr) 185 if (help->helper->to_nfattr)
176 ct->helper->to_nfattr(skb, ct); 186 help->helper->to_nfattr(skb, ct);
177 187
178 NFA_NEST_END(skb, nest_helper); 188 NFA_NEST_END(skb, nest_helper);
179 189
@@ -337,9 +347,10 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
337 group = NFNLGRP_CONNTRACK_UPDATE; 347 group = NFNLGRP_CONNTRACK_UPDATE;
338 } else 348 } else
339 return NOTIFY_DONE; 349 return NOTIFY_DONE;
340 350
341 /* FIXME: Check if there are any listeners before, don't hurt performance */ 351 if (!nfnetlink_has_listeners(group))
342 352 return NOTIFY_DONE;
353
343 skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); 354 skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
344 if (!skb) 355 if (!skb)
345 return NOTIFY_DONE; 356 return NOTIFY_DONE;
@@ -903,11 +914,17 @@ static inline int
903ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[]) 914ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
904{ 915{
905 struct nf_conntrack_helper *helper; 916 struct nf_conntrack_helper *helper;
917 struct nf_conn_help *help = nfct_help(ct);
906 char *helpname; 918 char *helpname;
907 int err; 919 int err;
908 920
909 DEBUGP("entered %s\n", __FUNCTION__); 921 DEBUGP("entered %s\n", __FUNCTION__);
910 922
923 if (!help) {
924 /* FIXME: we need to reallocate and rehash */
925 return -EBUSY;
926 }
927
911 /* don't change helper of sibling connections */ 928 /* don't change helper of sibling connections */
912 if (ct->master) 929 if (ct->master)
913 return -EINVAL; 930 return -EINVAL;
@@ -924,18 +941,18 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
924 return -EINVAL; 941 return -EINVAL;
925 } 942 }
926 943
927 if (ct->helper) { 944 if (help->helper) {
928 if (!helper) { 945 if (!helper) {
929 /* we had a helper before ... */ 946 /* we had a helper before ... */
930 nf_ct_remove_expectations(ct); 947 nf_ct_remove_expectations(ct);
931 ct->helper = NULL; 948 help->helper = NULL;
932 } else { 949 } else {
933 /* need to zero data of old helper */ 950 /* need to zero data of old helper */
934 memset(&ct->help, 0, sizeof(ct->help)); 951 memset(&help->help, 0, sizeof(help->help));
935 } 952 }
936 } 953 }
937 954
938 ct->helper = helper; 955 help->helper = helper;
939 956
940 return 0; 957 return 0;
941} 958}
@@ -1050,14 +1067,9 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
1050 ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); 1067 ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
1051#endif 1068#endif
1052 1069
1053 ct->helper = nf_ct_helper_find_get(rtuple);
1054
1055 add_timer(&ct->timeout); 1070 add_timer(&ct->timeout);
1056 nf_conntrack_hash_insert(ct); 1071 nf_conntrack_hash_insert(ct);
1057 1072
1058 if (ct->helper)
1059 nf_ct_helper_put(ct->helper);
1060
1061 DEBUGP("conntrack with id %u inserted\n", ct->id); 1073 DEBUGP("conntrack with id %u inserted\n", ct->id);
1062 return 0; 1074 return 0;
1063 1075
@@ -1150,6 +1162,37 @@ nfattr_failure:
1150} 1162}
1151 1163
1152static inline int 1164static inline int
1165ctnetlink_exp_dump_mask(struct sk_buff *skb,
1166 const struct nf_conntrack_tuple *tuple,
1167 const struct nf_conntrack_tuple *mask)
1168{
1169 int ret;
1170 struct nf_conntrack_l3proto *l3proto;
1171 struct nf_conntrack_protocol *proto;
1172 struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
1173
1174 l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
1175 ret = ctnetlink_dump_tuples_ip(skb, mask, l3proto);
1176 nf_ct_l3proto_put(l3proto);
1177
1178 if (unlikely(ret < 0))
1179 goto nfattr_failure;
1180
1181 proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
1182 ret = ctnetlink_dump_tuples_proto(skb, mask, proto);
1183 nf_ct_proto_put(proto);
1184 if (unlikely(ret < 0))
1185 goto nfattr_failure;
1186
1187 NFA_NEST_END(skb, nest_parms);
1188
1189 return 0;
1190
1191nfattr_failure:
1192 return -1;
1193}
1194
1195static inline int
1153ctnetlink_exp_dump_expect(struct sk_buff *skb, 1196ctnetlink_exp_dump_expect(struct sk_buff *skb,
1154 const struct nf_conntrack_expect *exp) 1197 const struct nf_conntrack_expect *exp)
1155{ 1198{
@@ -1159,7 +1202,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
1159 1202
1160 if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0) 1203 if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
1161 goto nfattr_failure; 1204 goto nfattr_failure;
1162 if (ctnetlink_exp_dump_tuple(skb, &exp->mask, CTA_EXPECT_MASK) < 0) 1205 if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
1163 goto nfattr_failure; 1206 goto nfattr_failure;
1164 if (ctnetlink_exp_dump_tuple(skb, 1207 if (ctnetlink_exp_dump_tuple(skb,
1165 &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple, 1208 &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
@@ -1417,7 +1460,8 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
1417 } 1460 }
1418 list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, 1461 list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list,
1419 list) { 1462 list) {
1420 if (exp->master->helper == h 1463 struct nf_conn_help *m_help = nfct_help(exp->master);
1464 if (m_help->helper == h
1421 && del_timer(&exp->timeout)) { 1465 && del_timer(&exp->timeout)) {
1422 nf_ct_unlink_expect(exp); 1466 nf_ct_unlink_expect(exp);
1423 nf_conntrack_expect_put(exp); 1467 nf_conntrack_expect_put(exp);
@@ -1452,6 +1496,7 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3)
1452 struct nf_conntrack_tuple_hash *h = NULL; 1496 struct nf_conntrack_tuple_hash *h = NULL;
1453 struct nf_conntrack_expect *exp; 1497 struct nf_conntrack_expect *exp;
1454 struct nf_conn *ct; 1498 struct nf_conn *ct;
1499 struct nf_conn_help *help;
1455 int err = 0; 1500 int err = 0;
1456 1501
1457 DEBUGP("entered %s\n", __FUNCTION__); 1502 DEBUGP("entered %s\n", __FUNCTION__);
@@ -1472,8 +1517,9 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3)
1472 if (!h) 1517 if (!h)
1473 return -ENOENT; 1518 return -ENOENT;
1474 ct = nf_ct_tuplehash_to_ctrack(h); 1519 ct = nf_ct_tuplehash_to_ctrack(h);
1520 help = nfct_help(ct);
1475 1521
1476 if (!ct->helper) { 1522 if (!help || !help->helper) {
1477 /* such conntrack hasn't got any helper, abort */ 1523 /* such conntrack hasn't got any helper, abort */
1478 err = -EINVAL; 1524 err = -EINVAL;
1479 goto out; 1525 goto out;
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 617599aeeead..75577e175b35 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -834,12 +834,13 @@ EXPORT_SYMBOL_GPL(__nf_ct_event_cache_init);
834EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache); 834EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache);
835EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events); 835EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events);
836#endif 836#endif
837EXPORT_SYMBOL(nf_ct_l3proto_try_module_get);
838EXPORT_SYMBOL(nf_ct_l3proto_module_put);
837EXPORT_SYMBOL(nf_conntrack_l3proto_register); 839EXPORT_SYMBOL(nf_conntrack_l3proto_register);
838EXPORT_SYMBOL(nf_conntrack_l3proto_unregister); 840EXPORT_SYMBOL(nf_conntrack_l3proto_unregister);
839EXPORT_SYMBOL(nf_conntrack_protocol_register); 841EXPORT_SYMBOL(nf_conntrack_protocol_register);
840EXPORT_SYMBOL(nf_conntrack_protocol_unregister); 842EXPORT_SYMBOL(nf_conntrack_protocol_unregister);
841EXPORT_SYMBOL(nf_ct_invert_tuplepr); 843EXPORT_SYMBOL(nf_ct_invert_tuplepr);
842EXPORT_SYMBOL(nf_conntrack_alter_reply);
843EXPORT_SYMBOL(nf_conntrack_destroyed); 844EXPORT_SYMBOL(nf_conntrack_destroyed);
844EXPORT_SYMBOL(need_conntrack); 845EXPORT_SYMBOL(need_conntrack);
845EXPORT_SYMBOL(nf_conntrack_helper_register); 846EXPORT_SYMBOL(nf_conntrack_helper_register);
diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c
index 61a833a9caa6..0a63d7dac7be 100644
--- a/net/netfilter/nf_sockopt.c
+++ b/net/netfilter/nf_sockopt.c
@@ -4,6 +4,7 @@
4#include <linux/module.h> 4#include <linux/module.h>
5#include <linux/skbuff.h> 5#include <linux/skbuff.h>
6#include <linux/netfilter.h> 6#include <linux/netfilter.h>
7#include <linux/mutex.h>
7#include <net/sock.h> 8#include <net/sock.h>
8 9
9#include "nf_internals.h" 10#include "nf_internals.h"
@@ -11,7 +12,7 @@
11/* Sockopts only registered and called from user context, so 12/* Sockopts only registered and called from user context, so
12 net locking would be overkill. Also, [gs]etsockopt calls may 13 net locking would be overkill. Also, [gs]etsockopt calls may
13 sleep. */ 14 sleep. */
14static DECLARE_MUTEX(nf_sockopt_mutex); 15static DEFINE_MUTEX(nf_sockopt_mutex);
15static LIST_HEAD(nf_sockopts); 16static LIST_HEAD(nf_sockopts);
16 17
17/* Do exclusive ranges overlap? */ 18/* Do exclusive ranges overlap? */
@@ -26,7 +27,7 @@ int nf_register_sockopt(struct nf_sockopt_ops *reg)
26 struct list_head *i; 27 struct list_head *i;
27 int ret = 0; 28 int ret = 0;
28 29
29 if (down_interruptible(&nf_sockopt_mutex) != 0) 30 if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
30 return -EINTR; 31 return -EINTR;
31 32
32 list_for_each(i, &nf_sockopts) { 33 list_for_each(i, &nf_sockopts) {
@@ -48,7 +49,7 @@ int nf_register_sockopt(struct nf_sockopt_ops *reg)
48 49
49 list_add(&reg->list, &nf_sockopts); 50 list_add(&reg->list, &nf_sockopts);
50out: 51out:
51 up(&nf_sockopt_mutex); 52 mutex_unlock(&nf_sockopt_mutex);
52 return ret; 53 return ret;
53} 54}
54EXPORT_SYMBOL(nf_register_sockopt); 55EXPORT_SYMBOL(nf_register_sockopt);
@@ -57,18 +58,18 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg)
57{ 58{
58 /* No point being interruptible: we're probably in cleanup_module() */ 59 /* No point being interruptible: we're probably in cleanup_module() */
59 restart: 60 restart:
60 down(&nf_sockopt_mutex); 61 mutex_lock(&nf_sockopt_mutex);
61 if (reg->use != 0) { 62 if (reg->use != 0) {
62 /* To be woken by nf_sockopt call... */ 63 /* To be woken by nf_sockopt call... */
63 /* FIXME: Stuart Young's name appears gratuitously. */ 64 /* FIXME: Stuart Young's name appears gratuitously. */
64 set_current_state(TASK_UNINTERRUPTIBLE); 65 set_current_state(TASK_UNINTERRUPTIBLE);
65 reg->cleanup_task = current; 66 reg->cleanup_task = current;
66 up(&nf_sockopt_mutex); 67 mutex_unlock(&nf_sockopt_mutex);
67 schedule(); 68 schedule();
68 goto restart; 69 goto restart;
69 } 70 }
70 list_del(&reg->list); 71 list_del(&reg->list);
71 up(&nf_sockopt_mutex); 72 mutex_unlock(&nf_sockopt_mutex);
72} 73}
73EXPORT_SYMBOL(nf_unregister_sockopt); 74EXPORT_SYMBOL(nf_unregister_sockopt);
74 75
@@ -80,7 +81,7 @@ static int nf_sockopt(struct sock *sk, int pf, int val,
80 struct nf_sockopt_ops *ops; 81 struct nf_sockopt_ops *ops;
81 int ret; 82 int ret;
82 83
83 if (down_interruptible(&nf_sockopt_mutex) != 0) 84 if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
84 return -EINTR; 85 return -EINTR;
85 86
86 list_for_each(i, &nf_sockopts) { 87 list_for_each(i, &nf_sockopts) {
@@ -90,7 +91,7 @@ static int nf_sockopt(struct sock *sk, int pf, int val,
90 if (val >= ops->get_optmin 91 if (val >= ops->get_optmin
91 && val < ops->get_optmax) { 92 && val < ops->get_optmax) {
92 ops->use++; 93 ops->use++;
93 up(&nf_sockopt_mutex); 94 mutex_unlock(&nf_sockopt_mutex);
94 ret = ops->get(sk, val, opt, len); 95 ret = ops->get(sk, val, opt, len);
95 goto out; 96 goto out;
96 } 97 }
@@ -98,22 +99,22 @@ static int nf_sockopt(struct sock *sk, int pf, int val,
98 if (val >= ops->set_optmin 99 if (val >= ops->set_optmin
99 && val < ops->set_optmax) { 100 && val < ops->set_optmax) {
100 ops->use++; 101 ops->use++;
101 up(&nf_sockopt_mutex); 102 mutex_unlock(&nf_sockopt_mutex);
102 ret = ops->set(sk, val, opt, *len); 103 ret = ops->set(sk, val, opt, *len);
103 goto out; 104 goto out;
104 } 105 }
105 } 106 }
106 } 107 }
107 } 108 }
108 up(&nf_sockopt_mutex); 109 mutex_unlock(&nf_sockopt_mutex);
109 return -ENOPROTOOPT; 110 return -ENOPROTOOPT;
110 111
111 out: 112 out:
112 down(&nf_sockopt_mutex); 113 mutex_lock(&nf_sockopt_mutex);
113 ops->use--; 114 ops->use--;
114 if (ops->cleanup_task) 115 if (ops->cleanup_task)
115 wake_up_process(ops->cleanup_task); 116 wake_up_process(ops->cleanup_task);
116 up(&nf_sockopt_mutex); 117 mutex_unlock(&nf_sockopt_mutex);
117 return ret; 118 return ret;
118} 119}
119 120
@@ -130,3 +131,72 @@ int nf_getsockopt(struct sock *sk, int pf, int val, char __user *opt, int *len)
130} 131}
131EXPORT_SYMBOL(nf_getsockopt); 132EXPORT_SYMBOL(nf_getsockopt);
132 133
134#ifdef CONFIG_COMPAT
135static int compat_nf_sockopt(struct sock *sk, int pf, int val,
136 char __user *opt, int *len, int get)
137{
138 struct list_head *i;
139 struct nf_sockopt_ops *ops;
140 int ret;
141
142 if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
143 return -EINTR;
144
145 list_for_each(i, &nf_sockopts) {
146 ops = (struct nf_sockopt_ops *)i;
147 if (ops->pf == pf) {
148 if (get) {
149 if (val >= ops->get_optmin
150 && val < ops->get_optmax) {
151 ops->use++;
152 mutex_unlock(&nf_sockopt_mutex);
153 if (ops->compat_get)
154 ret = ops->compat_get(sk,
155 val, opt, len);
156 else
157 ret = ops->get(sk,
158 val, opt, len);
159 goto out;
160 }
161 } else {
162 if (val >= ops->set_optmin
163 && val < ops->set_optmax) {
164 ops->use++;
165 mutex_unlock(&nf_sockopt_mutex);
166 if (ops->compat_set)
167 ret = ops->compat_set(sk,
168 val, opt, *len);
169 else
170 ret = ops->set(sk,
171 val, opt, *len);
172 goto out;
173 }
174 }
175 }
176 }
177 mutex_unlock(&nf_sockopt_mutex);
178 return -ENOPROTOOPT;
179
180 out:
181 mutex_lock(&nf_sockopt_mutex);
182 ops->use--;
183 if (ops->cleanup_task)
184 wake_up_process(ops->cleanup_task);
185 mutex_unlock(&nf_sockopt_mutex);
186 return ret;
187}
188
189int compat_nf_setsockopt(struct sock *sk, int pf,
190 int val, char __user *opt, int len)
191{
192 return compat_nf_sockopt(sk, pf, val, opt, &len, 0);
193}
194EXPORT_SYMBOL(compat_nf_setsockopt);
195
196int compat_nf_getsockopt(struct sock *sk, int pf,
197 int val, char __user *opt, int *len)
198{
199 return compat_nf_sockopt(sk, pf, val, opt, len, 1);
200}
201EXPORT_SYMBOL(compat_nf_getsockopt);
202#endif
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index f6063e8f0050..b88e82a1a987 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -191,6 +191,12 @@ nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys,
191 return 0; 191 return 0;
192} 192}
193 193
194int nfnetlink_has_listeners(unsigned int group)
195{
196 return netlink_has_listeners(nfnl, group);
197}
198EXPORT_SYMBOL_GPL(nfnetlink_has_listeners);
199
194int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo) 200int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
195{ 201{
196 gfp_t allocation = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; 202 gfp_t allocation = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 3b3c781b40c0..54cbbaa712dc 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -11,6 +11,10 @@
11 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
13 * 13 *
14 * 2006-01-26 Harald Welte <laforge@netfilter.org>
15 * - Add optional local and global sequence number to detect lost
16 * events from userspace
17 *
14 */ 18 */
15#include <linux/module.h> 19#include <linux/module.h>
16#include <linux/skbuff.h> 20#include <linux/skbuff.h>
@@ -68,11 +72,14 @@ struct nfulnl_instance {
68 unsigned int nlbufsiz; /* netlink buffer allocation size */ 72 unsigned int nlbufsiz; /* netlink buffer allocation size */
69 unsigned int qthreshold; /* threshold of the queue */ 73 unsigned int qthreshold; /* threshold of the queue */
70 u_int32_t copy_range; 74 u_int32_t copy_range;
75 u_int32_t seq; /* instance-local sequential counter */
71 u_int16_t group_num; /* number of this queue */ 76 u_int16_t group_num; /* number of this queue */
77 u_int16_t flags;
72 u_int8_t copy_mode; 78 u_int8_t copy_mode;
73}; 79};
74 80
75static DEFINE_RWLOCK(instances_lock); 81static DEFINE_RWLOCK(instances_lock);
82static atomic_t global_seq;
76 83
77#define INSTANCE_BUCKETS 16 84#define INSTANCE_BUCKETS 16
78static struct hlist_head instance_table[INSTANCE_BUCKETS]; 85static struct hlist_head instance_table[INSTANCE_BUCKETS];
@@ -310,6 +317,16 @@ nfulnl_set_qthresh(struct nfulnl_instance *inst, u_int32_t qthresh)
310 return 0; 317 return 0;
311} 318}
312 319
320static int
321nfulnl_set_flags(struct nfulnl_instance *inst, u_int16_t flags)
322{
323 spin_lock_bh(&inst->lock);
324 inst->flags = ntohs(flags);
325 spin_unlock_bh(&inst->lock);
326
327 return 0;
328}
329
313static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size, 330static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size,
314 unsigned int pkt_size) 331 unsigned int pkt_size)
315{ 332{
@@ -377,6 +394,8 @@ static void nfulnl_timer(unsigned long data)
377 spin_unlock_bh(&inst->lock); 394 spin_unlock_bh(&inst->lock);
378} 395}
379 396
397/* This is an inline function, we don't really care about a long
398 * list of arguments */
380static inline int 399static inline int
381__build_packet_message(struct nfulnl_instance *inst, 400__build_packet_message(struct nfulnl_instance *inst,
382 const struct sk_buff *skb, 401 const struct sk_buff *skb,
@@ -515,6 +534,17 @@ __build_packet_message(struct nfulnl_instance *inst,
515 read_unlock_bh(&skb->sk->sk_callback_lock); 534 read_unlock_bh(&skb->sk->sk_callback_lock);
516 } 535 }
517 536
537 /* local sequence number */
538 if (inst->flags & NFULNL_CFG_F_SEQ) {
539 tmp_uint = htonl(inst->seq++);
540 NFA_PUT(inst->skb, NFULA_SEQ, sizeof(tmp_uint), &tmp_uint);
541 }
542 /* global sequence number */
543 if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) {
544 tmp_uint = atomic_inc_return(&global_seq);
545 NFA_PUT(inst->skb, NFULA_SEQ_GLOBAL, sizeof(tmp_uint), &tmp_uint);
546 }
547
518 if (data_len) { 548 if (data_len) {
519 struct nfattr *nfa; 549 struct nfattr *nfa;
520 int size = NFA_LENGTH(data_len); 550 int size = NFA_LENGTH(data_len);
@@ -607,6 +637,11 @@ nfulnl_log_packet(unsigned int pf,
607 637
608 spin_lock_bh(&inst->lock); 638 spin_lock_bh(&inst->lock);
609 639
640 if (inst->flags & NFULNL_CFG_F_SEQ)
641 size += NFA_SPACE(sizeof(u_int32_t));
642 if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL)
643 size += NFA_SPACE(sizeof(u_int32_t));
644
610 qthreshold = inst->qthreshold; 645 qthreshold = inst->qthreshold;
611 /* per-rule qthreshold overrides per-instance */ 646 /* per-rule qthreshold overrides per-instance */
612 if (qthreshold > li->u.ulog.qthreshold) 647 if (qthreshold > li->u.ulog.qthreshold)
@@ -736,10 +771,14 @@ static const int nfula_min[NFULA_MAX] = {
736 [NFULA_TIMESTAMP-1] = sizeof(struct nfulnl_msg_packet_timestamp), 771 [NFULA_TIMESTAMP-1] = sizeof(struct nfulnl_msg_packet_timestamp),
737 [NFULA_IFINDEX_INDEV-1] = sizeof(u_int32_t), 772 [NFULA_IFINDEX_INDEV-1] = sizeof(u_int32_t),
738 [NFULA_IFINDEX_OUTDEV-1]= sizeof(u_int32_t), 773 [NFULA_IFINDEX_OUTDEV-1]= sizeof(u_int32_t),
774 [NFULA_IFINDEX_PHYSINDEV-1] = sizeof(u_int32_t),
775 [NFULA_IFINDEX_PHYSOUTDEV-1] = sizeof(u_int32_t),
739 [NFULA_HWADDR-1] = sizeof(struct nfulnl_msg_packet_hw), 776 [NFULA_HWADDR-1] = sizeof(struct nfulnl_msg_packet_hw),
740 [NFULA_PAYLOAD-1] = 0, 777 [NFULA_PAYLOAD-1] = 0,
741 [NFULA_PREFIX-1] = 0, 778 [NFULA_PREFIX-1] = 0,
742 [NFULA_UID-1] = sizeof(u_int32_t), 779 [NFULA_UID-1] = sizeof(u_int32_t),
780 [NFULA_SEQ-1] = sizeof(u_int32_t),
781 [NFULA_SEQ_GLOBAL-1] = sizeof(u_int32_t),
743}; 782};
744 783
745static const int nfula_cfg_min[NFULA_CFG_MAX] = { 784static const int nfula_cfg_min[NFULA_CFG_MAX] = {
@@ -748,6 +787,7 @@ static const int nfula_cfg_min[NFULA_CFG_MAX] = {
748 [NFULA_CFG_TIMEOUT-1] = sizeof(u_int32_t), 787 [NFULA_CFG_TIMEOUT-1] = sizeof(u_int32_t),
749 [NFULA_CFG_QTHRESH-1] = sizeof(u_int32_t), 788 [NFULA_CFG_QTHRESH-1] = sizeof(u_int32_t),
750 [NFULA_CFG_NLBUFSIZ-1] = sizeof(u_int32_t), 789 [NFULA_CFG_NLBUFSIZ-1] = sizeof(u_int32_t),
790 [NFULA_CFG_FLAGS-1] = sizeof(u_int16_t),
751}; 791};
752 792
753static int 793static int
@@ -859,6 +899,12 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
859 nfulnl_set_qthresh(inst, ntohl(qthresh)); 899 nfulnl_set_qthresh(inst, ntohl(qthresh));
860 } 900 }
861 901
902 if (nfula[NFULA_CFG_FLAGS-1]) {
903 u_int16_t flags =
904 *(u_int16_t *)NFA_DATA(nfula[NFULA_CFG_FLAGS-1]);
905 nfulnl_set_flags(inst, ntohl(flags));
906 }
907
862out_put: 908out_put:
863 instance_put(inst); 909 instance_put(inst);
864 return ret; 910 return ret;
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 2cf5fb8322c4..b5701662182e 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -354,16 +354,17 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
354 QDEBUG("entered\n"); 354 QDEBUG("entered\n");
355 355
356 /* all macros expand to constant values at compile time */ 356 /* all macros expand to constant values at compile time */
357 size = NLMSG_SPACE(sizeof(struct nfqnl_msg_packet_hdr)) 357 size = NLMSG_SPACE(sizeof(struct nfgenmsg)) +
358 + NLMSG_SPACE(sizeof(u_int32_t)) /* ifindex */ 358 + NFA_SPACE(sizeof(struct nfqnl_msg_packet_hdr))
359 + NLMSG_SPACE(sizeof(u_int32_t)) /* ifindex */ 359 + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
360 + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
360#ifdef CONFIG_BRIDGE_NETFILTER 361#ifdef CONFIG_BRIDGE_NETFILTER
361 + NLMSG_SPACE(sizeof(u_int32_t)) /* ifindex */ 362 + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
362 + NLMSG_SPACE(sizeof(u_int32_t)) /* ifindex */ 363 + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
363#endif 364#endif
364 + NLMSG_SPACE(sizeof(u_int32_t)) /* mark */ 365 + NFA_SPACE(sizeof(u_int32_t)) /* mark */
365 + NLMSG_SPACE(sizeof(struct nfqnl_msg_packet_hw)) 366 + NFA_SPACE(sizeof(struct nfqnl_msg_packet_hw))
366 + NLMSG_SPACE(sizeof(struct nfqnl_msg_packet_timestamp)); 367 + NFA_SPACE(sizeof(struct nfqnl_msg_packet_timestamp));
367 368
368 outdev = entinf->outdev; 369 outdev = entinf->outdev;
369 370
@@ -388,7 +389,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
388 else 389 else
389 data_len = queue->copy_range; 390 data_len = queue->copy_range;
390 391
391 size += NLMSG_SPACE(data_len); 392 size += NFA_SPACE(data_len);
392 break; 393 break;
393 394
394 default: 395 default:
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index d7817afc6b96..0a29a24d9a72 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -52,11 +52,17 @@ enum {
52 MATCH, 52 MATCH,
53}; 53};
54 54
55static const char *xt_prefix[NPROTO] = {
56 [AF_INET] = "ip",
57 [AF_INET6] = "ip6",
58 [NF_ARP] = "arp",
59};
60
55/* Registration hooks for targets. */ 61/* Registration hooks for targets. */
56int 62int
57xt_register_target(int af, struct xt_target *target) 63xt_register_target(struct xt_target *target)
58{ 64{
59 int ret; 65 int ret, af = target->family;
60 66
61 ret = down_interruptible(&xt[af].mutex); 67 ret = down_interruptible(&xt[af].mutex);
62 if (ret != 0) 68 if (ret != 0)
@@ -68,8 +74,10 @@ xt_register_target(int af, struct xt_target *target)
68EXPORT_SYMBOL(xt_register_target); 74EXPORT_SYMBOL(xt_register_target);
69 75
70void 76void
71xt_unregister_target(int af, struct xt_target *target) 77xt_unregister_target(struct xt_target *target)
72{ 78{
79 int af = target->family;
80
73 down(&xt[af].mutex); 81 down(&xt[af].mutex);
74 LIST_DELETE(&xt[af].target, target); 82 LIST_DELETE(&xt[af].target, target);
75 up(&xt[af].mutex); 83 up(&xt[af].mutex);
@@ -77,9 +85,9 @@ xt_unregister_target(int af, struct xt_target *target)
77EXPORT_SYMBOL(xt_unregister_target); 85EXPORT_SYMBOL(xt_unregister_target);
78 86
79int 87int
80xt_register_match(int af, struct xt_match *match) 88xt_register_match(struct xt_match *match)
81{ 89{
82 int ret; 90 int ret, af = match->family;
83 91
84 ret = down_interruptible(&xt[af].mutex); 92 ret = down_interruptible(&xt[af].mutex);
85 if (ret != 0) 93 if (ret != 0)
@@ -93,8 +101,10 @@ xt_register_match(int af, struct xt_match *match)
93EXPORT_SYMBOL(xt_register_match); 101EXPORT_SYMBOL(xt_register_match);
94 102
95void 103void
96xt_unregister_match(int af, struct xt_match *match) 104xt_unregister_match(struct xt_match *match)
97{ 105{
106 int af = match->family;
107
98 down(&xt[af].mutex); 108 down(&xt[af].mutex);
99 LIST_DELETE(&xt[af].match, match); 109 LIST_DELETE(&xt[af].match, match);
100 up(&xt[af].mutex); 110 up(&xt[af].mutex);
@@ -158,18 +168,12 @@ struct xt_target *xt_find_target(int af, const char *name, u8 revision)
158} 168}
159EXPORT_SYMBOL(xt_find_target); 169EXPORT_SYMBOL(xt_find_target);
160 170
161static const char *xt_prefix[NPROTO] = {
162 [AF_INET] = "ipt_%s",
163 [AF_INET6] = "ip6t_%s",
164 [NF_ARP] = "arpt_%s",
165};
166
167struct xt_target *xt_request_find_target(int af, const char *name, u8 revision) 171struct xt_target *xt_request_find_target(int af, const char *name, u8 revision)
168{ 172{
169 struct xt_target *target; 173 struct xt_target *target;
170 174
171 target = try_then_request_module(xt_find_target(af, name, revision), 175 target = try_then_request_module(xt_find_target(af, name, revision),
172 xt_prefix[af], name); 176 "%st_%s", xt_prefix[af], name);
173 if (IS_ERR(target) || !target) 177 if (IS_ERR(target) || !target)
174 return NULL; 178 return NULL;
175 return target; 179 return target;
@@ -237,6 +241,64 @@ int xt_find_revision(int af, const char *name, u8 revision, int target,
237} 241}
238EXPORT_SYMBOL_GPL(xt_find_revision); 242EXPORT_SYMBOL_GPL(xt_find_revision);
239 243
244int xt_check_match(const struct xt_match *match, unsigned short family,
245 unsigned int size, const char *table, unsigned int hook_mask,
246 unsigned short proto, int inv_proto)
247{
248 if (XT_ALIGN(match->matchsize) != size) {
249 printk("%s_tables: %s match: invalid size %Zu != %u\n",
250 xt_prefix[family], match->name,
251 XT_ALIGN(match->matchsize), size);
252 return -EINVAL;
253 }
254 if (match->table && strcmp(match->table, table)) {
255 printk("%s_tables: %s match: only valid in %s table, not %s\n",
256 xt_prefix[family], match->name, match->table, table);
257 return -EINVAL;
258 }
259 if (match->hooks && (hook_mask & ~match->hooks) != 0) {
260 printk("%s_tables: %s match: bad hook_mask %u\n",
261 xt_prefix[family], match->name, hook_mask);
262 return -EINVAL;
263 }
264 if (match->proto && (match->proto != proto || inv_proto)) {
265 printk("%s_tables: %s match: only valid for protocol %u\n",
266 xt_prefix[family], match->name, match->proto);
267 return -EINVAL;
268 }
269 return 0;
270}
271EXPORT_SYMBOL_GPL(xt_check_match);
272
273int xt_check_target(const struct xt_target *target, unsigned short family,
274 unsigned int size, const char *table, unsigned int hook_mask,
275 unsigned short proto, int inv_proto)
276{
277 if (XT_ALIGN(target->targetsize) != size) {
278 printk("%s_tables: %s target: invalid size %Zu != %u\n",
279 xt_prefix[family], target->name,
280 XT_ALIGN(target->targetsize), size);
281 return -EINVAL;
282 }
283 if (target->table && strcmp(target->table, table)) {
284 printk("%s_tables: %s target: only valid in %s table, not %s\n",
285 xt_prefix[family], target->name, target->table, table);
286 return -EINVAL;
287 }
288 if (target->hooks && (hook_mask & ~target->hooks) != 0) {
289 printk("%s_tables: %s target: bad hook_mask %u\n",
290 xt_prefix[family], target->name, hook_mask);
291 return -EINVAL;
292 }
293 if (target->proto && (target->proto != proto || inv_proto)) {
294 printk("%s_tables: %s target: only valid for protocol %u\n",
295 xt_prefix[family], target->name, target->proto);
296 return -EINVAL;
297 }
298 return 0;
299}
300EXPORT_SYMBOL_GPL(xt_check_target);
301
240struct xt_table_info *xt_alloc_table_info(unsigned int size) 302struct xt_table_info *xt_alloc_table_info(unsigned int size)
241{ 303{
242 struct xt_table_info *newinfo; 304 struct xt_table_info *newinfo;
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index 78ee266a12ee..3cd2ac90a25b 100644
--- a/net/netfilter/xt_CLASSIFY.c
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -28,6 +28,7 @@ target(struct sk_buff **pskb,
28 const struct net_device *in, 28 const struct net_device *in,
29 const struct net_device *out, 29 const struct net_device *out,
30 unsigned int hooknum, 30 unsigned int hooknum,
31 const struct xt_target *target,
31 const void *targinfo, 32 const void *targinfo,
32 void *userinfo) 33 void *userinfo)
33{ 34{
@@ -39,47 +40,24 @@ target(struct sk_buff **pskb,
39 return XT_CONTINUE; 40 return XT_CONTINUE;
40} 41}
41 42
42static int
43checkentry(const char *tablename,
44 const void *e,
45 void *targinfo,
46 unsigned int targinfosize,
47 unsigned int hook_mask)
48{
49 if (targinfosize != XT_ALIGN(sizeof(struct xt_classify_target_info))){
50 printk(KERN_ERR "CLASSIFY: invalid size (%u != %Zu).\n",
51 targinfosize,
52 XT_ALIGN(sizeof(struct xt_classify_target_info)));
53 return 0;
54 }
55
56 if (hook_mask & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) |
57 (1 << NF_IP_POST_ROUTING))) {
58 printk(KERN_ERR "CLASSIFY: only valid in LOCAL_OUT, FORWARD "
59 "and POST_ROUTING.\n");
60 return 0;
61 }
62
63 if (strcmp(tablename, "mangle") != 0) {
64 printk(KERN_ERR "CLASSIFY: can only be called from "
65 "\"mangle\" table, not \"%s\".\n",
66 tablename);
67 return 0;
68 }
69
70 return 1;
71}
72
73static struct xt_target classify_reg = { 43static struct xt_target classify_reg = {
74 .name = "CLASSIFY", 44 .name = "CLASSIFY",
75 .target = target, 45 .target = target,
76 .checkentry = checkentry, 46 .targetsize = sizeof(struct xt_classify_target_info),
47 .table = "mangle",
48 .hooks = (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) |
49 (1 << NF_IP_POST_ROUTING),
50 .family = AF_INET,
77 .me = THIS_MODULE, 51 .me = THIS_MODULE,
78}; 52};
79static struct xt_target classify6_reg = { 53static struct xt_target classify6_reg = {
80 .name = "CLASSIFY", 54 .name = "CLASSIFY",
81 .target = target, 55 .target = target,
82 .checkentry = checkentry, 56 .targetsize = sizeof(struct xt_classify_target_info),
57 .table = "mangle",
58 .hooks = (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) |
59 (1 << NF_IP_POST_ROUTING),
60 .family = AF_INET6,
83 .me = THIS_MODULE, 61 .me = THIS_MODULE,
84}; 62};
85 63
@@ -88,21 +66,21 @@ static int __init init(void)
88{ 66{
89 int ret; 67 int ret;
90 68
91 ret = xt_register_target(AF_INET, &classify_reg); 69 ret = xt_register_target(&classify_reg);
92 if (ret) 70 if (ret)
93 return ret; 71 return ret;
94 72
95 ret = xt_register_target(AF_INET6, &classify6_reg); 73 ret = xt_register_target(&classify6_reg);
96 if (ret) 74 if (ret)
97 xt_unregister_target(AF_INET, &classify_reg); 75 xt_unregister_target(&classify_reg);
98 76
99 return ret; 77 return ret;
100} 78}
101 79
102static void __exit fini(void) 80static void __exit fini(void)
103{ 81{
104 xt_unregister_target(AF_INET, &classify_reg); 82 xt_unregister_target(&classify_reg);
105 xt_unregister_target(AF_INET6, &classify6_reg); 83 xt_unregister_target(&classify6_reg);
106} 84}
107 85
108module_init(init); 86module_init(init);
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index 22506e376be5..35448b8e6883 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -37,6 +37,7 @@ target(struct sk_buff **pskb,
37 const struct net_device *in, 37 const struct net_device *in,
38 const struct net_device *out, 38 const struct net_device *out,
39 unsigned int hooknum, 39 unsigned int hooknum,
40 const struct xt_target *target,
40 const void *targinfo, 41 const void *targinfo,
41 void *userinfo) 42 void *userinfo)
42{ 43{
@@ -74,17 +75,12 @@ target(struct sk_buff **pskb,
74static int 75static int
75checkentry(const char *tablename, 76checkentry(const char *tablename,
76 const void *entry, 77 const void *entry,
78 const struct xt_target *target,
77 void *targinfo, 79 void *targinfo,
78 unsigned int targinfosize, 80 unsigned int targinfosize,
79 unsigned int hook_mask) 81 unsigned int hook_mask)
80{ 82{
81 struct xt_connmark_target_info *matchinfo = targinfo; 83 struct xt_connmark_target_info *matchinfo = targinfo;
82 if (targinfosize != XT_ALIGN(sizeof(struct xt_connmark_target_info))) {
83 printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
84 targinfosize,
85 XT_ALIGN(sizeof(struct xt_connmark_target_info)));
86 return 0;
87 }
88 84
89 if (matchinfo->mode == XT_CONNMARK_RESTORE) { 85 if (matchinfo->mode == XT_CONNMARK_RESTORE) {
90 if (strcmp(tablename, "mangle") != 0) { 86 if (strcmp(tablename, "mangle") != 0) {
@@ -102,16 +98,21 @@ checkentry(const char *tablename,
102} 98}
103 99
104static struct xt_target connmark_reg = { 100static struct xt_target connmark_reg = {
105 .name = "CONNMARK", 101 .name = "CONNMARK",
106 .target = &target, 102 .target = target,
107 .checkentry = &checkentry, 103 .targetsize = sizeof(struct xt_connmark_target_info),
108 .me = THIS_MODULE 104 .checkentry = checkentry,
105 .family = AF_INET,
106 .me = THIS_MODULE
109}; 107};
108
110static struct xt_target connmark6_reg = { 109static struct xt_target connmark6_reg = {
111 .name = "CONNMARK", 110 .name = "CONNMARK",
112 .target = &target, 111 .target = target,
113 .checkentry = &checkentry, 112 .targetsize = sizeof(struct xt_connmark_target_info),
114 .me = THIS_MODULE 113 .checkentry = checkentry,
114 .family = AF_INET6,
115 .me = THIS_MODULE
115}; 116};
116 117
117static int __init init(void) 118static int __init init(void)
@@ -120,21 +121,21 @@ static int __init init(void)
120 121
121 need_conntrack(); 122 need_conntrack();
122 123
123 ret = xt_register_target(AF_INET, &connmark_reg); 124 ret = xt_register_target(&connmark_reg);
124 if (ret) 125 if (ret)
125 return ret; 126 return ret;
126 127
127 ret = xt_register_target(AF_INET6, &connmark6_reg); 128 ret = xt_register_target(&connmark6_reg);
128 if (ret) 129 if (ret)
129 xt_unregister_target(AF_INET, &connmark_reg); 130 xt_unregister_target(&connmark_reg);
130 131
131 return ret; 132 return ret;
132} 133}
133 134
134static void __exit fini(void) 135static void __exit fini(void)
135{ 136{
136 xt_unregister_target(AF_INET, &connmark_reg); 137 xt_unregister_target(&connmark_reg);
137 xt_unregister_target(AF_INET6, &connmark6_reg); 138 xt_unregister_target(&connmark6_reg);
138} 139}
139 140
140module_init(init); 141module_init(init);
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c
index 0c11ee9550f3..73bdd5c80e17 100644
--- a/net/netfilter/xt_MARK.c
+++ b/net/netfilter/xt_MARK.c
@@ -26,6 +26,7 @@ target_v0(struct sk_buff **pskb,
26 const struct net_device *in, 26 const struct net_device *in,
27 const struct net_device *out, 27 const struct net_device *out,
28 unsigned int hooknum, 28 unsigned int hooknum,
29 const struct xt_target *target,
29 const void *targinfo, 30 const void *targinfo,
30 void *userinfo) 31 void *userinfo)
31{ 32{
@@ -42,6 +43,7 @@ target_v1(struct sk_buff **pskb,
42 const struct net_device *in, 43 const struct net_device *in,
43 const struct net_device *out, 44 const struct net_device *out,
44 unsigned int hooknum, 45 unsigned int hooknum,
46 const struct xt_target *target,
45 const void *targinfo, 47 const void *targinfo,
46 void *userinfo) 48 void *userinfo)
47{ 49{
@@ -72,53 +74,30 @@ target_v1(struct sk_buff **pskb,
72static int 74static int
73checkentry_v0(const char *tablename, 75checkentry_v0(const char *tablename,
74 const void *entry, 76 const void *entry,
77 const struct xt_target *target,
75 void *targinfo, 78 void *targinfo,
76 unsigned int targinfosize, 79 unsigned int targinfosize,
77 unsigned int hook_mask) 80 unsigned int hook_mask)
78{ 81{
79 struct xt_mark_target_info *markinfo = targinfo; 82 struct xt_mark_target_info *markinfo = targinfo;
80 83
81 if (targinfosize != XT_ALIGN(sizeof(struct xt_mark_target_info))) {
82 printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
83 targinfosize,
84 XT_ALIGN(sizeof(struct xt_mark_target_info)));
85 return 0;
86 }
87
88 if (strcmp(tablename, "mangle") != 0) {
89 printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
90 return 0;
91 }
92
93 if (markinfo->mark > 0xffffffff) { 84 if (markinfo->mark > 0xffffffff) {
94 printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n"); 85 printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
95 return 0; 86 return 0;
96 } 87 }
97
98 return 1; 88 return 1;
99} 89}
100 90
101static int 91static int
102checkentry_v1(const char *tablename, 92checkentry_v1(const char *tablename,
103 const void *entry, 93 const void *entry,
94 const struct xt_target *target,
104 void *targinfo, 95 void *targinfo,
105 unsigned int targinfosize, 96 unsigned int targinfosize,
106 unsigned int hook_mask) 97 unsigned int hook_mask)
107{ 98{
108 struct xt_mark_target_info_v1 *markinfo = targinfo; 99 struct xt_mark_target_info_v1 *markinfo = targinfo;
109 100
110 if (targinfosize != XT_ALIGN(sizeof(struct xt_mark_target_info_v1))){
111 printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
112 targinfosize,
113 XT_ALIGN(sizeof(struct xt_mark_target_info_v1)));
114 return 0;
115 }
116
117 if (strcmp(tablename, "mangle") != 0) {
118 printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
119 return 0;
120 }
121
122 if (markinfo->mode != XT_MARK_SET 101 if (markinfo->mode != XT_MARK_SET
123 && markinfo->mode != XT_MARK_AND 102 && markinfo->mode != XT_MARK_AND
124 && markinfo->mode != XT_MARK_OR) { 103 && markinfo->mode != XT_MARK_OR) {
@@ -126,36 +105,43 @@ checkentry_v1(const char *tablename,
126 markinfo->mode); 105 markinfo->mode);
127 return 0; 106 return 0;
128 } 107 }
129
130 if (markinfo->mark > 0xffffffff) { 108 if (markinfo->mark > 0xffffffff) {
131 printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n"); 109 printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
132 return 0; 110 return 0;
133 } 111 }
134
135 return 1; 112 return 1;
136} 113}
137 114
138static struct xt_target ipt_mark_reg_v0 = { 115static struct xt_target ipt_mark_reg_v0 = {
139 .name = "MARK", 116 .name = "MARK",
140 .target = target_v0, 117 .target = target_v0,
118 .targetsize = sizeof(struct xt_mark_target_info),
119 .table = "mangle",
141 .checkentry = checkentry_v0, 120 .checkentry = checkentry_v0,
142 .me = THIS_MODULE, 121 .me = THIS_MODULE,
122 .family = AF_INET,
143 .revision = 0, 123 .revision = 0,
144}; 124};
145 125
146static struct xt_target ipt_mark_reg_v1 = { 126static struct xt_target ipt_mark_reg_v1 = {
147 .name = "MARK", 127 .name = "MARK",
148 .target = target_v1, 128 .target = target_v1,
129 .targetsize = sizeof(struct xt_mark_target_info_v1),
130 .table = "mangle",
149 .checkentry = checkentry_v1, 131 .checkentry = checkentry_v1,
150 .me = THIS_MODULE, 132 .me = THIS_MODULE,
133 .family = AF_INET,
151 .revision = 1, 134 .revision = 1,
152}; 135};
153 136
154static struct xt_target ip6t_mark_reg_v0 = { 137static struct xt_target ip6t_mark_reg_v0 = {
155 .name = "MARK", 138 .name = "MARK",
156 .target = target_v0, 139 .target = target_v0,
140 .targetsize = sizeof(struct xt_mark_target_info),
141 .table = "mangle",
157 .checkentry = checkentry_v0, 142 .checkentry = checkentry_v0,
158 .me = THIS_MODULE, 143 .me = THIS_MODULE,
144 .family = AF_INET6,
159 .revision = 0, 145 .revision = 0,
160}; 146};
161 147
@@ -163,18 +149,18 @@ static int __init init(void)
163{ 149{
164 int err; 150 int err;
165 151
166 err = xt_register_target(AF_INET, &ipt_mark_reg_v0); 152 err = xt_register_target(&ipt_mark_reg_v0);
167 if (err) 153 if (err)
168 return err; 154 return err;
169 155
170 err = xt_register_target(AF_INET, &ipt_mark_reg_v1); 156 err = xt_register_target(&ipt_mark_reg_v1);
171 if (err) 157 if (err)
172 xt_unregister_target(AF_INET, &ipt_mark_reg_v0); 158 xt_unregister_target(&ipt_mark_reg_v0);
173 159
174 err = xt_register_target(AF_INET6, &ip6t_mark_reg_v0); 160 err = xt_register_target(&ip6t_mark_reg_v0);
175 if (err) { 161 if (err) {
176 xt_unregister_target(AF_INET, &ipt_mark_reg_v0); 162 xt_unregister_target(&ipt_mark_reg_v0);
177 xt_unregister_target(AF_INET, &ipt_mark_reg_v1); 163 xt_unregister_target(&ipt_mark_reg_v1);
178 } 164 }
179 165
180 return err; 166 return err;
@@ -182,9 +168,9 @@ static int __init init(void)
182 168
183static void __exit fini(void) 169static void __exit fini(void)
184{ 170{
185 xt_unregister_target(AF_INET, &ipt_mark_reg_v0); 171 xt_unregister_target(&ipt_mark_reg_v0);
186 xt_unregister_target(AF_INET, &ipt_mark_reg_v1); 172 xt_unregister_target(&ipt_mark_reg_v1);
187 xt_unregister_target(AF_INET6, &ip6t_mark_reg_v0); 173 xt_unregister_target(&ip6t_mark_reg_v0);
188} 174}
189 175
190module_init(init); 176module_init(init);
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index 8b76b6f8d1e4..2873e1c60f68 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -28,6 +28,7 @@ target(struct sk_buff **pskb,
28 const struct net_device *in, 28 const struct net_device *in,
29 const struct net_device *out, 29 const struct net_device *out,
30 unsigned int hooknum, 30 unsigned int hooknum,
31 const struct xt_target *target,
31 const void *targinfo, 32 const void *targinfo,
32 void *userinfo) 33 void *userinfo)
33{ 34{
@@ -36,71 +37,57 @@ target(struct sk_buff **pskb,
36 return NF_QUEUE_NR(tinfo->queuenum); 37 return NF_QUEUE_NR(tinfo->queuenum);
37} 38}
38 39
39static int
40checkentry(const char *tablename,
41 const void *entry,
42 void *targinfo,
43 unsigned int targinfosize,
44 unsigned int hook_mask)
45{
46 if (targinfosize != XT_ALIGN(sizeof(struct xt_NFQ_info))) {
47 printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n",
48 targinfosize,
49 XT_ALIGN(sizeof(struct xt_NFQ_info)));
50 return 0;
51 }
52
53 return 1;
54}
55
56static struct xt_target ipt_NFQ_reg = { 40static struct xt_target ipt_NFQ_reg = {
57 .name = "NFQUEUE", 41 .name = "NFQUEUE",
58 .target = target, 42 .target = target,
59 .checkentry = checkentry, 43 .targetsize = sizeof(struct xt_NFQ_info),
44 .family = AF_INET,
60 .me = THIS_MODULE, 45 .me = THIS_MODULE,
61}; 46};
62 47
63static struct xt_target ip6t_NFQ_reg = { 48static struct xt_target ip6t_NFQ_reg = {
64 .name = "NFQUEUE", 49 .name = "NFQUEUE",
65 .target = target, 50 .target = target,
66 .checkentry = checkentry, 51 .targetsize = sizeof(struct xt_NFQ_info),
52 .family = AF_INET6,
67 .me = THIS_MODULE, 53 .me = THIS_MODULE,
68}; 54};
69 55
70static struct xt_target arpt_NFQ_reg = { 56static struct xt_target arpt_NFQ_reg = {
71 .name = "NFQUEUE", 57 .name = "NFQUEUE",
72 .target = target, 58 .target = target,
73 .checkentry = checkentry, 59 .targetsize = sizeof(struct xt_NFQ_info),
60 .family = NF_ARP,
74 .me = THIS_MODULE, 61 .me = THIS_MODULE,
75}; 62};
76 63
77static int __init init(void) 64static int __init init(void)
78{ 65{
79 int ret; 66 int ret;
80 ret = xt_register_target(AF_INET, &ipt_NFQ_reg); 67 ret = xt_register_target(&ipt_NFQ_reg);
81 if (ret) 68 if (ret)
82 return ret; 69 return ret;
83 ret = xt_register_target(AF_INET6, &ip6t_NFQ_reg); 70 ret = xt_register_target(&ip6t_NFQ_reg);
84 if (ret) 71 if (ret)
85 goto out_ip; 72 goto out_ip;
86 ret = xt_register_target(NF_ARP, &arpt_NFQ_reg); 73 ret = xt_register_target(&arpt_NFQ_reg);
87 if (ret) 74 if (ret)
88 goto out_ip6; 75 goto out_ip6;
89 76
90 return ret; 77 return ret;
91out_ip6: 78out_ip6:
92 xt_unregister_target(AF_INET6, &ip6t_NFQ_reg); 79 xt_unregister_target(&ip6t_NFQ_reg);
93out_ip: 80out_ip:
94 xt_unregister_target(AF_INET, &ipt_NFQ_reg); 81 xt_unregister_target(&ipt_NFQ_reg);
95 82
96 return ret; 83 return ret;
97} 84}
98 85
99static void __exit fini(void) 86static void __exit fini(void)
100{ 87{
101 xt_unregister_target(NF_ARP, &arpt_NFQ_reg); 88 xt_unregister_target(&arpt_NFQ_reg);
102 xt_unregister_target(AF_INET6, &ip6t_NFQ_reg); 89 xt_unregister_target(&ip6t_NFQ_reg);
103 xt_unregister_target(AF_INET, &ipt_NFQ_reg); 90 xt_unregister_target(&ipt_NFQ_reg);
104} 91}
105 92
106module_init(init); 93module_init(init);
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index 24d477afa939..cf2ebd76fd6f 100644
--- a/net/netfilter/xt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -15,6 +15,7 @@ target(struct sk_buff **pskb,
15 const struct net_device *in, 15 const struct net_device *in,
16 const struct net_device *out, 16 const struct net_device *out,
17 unsigned int hooknum, 17 unsigned int hooknum,
18 const struct xt_target *target,
18 const void *targinfo, 19 const void *targinfo,
19 void *userinfo) 20 void *userinfo)
20{ 21{
@@ -33,59 +34,43 @@ target(struct sk_buff **pskb,
33 return XT_CONTINUE; 34 return XT_CONTINUE;
34} 35}
35 36
36static int 37static struct xt_target notrack_reg = {
37checkentry(const char *tablename, 38 .name = "NOTRACK",
38 const void *entry, 39 .target = target,
39 void *targinfo, 40 .targetsize = 0,
40 unsigned int targinfosize, 41 .table = "raw",
41 unsigned int hook_mask) 42 .family = AF_INET,
42{ 43 .me = THIS_MODULE,
43 if (targinfosize != 0) {
44 printk(KERN_WARNING "NOTRACK: targinfosize %u != 0\n",
45 targinfosize);
46 return 0;
47 }
48
49 if (strcmp(tablename, "raw") != 0) {
50 printk(KERN_WARNING "NOTRACK: can only be called from \"raw\" table, not \"%s\"\n", tablename);
51 return 0;
52 }
53
54 return 1;
55}
56
57static struct xt_target notrack_reg = {
58 .name = "NOTRACK",
59 .target = target,
60 .checkentry = checkentry,
61 .me = THIS_MODULE,
62}; 44};
63static struct xt_target notrack6_reg = { 45
64 .name = "NOTRACK", 46static struct xt_target notrack6_reg = {
65 .target = target, 47 .name = "NOTRACK",
66 .checkentry = checkentry, 48 .target = target,
67 .me = THIS_MODULE, 49 .targetsize = 0,
50 .table = "raw",
51 .family = AF_INET6,
52 .me = THIS_MODULE,
68}; 53};
69 54
70static int __init init(void) 55static int __init init(void)
71{ 56{
72 int ret; 57 int ret;
73 58
74 ret = xt_register_target(AF_INET, &notrack_reg); 59 ret = xt_register_target(&notrack_reg);
75 if (ret) 60 if (ret)
76 return ret; 61 return ret;
77 62
78 ret = xt_register_target(AF_INET6, &notrack6_reg); 63 ret = xt_register_target(&notrack6_reg);
79 if (ret) 64 if (ret)
80 xt_unregister_target(AF_INET, &notrack_reg); 65 xt_unregister_target(&notrack_reg);
81 66
82 return ret; 67 return ret;
83} 68}
84 69
85static void __exit fini(void) 70static void __exit fini(void)
86{ 71{
87 xt_unregister_target(AF_INET6, &notrack6_reg); 72 xt_unregister_target(&notrack6_reg);
88 xt_unregister_target(AF_INET, &notrack_reg); 73 xt_unregister_target(&notrack_reg);
89} 74}
90 75
91module_init(init); 76module_init(init);
diff --git a/net/netfilter/xt_comment.c b/net/netfilter/xt_comment.c
index 4ba6fd65c6e9..2637724b498d 100644
--- a/net/netfilter/xt_comment.c
+++ b/net/netfilter/xt_comment.c
@@ -19,6 +19,7 @@ static int
19match(const struct sk_buff *skb, 19match(const struct sk_buff *skb,
20 const struct net_device *in, 20 const struct net_device *in,
21 const struct net_device *out, 21 const struct net_device *out,
22 const struct xt_match *match,
22 const void *matchinfo, 23 const void *matchinfo,
23 int offset, 24 int offset,
24 unsigned int protooff, 25 unsigned int protooff,
@@ -28,30 +29,19 @@ match(const struct sk_buff *skb,
28 return 1; 29 return 1;
29} 30}
30 31
31static int
32checkentry(const char *tablename,
33 const void *ip,
34 void *matchinfo,
35 unsigned int matchsize,
36 unsigned int hook_mask)
37{
38 /* Check the size */
39 if (matchsize != XT_ALIGN(sizeof(struct xt_comment_info)))
40 return 0;
41 return 1;
42}
43
44static struct xt_match comment_match = { 32static struct xt_match comment_match = {
45 .name = "comment", 33 .name = "comment",
46 .match = match, 34 .match = match,
47 .checkentry = checkentry, 35 .matchsize = sizeof(struct xt_comment_info),
36 .family = AF_INET,
48 .me = THIS_MODULE 37 .me = THIS_MODULE
49}; 38};
50 39
51static struct xt_match comment6_match = { 40static struct xt_match comment6_match = {
52 .name = "comment", 41 .name = "comment",
53 .match = match, 42 .match = match,
54 .checkentry = checkentry, 43 .matchsize = sizeof(struct xt_comment_info),
44 .family = AF_INET6,
55 .me = THIS_MODULE 45 .me = THIS_MODULE
56}; 46};
57 47
@@ -59,21 +49,21 @@ static int __init init(void)
59{ 49{
60 int ret; 50 int ret;
61 51
62 ret = xt_register_match(AF_INET, &comment_match); 52 ret = xt_register_match(&comment_match);
63 if (ret) 53 if (ret)
64 return ret; 54 return ret;
65 55
66 ret = xt_register_match(AF_INET6, &comment6_match); 56 ret = xt_register_match(&comment6_match);
67 if (ret) 57 if (ret)
68 xt_unregister_match(AF_INET, &comment_match); 58 xt_unregister_match(&comment_match);
69 59
70 return ret; 60 return ret;
71} 61}
72 62
73static void __exit fini(void) 63static void __exit fini(void)
74{ 64{
75 xt_unregister_match(AF_INET, &comment_match); 65 xt_unregister_match(&comment_match);
76 xt_unregister_match(AF_INET6, &comment6_match); 66 xt_unregister_match(&comment6_match);
77} 67}
78 68
79module_init(init); 69module_init(init);
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index 150d2a4b0f71..4985f5ec58ca 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -44,6 +44,7 @@ static int
44match(const struct sk_buff *skb, 44match(const struct sk_buff *skb,
45 const struct net_device *in, 45 const struct net_device *in,
46 const struct net_device *out, 46 const struct net_device *out,
47 const struct xt_match *match,
47 const void *matchinfo, 48 const void *matchinfo,
48 int offset, 49 int offset,
49 unsigned int protoff, 50 unsigned int protoff,
@@ -122,15 +123,13 @@ match(const struct sk_buff *skb,
122 123
123static int check(const char *tablename, 124static int check(const char *tablename,
124 const void *ip, 125 const void *ip,
126 const struct xt_match *match,
125 void *matchinfo, 127 void *matchinfo,
126 unsigned int matchsize, 128 unsigned int matchsize,
127 unsigned int hook_mask) 129 unsigned int hook_mask)
128{ 130{
129 const struct xt_connbytes_info *sinfo = matchinfo; 131 const struct xt_connbytes_info *sinfo = matchinfo;
130 132
131 if (matchsize != XT_ALIGN(sizeof(struct xt_connbytes_info)))
132 return 0;
133
134 if (sinfo->what != XT_CONNBYTES_PKTS && 133 if (sinfo->what != XT_CONNBYTES_PKTS &&
135 sinfo->what != XT_CONNBYTES_BYTES && 134 sinfo->what != XT_CONNBYTES_BYTES &&
136 sinfo->what != XT_CONNBYTES_AVGPKT) 135 sinfo->what != XT_CONNBYTES_AVGPKT)
@@ -146,34 +145,38 @@ static int check(const char *tablename,
146 145
147static struct xt_match connbytes_match = { 146static struct xt_match connbytes_match = {
148 .name = "connbytes", 147 .name = "connbytes",
149 .match = &match, 148 .match = match,
150 .checkentry = &check, 149 .checkentry = check,
150 .matchsize = sizeof(struct xt_connbytes_info),
151 .family = AF_INET,
151 .me = THIS_MODULE 152 .me = THIS_MODULE
152}; 153};
153static struct xt_match connbytes6_match = { 154static struct xt_match connbytes6_match = {
154 .name = "connbytes", 155 .name = "connbytes",
155 .match = &match, 156 .match = match,
156 .checkentry = &check, 157 .checkentry = check,
158 .matchsize = sizeof(struct xt_connbytes_info),
159 .family = AF_INET6,
157 .me = THIS_MODULE 160 .me = THIS_MODULE
158}; 161};
159 162
160static int __init init(void) 163static int __init init(void)
161{ 164{
162 int ret; 165 int ret;
163 ret = xt_register_match(AF_INET, &connbytes_match); 166 ret = xt_register_match(&connbytes_match);
164 if (ret) 167 if (ret)
165 return ret; 168 return ret;
166 169
167 ret = xt_register_match(AF_INET6, &connbytes6_match); 170 ret = xt_register_match(&connbytes6_match);
168 if (ret) 171 if (ret)
169 xt_unregister_match(AF_INET, &connbytes_match); 172 xt_unregister_match(&connbytes_match);
170 return ret; 173 return ret;
171} 174}
172 175
173static void __exit fini(void) 176static void __exit fini(void)
174{ 177{
175 xt_unregister_match(AF_INET, &connbytes_match); 178 xt_unregister_match(&connbytes_match);
176 xt_unregister_match(AF_INET6, &connbytes6_match); 179 xt_unregister_match(&connbytes6_match);
177} 180}
178 181
179module_init(init); 182module_init(init);
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index d06e925032da..7b16f1ee16b4 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -35,6 +35,7 @@ static int
35match(const struct sk_buff *skb, 35match(const struct sk_buff *skb,
36 const struct net_device *in, 36 const struct net_device *in,
37 const struct net_device *out, 37 const struct net_device *out,
38 const struct xt_match *match,
38 const void *matchinfo, 39 const void *matchinfo,
39 int offset, 40 int offset,
40 unsigned int protoff, 41 unsigned int protoff,
@@ -52,57 +53,75 @@ match(const struct sk_buff *skb,
52static int 53static int
53checkentry(const char *tablename, 54checkentry(const char *tablename,
54 const void *ip, 55 const void *ip,
56 const struct xt_match *match,
55 void *matchinfo, 57 void *matchinfo,
56 unsigned int matchsize, 58 unsigned int matchsize,
57 unsigned int hook_mask) 59 unsigned int hook_mask)
58{ 60{
59 struct xt_connmark_info *cm = 61 struct xt_connmark_info *cm = (struct xt_connmark_info *)matchinfo;
60 (struct xt_connmark_info *)matchinfo;
61 if (matchsize != XT_ALIGN(sizeof(struct xt_connmark_info)))
62 return 0;
63 62
64 if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) { 63 if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) {
65 printk(KERN_WARNING "connmark: only support 32bit mark\n"); 64 printk(KERN_WARNING "connmark: only support 32bit mark\n");
66 return 0; 65 return 0;
67 } 66 }
68 67#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
68 if (nf_ct_l3proto_try_module_get(match->family) < 0) {
69 printk(KERN_WARNING "can't load nf_conntrack support for "
70 "proto=%d\n", match->family);
71 return 0;
72 }
73#endif
69 return 1; 74 return 1;
70} 75}
71 76
77static void
78destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
79{
80#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
81 nf_ct_l3proto_module_put(match->family);
82#endif
83}
84
72static struct xt_match connmark_match = { 85static struct xt_match connmark_match = {
73 .name = "connmark", 86 .name = "connmark",
74 .match = &match, 87 .match = match,
75 .checkentry = &checkentry, 88 .matchsize = sizeof(struct xt_connmark_info),
76 .me = THIS_MODULE 89 .checkentry = checkentry,
90 .destroy = destroy,
91 .family = AF_INET,
92 .me = THIS_MODULE
77}; 93};
94
78static struct xt_match connmark6_match = { 95static struct xt_match connmark6_match = {
79 .name = "connmark", 96 .name = "connmark",
80 .match = &match, 97 .match = match,
81 .checkentry = &checkentry, 98 .matchsize = sizeof(struct xt_connmark_info),
82 .me = THIS_MODULE 99 .checkentry = checkentry,
100 .destroy = destroy,
101 .family = AF_INET6,
102 .me = THIS_MODULE
83}; 103};
84 104
85
86static int __init init(void) 105static int __init init(void)
87{ 106{
88 int ret; 107 int ret;
89 108
90 need_conntrack(); 109 need_conntrack();
91 110
92 ret = xt_register_match(AF_INET, &connmark_match); 111 ret = xt_register_match(&connmark_match);
93 if (ret) 112 if (ret)
94 return ret; 113 return ret;
95 114
96 ret = xt_register_match(AF_INET6, &connmark6_match); 115 ret = xt_register_match(&connmark6_match);
97 if (ret) 116 if (ret)
98 xt_unregister_match(AF_INET, &connmark_match); 117 xt_unregister_match(&connmark_match);
99 return ret; 118 return ret;
100} 119}
101 120
102static void __exit fini(void) 121static void __exit fini(void)
103{ 122{
104 xt_unregister_match(AF_INET6, &connmark6_match); 123 xt_unregister_match(&connmark6_match);
105 xt_unregister_match(AF_INET, &connmark_match); 124 xt_unregister_match(&connmark_match);
106} 125}
107 126
108module_init(init); 127module_init(init);
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index ffdebc95eb95..65a84809fd30 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -32,6 +32,7 @@ static int
32match(const struct sk_buff *skb, 32match(const struct sk_buff *skb,
33 const struct net_device *in, 33 const struct net_device *in,
34 const struct net_device *out, 34 const struct net_device *out,
35 const struct xt_match *match,
35 const void *matchinfo, 36 const void *matchinfo,
36 int offset, 37 int offset,
37 unsigned int protoff, 38 unsigned int protoff,
@@ -118,6 +119,7 @@ static int
118match(const struct sk_buff *skb, 119match(const struct sk_buff *skb,
119 const struct net_device *in, 120 const struct net_device *in,
120 const struct net_device *out, 121 const struct net_device *out,
122 const struct xt_match *match,
121 const void *matchinfo, 123 const void *matchinfo,
122 int offset, 124 int offset,
123 unsigned int protoff, 125 unsigned int protoff,
@@ -201,22 +203,39 @@ match(const struct sk_buff *skb,
201 203
202#endif /* CONFIG_NF_IP_CONNTRACK */ 204#endif /* CONFIG_NF_IP_CONNTRACK */
203 205
204static int check(const char *tablename, 206static int
205 const void *ip, 207checkentry(const char *tablename,
206 void *matchinfo, 208 const void *ip,
207 unsigned int matchsize, 209 const struct xt_match *match,
208 unsigned int hook_mask) 210 void *matchinfo,
211 unsigned int matchsize,
212 unsigned int hook_mask)
209{ 213{
210 if (matchsize != XT_ALIGN(sizeof(struct xt_conntrack_info))) 214#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
215 if (nf_ct_l3proto_try_module_get(match->family) < 0) {
216 printk(KERN_WARNING "can't load nf_conntrack support for "
217 "proto=%d\n", match->family);
211 return 0; 218 return 0;
212 219 }
220#endif
213 return 1; 221 return 1;
214} 222}
215 223
224static void
225destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
226{
227#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
228 nf_ct_l3proto_module_put(match->family);
229#endif
230}
231
216static struct xt_match conntrack_match = { 232static struct xt_match conntrack_match = {
217 .name = "conntrack", 233 .name = "conntrack",
218 .match = &match, 234 .match = match,
219 .checkentry = &check, 235 .checkentry = checkentry,
236 .destroy = destroy,
237 .matchsize = sizeof(struct xt_conntrack_info),
238 .family = AF_INET,
220 .me = THIS_MODULE, 239 .me = THIS_MODULE,
221}; 240};
222 241
@@ -224,14 +243,14 @@ static int __init init(void)
224{ 243{
225 int ret; 244 int ret;
226 need_conntrack(); 245 need_conntrack();
227 ret = xt_register_match(AF_INET, &conntrack_match); 246 ret = xt_register_match(&conntrack_match);
228 247
229 return ret; 248 return ret;
230} 249}
231 250
232static void __exit fini(void) 251static void __exit fini(void)
233{ 252{
234 xt_unregister_match(AF_INET, &conntrack_match); 253 xt_unregister_match(&conntrack_match);
235} 254}
236 255
237module_init(init); 256module_init(init);
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
index 779f42fc9524..2f331decd151 100644
--- a/net/netfilter/xt_dccp.c
+++ b/net/netfilter/xt_dccp.c
@@ -95,6 +95,7 @@ static int
95match(const struct sk_buff *skb, 95match(const struct sk_buff *skb,
96 const struct net_device *in, 96 const struct net_device *in,
97 const struct net_device *out, 97 const struct net_device *out,
98 const struct xt_match *match,
98 const void *matchinfo, 99 const void *matchinfo,
99 int offset, 100 int offset,
100 unsigned int protoff, 101 unsigned int protoff,
@@ -129,56 +130,36 @@ match(const struct sk_buff *skb,
129static int 130static int
130checkentry(const char *tablename, 131checkentry(const char *tablename,
131 const void *inf, 132 const void *inf,
133 const struct xt_match *match,
132 void *matchinfo, 134 void *matchinfo,
133 unsigned int matchsize, 135 unsigned int matchsize,
134 unsigned int hook_mask) 136 unsigned int hook_mask)
135{ 137{
136 const struct ipt_ip *ip = inf; 138 const struct xt_dccp_info *info = matchinfo;
137 const struct xt_dccp_info *info;
138 139
139 info = (const struct xt_dccp_info *)matchinfo; 140 return !(info->flags & ~XT_DCCP_VALID_FLAGS)
140
141 return ip->proto == IPPROTO_DCCP
142 && !(ip->invflags & XT_INV_PROTO)
143 && matchsize == XT_ALIGN(sizeof(struct xt_dccp_info))
144 && !(info->flags & ~XT_DCCP_VALID_FLAGS)
145 && !(info->invflags & ~XT_DCCP_VALID_FLAGS)
146 && !(info->invflags & ~info->flags);
147}
148
149static int
150checkentry6(const char *tablename,
151 const void *inf,
152 void *matchinfo,
153 unsigned int matchsize,
154 unsigned int hook_mask)
155{
156 const struct ip6t_ip6 *ip = inf;
157 const struct xt_dccp_info *info;
158
159 info = (const struct xt_dccp_info *)matchinfo;
160
161 return ip->proto == IPPROTO_DCCP
162 && !(ip->invflags & XT_INV_PROTO)
163 && matchsize == XT_ALIGN(sizeof(struct xt_dccp_info))
164 && !(info->flags & ~XT_DCCP_VALID_FLAGS)
165 && !(info->invflags & ~XT_DCCP_VALID_FLAGS) 141 && !(info->invflags & ~XT_DCCP_VALID_FLAGS)
166 && !(info->invflags & ~info->flags); 142 && !(info->invflags & ~info->flags);
167} 143}
168 144
169
170static struct xt_match dccp_match = 145static struct xt_match dccp_match =
171{ 146{
172 .name = "dccp", 147 .name = "dccp",
173 .match = &match, 148 .match = match,
174 .checkentry = &checkentry, 149 .matchsize = sizeof(struct xt_dccp_info),
150 .proto = IPPROTO_DCCP,
151 .checkentry = checkentry,
152 .family = AF_INET,
175 .me = THIS_MODULE, 153 .me = THIS_MODULE,
176}; 154};
177static struct xt_match dccp6_match = 155static struct xt_match dccp6_match =
178{ 156{
179 .name = "dccp", 157 .name = "dccp",
180 .match = &match, 158 .match = match,
181 .checkentry = &checkentry6, 159 .matchsize = sizeof(struct xt_dccp_info),
160 .proto = IPPROTO_DCCP,
161 .checkentry = checkentry,
162 .family = AF_INET6,
182 .me = THIS_MODULE, 163 .me = THIS_MODULE,
183}; 164};
184 165
@@ -193,17 +174,17 @@ static int __init init(void)
193 dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL); 174 dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL);
194 if (!dccp_optbuf) 175 if (!dccp_optbuf)
195 return -ENOMEM; 176 return -ENOMEM;
196 ret = xt_register_match(AF_INET, &dccp_match); 177 ret = xt_register_match(&dccp_match);
197 if (ret) 178 if (ret)
198 goto out_kfree; 179 goto out_kfree;
199 ret = xt_register_match(AF_INET6, &dccp6_match); 180 ret = xt_register_match(&dccp6_match);
200 if (ret) 181 if (ret)
201 goto out_unreg; 182 goto out_unreg;
202 183
203 return ret; 184 return ret;
204 185
205out_unreg: 186out_unreg:
206 xt_unregister_match(AF_INET, &dccp_match); 187 xt_unregister_match(&dccp_match);
207out_kfree: 188out_kfree:
208 kfree(dccp_optbuf); 189 kfree(dccp_optbuf);
209 190
@@ -212,8 +193,8 @@ out_kfree:
212 193
213static void __exit fini(void) 194static void __exit fini(void)
214{ 195{
215 xt_unregister_match(AF_INET6, &dccp6_match); 196 xt_unregister_match(&dccp6_match);
216 xt_unregister_match(AF_INET, &dccp_match); 197 xt_unregister_match(&dccp_match);
217 kfree(dccp_optbuf); 198 kfree(dccp_optbuf);
218} 199}
219 200
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
index 38b6715e1db4..101f0005e987 100644
--- a/net/netfilter/xt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -42,6 +42,7 @@ static int
42match(const struct sk_buff *skb, 42match(const struct sk_buff *skb,
43 const struct net_device *in, 43 const struct net_device *in,
44 const struct net_device *out, 44 const struct net_device *out,
45 const struct xt_match *match,
45 const void *matchinfo, 46 const void *matchinfo,
46 int offset, 47 int offset,
47 unsigned int protoff, 48 unsigned int protoff,
@@ -89,6 +90,7 @@ static int
89match(const struct sk_buff *skb, 90match(const struct sk_buff *skb,
90 const struct net_device *in, 91 const struct net_device *in,
91 const struct net_device *out, 92 const struct net_device *out,
93 const struct xt_match *match,
92 const void *matchinfo, 94 const void *matchinfo,
93 int offset, 95 int offset,
94 unsigned int protoff, 96 unsigned int protoff,
@@ -96,6 +98,7 @@ match(const struct sk_buff *skb,
96{ 98{
97 const struct xt_helper_info *info = matchinfo; 99 const struct xt_helper_info *info = matchinfo;
98 struct nf_conn *ct; 100 struct nf_conn *ct;
101 struct nf_conn_help *master_help;
99 enum ip_conntrack_info ctinfo; 102 enum ip_conntrack_info ctinfo;
100 int ret = info->invert; 103 int ret = info->invert;
101 104
@@ -111,7 +114,8 @@ match(const struct sk_buff *skb,
111 } 114 }
112 115
113 read_lock_bh(&nf_conntrack_lock); 116 read_lock_bh(&nf_conntrack_lock);
114 if (!ct->master->helper) { 117 master_help = nfct_help(ct->master);
118 if (!master_help || !master_help->helper) {
115 DEBUGP("xt_helper: master ct %p has no helper\n", 119 DEBUGP("xt_helper: master ct %p has no helper\n",
116 exp->expectant); 120 exp->expectant);
117 goto out_unlock; 121 goto out_unlock;
@@ -123,8 +127,8 @@ match(const struct sk_buff *skb,
123 if (info->name[0] == '\0') 127 if (info->name[0] == '\0')
124 ret ^= 1; 128 ret ^= 1;
125 else 129 else
126 ret ^= !strncmp(ct->master->helper->name, info->name, 130 ret ^= !strncmp(master_help->helper->name, info->name,
127 strlen(ct->master->helper->name)); 131 strlen(master_help->helper->name));
128out_unlock: 132out_unlock:
129 read_unlock_bh(&nf_conntrack_lock); 133 read_unlock_bh(&nf_conntrack_lock);
130 return ret; 134 return ret;
@@ -133,31 +137,48 @@ out_unlock:
133 137
134static int check(const char *tablename, 138static int check(const char *tablename,
135 const void *inf, 139 const void *inf,
140 const struct xt_match *match,
136 void *matchinfo, 141 void *matchinfo,
137 unsigned int matchsize, 142 unsigned int matchsize,
138 unsigned int hook_mask) 143 unsigned int hook_mask)
139{ 144{
140 struct xt_helper_info *info = matchinfo; 145 struct xt_helper_info *info = matchinfo;
141 146
142 info->name[29] = '\0'; 147#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
143 148 if (nf_ct_l3proto_try_module_get(match->family) < 0) {
144 /* verify size */ 149 printk(KERN_WARNING "can't load nf_conntrack support for "
145 if (matchsize != XT_ALIGN(sizeof(struct xt_helper_info))) 150 "proto=%d\n", match->family);
146 return 0; 151 return 0;
147 152 }
153#endif
154 info->name[29] = '\0';
148 return 1; 155 return 1;
149} 156}
150 157
158static void
159destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
160{
161#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
162 nf_ct_l3proto_module_put(match->family);
163#endif
164}
165
151static struct xt_match helper_match = { 166static struct xt_match helper_match = {
152 .name = "helper", 167 .name = "helper",
153 .match = &match, 168 .match = match,
154 .checkentry = &check, 169 .matchsize = sizeof(struct xt_helper_info),
170 .checkentry = check,
171 .destroy = destroy,
172 .family = AF_INET,
155 .me = THIS_MODULE, 173 .me = THIS_MODULE,
156}; 174};
157static struct xt_match helper6_match = { 175static struct xt_match helper6_match = {
158 .name = "helper", 176 .name = "helper",
159 .match = &match, 177 .match = match,
160 .checkentry = &check, 178 .matchsize = sizeof(struct xt_helper_info),
179 .checkentry = check,
180 .destroy = destroy,
181 .family = AF_INET6,
161 .me = THIS_MODULE, 182 .me = THIS_MODULE,
162}; 183};
163 184
@@ -166,21 +187,21 @@ static int __init init(void)
166 int ret; 187 int ret;
167 need_conntrack(); 188 need_conntrack();
168 189
169 ret = xt_register_match(AF_INET, &helper_match); 190 ret = xt_register_match(&helper_match);
170 if (ret < 0) 191 if (ret < 0)
171 return ret; 192 return ret;
172 193
173 ret = xt_register_match(AF_INET6, &helper6_match); 194 ret = xt_register_match(&helper6_match);
174 if (ret < 0) 195 if (ret < 0)
175 xt_unregister_match(AF_INET, &helper_match); 196 xt_unregister_match(&helper_match);
176 197
177 return ret; 198 return ret;
178} 199}
179 200
180static void __exit fini(void) 201static void __exit fini(void)
181{ 202{
182 xt_unregister_match(AF_INET, &helper_match); 203 xt_unregister_match(&helper_match);
183 xt_unregister_match(AF_INET6, &helper6_match); 204 xt_unregister_match(&helper6_match);
184} 205}
185 206
186module_init(init); 207module_init(init);
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c
index 39c8faea63de..38560caef757 100644
--- a/net/netfilter/xt_length.c
+++ b/net/netfilter/xt_length.c
@@ -24,6 +24,7 @@ static int
24match(const struct sk_buff *skb, 24match(const struct sk_buff *skb,
25 const struct net_device *in, 25 const struct net_device *in,
26 const struct net_device *out, 26 const struct net_device *out,
27 const struct xt_match *match,
27 const void *matchinfo, 28 const void *matchinfo,
28 int offset, 29 int offset,
29 unsigned int protoff, 30 unsigned int protoff,
@@ -39,6 +40,7 @@ static int
39match6(const struct sk_buff *skb, 40match6(const struct sk_buff *skb,
40 const struct net_device *in, 41 const struct net_device *in,
41 const struct net_device *out, 42 const struct net_device *out,
43 const struct xt_match *match,
42 const void *matchinfo, 44 const void *matchinfo,
43 int offset, 45 int offset,
44 unsigned int protoff, 46 unsigned int protoff,
@@ -50,49 +52,39 @@ match6(const struct sk_buff *skb,
50 return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; 52 return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
51} 53}
52 54
53static int
54checkentry(const char *tablename,
55 const void *ip,
56 void *matchinfo,
57 unsigned int matchsize,
58 unsigned int hook_mask)
59{
60 if (matchsize != XT_ALIGN(sizeof(struct xt_length_info)))
61 return 0;
62
63 return 1;
64}
65
66static struct xt_match length_match = { 55static struct xt_match length_match = {
67 .name = "length", 56 .name = "length",
68 .match = &match, 57 .match = match,
69 .checkentry = &checkentry, 58 .matchsize = sizeof(struct xt_length_info),
59 .family = AF_INET,
70 .me = THIS_MODULE, 60 .me = THIS_MODULE,
71}; 61};
62
72static struct xt_match length6_match = { 63static struct xt_match length6_match = {
73 .name = "length", 64 .name = "length",
74 .match = &match6, 65 .match = match6,
75 .checkentry = &checkentry, 66 .matchsize = sizeof(struct xt_length_info),
67 .family = AF_INET6,
76 .me = THIS_MODULE, 68 .me = THIS_MODULE,
77}; 69};
78 70
79static int __init init(void) 71static int __init init(void)
80{ 72{
81 int ret; 73 int ret;
82 ret = xt_register_match(AF_INET, &length_match); 74 ret = xt_register_match(&length_match);
83 if (ret) 75 if (ret)
84 return ret; 76 return ret;
85 ret = xt_register_match(AF_INET6, &length6_match); 77 ret = xt_register_match(&length6_match);
86 if (ret) 78 if (ret)
87 xt_unregister_match(AF_INET, &length_match); 79 xt_unregister_match(&length_match);
88 80
89 return ret; 81 return ret;
90} 82}
91 83
92static void __exit fini(void) 84static void __exit fini(void)
93{ 85{
94 xt_unregister_match(AF_INET, &length_match); 86 xt_unregister_match(&length_match);
95 xt_unregister_match(AF_INET6, &length6_match); 87 xt_unregister_match(&length6_match);
96} 88}
97 89
98module_init(init); 90module_init(init);
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index 15e40506bc3a..e91c1a444e77 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -68,6 +68,7 @@ static int
68ipt_limit_match(const struct sk_buff *skb, 68ipt_limit_match(const struct sk_buff *skb,
69 const struct net_device *in, 69 const struct net_device *in,
70 const struct net_device *out, 70 const struct net_device *out,
71 const struct xt_match *match,
71 const void *matchinfo, 72 const void *matchinfo,
72 int offset, 73 int offset,
73 unsigned int protoff, 74 unsigned int protoff,
@@ -107,15 +108,13 @@ user2credits(u_int32_t user)
107static int 108static int
108ipt_limit_checkentry(const char *tablename, 109ipt_limit_checkentry(const char *tablename,
109 const void *inf, 110 const void *inf,
111 const struct xt_match *match,
110 void *matchinfo, 112 void *matchinfo,
111 unsigned int matchsize, 113 unsigned int matchsize,
112 unsigned int hook_mask) 114 unsigned int hook_mask)
113{ 115{
114 struct xt_rateinfo *r = matchinfo; 116 struct xt_rateinfo *r = matchinfo;
115 117
116 if (matchsize != XT_ALIGN(sizeof(struct xt_rateinfo)))
117 return 0;
118
119 /* Check for overflow. */ 118 /* Check for overflow. */
120 if (r->burst == 0 119 if (r->burst == 0
121 || user2credits(r->avg * r->burst) < user2credits(r->avg)) { 120 || user2credits(r->avg * r->burst) < user2credits(r->avg)) {
@@ -140,13 +139,17 @@ ipt_limit_checkentry(const char *tablename,
140static struct xt_match ipt_limit_reg = { 139static struct xt_match ipt_limit_reg = {
141 .name = "limit", 140 .name = "limit",
142 .match = ipt_limit_match, 141 .match = ipt_limit_match,
142 .matchsize = sizeof(struct xt_rateinfo),
143 .checkentry = ipt_limit_checkentry, 143 .checkentry = ipt_limit_checkentry,
144 .family = AF_INET,
144 .me = THIS_MODULE, 145 .me = THIS_MODULE,
145}; 146};
146static struct xt_match limit6_reg = { 147static struct xt_match limit6_reg = {
147 .name = "limit", 148 .name = "limit",
148 .match = ipt_limit_match, 149 .match = ipt_limit_match,
150 .matchsize = sizeof(struct xt_rateinfo),
149 .checkentry = ipt_limit_checkentry, 151 .checkentry = ipt_limit_checkentry,
152 .family = AF_INET6,
150 .me = THIS_MODULE, 153 .me = THIS_MODULE,
151}; 154};
152 155
@@ -154,21 +157,21 @@ static int __init init(void)
154{ 157{
155 int ret; 158 int ret;
156 159
157 ret = xt_register_match(AF_INET, &ipt_limit_reg); 160 ret = xt_register_match(&ipt_limit_reg);
158 if (ret) 161 if (ret)
159 return ret; 162 return ret;
160 163
161 ret = xt_register_match(AF_INET6, &limit6_reg); 164 ret = xt_register_match(&limit6_reg);
162 if (ret) 165 if (ret)
163 xt_unregister_match(AF_INET, &ipt_limit_reg); 166 xt_unregister_match(&ipt_limit_reg);
164 167
165 return ret; 168 return ret;
166} 169}
167 170
168static void __exit fini(void) 171static void __exit fini(void)
169{ 172{
170 xt_unregister_match(AF_INET, &ipt_limit_reg); 173 xt_unregister_match(&ipt_limit_reg);
171 xt_unregister_match(AF_INET6, &limit6_reg); 174 xt_unregister_match(&limit6_reg);
172} 175}
173 176
174module_init(init); 177module_init(init);
diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c
index 0461dcb5fc7a..f4defa28a6ec 100644
--- a/net/netfilter/xt_mac.c
+++ b/net/netfilter/xt_mac.c
@@ -27,6 +27,7 @@ static int
27match(const struct sk_buff *skb, 27match(const struct sk_buff *skb,
28 const struct net_device *in, 28 const struct net_device *in,
29 const struct net_device *out, 29 const struct net_device *out,
30 const struct xt_match *match,
30 const void *matchinfo, 31 const void *matchinfo,
31 int offset, 32 int offset,
32 unsigned int protoff, 33 unsigned int protoff,
@@ -42,58 +43,43 @@ match(const struct sk_buff *skb,
42 ^ info->invert)); 43 ^ info->invert));
43} 44}
44 45
45static int
46ipt_mac_checkentry(const char *tablename,
47 const void *inf,
48 void *matchinfo,
49 unsigned int matchsize,
50 unsigned int hook_mask)
51{
52 /* FORWARD isn't always valid, but it's nice to be able to do --RR */
53 if (hook_mask
54 & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN)
55 | (1 << NF_IP_FORWARD))) {
56 printk("xt_mac: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n");
57 return 0;
58 }
59
60 if (matchsize != XT_ALIGN(sizeof(struct xt_mac_info)))
61 return 0;
62
63 return 1;
64}
65
66static struct xt_match mac_match = { 46static struct xt_match mac_match = {
67 .name = "mac", 47 .name = "mac",
68 .match = &match, 48 .match = match,
69 .checkentry = &ipt_mac_checkentry, 49 .matchsize = sizeof(struct xt_mac_info),
50 .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) |
51 (1 << NF_IP_FORWARD),
52 .family = AF_INET,
70 .me = THIS_MODULE, 53 .me = THIS_MODULE,
71}; 54};
72static struct xt_match mac6_match = { 55static struct xt_match mac6_match = {
73 .name = "mac", 56 .name = "mac",
74 .match = &match, 57 .match = match,
75 .checkentry = &ipt_mac_checkentry, 58 .matchsize = sizeof(struct xt_mac_info),
59 .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) |
60 (1 << NF_IP_FORWARD),
61 .family = AF_INET6,
76 .me = THIS_MODULE, 62 .me = THIS_MODULE,
77}; 63};
78 64
79static int __init init(void) 65static int __init init(void)
80{ 66{
81 int ret; 67 int ret;
82 ret = xt_register_match(AF_INET, &mac_match); 68 ret = xt_register_match(&mac_match);
83 if (ret) 69 if (ret)
84 return ret; 70 return ret;
85 71
86 ret = xt_register_match(AF_INET6, &mac6_match); 72 ret = xt_register_match(&mac6_match);
87 if (ret) 73 if (ret)
88 xt_unregister_match(AF_INET, &mac_match); 74 xt_unregister_match(&mac_match);
89 75
90 return ret; 76 return ret;
91} 77}
92 78
93static void __exit fini(void) 79static void __exit fini(void)
94{ 80{
95 xt_unregister_match(AF_INET, &mac_match); 81 xt_unregister_match(&mac_match);
96 xt_unregister_match(AF_INET6, &mac6_match); 82 xt_unregister_match(&mac6_match);
97} 83}
98 84
99module_init(init); 85module_init(init);
diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c
index 2a0ac62b72c8..ce0badfeef9a 100644
--- a/net/netfilter/xt_mark.c
+++ b/net/netfilter/xt_mark.c
@@ -23,6 +23,7 @@ static int
23match(const struct sk_buff *skb, 23match(const struct sk_buff *skb,
24 const struct net_device *in, 24 const struct net_device *in,
25 const struct net_device *out, 25 const struct net_device *out,
26 const struct xt_match *match,
26 const void *matchinfo, 27 const void *matchinfo,
27 int offset, 28 int offset,
28 unsigned int protoff, 29 unsigned int protoff,
@@ -36,55 +37,56 @@ match(const struct sk_buff *skb,
36static int 37static int
37checkentry(const char *tablename, 38checkentry(const char *tablename,
38 const void *entry, 39 const void *entry,
40 const struct xt_match *match,
39 void *matchinfo, 41 void *matchinfo,
40 unsigned int matchsize, 42 unsigned int matchsize,
41 unsigned int hook_mask) 43 unsigned int hook_mask)
42{ 44{
43 struct xt_mark_info *minfo = (struct xt_mark_info *) matchinfo; 45 struct xt_mark_info *minfo = (struct xt_mark_info *) matchinfo;
44 46
45 if (matchsize != XT_ALIGN(sizeof(struct xt_mark_info)))
46 return 0;
47
48 if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) { 47 if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) {
49 printk(KERN_WARNING "mark: only supports 32bit mark\n"); 48 printk(KERN_WARNING "mark: only supports 32bit mark\n");
50 return 0; 49 return 0;
51 } 50 }
52
53 return 1; 51 return 1;
54} 52}
55 53
56static struct xt_match mark_match = { 54static struct xt_match mark_match = {
57 .name = "mark", 55 .name = "mark",
58 .match = &match, 56 .match = match,
59 .checkentry = &checkentry, 57 .matchsize = sizeof(struct xt_mark_info),
58 .checkentry = checkentry,
59 .family = AF_INET,
60 .me = THIS_MODULE, 60 .me = THIS_MODULE,
61}; 61};
62 62
63static struct xt_match mark6_match = { 63static struct xt_match mark6_match = {
64 .name = "mark", 64 .name = "mark",
65 .match = &match, 65 .match = match,
66 .checkentry = &checkentry, 66 .matchsize = sizeof(struct xt_mark_info),
67 .checkentry = checkentry,
68 .family = AF_INET6,
67 .me = THIS_MODULE, 69 .me = THIS_MODULE,
68}; 70};
69 71
70static int __init init(void) 72static int __init init(void)
71{ 73{
72 int ret; 74 int ret;
73 ret = xt_register_match(AF_INET, &mark_match); 75 ret = xt_register_match(&mark_match);
74 if (ret) 76 if (ret)
75 return ret; 77 return ret;
76 78
77 ret = xt_register_match(AF_INET6, &mark6_match); 79 ret = xt_register_match(&mark6_match);
78 if (ret) 80 if (ret)
79 xt_unregister_match(AF_INET, &mark_match); 81 xt_unregister_match(&mark_match);
80 82
81 return ret; 83 return ret;
82} 84}
83 85
84static void __exit fini(void) 86static void __exit fini(void)
85{ 87{
86 xt_unregister_match(AF_INET, &mark_match); 88 xt_unregister_match(&mark_match);
87 xt_unregister_match(AF_INET6, &mark6_match); 89 xt_unregister_match(&mark6_match);
88} 90}
89 91
90module_init(init); 92module_init(init);
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index 19bb57c14dfe..089f4f7e8636 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -26,6 +26,7 @@ static int
26match(const struct sk_buff *skb, 26match(const struct sk_buff *skb,
27 const struct net_device *in, 27 const struct net_device *in,
28 const struct net_device *out, 28 const struct net_device *out,
29 const struct xt_match *match,
29 const void *matchinfo, 30 const void *matchinfo,
30 int offset, 31 int offset,
31 unsigned int protoff, 32 unsigned int protoff,
@@ -102,14 +103,13 @@ match_outdev:
102static int 103static int
103checkentry(const char *tablename, 104checkentry(const char *tablename,
104 const void *ip, 105 const void *ip,
106 const struct xt_match *match,
105 void *matchinfo, 107 void *matchinfo,
106 unsigned int matchsize, 108 unsigned int matchsize,
107 unsigned int hook_mask) 109 unsigned int hook_mask)
108{ 110{
109 const struct xt_physdev_info *info = matchinfo; 111 const struct xt_physdev_info *info = matchinfo;
110 112
111 if (matchsize != XT_ALIGN(sizeof(struct xt_physdev_info)))
112 return 0;
113 if (!(info->bitmask & XT_PHYSDEV_OP_MASK) || 113 if (!(info->bitmask & XT_PHYSDEV_OP_MASK) ||
114 info->bitmask & ~XT_PHYSDEV_OP_MASK) 114 info->bitmask & ~XT_PHYSDEV_OP_MASK)
115 return 0; 115 return 0;
@@ -118,15 +118,19 @@ checkentry(const char *tablename,
118 118
119static struct xt_match physdev_match = { 119static struct xt_match physdev_match = {
120 .name = "physdev", 120 .name = "physdev",
121 .match = &match, 121 .match = match,
122 .checkentry = &checkentry, 122 .matchsize = sizeof(struct xt_physdev_info),
123 .checkentry = checkentry,
124 .family = AF_INET,
123 .me = THIS_MODULE, 125 .me = THIS_MODULE,
124}; 126};
125 127
126static struct xt_match physdev6_match = { 128static struct xt_match physdev6_match = {
127 .name = "physdev", 129 .name = "physdev",
128 .match = &match, 130 .match = match,
129 .checkentry = &checkentry, 131 .matchsize = sizeof(struct xt_physdev_info),
132 .checkentry = checkentry,
133 .family = AF_INET6,
130 .me = THIS_MODULE, 134 .me = THIS_MODULE,
131}; 135};
132 136
@@ -134,21 +138,21 @@ static int __init init(void)
134{ 138{
135 int ret; 139 int ret;
136 140
137 ret = xt_register_match(AF_INET, &physdev_match); 141 ret = xt_register_match(&physdev_match);
138 if (ret < 0) 142 if (ret < 0)
139 return ret; 143 return ret;
140 144
141 ret = xt_register_match(AF_INET6, &physdev6_match); 145 ret = xt_register_match(&physdev6_match);
142 if (ret < 0) 146 if (ret < 0)
143 xt_unregister_match(AF_INET, &physdev_match); 147 xt_unregister_match(&physdev_match);
144 148
145 return ret; 149 return ret;
146} 150}
147 151
148static void __exit fini(void) 152static void __exit fini(void)
149{ 153{
150 xt_unregister_match(AF_INET, &physdev_match); 154 xt_unregister_match(&physdev_match);
151 xt_unregister_match(AF_INET6, &physdev6_match); 155 xt_unregister_match(&physdev6_match);
152} 156}
153 157
154module_init(init); 158module_init(init);
diff --git a/net/netfilter/xt_pkttype.c b/net/netfilter/xt_pkttype.c
index ab1b2630f97d..8b8bca988ac6 100644
--- a/net/netfilter/xt_pkttype.c
+++ b/net/netfilter/xt_pkttype.c
@@ -22,6 +22,7 @@ MODULE_ALIAS("ip6t_pkttype");
22static int match(const struct sk_buff *skb, 22static int match(const struct sk_buff *skb,
23 const struct net_device *in, 23 const struct net_device *in,
24 const struct net_device *out, 24 const struct net_device *out,
25 const struct xt_match *match,
25 const void *matchinfo, 26 const void *matchinfo,
26 int offset, 27 int offset,
27 unsigned int protoff, 28 unsigned int protoff,
@@ -32,50 +33,40 @@ static int match(const struct sk_buff *skb,
32 return (skb->pkt_type == info->pkttype) ^ info->invert; 33 return (skb->pkt_type == info->pkttype) ^ info->invert;
33} 34}
34 35
35static int checkentry(const char *tablename,
36 const void *ip,
37 void *matchinfo,
38 unsigned int matchsize,
39 unsigned int hook_mask)
40{
41 if (matchsize != XT_ALIGN(sizeof(struct xt_pkttype_info)))
42 return 0;
43
44 return 1;
45}
46
47static struct xt_match pkttype_match = { 36static struct xt_match pkttype_match = {
48 .name = "pkttype", 37 .name = "pkttype",
49 .match = &match, 38 .match = match,
50 .checkentry = &checkentry, 39 .matchsize = sizeof(struct xt_pkttype_info),
40 .family = AF_INET,
51 .me = THIS_MODULE, 41 .me = THIS_MODULE,
52}; 42};
43
53static struct xt_match pkttype6_match = { 44static struct xt_match pkttype6_match = {
54 .name = "pkttype", 45 .name = "pkttype",
55 .match = &match, 46 .match = match,
56 .checkentry = &checkentry, 47 .matchsize = sizeof(struct xt_pkttype_info),
48 .family = AF_INET6,
57 .me = THIS_MODULE, 49 .me = THIS_MODULE,
58}; 50};
59 51
60
61static int __init init(void) 52static int __init init(void)
62{ 53{
63 int ret; 54 int ret;
64 ret = xt_register_match(AF_INET, &pkttype_match); 55 ret = xt_register_match(&pkttype_match);
65 if (ret) 56 if (ret)
66 return ret; 57 return ret;
67 58
68 ret = xt_register_match(AF_INET6, &pkttype6_match); 59 ret = xt_register_match(&pkttype6_match);
69 if (ret) 60 if (ret)
70 xt_unregister_match(AF_INET, &pkttype_match); 61 xt_unregister_match(&pkttype_match);
71 62
72 return ret; 63 return ret;
73} 64}
74 65
75static void __exit fini(void) 66static void __exit fini(void)
76{ 67{
77 xt_unregister_match(AF_INET, &pkttype_match); 68 xt_unregister_match(&pkttype_match);
78 xt_unregister_match(AF_INET6, &pkttype6_match); 69 xt_unregister_match(&pkttype6_match);
79} 70}
80 71
81module_init(init); 72module_init(init);
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
new file mode 100644
index 000000000000..1099cb005fcc
--- /dev/null
+++ b/net/netfilter/xt_policy.c
@@ -0,0 +1,211 @@
1/* IP tables module for matching IPsec policy
2 *
3 * Copyright (c) 2004,2005 Patrick McHardy, <kaber@trash.net>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/kernel.h>
11#include <linux/config.h>
12#include <linux/module.h>
13#include <linux/skbuff.h>
14#include <linux/init.h>
15#include <net/xfrm.h>
16
17#include <linux/netfilter/xt_policy.h>
18#include <linux/netfilter/x_tables.h>
19
20MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
21MODULE_DESCRIPTION("Xtables IPsec policy matching module");
22MODULE_LICENSE("GPL");
23
24static inline int
25xt_addr_cmp(const union xt_policy_addr *a1, const union xt_policy_addr *m,
26 const union xt_policy_addr *a2, unsigned short family)
27{
28 switch (family) {
29 case AF_INET:
30 return !((a1->a4.s_addr ^ a2->a4.s_addr) & m->a4.s_addr);
31 case AF_INET6:
32 return !ipv6_masked_addr_cmp(&a1->a6, &m->a6, &a2->a6);
33 }
34 return 0;
35}
36
37static inline int
38match_xfrm_state(struct xfrm_state *x, const struct xt_policy_elem *e,
39 unsigned short family)
40{
41#define MATCH_ADDR(x,y,z) (!e->match.x || \
42 (xt_addr_cmp(&e->x, &e->y, z, family) \
43 ^ e->invert.x))
44#define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x))
45
46 return MATCH_ADDR(saddr, smask, (union xt_policy_addr *)&x->props.saddr) &&
47 MATCH_ADDR(daddr, dmask, (union xt_policy_addr *)&x->id.daddr) &&
48 MATCH(proto, x->id.proto) &&
49 MATCH(mode, x->props.mode) &&
50 MATCH(spi, x->id.spi) &&
51 MATCH(reqid, x->props.reqid);
52}
53
54static int
55match_policy_in(const struct sk_buff *skb, const struct xt_policy_info *info,
56 unsigned short family)
57{
58 const struct xt_policy_elem *e;
59 struct sec_path *sp = skb->sp;
60 int strict = info->flags & XT_POLICY_MATCH_STRICT;
61 int i, pos;
62
63 if (sp == NULL)
64 return -1;
65 if (strict && info->len != sp->len)
66 return 0;
67
68 for (i = sp->len - 1; i >= 0; i--) {
69 pos = strict ? i - sp->len + 1 : 0;
70 if (pos >= info->len)
71 return 0;
72 e = &info->pol[pos];
73
74 if (match_xfrm_state(sp->x[i].xvec, e, family)) {
75 if (!strict)
76 return 1;
77 } else if (strict)
78 return 0;
79 }
80
81 return strict ? 1 : 0;
82}
83
84static int
85match_policy_out(const struct sk_buff *skb, const struct xt_policy_info *info,
86 unsigned short family)
87{
88 const struct xt_policy_elem *e;
89 struct dst_entry *dst = skb->dst;
90 int strict = info->flags & XT_POLICY_MATCH_STRICT;
91 int i, pos;
92
93 if (dst->xfrm == NULL)
94 return -1;
95
96 for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
97 pos = strict ? i : 0;
98 if (pos >= info->len)
99 return 0;
100 e = &info->pol[pos];
101
102 if (match_xfrm_state(dst->xfrm, e, family)) {
103 if (!strict)
104 return 1;
105 } else if (strict)
106 return 0;
107 }
108
109 return strict ? i == info->len : 0;
110}
111
112static int match(const struct sk_buff *skb,
113 const struct net_device *in,
114 const struct net_device *out,
115 const struct xt_match *match,
116 const void *matchinfo,
117 int offset,
118 unsigned int protoff,
119 int *hotdrop)
120{
121 const struct xt_policy_info *info = matchinfo;
122 int ret;
123
124 if (info->flags & XT_POLICY_MATCH_IN)
125 ret = match_policy_in(skb, info, match->family);
126 else
127 ret = match_policy_out(skb, info, match->family);
128
129 if (ret < 0)
130 ret = info->flags & XT_POLICY_MATCH_NONE ? 1 : 0;
131 else if (info->flags & XT_POLICY_MATCH_NONE)
132 ret = 0;
133
134 return ret;
135}
136
137static int checkentry(const char *tablename, const void *ip_void,
138 const struct xt_match *match,
139 void *matchinfo, unsigned int matchsize,
140 unsigned int hook_mask)
141{
142 struct xt_policy_info *info = matchinfo;
143
144 if (!(info->flags & (XT_POLICY_MATCH_IN|XT_POLICY_MATCH_OUT))) {
145 printk(KERN_ERR "xt_policy: neither incoming nor "
146 "outgoing policy selected\n");
147 return 0;
148 }
149 /* hook values are equal for IPv4 and IPv6 */
150 if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
151 && info->flags & XT_POLICY_MATCH_OUT) {
152 printk(KERN_ERR "xt_policy: output policy not valid in "
153 "PRE_ROUTING and INPUT\n");
154 return 0;
155 }
156 if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
157 && info->flags & XT_POLICY_MATCH_IN) {
158 printk(KERN_ERR "xt_policy: input policy not valid in "
159 "POST_ROUTING and OUTPUT\n");
160 return 0;
161 }
162 if (info->len > XT_POLICY_MAX_ELEM) {
163 printk(KERN_ERR "xt_policy: too many policy elements\n");
164 return 0;
165 }
166 return 1;
167}
168
169static struct xt_match policy_match = {
170 .name = "policy",
171 .family = AF_INET,
172 .match = match,
173 .matchsize = sizeof(struct xt_policy_info),
174 .checkentry = checkentry,
175 .family = AF_INET,
176 .me = THIS_MODULE,
177};
178
179static struct xt_match policy6_match = {
180 .name = "policy",
181 .family = AF_INET6,
182 .match = match,
183 .matchsize = sizeof(struct xt_policy_info),
184 .checkentry = checkentry,
185 .family = AF_INET6,
186 .me = THIS_MODULE,
187};
188
189static int __init init(void)
190{
191 int ret;
192
193 ret = xt_register_match(&policy_match);
194 if (ret)
195 return ret;
196 ret = xt_register_match(&policy6_match);
197 if (ret)
198 xt_unregister_match(&policy_match);
199 return ret;
200}
201
202static void __exit fini(void)
203{
204 xt_unregister_match(&policy6_match);
205 xt_unregister_match(&policy_match);
206}
207
208module_init(init);
209module_exit(fini);
210MODULE_ALIAS("ipt_policy");
211MODULE_ALIAS("ip6t_policy");
diff --git a/net/netfilter/xt_realm.c b/net/netfilter/xt_realm.c
index 2b7e1781d34d..5e31a4a835bf 100644
--- a/net/netfilter/xt_realm.c
+++ b/net/netfilter/xt_realm.c
@@ -27,6 +27,7 @@ static int
27match(const struct sk_buff *skb, 27match(const struct sk_buff *skb,
28 const struct net_device *in, 28 const struct net_device *in,
29 const struct net_device *out, 29 const struct net_device *out,
30 const struct xt_match *match,
30 const void *matchinfo, 31 const void *matchinfo,
31 int offset, 32 int offset,
32 unsigned int protoff, 33 unsigned int protoff,
@@ -38,41 +39,24 @@ match(const struct sk_buff *skb,
38 return (info->id == (dst->tclassid & info->mask)) ^ info->invert; 39 return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
39} 40}
40 41
41static int check(const char *tablename,
42 const void *ip,
43 void *matchinfo,
44 unsigned int matchsize,
45 unsigned int hook_mask)
46{
47 if (hook_mask
48 & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
49 (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN))) {
50 printk("xt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
51 "LOCAL_IN or FORWARD.\n");
52 return 0;
53 }
54 if (matchsize != XT_ALIGN(sizeof(struct xt_realm_info))) {
55 printk("xt_realm: invalid matchsize.\n");
56 return 0;
57 }
58 return 1;
59}
60
61static struct xt_match realm_match = { 42static struct xt_match realm_match = {
62 .name = "realm", 43 .name = "realm",
63 .match = match, 44 .match = match,
64 .checkentry = check, 45 .matchsize = sizeof(struct xt_realm_info),
46 .hooks = (1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
47 (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN),
48 .family = AF_INET,
65 .me = THIS_MODULE 49 .me = THIS_MODULE
66}; 50};
67 51
68static int __init init(void) 52static int __init init(void)
69{ 53{
70 return xt_register_match(AF_INET, &realm_match); 54 return xt_register_match(&realm_match);
71} 55}
72 56
73static void __exit fini(void) 57static void __exit fini(void)
74{ 58{
75 xt_unregister_match(AF_INET, &realm_match); 59 xt_unregister_match(&realm_match);
76} 60}
77 61
78module_init(init); 62module_init(init);
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index 10fbfc5ba758..c6eb24a2fe13 100644
--- a/net/netfilter/xt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -123,6 +123,7 @@ static int
123match(const struct sk_buff *skb, 123match(const struct sk_buff *skb,
124 const struct net_device *in, 124 const struct net_device *in,
125 const struct net_device *out, 125 const struct net_device *out,
126 const struct xt_match *match,
126 const void *matchinfo, 127 const void *matchinfo,
127 int offset, 128 int offset,
128 unsigned int protoff, 129 unsigned int protoff,
@@ -162,19 +163,14 @@ match(const struct sk_buff *skb,
162static int 163static int
163checkentry(const char *tablename, 164checkentry(const char *tablename,
164 const void *inf, 165 const void *inf,
166 const struct xt_match *match,
165 void *matchinfo, 167 void *matchinfo,
166 unsigned int matchsize, 168 unsigned int matchsize,
167 unsigned int hook_mask) 169 unsigned int hook_mask)
168{ 170{
169 const struct xt_sctp_info *info; 171 const struct xt_sctp_info *info = matchinfo;
170 const struct ipt_ip *ip = inf;
171
172 info = (const struct xt_sctp_info *)matchinfo;
173 172
174 return ip->proto == IPPROTO_SCTP 173 return !(info->flags & ~XT_SCTP_VALID_FLAGS)
175 && !(ip->invflags & XT_INV_PROTO)
176 && matchsize == XT_ALIGN(sizeof(struct xt_sctp_info))
177 && !(info->flags & ~XT_SCTP_VALID_FLAGS)
178 && !(info->invflags & ~XT_SCTP_VALID_FLAGS) 174 && !(info->invflags & ~XT_SCTP_VALID_FLAGS)
179 && !(info->invflags & ~info->flags) 175 && !(info->invflags & ~info->flags)
180 && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) || 176 && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) ||
@@ -184,66 +180,44 @@ checkentry(const char *tablename,
184 | SCTP_CHUNK_MATCH_ONLY))); 180 | SCTP_CHUNK_MATCH_ONLY)));
185} 181}
186 182
187static int 183static struct xt_match sctp_match = {
188checkentry6(const char *tablename, 184 .name = "sctp",
189 const void *inf, 185 .match = match,
190 void *matchinfo, 186 .matchsize = sizeof(struct xt_sctp_info),
191 unsigned int matchsize, 187 .proto = IPPROTO_SCTP,
192 unsigned int hook_mask) 188 .checkentry = checkentry,
193{ 189 .family = AF_INET,
194 const struct xt_sctp_info *info; 190 .me = THIS_MODULE
195 const struct ip6t_ip6 *ip = inf;
196
197 info = (const struct xt_sctp_info *)matchinfo;
198
199 return ip->proto == IPPROTO_SCTP
200 && !(ip->invflags & XT_INV_PROTO)
201 && matchsize == XT_ALIGN(sizeof(struct xt_sctp_info))
202 && !(info->flags & ~XT_SCTP_VALID_FLAGS)
203 && !(info->invflags & ~XT_SCTP_VALID_FLAGS)
204 && !(info->invflags & ~info->flags)
205 && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) ||
206 (info->chunk_match_type &
207 (SCTP_CHUNK_MATCH_ALL
208 | SCTP_CHUNK_MATCH_ANY
209 | SCTP_CHUNK_MATCH_ONLY)));
210}
211
212
213static struct xt_match sctp_match =
214{
215 .name = "sctp",
216 .match = &match,
217 .checkentry = &checkentry,
218 .me = THIS_MODULE
219};
220static struct xt_match sctp6_match =
221{
222 .name = "sctp",
223 .match = &match,
224 .checkentry = &checkentry6,
225 .me = THIS_MODULE
226}; 191};
227 192
193static struct xt_match sctp6_match = {
194 .name = "sctp",
195 .match = match,
196 .matchsize = sizeof(struct xt_sctp_info),
197 .proto = IPPROTO_SCTP,
198 .checkentry = checkentry,
199 .family = AF_INET6,
200 .me = THIS_MODULE
201};
228 202
229static int __init init(void) 203static int __init init(void)
230{ 204{
231 int ret; 205 int ret;
232 ret = xt_register_match(AF_INET, &sctp_match); 206 ret = xt_register_match(&sctp_match);
233 if (ret) 207 if (ret)
234 return ret; 208 return ret;
235 209
236 ret = xt_register_match(AF_INET6, &sctp6_match); 210 ret = xt_register_match(&sctp6_match);
237 if (ret) 211 if (ret)
238 xt_unregister_match(AF_INET, &sctp_match); 212 xt_unregister_match(&sctp_match);
239 213
240 return ret; 214 return ret;
241} 215}
242 216
243static void __exit fini(void) 217static void __exit fini(void)
244{ 218{
245 xt_unregister_match(AF_INET6, &sctp6_match); 219 xt_unregister_match(&sctp6_match);
246 xt_unregister_match(AF_INET, &sctp_match); 220 xt_unregister_match(&sctp_match);
247} 221}
248 222
249module_init(init); 223module_init(init);
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c
index 39ce808d40ef..e6c0be9d94d2 100644
--- a/net/netfilter/xt_state.c
+++ b/net/netfilter/xt_state.c
@@ -24,6 +24,7 @@ static int
24match(const struct sk_buff *skb, 24match(const struct sk_buff *skb,
25 const struct net_device *in, 25 const struct net_device *in,
26 const struct net_device *out, 26 const struct net_device *out,
27 const struct xt_match *match,
27 const void *matchinfo, 28 const void *matchinfo,
28 int offset, 29 int offset,
29 unsigned int protoff, 30 unsigned int protoff,
@@ -44,28 +45,47 @@ match(const struct sk_buff *skb,
44} 45}
45 46
46static int check(const char *tablename, 47static int check(const char *tablename,
47 const void *ip, 48 const void *inf,
49 const struct xt_match *match,
48 void *matchinfo, 50 void *matchinfo,
49 unsigned int matchsize, 51 unsigned int matchsize,
50 unsigned int hook_mask) 52 unsigned int hook_mask)
51{ 53{
52 if (matchsize != XT_ALIGN(sizeof(struct xt_state_info))) 54#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
55 if (nf_ct_l3proto_try_module_get(match->family) < 0) {
56 printk(KERN_WARNING "can't load nf_conntrack support for "
57 "proto=%d\n", match->family);
53 return 0; 58 return 0;
54 59 }
60#endif
55 return 1; 61 return 1;
56} 62}
57 63
64static void
65destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
66{
67#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
68 nf_ct_l3proto_module_put(match->family);
69#endif
70}
71
58static struct xt_match state_match = { 72static struct xt_match state_match = {
59 .name = "state", 73 .name = "state",
60 .match = &match, 74 .match = match,
61 .checkentry = &check, 75 .checkentry = check,
76 .destroy = destroy,
77 .matchsize = sizeof(struct xt_state_info),
78 .family = AF_INET,
62 .me = THIS_MODULE, 79 .me = THIS_MODULE,
63}; 80};
64 81
65static struct xt_match state6_match = { 82static struct xt_match state6_match = {
66 .name = "state", 83 .name = "state",
67 .match = &match, 84 .match = match,
68 .checkentry = &check, 85 .checkentry = check,
86 .destroy = destroy,
87 .matchsize = sizeof(struct xt_state_info),
88 .family = AF_INET6,
69 .me = THIS_MODULE, 89 .me = THIS_MODULE,
70}; 90};
71 91
@@ -75,21 +95,21 @@ static int __init init(void)
75 95
76 need_conntrack(); 96 need_conntrack();
77 97
78 ret = xt_register_match(AF_INET, &state_match); 98 ret = xt_register_match(&state_match);
79 if (ret < 0) 99 if (ret < 0)
80 return ret; 100 return ret;
81 101
82 ret = xt_register_match(AF_INET6, &state6_match); 102 ret = xt_register_match(&state6_match);
83 if (ret < 0) 103 if (ret < 0)
84 xt_unregister_match(AF_INET,&state_match); 104 xt_unregister_match(&state_match);
85 105
86 return ret; 106 return ret;
87} 107}
88 108
89static void __exit fini(void) 109static void __exit fini(void)
90{ 110{
91 xt_unregister_match(AF_INET, &state_match); 111 xt_unregister_match(&state_match);
92 xt_unregister_match(AF_INET6, &state6_match); 112 xt_unregister_match(&state6_match);
93} 113}
94 114
95module_init(init); 115module_init(init);
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c
index 7c7d5c8807d6..703d80fccacf 100644
--- a/net/netfilter/xt_string.c
+++ b/net/netfilter/xt_string.c
@@ -24,6 +24,7 @@ MODULE_ALIAS("ip6t_string");
24static int match(const struct sk_buff *skb, 24static int match(const struct sk_buff *skb,
25 const struct net_device *in, 25 const struct net_device *in,
26 const struct net_device *out, 26 const struct net_device *out,
27 const struct xt_match *match,
27 const void *matchinfo, 28 const void *matchinfo,
28 int offset, 29 int offset,
29 unsigned int protoff, 30 unsigned int protoff,
@@ -43,6 +44,7 @@ static int match(const struct sk_buff *skb,
43 44
44static int checkentry(const char *tablename, 45static int checkentry(const char *tablename,
45 const void *ip, 46 const void *ip,
47 const struct xt_match *match,
46 void *matchinfo, 48 void *matchinfo,
47 unsigned int matchsize, 49 unsigned int matchsize,
48 unsigned int hook_mask) 50 unsigned int hook_mask)
@@ -50,9 +52,6 @@ static int checkentry(const char *tablename,
50 struct xt_string_info *conf = matchinfo; 52 struct xt_string_info *conf = matchinfo;
51 struct ts_config *ts_conf; 53 struct ts_config *ts_conf;
52 54
53 if (matchsize != XT_ALIGN(sizeof(struct xt_string_info)))
54 return 0;
55
56 /* Damn, can't handle this case properly with iptables... */ 55 /* Damn, can't handle this case properly with iptables... */
57 if (conf->from_offset > conf->to_offset) 56 if (conf->from_offset > conf->to_offset)
58 return 0; 57 return 0;
@@ -67,7 +66,8 @@ static int checkentry(const char *tablename,
67 return 1; 66 return 1;
68} 67}
69 68
70static void destroy(void *matchinfo, unsigned int matchsize) 69static void destroy(const struct xt_match *match, void *matchinfo,
70 unsigned int matchsize)
71{ 71{
72 textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config); 72 textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config);
73} 73}
@@ -75,15 +75,19 @@ static void destroy(void *matchinfo, unsigned int matchsize)
75static struct xt_match string_match = { 75static struct xt_match string_match = {
76 .name = "string", 76 .name = "string",
77 .match = match, 77 .match = match,
78 .matchsize = sizeof(struct xt_string_info),
78 .checkentry = checkentry, 79 .checkentry = checkentry,
79 .destroy = destroy, 80 .destroy = destroy,
81 .family = AF_INET,
80 .me = THIS_MODULE 82 .me = THIS_MODULE
81}; 83};
82static struct xt_match string6_match = { 84static struct xt_match string6_match = {
83 .name = "string", 85 .name = "string",
84 .match = match, 86 .match = match,
87 .matchsize = sizeof(struct xt_string_info),
85 .checkentry = checkentry, 88 .checkentry = checkentry,
86 .destroy = destroy, 89 .destroy = destroy,
90 .family = AF_INET6,
87 .me = THIS_MODULE 91 .me = THIS_MODULE
88}; 92};
89 93
@@ -91,20 +95,20 @@ static int __init init(void)
91{ 95{
92 int ret; 96 int ret;
93 97
94 ret = xt_register_match(AF_INET, &string_match); 98 ret = xt_register_match(&string_match);
95 if (ret) 99 if (ret)
96 return ret; 100 return ret;
97 ret = xt_register_match(AF_INET6, &string6_match); 101 ret = xt_register_match(&string6_match);
98 if (ret) 102 if (ret)
99 xt_unregister_match(AF_INET, &string_match); 103 xt_unregister_match(&string_match);
100 104
101 return ret; 105 return ret;
102} 106}
103 107
104static void __exit fini(void) 108static void __exit fini(void)
105{ 109{
106 xt_unregister_match(AF_INET, &string_match); 110 xt_unregister_match(&string_match);
107 xt_unregister_match(AF_INET6, &string6_match); 111 xt_unregister_match(&string6_match);
108} 112}
109 113
110module_init(init); 114module_init(init);
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index acf7f533e9f1..70a8858ae3f1 100644
--- a/net/netfilter/xt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -81,6 +81,7 @@ static int
81match(const struct sk_buff *skb, 81match(const struct sk_buff *skb,
82 const struct net_device *in, 82 const struct net_device *in,
83 const struct net_device *out, 83 const struct net_device *out,
84 const struct xt_match *match,
84 const void *matchinfo, 85 const void *matchinfo,
85 int offset, 86 int offset,
86 unsigned int protoff, 87 unsigned int protoff,
@@ -92,58 +93,21 @@ match(const struct sk_buff *skb,
92 info->invert, hotdrop); 93 info->invert, hotdrop);
93} 94}
94 95
95static int
96checkentry(const char *tablename,
97 const void *ipinfo,
98 void *matchinfo,
99 unsigned int matchsize,
100 unsigned int hook_mask)
101{
102 const struct ipt_ip *ip = ipinfo;
103 if (matchsize != XT_ALIGN(sizeof(struct xt_tcpmss_match_info)))
104 return 0;
105
106 /* Must specify -p tcp */
107 if (ip->proto != IPPROTO_TCP || (ip->invflags & IPT_INV_PROTO)) {
108 printk("tcpmss: Only works on TCP packets\n");
109 return 0;
110 }
111
112 return 1;
113}
114
115static int
116checkentry6(const char *tablename,
117 const void *ipinfo,
118 void *matchinfo,
119 unsigned int matchsize,
120 unsigned int hook_mask)
121{
122 const struct ip6t_ip6 *ip = ipinfo;
123
124 if (matchsize != XT_ALIGN(sizeof(struct xt_tcpmss_match_info)))
125 return 0;
126
127 /* Must specify -p tcp */
128 if (ip->proto != IPPROTO_TCP || (ip->invflags & XT_INV_PROTO)) {
129 printk("tcpmss: Only works on TCP packets\n");
130 return 0;
131 }
132
133 return 1;
134}
135
136static struct xt_match tcpmss_match = { 96static struct xt_match tcpmss_match = {
137 .name = "tcpmss", 97 .name = "tcpmss",
138 .match = &match, 98 .match = match,
139 .checkentry = &checkentry, 99 .matchsize = sizeof(struct xt_tcpmss_match_info),
100 .proto = IPPROTO_TCP,
101 .family = AF_INET,
140 .me = THIS_MODULE, 102 .me = THIS_MODULE,
141}; 103};
142 104
143static struct xt_match tcpmss6_match = { 105static struct xt_match tcpmss6_match = {
144 .name = "tcpmss", 106 .name = "tcpmss",
145 .match = &match, 107 .match = match,
146 .checkentry = &checkentry6, 108 .matchsize = sizeof(struct xt_tcpmss_match_info),
109 .proto = IPPROTO_TCP,
110 .family = AF_INET6,
147 .me = THIS_MODULE, 111 .me = THIS_MODULE,
148}; 112};
149 113
@@ -151,21 +115,21 @@ static struct xt_match tcpmss6_match = {
151static int __init init(void) 115static int __init init(void)
152{ 116{
153 int ret; 117 int ret;
154 ret = xt_register_match(AF_INET, &tcpmss_match); 118 ret = xt_register_match(&tcpmss_match);
155 if (ret) 119 if (ret)
156 return ret; 120 return ret;
157 121
158 ret = xt_register_match(AF_INET6, &tcpmss6_match); 122 ret = xt_register_match(&tcpmss6_match);
159 if (ret) 123 if (ret)
160 xt_unregister_match(AF_INET, &tcpmss_match); 124 xt_unregister_match(&tcpmss_match);
161 125
162 return ret; 126 return ret;
163} 127}
164 128
165static void __exit fini(void) 129static void __exit fini(void)
166{ 130{
167 xt_unregister_match(AF_INET6, &tcpmss6_match); 131 xt_unregister_match(&tcpmss6_match);
168 xt_unregister_match(AF_INET, &tcpmss_match); 132 xt_unregister_match(&tcpmss_match);
169} 133}
170 134
171module_init(init); 135module_init(init);
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
index 669c8113cc60..14a990eb666a 100644
--- a/net/netfilter/xt_tcpudp.c
+++ b/net/netfilter/xt_tcpudp.c
@@ -74,6 +74,7 @@ static int
74tcp_match(const struct sk_buff *skb, 74tcp_match(const struct sk_buff *skb,
75 const struct net_device *in, 75 const struct net_device *in,
76 const struct net_device *out, 76 const struct net_device *out,
77 const struct xt_match *match,
77 const void *matchinfo, 78 const void *matchinfo,
78 int offset, 79 int offset,
79 unsigned int protoff, 80 unsigned int protoff,
@@ -138,43 +139,22 @@ tcp_match(const struct sk_buff *skb,
138static int 139static int
139tcp_checkentry(const char *tablename, 140tcp_checkentry(const char *tablename,
140 const void *info, 141 const void *info,
142 const struct xt_match *match,
141 void *matchinfo, 143 void *matchinfo,
142 unsigned int matchsize, 144 unsigned int matchsize,
143 unsigned int hook_mask) 145 unsigned int hook_mask)
144{ 146{
145 const struct ipt_ip *ip = info;
146 const struct xt_tcp *tcpinfo = matchinfo; 147 const struct xt_tcp *tcpinfo = matchinfo;
147 148
148 /* Must specify proto == TCP, and no unknown invflags */ 149 /* Must specify no unknown invflags */
149 return ip->proto == IPPROTO_TCP 150 return !(tcpinfo->invflags & ~XT_TCP_INV_MASK);
150 && !(ip->invflags & XT_INV_PROTO)
151 && matchsize == XT_ALIGN(sizeof(struct xt_tcp))
152 && !(tcpinfo->invflags & ~XT_TCP_INV_MASK);
153} 151}
154 152
155/* Called when user tries to insert an entry of this type. */
156static int
157tcp6_checkentry(const char *tablename,
158 const void *entry,
159 void *matchinfo,
160 unsigned int matchsize,
161 unsigned int hook_mask)
162{
163 const struct ip6t_ip6 *ipv6 = entry;
164 const struct xt_tcp *tcpinfo = matchinfo;
165
166 /* Must specify proto == TCP, and no unknown invflags */
167 return ipv6->proto == IPPROTO_TCP
168 && !(ipv6->invflags & XT_INV_PROTO)
169 && matchsize == XT_ALIGN(sizeof(struct xt_tcp))
170 && !(tcpinfo->invflags & ~XT_TCP_INV_MASK);
171}
172
173
174static int 153static int
175udp_match(const struct sk_buff *skb, 154udp_match(const struct sk_buff *skb,
176 const struct net_device *in, 155 const struct net_device *in,
177 const struct net_device *out, 156 const struct net_device *out,
157 const struct xt_match *match,
178 const void *matchinfo, 158 const void *matchinfo,
179 int offset, 159 int offset,
180 unsigned int protoff, 160 unsigned int protoff,
@@ -208,126 +188,92 @@ udp_match(const struct sk_buff *skb,
208static int 188static int
209udp_checkentry(const char *tablename, 189udp_checkentry(const char *tablename,
210 const void *info, 190 const void *info,
191 const struct xt_match *match,
211 void *matchinfo, 192 void *matchinfo,
212 unsigned int matchinfosize, 193 unsigned int matchsize,
213 unsigned int hook_mask)
214{
215 const struct ipt_ip *ip = info;
216 const struct xt_udp *udpinfo = matchinfo;
217
218 /* Must specify proto == UDP, and no unknown invflags */
219 if (ip->proto != IPPROTO_UDP || (ip->invflags & XT_INV_PROTO)) {
220 duprintf("ipt_udp: Protocol %u != %u\n", ip->proto,
221 IPPROTO_UDP);
222 return 0;
223 }
224 if (matchinfosize != XT_ALIGN(sizeof(struct xt_udp))) {
225 duprintf("ipt_udp: matchsize %u != %u\n",
226 matchinfosize, XT_ALIGN(sizeof(struct xt_udp)));
227 return 0;
228 }
229 if (udpinfo->invflags & ~XT_UDP_INV_MASK) {
230 duprintf("ipt_udp: unknown flags %X\n",
231 udpinfo->invflags);
232 return 0;
233 }
234
235 return 1;
236}
237
238/* Called when user tries to insert an entry of this type. */
239static int
240udp6_checkentry(const char *tablename,
241 const void *entry,
242 void *matchinfo,
243 unsigned int matchinfosize,
244 unsigned int hook_mask) 194 unsigned int hook_mask)
245{ 195{
246 const struct ip6t_ip6 *ipv6 = entry; 196 const struct xt_tcp *udpinfo = matchinfo;
247 const struct xt_udp *udpinfo = matchinfo;
248 197
249 /* Must specify proto == UDP, and no unknown invflags */ 198 /* Must specify no unknown invflags */
250 if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & XT_INV_PROTO)) { 199 return !(udpinfo->invflags & ~XT_UDP_INV_MASK);
251 duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto,
252 IPPROTO_UDP);
253 return 0;
254 }
255 if (matchinfosize != XT_ALIGN(sizeof(struct xt_udp))) {
256 duprintf("ip6t_udp: matchsize %u != %u\n",
257 matchinfosize, XT_ALIGN(sizeof(struct xt_udp)));
258 return 0;
259 }
260 if (udpinfo->invflags & ~XT_UDP_INV_MASK) {
261 duprintf("ip6t_udp: unknown flags %X\n",
262 udpinfo->invflags);
263 return 0;
264 }
265
266 return 1;
267} 200}
268 201
269static struct xt_match tcp_matchstruct = { 202static struct xt_match tcp_matchstruct = {
270 .name = "tcp", 203 .name = "tcp",
271 .match = &tcp_match, 204 .match = tcp_match,
272 .checkentry = &tcp_checkentry, 205 .matchsize = sizeof(struct xt_tcp),
206 .proto = IPPROTO_TCP,
207 .family = AF_INET,
208 .checkentry = tcp_checkentry,
273 .me = THIS_MODULE, 209 .me = THIS_MODULE,
274}; 210};
211
275static struct xt_match tcp6_matchstruct = { 212static struct xt_match tcp6_matchstruct = {
276 .name = "tcp", 213 .name = "tcp",
277 .match = &tcp_match, 214 .match = tcp_match,
278 .checkentry = &tcp6_checkentry, 215 .matchsize = sizeof(struct xt_tcp),
216 .proto = IPPROTO_TCP,
217 .family = AF_INET6,
218 .checkentry = tcp_checkentry,
279 .me = THIS_MODULE, 219 .me = THIS_MODULE,
280}; 220};
281 221
282static struct xt_match udp_matchstruct = { 222static struct xt_match udp_matchstruct = {
283 .name = "udp", 223 .name = "udp",
284 .match = &udp_match, 224 .match = udp_match,
285 .checkentry = &udp_checkentry, 225 .matchsize = sizeof(struct xt_udp),
226 .proto = IPPROTO_UDP,
227 .family = AF_INET,
228 .checkentry = udp_checkentry,
286 .me = THIS_MODULE, 229 .me = THIS_MODULE,
287}; 230};
288static struct xt_match udp6_matchstruct = { 231static struct xt_match udp6_matchstruct = {
289 .name = "udp", 232 .name = "udp",
290 .match = &udp_match, 233 .match = udp_match,
291 .checkentry = &udp6_checkentry, 234 .matchsize = sizeof(struct xt_udp),
235 .proto = IPPROTO_UDP,
236 .family = AF_INET6,
237 .checkentry = udp_checkentry,
292 .me = THIS_MODULE, 238 .me = THIS_MODULE,
293}; 239};
294 240
295static int __init init(void) 241static int __init init(void)
296{ 242{
297 int ret; 243 int ret;
298 ret = xt_register_match(AF_INET, &tcp_matchstruct); 244 ret = xt_register_match(&tcp_matchstruct);
299 if (ret) 245 if (ret)
300 return ret; 246 return ret;
301 247
302 ret = xt_register_match(AF_INET6, &tcp6_matchstruct); 248 ret = xt_register_match(&tcp6_matchstruct);
303 if (ret) 249 if (ret)
304 goto out_unreg_tcp; 250 goto out_unreg_tcp;
305 251
306 ret = xt_register_match(AF_INET, &udp_matchstruct); 252 ret = xt_register_match(&udp_matchstruct);
307 if (ret) 253 if (ret)
308 goto out_unreg_tcp6; 254 goto out_unreg_tcp6;
309 255
310 ret = xt_register_match(AF_INET6, &udp6_matchstruct); 256 ret = xt_register_match(&udp6_matchstruct);
311 if (ret) 257 if (ret)
312 goto out_unreg_udp; 258 goto out_unreg_udp;
313 259
314 return ret; 260 return ret;
315 261
316out_unreg_udp: 262out_unreg_udp:
317 xt_unregister_match(AF_INET, &tcp_matchstruct); 263 xt_unregister_match(&tcp_matchstruct);
318out_unreg_tcp6: 264out_unreg_tcp6:
319 xt_unregister_match(AF_INET6, &tcp6_matchstruct); 265 xt_unregister_match(&tcp6_matchstruct);
320out_unreg_tcp: 266out_unreg_tcp:
321 xt_unregister_match(AF_INET, &tcp_matchstruct); 267 xt_unregister_match(&tcp_matchstruct);
322 return ret; 268 return ret;
323} 269}
324 270
325static void __exit fini(void) 271static void __exit fini(void)
326{ 272{
327 xt_unregister_match(AF_INET6, &udp6_matchstruct); 273 xt_unregister_match(&udp6_matchstruct);
328 xt_unregister_match(AF_INET, &udp_matchstruct); 274 xt_unregister_match(&udp_matchstruct);
329 xt_unregister_match(AF_INET6, &tcp6_matchstruct); 275 xt_unregister_match(&tcp6_matchstruct);
330 xt_unregister_match(AF_INET, &tcp_matchstruct); 276 xt_unregister_match(&tcp_matchstruct);
331} 277}
332 278
333module_init(init); 279module_init(init);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 59dc7d140600..d00a9034cb5f 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -106,6 +106,7 @@ struct nl_pid_hash {
106struct netlink_table { 106struct netlink_table {
107 struct nl_pid_hash hash; 107 struct nl_pid_hash hash;
108 struct hlist_head mc_list; 108 struct hlist_head mc_list;
109 unsigned long *listeners;
109 unsigned int nl_nonroot; 110 unsigned int nl_nonroot;
110 unsigned int groups; 111 unsigned int groups;
111 struct module *module; 112 struct module *module;
@@ -296,6 +297,24 @@ static inline int nl_pid_hash_dilute(struct nl_pid_hash *hash, int len)
296 297
297static const struct proto_ops netlink_ops; 298static const struct proto_ops netlink_ops;
298 299
300static void
301netlink_update_listeners(struct sock *sk)
302{
303 struct netlink_table *tbl = &nl_table[sk->sk_protocol];
304 struct hlist_node *node;
305 unsigned long mask;
306 unsigned int i;
307
308 for (i = 0; i < NLGRPSZ(tbl->groups)/sizeof(unsigned long); i++) {
309 mask = 0;
310 sk_for_each_bound(sk, node, &tbl->mc_list)
311 mask |= nlk_sk(sk)->groups[i];
312 tbl->listeners[i] = mask;
313 }
314 /* this function is only called with the netlink table "grabbed", which
315 * makes sure updates are visible before bind or setsockopt return. */
316}
317
299static int netlink_insert(struct sock *sk, u32 pid) 318static int netlink_insert(struct sock *sk, u32 pid)
300{ 319{
301 struct nl_pid_hash *hash = &nl_table[sk->sk_protocol].hash; 320 struct nl_pid_hash *hash = &nl_table[sk->sk_protocol].hash;
@@ -456,12 +475,14 @@ static int netlink_release(struct socket *sock)
456 if (nlk->module) 475 if (nlk->module)
457 module_put(nlk->module); 476 module_put(nlk->module);
458 477
478 netlink_table_grab();
459 if (nlk->flags & NETLINK_KERNEL_SOCKET) { 479 if (nlk->flags & NETLINK_KERNEL_SOCKET) {
460 netlink_table_grab(); 480 kfree(nl_table[sk->sk_protocol].listeners);
461 nl_table[sk->sk_protocol].module = NULL; 481 nl_table[sk->sk_protocol].module = NULL;
462 nl_table[sk->sk_protocol].registered = 0; 482 nl_table[sk->sk_protocol].registered = 0;
463 netlink_table_ungrab(); 483 } else if (nlk->subscriptions)
464 } 484 netlink_update_listeners(sk);
485 netlink_table_ungrab();
465 486
466 kfree(nlk->groups); 487 kfree(nlk->groups);
467 nlk->groups = NULL; 488 nlk->groups = NULL;
@@ -589,6 +610,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len
589 hweight32(nladdr->nl_groups) - 610 hweight32(nladdr->nl_groups) -
590 hweight32(nlk->groups[0])); 611 hweight32(nlk->groups[0]));
591 nlk->groups[0] = (nlk->groups[0] & ~0xffffffffUL) | nladdr->nl_groups; 612 nlk->groups[0] = (nlk->groups[0] & ~0xffffffffUL) | nladdr->nl_groups;
613 netlink_update_listeners(sk);
592 netlink_table_ungrab(); 614 netlink_table_ungrab();
593 615
594 return 0; 616 return 0;
@@ -807,6 +829,17 @@ retry:
807 return netlink_sendskb(sk, skb, ssk->sk_protocol); 829 return netlink_sendskb(sk, skb, ssk->sk_protocol);
808} 830}
809 831
832int netlink_has_listeners(struct sock *sk, unsigned int group)
833{
834 int res = 0;
835
836 BUG_ON(!(nlk_sk(sk)->flags & NETLINK_KERNEL_SOCKET));
837 if (group - 1 < nl_table[sk->sk_protocol].groups)
838 res = test_bit(group - 1, nl_table[sk->sk_protocol].listeners);
839 return res;
840}
841EXPORT_SYMBOL_GPL(netlink_has_listeners);
842
810static __inline__ int netlink_broadcast_deliver(struct sock *sk, struct sk_buff *skb) 843static __inline__ int netlink_broadcast_deliver(struct sock *sk, struct sk_buff *skb)
811{ 844{
812 struct netlink_sock *nlk = nlk_sk(sk); 845 struct netlink_sock *nlk = nlk_sk(sk);
@@ -1011,6 +1044,7 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
1011 else 1044 else
1012 __clear_bit(val - 1, nlk->groups); 1045 __clear_bit(val - 1, nlk->groups);
1013 netlink_update_subscriptions(sk, subscriptions); 1046 netlink_update_subscriptions(sk, subscriptions);
1047 netlink_update_listeners(sk);
1014 netlink_table_ungrab(); 1048 netlink_table_ungrab();
1015 err = 0; 1049 err = 0;
1016 break; 1050 break;
@@ -1237,6 +1271,7 @@ netlink_kernel_create(int unit, unsigned int groups,
1237 struct socket *sock; 1271 struct socket *sock;
1238 struct sock *sk; 1272 struct sock *sk;
1239 struct netlink_sock *nlk; 1273 struct netlink_sock *nlk;
1274 unsigned long *listeners = NULL;
1240 1275
1241 if (!nl_table) 1276 if (!nl_table)
1242 return NULL; 1277 return NULL;
@@ -1250,6 +1285,13 @@ netlink_kernel_create(int unit, unsigned int groups,
1250 if (__netlink_create(sock, unit) < 0) 1285 if (__netlink_create(sock, unit) < 0)
1251 goto out_sock_release; 1286 goto out_sock_release;
1252 1287
1288 if (groups < 32)
1289 groups = 32;
1290
1291 listeners = kzalloc(NLGRPSZ(groups), GFP_KERNEL);
1292 if (!listeners)
1293 goto out_sock_release;
1294
1253 sk = sock->sk; 1295 sk = sock->sk;
1254 sk->sk_data_ready = netlink_data_ready; 1296 sk->sk_data_ready = netlink_data_ready;
1255 if (input) 1297 if (input)
@@ -1262,7 +1304,8 @@ netlink_kernel_create(int unit, unsigned int groups,
1262 nlk->flags |= NETLINK_KERNEL_SOCKET; 1304 nlk->flags |= NETLINK_KERNEL_SOCKET;
1263 1305
1264 netlink_table_grab(); 1306 netlink_table_grab();
1265 nl_table[unit].groups = groups < 32 ? 32 : groups; 1307 nl_table[unit].groups = groups;
1308 nl_table[unit].listeners = listeners;
1266 nl_table[unit].module = module; 1309 nl_table[unit].module = module;
1267 nl_table[unit].registered = 1; 1310 nl_table[unit].registered = 1;
1268 netlink_table_ungrab(); 1311 netlink_table_ungrab();
@@ -1270,6 +1313,7 @@ netlink_kernel_create(int unit, unsigned int groups,
1270 return sk; 1313 return sk;
1271 1314
1272out_sock_release: 1315out_sock_release:
1316 kfree(listeners);
1273 sock_release(sock); 1317 sock_release(sock);
1274 return NULL; 1318 return NULL;
1275} 1319}
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 778b1e5a4b50..13eeee582886 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -434,7 +434,6 @@ config NET_EMATCH_TEXT
434 434
435config NET_CLS_ACT 435config NET_CLS_ACT
436 bool "Actions" 436 bool "Actions"
437 depends on EXPERIMENTAL
438 select NET_ESTIMATOR 437 select NET_ESTIMATOR
439 ---help--- 438 ---help---
440 Say Y here if you want to use traffic control actions. Actions 439 Say Y here if you want to use traffic control actions. Actions
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 39a22a3ffe78..6056d20ef429 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -70,7 +70,8 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
70 t->u.kernel.target = target; 70 t->u.kernel.target = target;
71 71
72 if (t->u.kernel.target->checkentry 72 if (t->u.kernel.target->checkentry
73 && !t->u.kernel.target->checkentry(table, NULL, t->data, 73 && !t->u.kernel.target->checkentry(table, NULL,
74 t->u.kernel.target, t->data,
74 t->u.target_size - sizeof(*t), 75 t->u.target_size - sizeof(*t),
75 hook)) { 76 hook)) {
76 DPRINTK("ipt_init_target: check failed for `%s'.\n", 77 DPRINTK("ipt_init_target: check failed for `%s'.\n",
@@ -86,7 +87,7 @@ static void
86ipt_destroy_target(struct ipt_entry_target *t) 87ipt_destroy_target(struct ipt_entry_target *t)
87{ 88{
88 if (t->u.kernel.target->destroy) 89 if (t->u.kernel.target->destroy)
89 t->u.kernel.target->destroy(t->data, 90 t->u.kernel.target->destroy(t->u.kernel.target, t->data,
90 t->u.target_size - sizeof(*t)); 91 t->u.target_size - sizeof(*t));
91 module_put(t->u.kernel.target->me); 92 module_put(t->u.kernel.target->me);
92} 93}
@@ -224,8 +225,9 @@ tcf_ipt(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
224 /* iptables targets take a double skb pointer in case the skb 225 /* iptables targets take a double skb pointer in case the skb
225 * needs to be replaced. We don't own the skb, so this must not 226 * needs to be replaced. We don't own the skb, so this must not
226 * happen. The pskb_expand_head above should make sure of this */ 227 * happen. The pskb_expand_head above should make sure of this */
227 ret = p->t->u.kernel.target->target(&skb, skb->dev, NULL, 228 ret = p->t->u.kernel.target->target(&skb, skb->dev, NULL, p->hook,
228 p->hook, p->t->data, NULL); 229 p->t->u.kernel.target, p->t->data,
230 NULL);
229 switch (ret) { 231 switch (ret) {
230 case NF_ACCEPT: 232 case NF_ACCEPT:
231 result = TC_ACT_OK; 233 result = TC_ACT_OK;
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 2b670479dde1..78e052591fa9 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -347,8 +347,7 @@ static int u32_destroy_key(struct tcf_proto *tp, struct tc_u_knode *n)
347 if (n->ht_down) 347 if (n->ht_down)
348 n->ht_down->refcnt--; 348 n->ht_down->refcnt--;
349#ifdef CONFIG_CLS_U32_PERF 349#ifdef CONFIG_CLS_U32_PERF
350 if (n) 350 kfree(n->pf);
351 kfree(n->pf);
352#endif 351#endif
353 kfree(n); 352 kfree(n);
354 return 0; 353 return 0;
@@ -680,8 +679,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
680 return 0; 679 return 0;
681 } 680 }
682#ifdef CONFIG_CLS_U32_PERF 681#ifdef CONFIG_CLS_U32_PERF
683 if (n) 682 kfree(n->pf);
684 kfree(n->pf);
685#endif 683#endif
686 kfree(n); 684 kfree(n);
687 return err; 685 return err;
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 93ebce40acac..ac7cb60d1e25 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -638,6 +638,7 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl,
638 sch,p,flow,skb,tcm); 638 sch,p,flow,skb,tcm);
639 if (!find_flow(p,flow)) return -EINVAL; 639 if (!find_flow(p,flow)) return -EINVAL;
640 tcm->tcm_handle = flow->classid; 640 tcm->tcm_handle = flow->classid;
641 tcm->tcm_info = flow->q->handle;
641 rta = (struct rtattr *) b; 642 rta = (struct rtattr *) b;
642 RTA_PUT(skb,TCA_OPTIONS,0,NULL); 643 RTA_PUT(skb,TCA_OPTIONS,0,NULL);
643 RTA_PUT(skb,TCA_ATM_HDR,flow->hdr_len,flow->hdr); 644 RTA_PUT(skb,TCA_ATM_HDR,flow->hdr_len,flow->hdr);
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index 13e0e7b3856b..f6320ca70493 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -438,6 +438,7 @@ static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl,
438 return -EINVAL; 438 return -EINVAL;
439 439
440 tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle), cl-1); 440 tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle), cl-1);
441 tcm->tcm_info = p->q->handle;
441 442
442 opts = RTA_NEST(skb, TCA_OPTIONS); 443 opts = RTA_NEST(skb, TCA_OPTIONS);
443 RTA_PUT_U8(skb,TCA_DSMARK_MASK, p->mask[cl-1]); 444 RTA_PUT_U8(skb,TCA_DSMARK_MASK, p->mask[cl-1]);
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 99ceb91f0150..31eb83717c26 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -234,7 +234,7 @@ static void dev_watchdog_down(struct net_device *dev)
234{ 234{
235 spin_lock_bh(&dev->xmit_lock); 235 spin_lock_bh(&dev->xmit_lock);
236 if (del_timer(&dev->watchdog_timer)) 236 if (del_timer(&dev->watchdog_timer))
237 __dev_put(dev); 237 dev_put(dev);
238 spin_unlock_bh(&dev->xmit_lock); 238 spin_unlock_bh(&dev->xmit_lock);
239} 239}
240 240
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index ba5283204837..7228d30512c7 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -252,9 +252,9 @@ static int netem_requeue(struct sk_buff *skb, struct Qdisc *sch)
252static unsigned int netem_drop(struct Qdisc* sch) 252static unsigned int netem_drop(struct Qdisc* sch)
253{ 253{
254 struct netem_sched_data *q = qdisc_priv(sch); 254 struct netem_sched_data *q = qdisc_priv(sch);
255 unsigned int len; 255 unsigned int len = 0;
256 256
257 if ((len = q->qdisc->ops->drop(q->qdisc)) != 0) { 257 if (q->qdisc->ops->drop && (len = q->qdisc->ops->drop(q->qdisc)) != 0) {
258 sch->q.qlen--; 258 sch->q.qlen--;
259 sch->qstats.drops++; 259 sch->qstats.drops++;
260 } 260 }
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 1641db33a994..3395ca7bcadf 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -165,7 +165,7 @@ static unsigned int prio_drop(struct Qdisc* sch)
165 165
166 for (prio = q->bands-1; prio >= 0; prio--) { 166 for (prio = q->bands-1; prio >= 0; prio--) {
167 qdisc = q->queues[prio]; 167 qdisc = q->queues[prio];
168 if ((len = qdisc->ops->drop(qdisc)) != 0) { 168 if (qdisc->ops->drop && (len = qdisc->ops->drop(qdisc)) != 0) {
169 sch->q.qlen--; 169 sch->q.qlen--;
170 return len; 170 return len;
171 } 171 }
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index dccfa44c2d71..2be563cba72b 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -44,6 +44,7 @@ struct red_sched_data
44 unsigned char flags; 44 unsigned char flags;
45 struct red_parms parms; 45 struct red_parms parms;
46 struct red_stats stats; 46 struct red_stats stats;
47 struct Qdisc *qdisc;
47}; 48};
48 49
49static inline int red_use_ecn(struct red_sched_data *q) 50static inline int red_use_ecn(struct red_sched_data *q)
@@ -59,8 +60,10 @@ static inline int red_use_harddrop(struct red_sched_data *q)
59static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch) 60static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch)
60{ 61{
61 struct red_sched_data *q = qdisc_priv(sch); 62 struct red_sched_data *q = qdisc_priv(sch);
63 struct Qdisc *child = q->qdisc;
64 int ret;
62 65
63 q->parms.qavg = red_calc_qavg(&q->parms, sch->qstats.backlog); 66 q->parms.qavg = red_calc_qavg(&q->parms, child->qstats.backlog);
64 67
65 if (red_is_idling(&q->parms)) 68 if (red_is_idling(&q->parms))
66 red_end_of_idle_period(&q->parms); 69 red_end_of_idle_period(&q->parms);
@@ -91,11 +94,16 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch)
91 break; 94 break;
92 } 95 }
93 96
94 if (sch->qstats.backlog + skb->len <= q->limit) 97 ret = child->enqueue(skb, child);
95 return qdisc_enqueue_tail(skb, sch); 98 if (likely(ret == NET_XMIT_SUCCESS)) {
96 99 sch->bstats.bytes += skb->len;
97 q->stats.pdrop++; 100 sch->bstats.packets++;
98 return qdisc_drop(skb, sch); 101 sch->q.qlen++;
102 } else {
103 q->stats.pdrop++;
104 sch->qstats.drops++;
105 }
106 return ret;
99 107
100congestion_drop: 108congestion_drop:
101 qdisc_drop(skb, sch); 109 qdisc_drop(skb, sch);
@@ -105,21 +113,30 @@ congestion_drop:
105static int red_requeue(struct sk_buff *skb, struct Qdisc* sch) 113static int red_requeue(struct sk_buff *skb, struct Qdisc* sch)
106{ 114{
107 struct red_sched_data *q = qdisc_priv(sch); 115 struct red_sched_data *q = qdisc_priv(sch);
116 struct Qdisc *child = q->qdisc;
117 int ret;
108 118
109 if (red_is_idling(&q->parms)) 119 if (red_is_idling(&q->parms))
110 red_end_of_idle_period(&q->parms); 120 red_end_of_idle_period(&q->parms);
111 121
112 return qdisc_requeue(skb, sch); 122 ret = child->ops->requeue(skb, child);
123 if (likely(ret == NET_XMIT_SUCCESS)) {
124 sch->qstats.requeues++;
125 sch->q.qlen++;
126 }
127 return ret;
113} 128}
114 129
115static struct sk_buff * red_dequeue(struct Qdisc* sch) 130static struct sk_buff * red_dequeue(struct Qdisc* sch)
116{ 131{
117 struct sk_buff *skb; 132 struct sk_buff *skb;
118 struct red_sched_data *q = qdisc_priv(sch); 133 struct red_sched_data *q = qdisc_priv(sch);
134 struct Qdisc *child = q->qdisc;
119 135
120 skb = qdisc_dequeue_head(sch); 136 skb = child->dequeue(child);
121 137 if (skb)
122 if (skb == NULL && !red_is_idling(&q->parms)) 138 sch->q.qlen--;
139 else if (!red_is_idling(&q->parms))
123 red_start_of_idle_period(&q->parms); 140 red_start_of_idle_period(&q->parms);
124 141
125 return skb; 142 return skb;
@@ -127,14 +144,14 @@ static struct sk_buff * red_dequeue(struct Qdisc* sch)
127 144
128static unsigned int red_drop(struct Qdisc* sch) 145static unsigned int red_drop(struct Qdisc* sch)
129{ 146{
130 struct sk_buff *skb;
131 struct red_sched_data *q = qdisc_priv(sch); 147 struct red_sched_data *q = qdisc_priv(sch);
148 struct Qdisc *child = q->qdisc;
149 unsigned int len;
132 150
133 skb = qdisc_dequeue_tail(sch); 151 if (child->ops->drop && (len = child->ops->drop(child)) > 0) {
134 if (skb) {
135 unsigned int len = skb->len;
136 q->stats.other++; 152 q->stats.other++;
137 qdisc_drop(skb, sch); 153 sch->qstats.drops++;
154 sch->q.qlen--;
138 return len; 155 return len;
139 } 156 }
140 157
@@ -148,15 +165,48 @@ static void red_reset(struct Qdisc* sch)
148{ 165{
149 struct red_sched_data *q = qdisc_priv(sch); 166 struct red_sched_data *q = qdisc_priv(sch);
150 167
151 qdisc_reset_queue(sch); 168 qdisc_reset(q->qdisc);
169 sch->q.qlen = 0;
152 red_restart(&q->parms); 170 red_restart(&q->parms);
153} 171}
154 172
173static void red_destroy(struct Qdisc *sch)
174{
175 struct red_sched_data *q = qdisc_priv(sch);
176 qdisc_destroy(q->qdisc);
177}
178
179static struct Qdisc *red_create_dflt(struct net_device *dev, u32 limit)
180{
181 struct Qdisc *q = qdisc_create_dflt(dev, &bfifo_qdisc_ops);
182 struct rtattr *rta;
183 int ret;
184
185 if (q) {
186 rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)),
187 GFP_KERNEL);
188 if (rta) {
189 rta->rta_type = RTM_NEWQDISC;
190 rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt));
191 ((struct tc_fifo_qopt *)RTA_DATA(rta))->limit = limit;
192
193 ret = q->ops->change(q, rta);
194 kfree(rta);
195
196 if (ret == 0)
197 return q;
198 }
199 qdisc_destroy(q);
200 }
201 return NULL;
202}
203
155static int red_change(struct Qdisc *sch, struct rtattr *opt) 204static int red_change(struct Qdisc *sch, struct rtattr *opt)
156{ 205{
157 struct red_sched_data *q = qdisc_priv(sch); 206 struct red_sched_data *q = qdisc_priv(sch);
158 struct rtattr *tb[TCA_RED_MAX]; 207 struct rtattr *tb[TCA_RED_MAX];
159 struct tc_red_qopt *ctl; 208 struct tc_red_qopt *ctl;
209 struct Qdisc *child = NULL;
160 210
161 if (opt == NULL || rtattr_parse_nested(tb, TCA_RED_MAX, opt)) 211 if (opt == NULL || rtattr_parse_nested(tb, TCA_RED_MAX, opt))
162 return -EINVAL; 212 return -EINVAL;
@@ -169,9 +219,17 @@ static int red_change(struct Qdisc *sch, struct rtattr *opt)
169 219
170 ctl = RTA_DATA(tb[TCA_RED_PARMS-1]); 220 ctl = RTA_DATA(tb[TCA_RED_PARMS-1]);
171 221
222 if (ctl->limit > 0) {
223 child = red_create_dflt(sch->dev, ctl->limit);
224 if (child == NULL)
225 return -ENOMEM;
226 }
227
172 sch_tree_lock(sch); 228 sch_tree_lock(sch);
173 q->flags = ctl->flags; 229 q->flags = ctl->flags;
174 q->limit = ctl->limit; 230 q->limit = ctl->limit;
231 if (child)
232 qdisc_destroy(xchg(&q->qdisc, child));
175 233
176 red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog, 234 red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog,
177 ctl->Plog, ctl->Scell_log, 235 ctl->Plog, ctl->Scell_log,
@@ -186,6 +244,9 @@ static int red_change(struct Qdisc *sch, struct rtattr *opt)
186 244
187static int red_init(struct Qdisc* sch, struct rtattr *opt) 245static int red_init(struct Qdisc* sch, struct rtattr *opt)
188{ 246{
247 struct red_sched_data *q = qdisc_priv(sch);
248
249 q->qdisc = &noop_qdisc;
189 return red_change(sch, opt); 250 return red_change(sch, opt);
190} 251}
191 252
@@ -224,15 +285,101 @@ static int red_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
224 return gnet_stats_copy_app(d, &st, sizeof(st)); 285 return gnet_stats_copy_app(d, &st, sizeof(st));
225} 286}
226 287
288static int red_dump_class(struct Qdisc *sch, unsigned long cl,
289 struct sk_buff *skb, struct tcmsg *tcm)
290{
291 struct red_sched_data *q = qdisc_priv(sch);
292
293 if (cl != 1)
294 return -ENOENT;
295 tcm->tcm_handle |= TC_H_MIN(1);
296 tcm->tcm_info = q->qdisc->handle;
297 return 0;
298}
299
300static int red_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
301 struct Qdisc **old)
302{
303 struct red_sched_data *q = qdisc_priv(sch);
304
305 if (new == NULL)
306 new = &noop_qdisc;
307
308 sch_tree_lock(sch);
309 *old = xchg(&q->qdisc, new);
310 qdisc_reset(*old);
311 sch->q.qlen = 0;
312 sch_tree_unlock(sch);
313 return 0;
314}
315
316static struct Qdisc *red_leaf(struct Qdisc *sch, unsigned long arg)
317{
318 struct red_sched_data *q = qdisc_priv(sch);
319 return q->qdisc;
320}
321
322static unsigned long red_get(struct Qdisc *sch, u32 classid)
323{
324 return 1;
325}
326
327static void red_put(struct Qdisc *sch, unsigned long arg)
328{
329 return;
330}
331
332static int red_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
333 struct rtattr **tca, unsigned long *arg)
334{
335 return -ENOSYS;
336}
337
338static int red_delete(struct Qdisc *sch, unsigned long cl)
339{
340 return -ENOSYS;
341}
342
343static void red_walk(struct Qdisc *sch, struct qdisc_walker *walker)
344{
345 if (!walker->stop) {
346 if (walker->count >= walker->skip)
347 if (walker->fn(sch, 1, walker) < 0) {
348 walker->stop = 1;
349 return;
350 }
351 walker->count++;
352 }
353}
354
355static struct tcf_proto **red_find_tcf(struct Qdisc *sch, unsigned long cl)
356{
357 return NULL;
358}
359
360static struct Qdisc_class_ops red_class_ops = {
361 .graft = red_graft,
362 .leaf = red_leaf,
363 .get = red_get,
364 .put = red_put,
365 .change = red_change_class,
366 .delete = red_delete,
367 .walk = red_walk,
368 .tcf_chain = red_find_tcf,
369 .dump = red_dump_class,
370};
371
227static struct Qdisc_ops red_qdisc_ops = { 372static struct Qdisc_ops red_qdisc_ops = {
228 .id = "red", 373 .id = "red",
229 .priv_size = sizeof(struct red_sched_data), 374 .priv_size = sizeof(struct red_sched_data),
375 .cl_ops = &red_class_ops,
230 .enqueue = red_enqueue, 376 .enqueue = red_enqueue,
231 .dequeue = red_dequeue, 377 .dequeue = red_dequeue,
232 .requeue = red_requeue, 378 .requeue = red_requeue,
233 .drop = red_drop, 379 .drop = red_drop,
234 .init = red_init, 380 .init = red_init,
235 .reset = red_reset, 381 .reset = red_reset,
382 .destroy = red_destroy,
236 .change = red_change, 383 .change = red_change,
237 .dump = red_dump, 384 .dump = red_dump,
238 .dump_stats = red_dump_stats, 385 .dump_stats = red_dump_stats,
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 86d8da0cbd02..e057768f68b4 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -232,6 +232,7 @@ static unsigned int sfq_drop(struct Qdisc *sch)
232 sfq_dec(q, x); 232 sfq_dec(q, x);
233 sch->q.qlen--; 233 sch->q.qlen--;
234 sch->qstats.drops++; 234 sch->qstats.drops++;
235 sch->qstats.backlog -= len;
235 return len; 236 return len;
236 } 237 }
237 238
@@ -248,6 +249,7 @@ static unsigned int sfq_drop(struct Qdisc *sch)
248 sch->q.qlen--; 249 sch->q.qlen--;
249 q->ht[q->hash[d]] = SFQ_DEPTH; 250 q->ht[q->hash[d]] = SFQ_DEPTH;
250 sch->qstats.drops++; 251 sch->qstats.drops++;
252 sch->qstats.backlog -= len;
251 return len; 253 return len;
252 } 254 }
253 255
@@ -266,6 +268,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)
266 q->ht[hash] = x = q->dep[SFQ_DEPTH].next; 268 q->ht[hash] = x = q->dep[SFQ_DEPTH].next;
267 q->hash[x] = hash; 269 q->hash[x] = hash;
268 } 270 }
271 sch->qstats.backlog += skb->len;
269 __skb_queue_tail(&q->qs[x], skb); 272 __skb_queue_tail(&q->qs[x], skb);
270 sfq_inc(q, x); 273 sfq_inc(q, x);
271 if (q->qs[x].qlen == 1) { /* The flow is new */ 274 if (q->qs[x].qlen == 1) { /* The flow is new */
@@ -301,6 +304,7 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc* sch)
301 q->ht[hash] = x = q->dep[SFQ_DEPTH].next; 304 q->ht[hash] = x = q->dep[SFQ_DEPTH].next;
302 q->hash[x] = hash; 305 q->hash[x] = hash;
303 } 306 }
307 sch->qstats.backlog += skb->len;
304 __skb_queue_head(&q->qs[x], skb); 308 __skb_queue_head(&q->qs[x], skb);
305 sfq_inc(q, x); 309 sfq_inc(q, x);
306 if (q->qs[x].qlen == 1) { /* The flow is new */ 310 if (q->qs[x].qlen == 1) { /* The flow is new */
@@ -344,6 +348,7 @@ sfq_dequeue(struct Qdisc* sch)
344 skb = __skb_dequeue(&q->qs[a]); 348 skb = __skb_dequeue(&q->qs[a]);
345 sfq_dec(q, a); 349 sfq_dec(q, a);
346 sch->q.qlen--; 350 sch->q.qlen--;
351 sch->qstats.backlog -= skb->len;
347 352
348 /* Is the slot empty? */ 353 /* Is the slot empty? */
349 if (q->qs[a].qlen == 0) { 354 if (q->qs[a].qlen == 0) {
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index cb9711ea8c6c..d8e03c74ca76 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -177,9 +177,9 @@ static int tbf_requeue(struct sk_buff *skb, struct Qdisc* sch)
177static unsigned int tbf_drop(struct Qdisc* sch) 177static unsigned int tbf_drop(struct Qdisc* sch)
178{ 178{
179 struct tbf_sched_data *q = qdisc_priv(sch); 179 struct tbf_sched_data *q = qdisc_priv(sch);
180 unsigned int len; 180 unsigned int len = 0;
181 181
182 if ((len = q->qdisc->ops->drop(q->qdisc)) != 0) { 182 if (q->qdisc->ops->drop && (len = q->qdisc->ops->drop(q->qdisc)) != 0) {
183 sch->q.qlen--; 183 sch->q.qlen--;
184 sch->qstats.drops++; 184 sch->qstats.drops++;
185 } 185 }
@@ -341,13 +341,14 @@ static int tbf_change(struct Qdisc* sch, struct rtattr *opt)
341 if (max_size < 0) 341 if (max_size < 0)
342 goto done; 342 goto done;
343 343
344 if (q->qdisc == &noop_qdisc) { 344 if (qopt->limit > 0) {
345 if ((child = tbf_create_dflt_qdisc(sch->dev, qopt->limit)) == NULL) 345 if ((child = tbf_create_dflt_qdisc(sch->dev, qopt->limit)) == NULL)
346 goto done; 346 goto done;
347 } 347 }
348 348
349 sch_tree_lock(sch); 349 sch_tree_lock(sch);
350 if (child) q->qdisc = child; 350 if (child)
351 qdisc_destroy(xchg(&q->qdisc, child));
351 q->limit = qopt->limit; 352 q->limit = qopt->limit;
352 q->mtu = qopt->mtu; 353 q->mtu = qopt->mtu;
353 q->max_size = max_size; 354 q->max_size = max_size;
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 2e266129a764..c20d282fac06 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -861,23 +861,27 @@ static int sctp_inet6_supported_addrs(const struct sctp_sock *opt,
861} 861}
862 862
863static const struct proto_ops inet6_seqpacket_ops = { 863static const struct proto_ops inet6_seqpacket_ops = {
864 .family = PF_INET6, 864 .family = PF_INET6,
865 .owner = THIS_MODULE, 865 .owner = THIS_MODULE,
866 .release = inet6_release, 866 .release = inet6_release,
867 .bind = inet6_bind, 867 .bind = inet6_bind,
868 .connect = inet_dgram_connect, 868 .connect = inet_dgram_connect,
869 .socketpair = sock_no_socketpair, 869 .socketpair = sock_no_socketpair,
870 .accept = inet_accept, 870 .accept = inet_accept,
871 .getname = inet6_getname, 871 .getname = inet6_getname,
872 .poll = sctp_poll, 872 .poll = sctp_poll,
873 .ioctl = inet6_ioctl, 873 .ioctl = inet6_ioctl,
874 .listen = sctp_inet_listen, 874 .listen = sctp_inet_listen,
875 .shutdown = inet_shutdown, 875 .shutdown = inet_shutdown,
876 .setsockopt = sock_common_setsockopt, 876 .setsockopt = sock_common_setsockopt,
877 .getsockopt = sock_common_getsockopt, 877 .getsockopt = sock_common_getsockopt,
878 .sendmsg = inet_sendmsg, 878 .sendmsg = inet_sendmsg,
879 .recvmsg = sock_common_recvmsg, 879 .recvmsg = sock_common_recvmsg,
880 .mmap = sock_no_mmap, 880 .mmap = sock_no_mmap,
881#ifdef CONFIG_COMPAT
882 .compat_setsockopt = compat_sock_common_setsockopt,
883 .compat_getsockopt = compat_sock_common_getsockopt,
884#endif
881}; 885};
882 886
883static struct inet_protosw sctpv6_seqpacket_protosw = { 887static struct inet_protosw sctpv6_seqpacket_protosw = {
@@ -911,31 +915,35 @@ static struct inet6_protocol sctpv6_protocol = {
911}; 915};
912 916
913static struct sctp_af sctp_ipv6_specific = { 917static struct sctp_af sctp_ipv6_specific = {
914 .sctp_xmit = sctp_v6_xmit, 918 .sa_family = AF_INET6,
915 .setsockopt = ipv6_setsockopt, 919 .sctp_xmit = sctp_v6_xmit,
916 .getsockopt = ipv6_getsockopt, 920 .setsockopt = ipv6_setsockopt,
917 .get_dst = sctp_v6_get_dst, 921 .getsockopt = ipv6_getsockopt,
918 .get_saddr = sctp_v6_get_saddr, 922 .get_dst = sctp_v6_get_dst,
919 .copy_addrlist = sctp_v6_copy_addrlist, 923 .get_saddr = sctp_v6_get_saddr,
920 .from_skb = sctp_v6_from_skb, 924 .copy_addrlist = sctp_v6_copy_addrlist,
921 .from_sk = sctp_v6_from_sk, 925 .from_skb = sctp_v6_from_skb,
922 .to_sk_saddr = sctp_v6_to_sk_saddr, 926 .from_sk = sctp_v6_from_sk,
923 .to_sk_daddr = sctp_v6_to_sk_daddr, 927 .to_sk_saddr = sctp_v6_to_sk_saddr,
924 .from_addr_param = sctp_v6_from_addr_param, 928 .to_sk_daddr = sctp_v6_to_sk_daddr,
925 .to_addr_param = sctp_v6_to_addr_param, 929 .from_addr_param = sctp_v6_from_addr_param,
926 .dst_saddr = sctp_v6_dst_saddr, 930 .to_addr_param = sctp_v6_to_addr_param,
927 .cmp_addr = sctp_v6_cmp_addr, 931 .dst_saddr = sctp_v6_dst_saddr,
928 .scope = sctp_v6_scope, 932 .cmp_addr = sctp_v6_cmp_addr,
929 .addr_valid = sctp_v6_addr_valid, 933 .scope = sctp_v6_scope,
930 .inaddr_any = sctp_v6_inaddr_any, 934 .addr_valid = sctp_v6_addr_valid,
931 .is_any = sctp_v6_is_any, 935 .inaddr_any = sctp_v6_inaddr_any,
932 .available = sctp_v6_available, 936 .is_any = sctp_v6_is_any,
933 .skb_iif = sctp_v6_skb_iif, 937 .available = sctp_v6_available,
934 .is_ce = sctp_v6_is_ce, 938 .skb_iif = sctp_v6_skb_iif,
935 .seq_dump_addr = sctp_v6_seq_dump_addr, 939 .is_ce = sctp_v6_is_ce,
936 .net_header_len = sizeof(struct ipv6hdr), 940 .seq_dump_addr = sctp_v6_seq_dump_addr,
937 .sockaddr_len = sizeof(struct sockaddr_in6), 941 .net_header_len = sizeof(struct ipv6hdr),
938 .sa_family = AF_INET6, 942 .sockaddr_len = sizeof(struct sockaddr_in6),
943#ifdef CONFIG_COMPAT
944 .compat_setsockopt = compat_ipv6_setsockopt,
945 .compat_getsockopt = compat_ipv6_getsockopt,
946#endif
939}; 947};
940 948
941static struct sctp_pf sctp_pf_inet6_specific = { 949static struct sctp_pf sctp_pf_inet6_specific = {
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index de693b43c8ea..2088aa992b7a 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -831,24 +831,28 @@ static struct notifier_block sctp_inetaddr_notifier = {
831 831
832/* Socket operations. */ 832/* Socket operations. */
833static const struct proto_ops inet_seqpacket_ops = { 833static const struct proto_ops inet_seqpacket_ops = {
834 .family = PF_INET, 834 .family = PF_INET,
835 .owner = THIS_MODULE, 835 .owner = THIS_MODULE,
836 .release = inet_release, /* Needs to be wrapped... */ 836 .release = inet_release, /* Needs to be wrapped... */
837 .bind = inet_bind, 837 .bind = inet_bind,
838 .connect = inet_dgram_connect, 838 .connect = inet_dgram_connect,
839 .socketpair = sock_no_socketpair, 839 .socketpair = sock_no_socketpair,
840 .accept = inet_accept, 840 .accept = inet_accept,
841 .getname = inet_getname, /* Semantics are different. */ 841 .getname = inet_getname, /* Semantics are different. */
842 .poll = sctp_poll, 842 .poll = sctp_poll,
843 .ioctl = inet_ioctl, 843 .ioctl = inet_ioctl,
844 .listen = sctp_inet_listen, 844 .listen = sctp_inet_listen,
845 .shutdown = inet_shutdown, /* Looks harmless. */ 845 .shutdown = inet_shutdown, /* Looks harmless. */
846 .setsockopt = sock_common_setsockopt, /* IP_SOL IP_OPTION is a problem. */ 846 .setsockopt = sock_common_setsockopt, /* IP_SOL IP_OPTION is a problem */
847 .getsockopt = sock_common_getsockopt, 847 .getsockopt = sock_common_getsockopt,
848 .sendmsg = inet_sendmsg, 848 .sendmsg = inet_sendmsg,
849 .recvmsg = sock_common_recvmsg, 849 .recvmsg = sock_common_recvmsg,
850 .mmap = sock_no_mmap, 850 .mmap = sock_no_mmap,
851 .sendpage = sock_no_sendpage, 851 .sendpage = sock_no_sendpage,
852#ifdef CONFIG_COMPAT
853 .compat_setsockopt = compat_sock_common_setsockopt,
854 .compat_getsockopt = compat_sock_common_getsockopt,
855#endif
852}; 856};
853 857
854/* Registration with AF_INET family. */ 858/* Registration with AF_INET family. */
@@ -880,31 +884,35 @@ static struct net_protocol sctp_protocol = {
880 884
881/* IPv4 address related functions. */ 885/* IPv4 address related functions. */
882static struct sctp_af sctp_ipv4_specific = { 886static struct sctp_af sctp_ipv4_specific = {
883 .sctp_xmit = sctp_v4_xmit, 887 .sa_family = AF_INET,
884 .setsockopt = ip_setsockopt, 888 .sctp_xmit = sctp_v4_xmit,
885 .getsockopt = ip_getsockopt, 889 .setsockopt = ip_setsockopt,
886 .get_dst = sctp_v4_get_dst, 890 .getsockopt = ip_getsockopt,
887 .get_saddr = sctp_v4_get_saddr, 891 .get_dst = sctp_v4_get_dst,
888 .copy_addrlist = sctp_v4_copy_addrlist, 892 .get_saddr = sctp_v4_get_saddr,
889 .from_skb = sctp_v4_from_skb, 893 .copy_addrlist = sctp_v4_copy_addrlist,
890 .from_sk = sctp_v4_from_sk, 894 .from_skb = sctp_v4_from_skb,
891 .to_sk_saddr = sctp_v4_to_sk_saddr, 895 .from_sk = sctp_v4_from_sk,
892 .to_sk_daddr = sctp_v4_to_sk_daddr, 896 .to_sk_saddr = sctp_v4_to_sk_saddr,
893 .from_addr_param= sctp_v4_from_addr_param, 897 .to_sk_daddr = sctp_v4_to_sk_daddr,
894 .to_addr_param = sctp_v4_to_addr_param, 898 .from_addr_param = sctp_v4_from_addr_param,
895 .dst_saddr = sctp_v4_dst_saddr, 899 .to_addr_param = sctp_v4_to_addr_param,
896 .cmp_addr = sctp_v4_cmp_addr, 900 .dst_saddr = sctp_v4_dst_saddr,
897 .addr_valid = sctp_v4_addr_valid, 901 .cmp_addr = sctp_v4_cmp_addr,
898 .inaddr_any = sctp_v4_inaddr_any, 902 .addr_valid = sctp_v4_addr_valid,
899 .is_any = sctp_v4_is_any, 903 .inaddr_any = sctp_v4_inaddr_any,
900 .available = sctp_v4_available, 904 .is_any = sctp_v4_is_any,
901 .scope = sctp_v4_scope, 905 .available = sctp_v4_available,
902 .skb_iif = sctp_v4_skb_iif, 906 .scope = sctp_v4_scope,
903 .is_ce = sctp_v4_is_ce, 907 .skb_iif = sctp_v4_skb_iif,
904 .seq_dump_addr = sctp_v4_seq_dump_addr, 908 .is_ce = sctp_v4_is_ce,
905 .net_header_len = sizeof(struct iphdr), 909 .seq_dump_addr = sctp_v4_seq_dump_addr,
906 .sockaddr_len = sizeof(struct sockaddr_in), 910 .net_header_len = sizeof(struct iphdr),
907 .sa_family = AF_INET, 911 .sockaddr_len = sizeof(struct sockaddr_in),
912#ifdef CONFIG_COMPAT
913 .compat_setsockopt = compat_ip_setsockopt,
914 .compat_getsockopt = compat_ip_getsockopt,
915#endif
908}; 916};
909 917
910struct sctp_pf *sctp_get_pf_specific(sa_family_t family) { 918struct sctp_pf *sctp_get_pf_specific(sa_family_t family) {
diff --git a/net/socket.c b/net/socket.c
index 7e1bdef8b09e..e2d5bae994de 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -68,6 +68,7 @@
68#include <linux/netdevice.h> 68#include <linux/netdevice.h>
69#include <linux/proc_fs.h> 69#include <linux/proc_fs.h>
70#include <linux/seq_file.h> 70#include <linux/seq_file.h>
71#include <linux/mutex.h>
71#include <linux/wanrouter.h> 72#include <linux/wanrouter.h>
72#include <linux/if_bridge.h> 73#include <linux/if_bridge.h>
73#include <linux/if_frad.h> 74#include <linux/if_frad.h>
@@ -106,6 +107,10 @@ static unsigned int sock_poll(struct file *file,
106 struct poll_table_struct *wait); 107 struct poll_table_struct *wait);
107static long sock_ioctl(struct file *file, 108static long sock_ioctl(struct file *file,
108 unsigned int cmd, unsigned long arg); 109 unsigned int cmd, unsigned long arg);
110#ifdef CONFIG_COMPAT
111static long compat_sock_ioctl(struct file *file,
112 unsigned int cmd, unsigned long arg);
113#endif
109static int sock_fasync(int fd, struct file *filp, int on); 114static int sock_fasync(int fd, struct file *filp, int on);
110static ssize_t sock_readv(struct file *file, const struct iovec *vector, 115static ssize_t sock_readv(struct file *file, const struct iovec *vector,
111 unsigned long count, loff_t *ppos); 116 unsigned long count, loff_t *ppos);
@@ -127,6 +132,9 @@ static struct file_operations socket_file_ops = {
127 .aio_write = sock_aio_write, 132 .aio_write = sock_aio_write,
128 .poll = sock_poll, 133 .poll = sock_poll,
129 .unlocked_ioctl = sock_ioctl, 134 .unlocked_ioctl = sock_ioctl,
135#ifdef CONFIG_COMPAT
136 .compat_ioctl = compat_sock_ioctl,
137#endif
130 .mmap = sock_mmap, 138 .mmap = sock_mmap,
131 .open = sock_no_open, /* special open code to disallow open via /proc */ 139 .open = sock_no_open, /* special open code to disallow open via /proc */
132 .release = sock_close, 140 .release = sock_close,
@@ -348,8 +356,8 @@ static struct dentry_operations sockfs_dentry_operations = {
348/* 356/*
349 * Obtains the first available file descriptor and sets it up for use. 357 * Obtains the first available file descriptor and sets it up for use.
350 * 358 *
351 * This function creates file structure and maps it to fd space 359 * These functions create file structures and maps them to fd space
352 * of current process. On success it returns file descriptor 360 * of the current process. On success it returns file descriptor
353 * and file struct implicitly stored in sock->file. 361 * and file struct implicitly stored in sock->file.
354 * Note that another thread may close file descriptor before we return 362 * Note that another thread may close file descriptor before we return
355 * from this function. We use the fact that now we do not refer 363 * from this function. We use the fact that now we do not refer
@@ -362,53 +370,90 @@ static struct dentry_operations sockfs_dentry_operations = {
362 * but we take care of internal coherence yet. 370 * but we take care of internal coherence yet.
363 */ 371 */
364 372
365int sock_map_fd(struct socket *sock) 373static int sock_alloc_fd(struct file **filep)
366{ 374{
367 int fd; 375 int fd;
368 struct qstr this;
369 char name[32];
370
371 /*
372 * Find a file descriptor suitable for return to the user.
373 */
374 376
375 fd = get_unused_fd(); 377 fd = get_unused_fd();
376 if (fd >= 0) { 378 if (likely(fd >= 0)) {
377 struct file *file = get_empty_filp(); 379 struct file *file = get_empty_filp();
378 380
379 if (!file) { 381 *filep = file;
382 if (unlikely(!file)) {
380 put_unused_fd(fd); 383 put_unused_fd(fd);
381 fd = -ENFILE; 384 return -ENFILE;
382 goto out;
383 } 385 }
386 } else
387 *filep = NULL;
388 return fd;
389}
390
391static int sock_attach_fd(struct socket *sock, struct file *file)
392{
393 struct qstr this;
394 char name[32];
384 395
385 this.len = sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino); 396 this.len = sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino);
386 this.name = name; 397 this.name = name;
387 this.hash = SOCK_INODE(sock)->i_ino; 398 this.hash = SOCK_INODE(sock)->i_ino;
388 399
389 file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this); 400 file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this);
390 if (!file->f_dentry) { 401 if (unlikely(!file->f_dentry))
391 put_filp(file); 402 return -ENOMEM;
403
404 file->f_dentry->d_op = &sockfs_dentry_operations;
405 d_add(file->f_dentry, SOCK_INODE(sock));
406 file->f_vfsmnt = mntget(sock_mnt);
407 file->f_mapping = file->f_dentry->d_inode->i_mapping;
408
409 sock->file = file;
410 file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops;
411 file->f_mode = FMODE_READ | FMODE_WRITE;
412 file->f_flags = O_RDWR;
413 file->f_pos = 0;
414 file->private_data = sock;
415
416 return 0;
417}
418
419int sock_map_fd(struct socket *sock)
420{
421 struct file *newfile;
422 int fd = sock_alloc_fd(&newfile);
423
424 if (likely(fd >= 0)) {
425 int err = sock_attach_fd(sock, newfile);
426
427 if (unlikely(err < 0)) {
428 put_filp(newfile);
392 put_unused_fd(fd); 429 put_unused_fd(fd);
393 fd = -ENOMEM; 430 return err;
394 goto out;
395 } 431 }
396 file->f_dentry->d_op = &sockfs_dentry_operations; 432 fd_install(fd, newfile);
397 d_add(file->f_dentry, SOCK_INODE(sock)); 433 }
398 file->f_vfsmnt = mntget(sock_mnt); 434 return fd;
399 file->f_mapping = file->f_dentry->d_inode->i_mapping; 435}
400 436
401 sock->file = file; 437static struct socket *sock_from_file(struct file *file, int *err)
402 file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops; 438{
403 file->f_mode = FMODE_READ | FMODE_WRITE; 439 struct inode *inode;
404 file->f_flags = O_RDWR; 440 struct socket *sock;
405 file->f_pos = 0; 441
406 file->private_data = sock; 442 if (file->f_op == &socket_file_ops)
407 fd_install(fd, file); 443 return file->private_data; /* set in sock_map_fd */
444
445 inode = file->f_dentry->d_inode;
446 if (!S_ISSOCK(inode->i_mode)) {
447 *err = -ENOTSOCK;
448 return NULL;
408 } 449 }
409 450
410out: 451 sock = SOCKET_I(inode);
411 return fd; 452 if (sock->file != file) {
453 printk(KERN_ERR "socki_lookup: socket file changed!\n");
454 sock->file = file;
455 }
456 return sock;
412} 457}
413 458
414/** 459/**
@@ -427,31 +472,31 @@ out:
427struct socket *sockfd_lookup(int fd, int *err) 472struct socket *sockfd_lookup(int fd, int *err)
428{ 473{
429 struct file *file; 474 struct file *file;
430 struct inode *inode;
431 struct socket *sock; 475 struct socket *sock;
432 476
433 if (!(file = fget(fd))) 477 if (!(file = fget(fd))) {
434 {
435 *err = -EBADF; 478 *err = -EBADF;
436 return NULL; 479 return NULL;
437 } 480 }
438 481 sock = sock_from_file(file, err);
439 if (file->f_op == &socket_file_ops) 482 if (!sock)
440 return file->private_data; /* set in sock_map_fd */
441
442 inode = file->f_dentry->d_inode;
443 if (!S_ISSOCK(inode->i_mode)) {
444 *err = -ENOTSOCK;
445 fput(file); 483 fput(file);
446 return NULL; 484 return sock;
447 } 485}
448 486
449 sock = SOCKET_I(inode); 487static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
450 if (sock->file != file) { 488{
451 printk(KERN_ERR "socki_lookup: socket file changed!\n"); 489 struct file *file;
452 sock->file = file; 490 struct socket *sock;
491
492 file = fget_light(fd, fput_needed);
493 if (file) {
494 sock = sock_from_file(file, err);
495 if (sock)
496 return sock;
497 fput_light(file, *fput_needed);
453 } 498 }
454 return sock; 499 return NULL;
455} 500}
456 501
457/** 502/**
@@ -789,36 +834,36 @@ static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf,
789 * with module unload. 834 * with module unload.
790 */ 835 */
791 836
792static DECLARE_MUTEX(br_ioctl_mutex); 837static DEFINE_MUTEX(br_ioctl_mutex);
793static int (*br_ioctl_hook)(unsigned int cmd, void __user *arg) = NULL; 838static int (*br_ioctl_hook)(unsigned int cmd, void __user *arg) = NULL;
794 839
795void brioctl_set(int (*hook)(unsigned int, void __user *)) 840void brioctl_set(int (*hook)(unsigned int, void __user *))
796{ 841{
797 down(&br_ioctl_mutex); 842 mutex_lock(&br_ioctl_mutex);
798 br_ioctl_hook = hook; 843 br_ioctl_hook = hook;
799 up(&br_ioctl_mutex); 844 mutex_unlock(&br_ioctl_mutex);
800} 845}
801EXPORT_SYMBOL(brioctl_set); 846EXPORT_SYMBOL(brioctl_set);
802 847
803static DECLARE_MUTEX(vlan_ioctl_mutex); 848static DEFINE_MUTEX(vlan_ioctl_mutex);
804static int (*vlan_ioctl_hook)(void __user *arg); 849static int (*vlan_ioctl_hook)(void __user *arg);
805 850
806void vlan_ioctl_set(int (*hook)(void __user *)) 851void vlan_ioctl_set(int (*hook)(void __user *))
807{ 852{
808 down(&vlan_ioctl_mutex); 853 mutex_lock(&vlan_ioctl_mutex);
809 vlan_ioctl_hook = hook; 854 vlan_ioctl_hook = hook;
810 up(&vlan_ioctl_mutex); 855 mutex_unlock(&vlan_ioctl_mutex);
811} 856}
812EXPORT_SYMBOL(vlan_ioctl_set); 857EXPORT_SYMBOL(vlan_ioctl_set);
813 858
814static DECLARE_MUTEX(dlci_ioctl_mutex); 859static DEFINE_MUTEX(dlci_ioctl_mutex);
815static int (*dlci_ioctl_hook)(unsigned int, void __user *); 860static int (*dlci_ioctl_hook)(unsigned int, void __user *);
816 861
817void dlci_ioctl_set(int (*hook)(unsigned int, void __user *)) 862void dlci_ioctl_set(int (*hook)(unsigned int, void __user *))
818{ 863{
819 down(&dlci_ioctl_mutex); 864 mutex_lock(&dlci_ioctl_mutex);
820 dlci_ioctl_hook = hook; 865 dlci_ioctl_hook = hook;
821 up(&dlci_ioctl_mutex); 866 mutex_unlock(&dlci_ioctl_mutex);
822} 867}
823EXPORT_SYMBOL(dlci_ioctl_set); 868EXPORT_SYMBOL(dlci_ioctl_set);
824 869
@@ -862,10 +907,10 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
862 if (!br_ioctl_hook) 907 if (!br_ioctl_hook)
863 request_module("bridge"); 908 request_module("bridge");
864 909
865 down(&br_ioctl_mutex); 910 mutex_lock(&br_ioctl_mutex);
866 if (br_ioctl_hook) 911 if (br_ioctl_hook)
867 err = br_ioctl_hook(cmd, argp); 912 err = br_ioctl_hook(cmd, argp);
868 up(&br_ioctl_mutex); 913 mutex_unlock(&br_ioctl_mutex);
869 break; 914 break;
870 case SIOCGIFVLAN: 915 case SIOCGIFVLAN:
871 case SIOCSIFVLAN: 916 case SIOCSIFVLAN:
@@ -873,10 +918,10 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
873 if (!vlan_ioctl_hook) 918 if (!vlan_ioctl_hook)
874 request_module("8021q"); 919 request_module("8021q");
875 920
876 down(&vlan_ioctl_mutex); 921 mutex_lock(&vlan_ioctl_mutex);
877 if (vlan_ioctl_hook) 922 if (vlan_ioctl_hook)
878 err = vlan_ioctl_hook(argp); 923 err = vlan_ioctl_hook(argp);
879 up(&vlan_ioctl_mutex); 924 mutex_unlock(&vlan_ioctl_mutex);
880 break; 925 break;
881 case SIOCGIFDIVERT: 926 case SIOCGIFDIVERT:
882 case SIOCSIFDIVERT: 927 case SIOCSIFDIVERT:
@@ -890,9 +935,9 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
890 request_module("dlci"); 935 request_module("dlci");
891 936
892 if (dlci_ioctl_hook) { 937 if (dlci_ioctl_hook) {
893 down(&dlci_ioctl_mutex); 938 mutex_lock(&dlci_ioctl_mutex);
894 err = dlci_ioctl_hook(cmd, argp); 939 err = dlci_ioctl_hook(cmd, argp);
895 up(&dlci_ioctl_mutex); 940 mutex_unlock(&dlci_ioctl_mutex);
896 } 941 }
897 break; 942 break;
898 default: 943 default:
@@ -1286,19 +1331,17 @@ asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
1286{ 1331{
1287 struct socket *sock; 1332 struct socket *sock;
1288 char address[MAX_SOCK_ADDR]; 1333 char address[MAX_SOCK_ADDR];
1289 int err; 1334 int err, fput_needed;
1290 1335
1291 if((sock = sockfd_lookup(fd,&err))!=NULL) 1336 if((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL)
1292 { 1337 {
1293 if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) { 1338 if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) {
1294 err = security_socket_bind(sock, (struct sockaddr *)address, addrlen); 1339 err = security_socket_bind(sock, (struct sockaddr *)address, addrlen);
1295 if (err) { 1340 if (!err)
1296 sockfd_put(sock); 1341 err = sock->ops->bind(sock,
1297 return err; 1342 (struct sockaddr *)address, addrlen);
1298 }
1299 err = sock->ops->bind(sock, (struct sockaddr *)address, addrlen);
1300 } 1343 }
1301 sockfd_put(sock); 1344 fput_light(sock->file, fput_needed);
1302 } 1345 }
1303 return err; 1346 return err;
1304} 1347}
@@ -1315,20 +1358,17 @@ int sysctl_somaxconn = SOMAXCONN;
1315asmlinkage long sys_listen(int fd, int backlog) 1358asmlinkage long sys_listen(int fd, int backlog)
1316{ 1359{
1317 struct socket *sock; 1360 struct socket *sock;
1318 int err; 1361 int err, fput_needed;
1319 1362
1320 if ((sock = sockfd_lookup(fd, &err)) != NULL) { 1363 if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
1321 if ((unsigned) backlog > sysctl_somaxconn) 1364 if ((unsigned) backlog > sysctl_somaxconn)
1322 backlog = sysctl_somaxconn; 1365 backlog = sysctl_somaxconn;
1323 1366
1324 err = security_socket_listen(sock, backlog); 1367 err = security_socket_listen(sock, backlog);
1325 if (err) { 1368 if (!err)
1326 sockfd_put(sock); 1369 err = sock->ops->listen(sock, backlog);
1327 return err;
1328 }
1329 1370
1330 err=sock->ops->listen(sock, backlog); 1371 fput_light(sock->file, fput_needed);
1331 sockfd_put(sock);
1332 } 1372 }
1333 return err; 1373 return err;
1334} 1374}
@@ -1349,10 +1389,11 @@ asmlinkage long sys_listen(int fd, int backlog)
1349asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen) 1389asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen)
1350{ 1390{
1351 struct socket *sock, *newsock; 1391 struct socket *sock, *newsock;
1352 int err, len; 1392 struct file *newfile;
1393 int err, len, newfd, fput_needed;
1353 char address[MAX_SOCK_ADDR]; 1394 char address[MAX_SOCK_ADDR];
1354 1395
1355 sock = sockfd_lookup(fd, &err); 1396 sock = sockfd_lookup_light(fd, &err, &fput_needed);
1356 if (!sock) 1397 if (!sock)
1357 goto out; 1398 goto out;
1358 1399
@@ -1369,35 +1410,48 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _
1369 */ 1410 */
1370 __module_get(newsock->ops->owner); 1411 __module_get(newsock->ops->owner);
1371 1412
1413 newfd = sock_alloc_fd(&newfile);
1414 if (unlikely(newfd < 0)) {
1415 err = newfd;
1416 goto out_release;
1417 }
1418
1419 err = sock_attach_fd(newsock, newfile);
1420 if (err < 0)
1421 goto out_fd;
1422
1372 err = security_socket_accept(sock, newsock); 1423 err = security_socket_accept(sock, newsock);
1373 if (err) 1424 if (err)
1374 goto out_release; 1425 goto out_fd;
1375 1426
1376 err = sock->ops->accept(sock, newsock, sock->file->f_flags); 1427 err = sock->ops->accept(sock, newsock, sock->file->f_flags);
1377 if (err < 0) 1428 if (err < 0)
1378 goto out_release; 1429 goto out_fd;
1379 1430
1380 if (upeer_sockaddr) { 1431 if (upeer_sockaddr) {
1381 if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) { 1432 if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) {
1382 err = -ECONNABORTED; 1433 err = -ECONNABORTED;
1383 goto out_release; 1434 goto out_fd;
1384 } 1435 }
1385 err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen); 1436 err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen);
1386 if (err < 0) 1437 if (err < 0)
1387 goto out_release; 1438 goto out_fd;
1388 } 1439 }
1389 1440
1390 /* File flags are not inherited via accept() unlike another OSes. */ 1441 /* File flags are not inherited via accept() unlike another OSes. */
1391 1442
1392 if ((err = sock_map_fd(newsock)) < 0) 1443 fd_install(newfd, newfile);
1393 goto out_release; 1444 err = newfd;
1394 1445
1395 security_socket_post_accept(sock, newsock); 1446 security_socket_post_accept(sock, newsock);
1396 1447
1397out_put: 1448out_put:
1398 sockfd_put(sock); 1449 fput_light(sock->file, fput_needed);
1399out: 1450out:
1400 return err; 1451 return err;
1452out_fd:
1453 put_filp(newfile);
1454 put_unused_fd(newfd);
1401out_release: 1455out_release:
1402 sock_release(newsock); 1456 sock_release(newsock);
1403 goto out_put; 1457 goto out_put;
@@ -1420,9 +1474,9 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrl
1420{ 1474{
1421 struct socket *sock; 1475 struct socket *sock;
1422 char address[MAX_SOCK_ADDR]; 1476 char address[MAX_SOCK_ADDR];
1423 int err; 1477 int err, fput_needed;
1424 1478
1425 sock = sockfd_lookup(fd, &err); 1479 sock = sockfd_lookup_light(fd, &err, &fput_needed);
1426 if (!sock) 1480 if (!sock)
1427 goto out; 1481 goto out;
1428 err = move_addr_to_kernel(uservaddr, addrlen, address); 1482 err = move_addr_to_kernel(uservaddr, addrlen, address);
@@ -1436,7 +1490,7 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrl
1436 err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen, 1490 err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen,
1437 sock->file->f_flags); 1491 sock->file->f_flags);
1438out_put: 1492out_put:
1439 sockfd_put(sock); 1493 fput_light(sock->file, fput_needed);
1440out: 1494out:
1441 return err; 1495 return err;
1442} 1496}
@@ -1450,9 +1504,9 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int _
1450{ 1504{
1451 struct socket *sock; 1505 struct socket *sock;
1452 char address[MAX_SOCK_ADDR]; 1506 char address[MAX_SOCK_ADDR];
1453 int len, err; 1507 int len, err, fput_needed;
1454 1508
1455 sock = sockfd_lookup(fd, &err); 1509 sock = sockfd_lookup_light(fd, &err, &fput_needed);
1456 if (!sock) 1510 if (!sock)
1457 goto out; 1511 goto out;
1458 1512
@@ -1466,7 +1520,7 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int _
1466 err = move_addr_to_user(address, len, usockaddr, usockaddr_len); 1520 err = move_addr_to_user(address, len, usockaddr, usockaddr_len);
1467 1521
1468out_put: 1522out_put:
1469 sockfd_put(sock); 1523 fput_light(sock->file, fput_needed);
1470out: 1524out:
1471 return err; 1525 return err;
1472} 1526}
@@ -1480,20 +1534,19 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int _
1480{ 1534{
1481 struct socket *sock; 1535 struct socket *sock;
1482 char address[MAX_SOCK_ADDR]; 1536 char address[MAX_SOCK_ADDR];
1483 int len, err; 1537 int len, err, fput_needed;
1484 1538
1485 if ((sock = sockfd_lookup(fd, &err))!=NULL) 1539 if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
1486 {
1487 err = security_socket_getpeername(sock); 1540 err = security_socket_getpeername(sock);
1488 if (err) { 1541 if (err) {
1489 sockfd_put(sock); 1542 fput_light(sock->file, fput_needed);
1490 return err; 1543 return err;
1491 } 1544 }
1492 1545
1493 err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1); 1546 err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1);
1494 if (!err) 1547 if (!err)
1495 err=move_addr_to_user(address,len, usockaddr, usockaddr_len); 1548 err=move_addr_to_user(address,len, usockaddr, usockaddr_len);
1496 sockfd_put(sock); 1549 fput_light(sock->file, fput_needed);
1497 } 1550 }
1498 return err; 1551 return err;
1499} 1552}
@@ -1512,10 +1565,16 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag
1512 int err; 1565 int err;
1513 struct msghdr msg; 1566 struct msghdr msg;
1514 struct iovec iov; 1567 struct iovec iov;
1515 1568 int fput_needed;
1516 sock = sockfd_lookup(fd, &err); 1569 struct file *sock_file;
1570
1571 sock_file = fget_light(fd, &fput_needed);
1572 if (!sock_file)
1573 return -EBADF;
1574
1575 sock = sock_from_file(sock_file, &err);
1517 if (!sock) 1576 if (!sock)
1518 goto out; 1577 goto out_put;
1519 iov.iov_base=buff; 1578 iov.iov_base=buff;
1520 iov.iov_len=len; 1579 iov.iov_len=len;
1521 msg.msg_name=NULL; 1580 msg.msg_name=NULL;
@@ -1524,8 +1583,7 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag
1524 msg.msg_control=NULL; 1583 msg.msg_control=NULL;
1525 msg.msg_controllen=0; 1584 msg.msg_controllen=0;
1526 msg.msg_namelen=0; 1585 msg.msg_namelen=0;
1527 if(addr) 1586 if (addr) {
1528 {
1529 err = move_addr_to_kernel(addr, addr_len, address); 1587 err = move_addr_to_kernel(addr, addr_len, address);
1530 if (err < 0) 1588 if (err < 0)
1531 goto out_put; 1589 goto out_put;
@@ -1538,8 +1596,7 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag
1538 err = sock_sendmsg(sock, &msg, len); 1596 err = sock_sendmsg(sock, &msg, len);
1539 1597
1540out_put: 1598out_put:
1541 sockfd_put(sock); 1599 fput_light(sock_file, fput_needed);
1542out:
1543 return err; 1600 return err;
1544} 1601}
1545 1602
@@ -1566,8 +1623,14 @@ asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned f
1566 struct msghdr msg; 1623 struct msghdr msg;
1567 char address[MAX_SOCK_ADDR]; 1624 char address[MAX_SOCK_ADDR];
1568 int err,err2; 1625 int err,err2;
1626 struct file *sock_file;
1627 int fput_needed;
1628
1629 sock_file = fget_light(fd, &fput_needed);
1630 if (!sock_file)
1631 return -EBADF;
1569 1632
1570 sock = sockfd_lookup(fd, &err); 1633 sock = sock_from_file(sock_file, &err);
1571 if (!sock) 1634 if (!sock)
1572 goto out; 1635 goto out;
1573 1636
@@ -1589,8 +1652,8 @@ asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned f
1589 if(err2<0) 1652 if(err2<0)
1590 err=err2; 1653 err=err2;
1591 } 1654 }
1592 sockfd_put(sock);
1593out: 1655out:
1656 fput_light(sock_file, fput_needed);
1594 return err; 1657 return err;
1595} 1658}
1596 1659
@@ -1610,25 +1673,24 @@ asmlinkage long sys_recv(int fd, void __user * ubuf, size_t size, unsigned flags
1610 1673
1611asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen) 1674asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen)
1612{ 1675{
1613 int err; 1676 int err, fput_needed;
1614 struct socket *sock; 1677 struct socket *sock;
1615 1678
1616 if (optlen < 0) 1679 if (optlen < 0)
1617 return -EINVAL; 1680 return -EINVAL;
1618 1681
1619 if ((sock = sockfd_lookup(fd, &err))!=NULL) 1682 if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL)
1620 { 1683 {
1621 err = security_socket_setsockopt(sock,level,optname); 1684 err = security_socket_setsockopt(sock,level,optname);
1622 if (err) { 1685 if (err)
1623 sockfd_put(sock); 1686 goto out_put;
1624 return err;
1625 }
1626 1687
1627 if (level == SOL_SOCKET) 1688 if (level == SOL_SOCKET)
1628 err=sock_setsockopt(sock,level,optname,optval,optlen); 1689 err=sock_setsockopt(sock,level,optname,optval,optlen);
1629 else 1690 else
1630 err=sock->ops->setsockopt(sock, level, optname, optval, optlen); 1691 err=sock->ops->setsockopt(sock, level, optname, optval, optlen);
1631 sockfd_put(sock); 1692out_put:
1693 fput_light(sock->file, fput_needed);
1632 } 1694 }
1633 return err; 1695 return err;
1634} 1696}
@@ -1640,23 +1702,20 @@ asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optv
1640 1702
1641asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen) 1703asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen)
1642{ 1704{
1643 int err; 1705 int err, fput_needed;
1644 struct socket *sock; 1706 struct socket *sock;
1645 1707
1646 if ((sock = sockfd_lookup(fd, &err))!=NULL) 1708 if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
1647 { 1709 err = security_socket_getsockopt(sock, level, optname);
1648 err = security_socket_getsockopt(sock, level, 1710 if (err)
1649 optname); 1711 goto out_put;
1650 if (err) {
1651 sockfd_put(sock);
1652 return err;
1653 }
1654 1712
1655 if (level == SOL_SOCKET) 1713 if (level == SOL_SOCKET)
1656 err=sock_getsockopt(sock,level,optname,optval,optlen); 1714 err=sock_getsockopt(sock,level,optname,optval,optlen);
1657 else 1715 else
1658 err=sock->ops->getsockopt(sock, level, optname, optval, optlen); 1716 err=sock->ops->getsockopt(sock, level, optname, optval, optlen);
1659 sockfd_put(sock); 1717out_put:
1718 fput_light(sock->file, fput_needed);
1660 } 1719 }
1661 return err; 1720 return err;
1662} 1721}
@@ -1668,19 +1727,15 @@ asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optv
1668 1727
1669asmlinkage long sys_shutdown(int fd, int how) 1728asmlinkage long sys_shutdown(int fd, int how)
1670{ 1729{
1671 int err; 1730 int err, fput_needed;
1672 struct socket *sock; 1731 struct socket *sock;
1673 1732
1674 if ((sock = sockfd_lookup(fd, &err))!=NULL) 1733 if ((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL)
1675 { 1734 {
1676 err = security_socket_shutdown(sock, how); 1735 err = security_socket_shutdown(sock, how);
1677 if (err) { 1736 if (!err)
1678 sockfd_put(sock); 1737 err = sock->ops->shutdown(sock, how);
1679 return err; 1738 fput_light(sock->file, fput_needed);
1680 }
1681
1682 err=sock->ops->shutdown(sock, how);
1683 sockfd_put(sock);
1684 } 1739 }
1685 return err; 1740 return err;
1686} 1741}
@@ -1709,6 +1764,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
1709 unsigned char *ctl_buf = ctl; 1764 unsigned char *ctl_buf = ctl;
1710 struct msghdr msg_sys; 1765 struct msghdr msg_sys;
1711 int err, ctl_len, iov_size, total_len; 1766 int err, ctl_len, iov_size, total_len;
1767 int fput_needed;
1712 1768
1713 err = -EFAULT; 1769 err = -EFAULT;
1714 if (MSG_CMSG_COMPAT & flags) { 1770 if (MSG_CMSG_COMPAT & flags) {
@@ -1717,7 +1773,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
1717 } else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr))) 1773 } else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
1718 return -EFAULT; 1774 return -EFAULT;
1719 1775
1720 sock = sockfd_lookup(fd, &err); 1776 sock = sockfd_lookup_light(fd, &err, &fput_needed);
1721 if (!sock) 1777 if (!sock)
1722 goto out; 1778 goto out;
1723 1779
@@ -1785,7 +1841,7 @@ out_freeiov:
1785 if (iov != iovstack) 1841 if (iov != iovstack)
1786 sock_kfree_s(sock->sk, iov, iov_size); 1842 sock_kfree_s(sock->sk, iov, iov_size);
1787out_put: 1843out_put:
1788 sockfd_put(sock); 1844 fput_light(sock->file, fput_needed);
1789out: 1845out:
1790 return err; 1846 return err;
1791} 1847}
@@ -1803,6 +1859,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flag
1803 struct msghdr msg_sys; 1859 struct msghdr msg_sys;
1804 unsigned long cmsg_ptr; 1860 unsigned long cmsg_ptr;
1805 int err, iov_size, total_len, len; 1861 int err, iov_size, total_len, len;
1862 int fput_needed;
1806 1863
1807 /* kernel mode address */ 1864 /* kernel mode address */
1808 char addr[MAX_SOCK_ADDR]; 1865 char addr[MAX_SOCK_ADDR];
@@ -1818,7 +1875,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flag
1818 if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr))) 1875 if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
1819 return -EFAULT; 1876 return -EFAULT;
1820 1877
1821 sock = sockfd_lookup(fd, &err); 1878 sock = sockfd_lookup_light(fd, &err, &fput_needed);
1822 if (!sock) 1879 if (!sock)
1823 goto out; 1880 goto out;
1824 1881
@@ -1885,7 +1942,7 @@ out_freeiov:
1885 if (iov != iovstack) 1942 if (iov != iovstack)
1886 sock_kfree_s(sock->sk, iov, iov_size); 1943 sock_kfree_s(sock->sk, iov, iov_size);
1887out_put: 1944out_put:
1888 sockfd_put(sock); 1945 fput_light(sock->file, fput_needed);
1889out: 1946out:
1890 return err; 1947 return err;
1891} 1948}
@@ -2086,6 +2143,20 @@ void socket_seq_show(struct seq_file *seq)
2086} 2143}
2087#endif /* CONFIG_PROC_FS */ 2144#endif /* CONFIG_PROC_FS */
2088 2145
2146#ifdef CONFIG_COMPAT
2147static long compat_sock_ioctl(struct file *file, unsigned cmd,
2148 unsigned long arg)
2149{
2150 struct socket *sock = file->private_data;
2151 int ret = -ENOIOCTLCMD;
2152
2153 if (sock->ops->compat_ioctl)
2154 ret = sock->ops->compat_ioctl(sock, cmd, arg);
2155
2156 return ret;
2157}
2158#endif
2159
2089/* ABI emulation layers need these two */ 2160/* ABI emulation layers need these two */
2090EXPORT_SYMBOL(move_addr_to_kernel); 2161EXPORT_SYMBOL(move_addr_to_kernel);
2091EXPORT_SYMBOL(move_addr_to_user); 2162EXPORT_SYMBOL(move_addr_to_user);
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index dcaa0c4453ff..0acccfeeb284 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -26,6 +26,7 @@
26#include <linux/proc_fs.h> 26#include <linux/proc_fs.h>
27#include <linux/net.h> 27#include <linux/net.h>
28#include <linux/workqueue.h> 28#include <linux/workqueue.h>
29#include <linux/mutex.h>
29#include <asm/ioctls.h> 30#include <asm/ioctls.h>
30#include <linux/sunrpc/types.h> 31#include <linux/sunrpc/types.h>
31#include <linux/sunrpc/cache.h> 32#include <linux/sunrpc/cache.h>
@@ -532,7 +533,7 @@ void cache_clean_deferred(void *owner)
532 */ 533 */
533 534
534static DEFINE_SPINLOCK(queue_lock); 535static DEFINE_SPINLOCK(queue_lock);
535static DECLARE_MUTEX(queue_io_sem); 536static DEFINE_MUTEX(queue_io_mutex);
536 537
537struct cache_queue { 538struct cache_queue {
538 struct list_head list; 539 struct list_head list;
@@ -561,7 +562,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
561 if (count == 0) 562 if (count == 0)
562 return 0; 563 return 0;
563 564
564 down(&queue_io_sem); /* protect against multiple concurrent 565 mutex_lock(&queue_io_mutex); /* protect against multiple concurrent
565 * readers on this file */ 566 * readers on this file */
566 again: 567 again:
567 spin_lock(&queue_lock); 568 spin_lock(&queue_lock);
@@ -574,7 +575,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
574 } 575 }
575 if (rp->q.list.next == &cd->queue) { 576 if (rp->q.list.next == &cd->queue) {
576 spin_unlock(&queue_lock); 577 spin_unlock(&queue_lock);
577 up(&queue_io_sem); 578 mutex_unlock(&queue_io_mutex);
578 BUG_ON(rp->offset); 579 BUG_ON(rp->offset);
579 return 0; 580 return 0;
580 } 581 }
@@ -621,11 +622,11 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
621 } 622 }
622 if (err == -EAGAIN) 623 if (err == -EAGAIN)
623 goto again; 624 goto again;
624 up(&queue_io_sem); 625 mutex_unlock(&queue_io_mutex);
625 return err ? err : count; 626 return err ? err : count;
626} 627}
627 628
628static char write_buf[8192]; /* protected by queue_io_sem */ 629static char write_buf[8192]; /* protected by queue_io_mutex */
629 630
630static ssize_t 631static ssize_t
631cache_write(struct file *filp, const char __user *buf, size_t count, 632cache_write(struct file *filp, const char __user *buf, size_t count,
@@ -639,10 +640,10 @@ cache_write(struct file *filp, const char __user *buf, size_t count,
639 if (count >= sizeof(write_buf)) 640 if (count >= sizeof(write_buf))
640 return -EINVAL; 641 return -EINVAL;
641 642
642 down(&queue_io_sem); 643 mutex_lock(&queue_io_mutex);
643 644
644 if (copy_from_user(write_buf, buf, count)) { 645 if (copy_from_user(write_buf, buf, count)) {
645 up(&queue_io_sem); 646 mutex_unlock(&queue_io_mutex);
646 return -EFAULT; 647 return -EFAULT;
647 } 648 }
648 write_buf[count] = '\0'; 649 write_buf[count] = '\0';
@@ -651,7 +652,7 @@ cache_write(struct file *filp, const char __user *buf, size_t count,
651 else 652 else
652 err = -EINVAL; 653 err = -EINVAL;
653 654
654 up(&queue_io_sem); 655 mutex_unlock(&queue_io_mutex);
655 return err ? err : count; 656 return err ? err : count;
656} 657}
657 658
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 3fc13bea302d..b9969b91a9f7 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -18,6 +18,7 @@
18#include <linux/smp.h> 18#include <linux/smp.h>
19#include <linux/smp_lock.h> 19#include <linux/smp_lock.h>
20#include <linux/spinlock.h> 20#include <linux/spinlock.h>
21#include <linux/mutex.h>
21 22
22#include <linux/sunrpc/clnt.h> 23#include <linux/sunrpc/clnt.h>
23#include <linux/sunrpc/xprt.h> 24#include <linux/sunrpc/xprt.h>
@@ -62,7 +63,7 @@ static LIST_HEAD(all_tasks);
62/* 63/*
63 * rpciod-related stuff 64 * rpciod-related stuff
64 */ 65 */
65static DECLARE_MUTEX(rpciod_sema); 66static DEFINE_MUTEX(rpciod_mutex);
66static unsigned int rpciod_users; 67static unsigned int rpciod_users;
67struct workqueue_struct *rpciod_workqueue; 68struct workqueue_struct *rpciod_workqueue;
68 69
@@ -1055,7 +1056,7 @@ rpciod_up(void)
1055 struct workqueue_struct *wq; 1056 struct workqueue_struct *wq;
1056 int error = 0; 1057 int error = 0;
1057 1058
1058 down(&rpciod_sema); 1059 mutex_lock(&rpciod_mutex);
1059 dprintk("rpciod_up: users %d\n", rpciod_users); 1060 dprintk("rpciod_up: users %d\n", rpciod_users);
1060 rpciod_users++; 1061 rpciod_users++;
1061 if (rpciod_workqueue) 1062 if (rpciod_workqueue)
@@ -1078,14 +1079,14 @@ rpciod_up(void)
1078 rpciod_workqueue = wq; 1079 rpciod_workqueue = wq;
1079 error = 0; 1080 error = 0;
1080out: 1081out:
1081 up(&rpciod_sema); 1082 mutex_unlock(&rpciod_mutex);
1082 return error; 1083 return error;
1083} 1084}
1084 1085
1085void 1086void
1086rpciod_down(void) 1087rpciod_down(void)
1087{ 1088{
1088 down(&rpciod_sema); 1089 mutex_lock(&rpciod_mutex);
1089 dprintk("rpciod_down sema %d\n", rpciod_users); 1090 dprintk("rpciod_down sema %d\n", rpciod_users);
1090 if (rpciod_users) { 1091 if (rpciod_users) {
1091 if (--rpciod_users) 1092 if (--rpciod_users)
@@ -1102,7 +1103,7 @@ rpciod_down(void)
1102 destroy_workqueue(rpciod_workqueue); 1103 destroy_workqueue(rpciod_workqueue);
1103 rpciod_workqueue = NULL; 1104 rpciod_workqueue = NULL;
1104 out: 1105 out:
1105 up(&rpciod_sema); 1106 mutex_unlock(&rpciod_mutex);
1106} 1107}
1107 1108
1108#ifdef RPC_DEBUG 1109#ifdef RPC_DEBUG
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 50580620e897..a27905a0ad27 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1296,13 +1296,13 @@ svc_send(struct svc_rqst *rqstp)
1296 xb->page_len + 1296 xb->page_len +
1297 xb->tail[0].iov_len; 1297 xb->tail[0].iov_len;
1298 1298
1299 /* Grab svsk->sk_sem to serialize outgoing data. */ 1299 /* Grab svsk->sk_mutex to serialize outgoing data. */
1300 down(&svsk->sk_sem); 1300 mutex_lock(&svsk->sk_mutex);
1301 if (test_bit(SK_DEAD, &svsk->sk_flags)) 1301 if (test_bit(SK_DEAD, &svsk->sk_flags))
1302 len = -ENOTCONN; 1302 len = -ENOTCONN;
1303 else 1303 else
1304 len = svsk->sk_sendto(rqstp); 1304 len = svsk->sk_sendto(rqstp);
1305 up(&svsk->sk_sem); 1305 mutex_unlock(&svsk->sk_mutex);
1306 svc_sock_release(rqstp); 1306 svc_sock_release(rqstp);
1307 1307
1308 if (len == -ECONNREFUSED || len == -ENOTCONN || len == -EAGAIN) 1308 if (len == -ECONNREFUSED || len == -ENOTCONN || len == -EAGAIN)
@@ -1351,7 +1351,7 @@ svc_setup_socket(struct svc_serv *serv, struct socket *sock,
1351 svsk->sk_lastrecv = get_seconds(); 1351 svsk->sk_lastrecv = get_seconds();
1352 INIT_LIST_HEAD(&svsk->sk_deferred); 1352 INIT_LIST_HEAD(&svsk->sk_deferred);
1353 INIT_LIST_HEAD(&svsk->sk_ready); 1353 INIT_LIST_HEAD(&svsk->sk_ready);
1354 sema_init(&svsk->sk_sem, 1); 1354 mutex_init(&svsk->sk_mutex);
1355 1355
1356 /* Initialize the socket */ 1356 /* Initialize the socket */
1357 if (sock->type == SOCK_DGRAM) 1357 if (sock->type == SOCK_DGRAM)
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index a7b04f397c12..2c4ecbe50082 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -107,22 +107,22 @@ static spinlock_t bc_lock = SPIN_LOCK_UNLOCKED;
107char tipc_bclink_name[] = "multicast-link"; 107char tipc_bclink_name[] = "multicast-link";
108 108
109 109
110static inline u32 buf_seqno(struct sk_buff *buf) 110static u32 buf_seqno(struct sk_buff *buf)
111{ 111{
112 return msg_seqno(buf_msg(buf)); 112 return msg_seqno(buf_msg(buf));
113} 113}
114 114
115static inline u32 bcbuf_acks(struct sk_buff *buf) 115static u32 bcbuf_acks(struct sk_buff *buf)
116{ 116{
117 return (u32)(unsigned long)TIPC_SKB_CB(buf)->handle; 117 return (u32)(unsigned long)TIPC_SKB_CB(buf)->handle;
118} 118}
119 119
120static inline void bcbuf_set_acks(struct sk_buff *buf, u32 acks) 120static void bcbuf_set_acks(struct sk_buff *buf, u32 acks)
121{ 121{
122 TIPC_SKB_CB(buf)->handle = (void *)(unsigned long)acks; 122 TIPC_SKB_CB(buf)->handle = (void *)(unsigned long)acks;
123} 123}
124 124
125static inline void bcbuf_decr_acks(struct sk_buff *buf) 125static void bcbuf_decr_acks(struct sk_buff *buf)
126{ 126{
127 bcbuf_set_acks(buf, bcbuf_acks(buf) - 1); 127 bcbuf_set_acks(buf, bcbuf_acks(buf) - 1);
128} 128}
@@ -134,7 +134,7 @@ static inline void bcbuf_decr_acks(struct sk_buff *buf)
134 * Called with 'node' locked, bc_lock unlocked 134 * Called with 'node' locked, bc_lock unlocked
135 */ 135 */
136 136
137static inline void bclink_set_gap(struct node *n_ptr) 137static void bclink_set_gap(struct node *n_ptr)
138{ 138{
139 struct sk_buff *buf = n_ptr->bclink.deferred_head; 139 struct sk_buff *buf = n_ptr->bclink.deferred_head;
140 140
@@ -154,7 +154,7 @@ static inline void bclink_set_gap(struct node *n_ptr)
154 * distribute NACKs, but tries to use the same spacing (divide by 16). 154 * distribute NACKs, but tries to use the same spacing (divide by 16).
155 */ 155 */
156 156
157static inline int bclink_ack_allowed(u32 n) 157static int bclink_ack_allowed(u32 n)
158{ 158{
159 return((n % TIPC_MIN_LINK_WIN) == tipc_own_tag); 159 return((n % TIPC_MIN_LINK_WIN) == tipc_own_tag);
160} 160}
@@ -271,7 +271,7 @@ static void bclink_send_nack(struct node *n_ptr)
271 msg_set_bcgap_to(msg, n_ptr->bclink.gap_to); 271 msg_set_bcgap_to(msg, n_ptr->bclink.gap_to);
272 msg_set_bcast_tag(msg, tipc_own_tag); 272 msg_set_bcast_tag(msg, tipc_own_tag);
273 273
274 if (tipc_bearer_send(&bcbearer->bearer, buf, 0)) { 274 if (tipc_bearer_send(&bcbearer->bearer, buf, NULL)) {
275 bcl->stats.sent_nacks++; 275 bcl->stats.sent_nacks++;
276 buf_discard(buf); 276 buf_discard(buf);
277 } else { 277 } else {
@@ -314,7 +314,7 @@ void tipc_bclink_check_gap(struct node *n_ptr, u32 last_sent)
314 * Only tipc_net_lock set. 314 * Only tipc_net_lock set.
315 */ 315 */
316 316
317void tipc_bclink_peek_nack(u32 dest, u32 sender_tag, u32 gap_after, u32 gap_to) 317static void tipc_bclink_peek_nack(u32 dest, u32 sender_tag, u32 gap_after, u32 gap_to)
318{ 318{
319 struct node *n_ptr = tipc_node_find(dest); 319 struct node *n_ptr = tipc_node_find(dest);
320 u32 my_after, my_to; 320 u32 my_after, my_to;
@@ -425,9 +425,9 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf)
425 msg_bcgap_to(msg)); 425 msg_bcgap_to(msg));
426 } else { 426 } else {
427 tipc_bclink_peek_nack(msg_destnode(msg), 427 tipc_bclink_peek_nack(msg_destnode(msg),
428 msg_bcast_tag(msg), 428 msg_bcast_tag(msg),
429 msg_bcgap_after(msg), 429 msg_bcgap_after(msg),
430 msg_bcgap_to(msg)); 430 msg_bcgap_to(msg));
431 } 431 }
432 buf_discard(buf); 432 buf_discard(buf);
433 return; 433 return;
@@ -525,16 +525,18 @@ u32 tipc_bclink_acks_missing(struct node *n_ptr)
525 * Returns 0 if packet sent successfully, non-zero if not 525 * Returns 0 if packet sent successfully, non-zero if not
526 */ 526 */
527 527
528int tipc_bcbearer_send(struct sk_buff *buf, 528static int tipc_bcbearer_send(struct sk_buff *buf,
529 struct tipc_bearer *unused1, 529 struct tipc_bearer *unused1,
530 struct tipc_media_addr *unused2) 530 struct tipc_media_addr *unused2)
531{ 531{
532 static int send_count = 0; 532 static int send_count = 0;
533 533
534 struct node_map remains; 534 struct node_map *remains;
535 struct node_map remains_new; 535 struct node_map *remains_new;
536 struct node_map *remains_tmp;
536 int bp_index; 537 int bp_index;
537 int swap_time; 538 int swap_time;
539 int err;
538 540
539 /* Prepare buffer for broadcasting (if first time trying to send it) */ 541 /* Prepare buffer for broadcasting (if first time trying to send it) */
540 542
@@ -555,7 +557,9 @@ int tipc_bcbearer_send(struct sk_buff *buf,
555 557
556 /* Send buffer over bearers until all targets reached */ 558 /* Send buffer over bearers until all targets reached */
557 559
558 remains = tipc_cltr_bcast_nodes; 560 remains = kmalloc(sizeof(struct node_map), GFP_ATOMIC);
561 remains_new = kmalloc(sizeof(struct node_map), GFP_ATOMIC);
562 *remains = tipc_cltr_bcast_nodes;
559 563
560 for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) { 564 for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) {
561 struct bearer *p = bcbearer->bpairs[bp_index].primary; 565 struct bearer *p = bcbearer->bpairs[bp_index].primary;
@@ -564,8 +568,8 @@ int tipc_bcbearer_send(struct sk_buff *buf,
564 if (!p) 568 if (!p)
565 break; /* no more bearers to try */ 569 break; /* no more bearers to try */
566 570
567 tipc_nmap_diff(&remains, &p->nodes, &remains_new); 571 tipc_nmap_diff(remains, &p->nodes, remains_new);
568 if (remains_new.count == remains.count) 572 if (remains_new->count == remains->count)
569 continue; /* bearer pair doesn't add anything */ 573 continue; /* bearer pair doesn't add anything */
570 574
571 if (!p->publ.blocked && 575 if (!p->publ.blocked &&
@@ -583,17 +587,27 @@ swap:
583 bcbearer->bpairs[bp_index].primary = s; 587 bcbearer->bpairs[bp_index].primary = s;
584 bcbearer->bpairs[bp_index].secondary = p; 588 bcbearer->bpairs[bp_index].secondary = p;
585update: 589update:
586 if (remains_new.count == 0) 590 if (remains_new->count == 0) {
587 return TIPC_OK; 591 err = TIPC_OK;
592 goto out;
593 }
588 594
595 /* swap map */
596 remains_tmp = remains;
589 remains = remains_new; 597 remains = remains_new;
598 remains_new = remains_tmp;
590 } 599 }
591 600
592 /* Unable to reach all targets */ 601 /* Unable to reach all targets */
593 602
594 bcbearer->bearer.publ.blocked = 1; 603 bcbearer->bearer.publ.blocked = 1;
595 bcl->stats.bearer_congs++; 604 bcl->stats.bearer_congs++;
596 return ~TIPC_OK; 605 err = ~TIPC_OK;
606
607 out:
608 kfree(remains_new);
609 kfree(remains);
610 return err;
597} 611}
598 612
599/** 613/**
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 64dcb0f3a8b2..e213a8e54855 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -45,10 +45,10 @@
45 45
46#define MAX_ADDR_STR 32 46#define MAX_ADDR_STR 32
47 47
48static struct media *media_list = 0; 48static struct media *media_list = NULL;
49static u32 media_count = 0; 49static u32 media_count = 0;
50 50
51struct bearer *tipc_bearers = 0; 51struct bearer *tipc_bearers = NULL;
52 52
53/** 53/**
54 * media_name_valid - validate media name 54 * media_name_valid - validate media name
@@ -79,7 +79,7 @@ static struct media *media_find(const char *name)
79 if (!strcmp(m_ptr->name, name)) 79 if (!strcmp(m_ptr->name, name))
80 return m_ptr; 80 return m_ptr;
81 } 81 }
82 return 0; 82 return NULL;
83} 83}
84 84
85/** 85/**
@@ -287,7 +287,7 @@ static struct bearer *bearer_find(const char *name)
287 if (b_ptr->active && (!strcmp(b_ptr->publ.name, name))) 287 if (b_ptr->active && (!strcmp(b_ptr->publ.name, name)))
288 return b_ptr; 288 return b_ptr;
289 } 289 }
290 return 0; 290 return NULL;
291} 291}
292 292
293/** 293/**
@@ -307,7 +307,7 @@ struct bearer *tipc_bearer_find_interface(const char *if_name)
307 if (!strcmp(b_if_name, if_name)) 307 if (!strcmp(b_if_name, if_name))
308 return b_ptr; 308 return b_ptr;
309 } 309 }
310 return 0; 310 return NULL;
311} 311}
312 312
313/** 313/**
@@ -569,7 +569,7 @@ failed:
569 569
570int tipc_block_bearer(const char *name) 570int tipc_block_bearer(const char *name)
571{ 571{
572 struct bearer *b_ptr = 0; 572 struct bearer *b_ptr = NULL;
573 struct link *l_ptr; 573 struct link *l_ptr;
574 struct link *temp_l_ptr; 574 struct link *temp_l_ptr;
575 575
@@ -666,8 +666,8 @@ int tipc_bearer_init(void)
666 } else { 666 } else {
667 kfree(tipc_bearers); 667 kfree(tipc_bearers);
668 kfree(media_list); 668 kfree(media_list);
669 tipc_bearers = 0; 669 tipc_bearers = NULL;
670 media_list = 0; 670 media_list = NULL;
671 res = -ENOMEM; 671 res = -ENOMEM;
672 } 672 }
673 write_unlock_bh(&tipc_net_lock); 673 write_unlock_bh(&tipc_net_lock);
@@ -691,8 +691,8 @@ void tipc_bearer_stop(void)
691 } 691 }
692 kfree(tipc_bearers); 692 kfree(tipc_bearers);
693 kfree(media_list); 693 kfree(media_list);
694 tipc_bearers = 0; 694 tipc_bearers = NULL;
695 media_list = 0; 695 media_list = NULL;
696 media_count = 0; 696 media_count = 0;
697} 697}
698 698
diff --git a/net/tipc/cluster.c b/net/tipc/cluster.c
index ab974ca19371..1aed81584e96 100644
--- a/net/tipc/cluster.c
+++ b/net/tipc/cluster.c
@@ -44,11 +44,11 @@
44#include "msg.h" 44#include "msg.h"
45#include "bearer.h" 45#include "bearer.h"
46 46
47void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf, 47static void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf,
48 u32 lower, u32 upper); 48 u32 lower, u32 upper);
49struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest); 49static struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest);
50 50
51struct node **tipc_local_nodes = 0; 51struct node **tipc_local_nodes = NULL;
52struct node_map tipc_cltr_bcast_nodes = {0,{0,}}; 52struct node_map tipc_cltr_bcast_nodes = {0,{0,}};
53u32 tipc_highest_allowed_slave = 0; 53u32 tipc_highest_allowed_slave = 0;
54 54
@@ -61,7 +61,7 @@ struct cluster *tipc_cltr_create(u32 addr)
61 61
62 c_ptr = (struct cluster *)kmalloc(sizeof(*c_ptr), GFP_ATOMIC); 62 c_ptr = (struct cluster *)kmalloc(sizeof(*c_ptr), GFP_ATOMIC);
63 if (c_ptr == NULL) 63 if (c_ptr == NULL)
64 return 0; 64 return NULL;
65 memset(c_ptr, 0, sizeof(*c_ptr)); 65 memset(c_ptr, 0, sizeof(*c_ptr));
66 66
67 c_ptr->addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0); 67 c_ptr->addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0);
@@ -73,7 +73,7 @@ struct cluster *tipc_cltr_create(u32 addr)
73 c_ptr->nodes = (struct node **)kmalloc(alloc, GFP_ATOMIC); 73 c_ptr->nodes = (struct node **)kmalloc(alloc, GFP_ATOMIC);
74 if (c_ptr->nodes == NULL) { 74 if (c_ptr->nodes == NULL) {
75 kfree(c_ptr); 75 kfree(c_ptr);
76 return 0; 76 return NULL;
77 } 77 }
78 memset(c_ptr->nodes, 0, alloc); 78 memset(c_ptr->nodes, 0, alloc);
79 if (in_own_cluster(addr)) 79 if (in_own_cluster(addr))
@@ -91,7 +91,7 @@ struct cluster *tipc_cltr_create(u32 addr)
91 } 91 }
92 else { 92 else {
93 kfree(c_ptr); 93 kfree(c_ptr);
94 c_ptr = 0; 94 c_ptr = NULL;
95 } 95 }
96 96
97 return c_ptr; 97 return c_ptr;
@@ -204,7 +204,7 @@ struct node *tipc_cltr_select_node(struct cluster *c_ptr, u32 selector)
204 204
205 assert(!in_own_cluster(c_ptr->addr)); 205 assert(!in_own_cluster(c_ptr->addr));
206 if (!c_ptr->highest_node) 206 if (!c_ptr->highest_node)
207 return 0; 207 return NULL;
208 208
209 /* Start entry must be random */ 209 /* Start entry must be random */
210 while (mask > c_ptr->highest_node) { 210 while (mask > c_ptr->highest_node) {
@@ -222,14 +222,14 @@ struct node *tipc_cltr_select_node(struct cluster *c_ptr, u32 selector)
222 if (tipc_node_has_active_links(c_ptr->nodes[n_num])) 222 if (tipc_node_has_active_links(c_ptr->nodes[n_num]))
223 return c_ptr->nodes[n_num]; 223 return c_ptr->nodes[n_num];
224 } 224 }
225 return 0; 225 return NULL;
226} 226}
227 227
228/* 228/*
229 * Routing table management: See description in node.c 229 * Routing table management: See description in node.c
230 */ 230 */
231 231
232struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest) 232static struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest)
233{ 233{
234 u32 size = INT_H_SIZE + data_size; 234 u32 size = INT_H_SIZE + data_size;
235 struct sk_buff *buf = buf_acquire(size); 235 struct sk_buff *buf = buf_acquire(size);
@@ -495,7 +495,7 @@ void tipc_cltr_remove_as_router(struct cluster *c_ptr, u32 router)
495 * tipc_cltr_multicast - multicast message to local nodes 495 * tipc_cltr_multicast - multicast message to local nodes
496 */ 496 */
497 497
498void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf, 498static void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf,
499 u32 lower, u32 upper) 499 u32 lower, u32 upper)
500{ 500{
501 struct sk_buff *buf_copy; 501 struct sk_buff *buf_copy;
diff --git a/net/tipc/cluster.h b/net/tipc/cluster.h
index 9963642e1058..1b4cd309495a 100644
--- a/net/tipc/cluster.h
+++ b/net/tipc/cluster.h
@@ -86,7 +86,7 @@ static inline struct cluster *tipc_cltr_find(u32 addr)
86 86
87 if (z_ptr) 87 if (z_ptr)
88 return z_ptr->clusters[1]; 88 return z_ptr->clusters[1];
89 return 0; 89 return NULL;
90} 90}
91 91
92#endif 92#endif
diff --git a/net/tipc/config.c b/net/tipc/config.c
index 3c8e6740e5ae..48b5de2dbe60 100644
--- a/net/tipc/config.c
+++ b/net/tipc/config.c
@@ -683,11 +683,11 @@ int tipc_cfg_init(void)
683 memset(&mng, 0, sizeof(mng)); 683 memset(&mng, 0, sizeof(mng));
684 INIT_LIST_HEAD(&mng.link_subscribers); 684 INIT_LIST_HEAD(&mng.link_subscribers);
685 685
686 res = tipc_attach(&mng.user_ref, 0, 0); 686 res = tipc_attach(&mng.user_ref, NULL, NULL);
687 if (res) 687 if (res)
688 goto failed; 688 goto failed;
689 689
690 res = tipc_createport(mng.user_ref, 0, TIPC_CRITICAL_IMPORTANCE, 690 res = tipc_createport(mng.user_ref, NULL, TIPC_CRITICAL_IMPORTANCE,
691 NULL, NULL, NULL, 691 NULL, NULL, NULL,
692 NULL, cfg_named_msg_event, NULL, 692 NULL, cfg_named_msg_event, NULL,
693 NULL, &mng.port_ref); 693 NULL, &mng.port_ref);
diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c
index 4f4beefa7830..26ef95d5fe38 100644
--- a/net/tipc/dbg.c
+++ b/net/tipc/dbg.c
@@ -81,7 +81,7 @@ void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 sz)
81 81
82 pb->crs = pb->buf = raw; 82 pb->crs = pb->buf = raw;
83 pb->size = sz; 83 pb->size = sz;
84 pb->next = 0; 84 pb->next = NULL;
85 pb->buf[0] = 0; 85 pb->buf[0] = 0;
86 pb->buf[sz-1] = ~0; 86 pb->buf[sz-1] = ~0;
87} 87}
@@ -216,7 +216,7 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...)
216 } 216 }
217 } 217 }
218 pb_next = pb->next; 218 pb_next = pb->next;
219 pb->next = 0; 219 pb->next = NULL;
220 pb = pb_next; 220 pb = pb_next;
221 } 221 }
222 spin_unlock_bh(&print_lock); 222 spin_unlock_bh(&print_lock);
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index 53ba4630c10d..92601385e5f5 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -110,10 +110,10 @@ void tipc_disc_link_event(u32 addr, char *name, int up)
110 * @b_ptr: ptr to bearer issuing message 110 * @b_ptr: ptr to bearer issuing message
111 */ 111 */
112 112
113struct sk_buff *tipc_disc_init_msg(u32 type, 113static struct sk_buff *tipc_disc_init_msg(u32 type,
114 u32 req_links, 114 u32 req_links,
115 u32 dest_domain, 115 u32 dest_domain,
116 struct bearer *b_ptr) 116 struct bearer *b_ptr)
117{ 117{
118 struct sk_buff *buf = buf_acquire(DSC_H_SIZE); 118 struct sk_buff *buf = buf_acquire(DSC_H_SIZE);
119 struct tipc_msg *msg; 119 struct tipc_msg *msg;
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index 1f8d83b9c8b4..7a252785f727 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -169,7 +169,7 @@ static int enable_bearer(struct tipc_bearer *tb_ptr)
169 169
170static void disable_bearer(struct tipc_bearer *tb_ptr) 170static void disable_bearer(struct tipc_bearer *tb_ptr)
171{ 171{
172 ((struct eth_bearer *)tb_ptr->usr_handle)->bearer = 0; 172 ((struct eth_bearer *)tb_ptr->usr_handle)->bearer = NULL;
173} 173}
174 174
175/** 175/**
@@ -285,7 +285,7 @@ void tipc_eth_media_stop(void)
285 for (i = 0; i < MAX_ETH_BEARERS ; i++) { 285 for (i = 0; i < MAX_ETH_BEARERS ; i++) {
286 if (eth_bearers[i].bearer) { 286 if (eth_bearers[i].bearer) {
287 eth_bearers[i].bearer->blocked = 1; 287 eth_bearers[i].bearer->blocked = 1;
288 eth_bearers[i].bearer = 0; 288 eth_bearers[i].bearer = NULL;
289 } 289 }
290 if (eth_bearers[i].dev) { 290 if (eth_bearers[i].dev) {
291 dev_remove_pack(&eth_bearers[i].tipc_packet_type); 291 dev_remove_pack(&eth_bearers[i].tipc_packet_type);
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 511872afa459..910b37e5083d 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -157,13 +157,13 @@ static void link_print(struct link *l_ptr, struct print_buf *buf,
157 } \ 157 } \
158} while (0) 158} while (0)
159 159
160static inline void dbg_print_link(struct link *l_ptr, const char *str) 160static void dbg_print_link(struct link *l_ptr, const char *str)
161{ 161{
162 if (DBG_OUTPUT) 162 if (DBG_OUTPUT)
163 link_print(l_ptr, DBG_OUTPUT, str); 163 link_print(l_ptr, DBG_OUTPUT, str);
164} 164}
165 165
166static inline void dbg_print_buf_chain(struct sk_buff *root_buf) 166static void dbg_print_buf_chain(struct sk_buff *root_buf)
167{ 167{
168 if (DBG_OUTPUT) { 168 if (DBG_OUTPUT) {
169 struct sk_buff *buf = root_buf; 169 struct sk_buff *buf = root_buf;
@@ -176,50 +176,50 @@ static inline void dbg_print_buf_chain(struct sk_buff *root_buf)
176} 176}
177 177
178/* 178/*
179 * Simple inlined link routines 179 * Simple link routines
180 */ 180 */
181 181
182static inline unsigned int align(unsigned int i) 182static unsigned int align(unsigned int i)
183{ 183{
184 return (i + 3) & ~3u; 184 return (i + 3) & ~3u;
185} 185}
186 186
187static inline int link_working_working(struct link *l_ptr) 187static int link_working_working(struct link *l_ptr)
188{ 188{
189 return (l_ptr->state == WORKING_WORKING); 189 return (l_ptr->state == WORKING_WORKING);
190} 190}
191 191
192static inline int link_working_unknown(struct link *l_ptr) 192static int link_working_unknown(struct link *l_ptr)
193{ 193{
194 return (l_ptr->state == WORKING_UNKNOWN); 194 return (l_ptr->state == WORKING_UNKNOWN);
195} 195}
196 196
197static inline int link_reset_unknown(struct link *l_ptr) 197static int link_reset_unknown(struct link *l_ptr)
198{ 198{
199 return (l_ptr->state == RESET_UNKNOWN); 199 return (l_ptr->state == RESET_UNKNOWN);
200} 200}
201 201
202static inline int link_reset_reset(struct link *l_ptr) 202static int link_reset_reset(struct link *l_ptr)
203{ 203{
204 return (l_ptr->state == RESET_RESET); 204 return (l_ptr->state == RESET_RESET);
205} 205}
206 206
207static inline int link_blocked(struct link *l_ptr) 207static int link_blocked(struct link *l_ptr)
208{ 208{
209 return (l_ptr->exp_msg_count || l_ptr->blocked); 209 return (l_ptr->exp_msg_count || l_ptr->blocked);
210} 210}
211 211
212static inline int link_congested(struct link *l_ptr) 212static int link_congested(struct link *l_ptr)
213{ 213{
214 return (l_ptr->out_queue_size >= l_ptr->queue_limit[0]); 214 return (l_ptr->out_queue_size >= l_ptr->queue_limit[0]);
215} 215}
216 216
217static inline u32 link_max_pkt(struct link *l_ptr) 217static u32 link_max_pkt(struct link *l_ptr)
218{ 218{
219 return l_ptr->max_pkt; 219 return l_ptr->max_pkt;
220} 220}
221 221
222static inline void link_init_max_pkt(struct link *l_ptr) 222static void link_init_max_pkt(struct link *l_ptr)
223{ 223{
224 u32 max_pkt; 224 u32 max_pkt;
225 225
@@ -236,20 +236,20 @@ static inline void link_init_max_pkt(struct link *l_ptr)
236 l_ptr->max_pkt_probes = 0; 236 l_ptr->max_pkt_probes = 0;
237} 237}
238 238
239static inline u32 link_next_sent(struct link *l_ptr) 239static u32 link_next_sent(struct link *l_ptr)
240{ 240{
241 if (l_ptr->next_out) 241 if (l_ptr->next_out)
242 return msg_seqno(buf_msg(l_ptr->next_out)); 242 return msg_seqno(buf_msg(l_ptr->next_out));
243 return mod(l_ptr->next_out_no); 243 return mod(l_ptr->next_out_no);
244} 244}
245 245
246static inline u32 link_last_sent(struct link *l_ptr) 246static u32 link_last_sent(struct link *l_ptr)
247{ 247{
248 return mod(link_next_sent(l_ptr) - 1); 248 return mod(link_next_sent(l_ptr) - 1);
249} 249}
250 250
251/* 251/*
252 * Simple non-inlined link routines (i.e. referenced outside this file) 252 * Simple non-static link routines (i.e. referenced outside this file)
253 */ 253 */
254 254
255int tipc_link_is_up(struct link *l_ptr) 255int tipc_link_is_up(struct link *l_ptr)
@@ -396,7 +396,7 @@ static void link_timeout(struct link *l_ptr)
396 tipc_node_unlock(l_ptr->owner); 396 tipc_node_unlock(l_ptr->owner);
397} 397}
398 398
399static inline void link_set_timer(struct link *l_ptr, u32 time) 399static void link_set_timer(struct link *l_ptr, u32 time)
400{ 400{
401 k_start_timer(&l_ptr->timer, time); 401 k_start_timer(&l_ptr->timer, time);
402} 402}
@@ -573,7 +573,7 @@ void tipc_link_wakeup_ports(struct link *l_ptr, int all)
573 if (win <= 0) 573 if (win <= 0)
574 break; 574 break;
575 list_del_init(&p_ptr->wait_list); 575 list_del_init(&p_ptr->wait_list);
576 p_ptr->congested_link = 0; 576 p_ptr->congested_link = NULL;
577 assert(p_ptr->wakeup); 577 assert(p_ptr->wakeup);
578 spin_lock_bh(p_ptr->publ.lock); 578 spin_lock_bh(p_ptr->publ.lock);
579 p_ptr->publ.congested = 0; 579 p_ptr->publ.congested = 0;
@@ -1004,9 +1004,9 @@ static int link_bundle_buf(struct link *l_ptr,
1004 return 1; 1004 return 1;
1005} 1005}
1006 1006
1007static inline void link_add_to_outqueue(struct link *l_ptr, 1007static void link_add_to_outqueue(struct link *l_ptr,
1008 struct sk_buff *buf, 1008 struct sk_buff *buf,
1009 struct tipc_msg *msg) 1009 struct tipc_msg *msg)
1010{ 1010{
1011 u32 ack = mod(l_ptr->next_in_no - 1); 1011 u32 ack = mod(l_ptr->next_in_no - 1);
1012 u32 seqno = mod(l_ptr->next_out_no++); 1012 u32 seqno = mod(l_ptr->next_out_no++);
@@ -1156,8 +1156,8 @@ int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector)
1156 * Link is locked. Returns user data length. 1156 * Link is locked. Returns user data length.
1157 */ 1157 */
1158 1158
1159static inline int link_send_buf_fast(struct link *l_ptr, struct sk_buff *buf, 1159static int link_send_buf_fast(struct link *l_ptr, struct sk_buff *buf,
1160 u32 *used_max_pkt) 1160 u32 *used_max_pkt)
1161{ 1161{
1162 struct tipc_msg *msg = buf_msg(buf); 1162 struct tipc_msg *msg = buf_msg(buf);
1163 int res = msg_data_sz(msg); 1163 int res = msg_data_sz(msg);
@@ -1355,7 +1355,7 @@ again:
1355 fragm_crs = 0; 1355 fragm_crs = 0;
1356 fragm_rest = 0; 1356 fragm_rest = 0;
1357 sect_rest = 0; 1357 sect_rest = 0;
1358 sect_crs = 0; 1358 sect_crs = NULL;
1359 curr_sect = -1; 1359 curr_sect = -1;
1360 1360
1361 /* Prepare reusable fragment header: */ 1361 /* Prepare reusable fragment header: */
@@ -1549,7 +1549,7 @@ u32 tipc_link_push_packet(struct link *l_ptr)
1549 msg_dbg(buf_msg(buf), ">DEF-PROT>"); 1549 msg_dbg(buf_msg(buf), ">DEF-PROT>");
1550 l_ptr->unacked_window = 0; 1550 l_ptr->unacked_window = 0;
1551 buf_discard(buf); 1551 buf_discard(buf);
1552 l_ptr->proto_msg_queue = 0; 1552 l_ptr->proto_msg_queue = NULL;
1553 return TIPC_OK; 1553 return TIPC_OK;
1554 } else { 1554 } else {
1555 msg_dbg(buf_msg(buf), "|>DEF-PROT>"); 1555 msg_dbg(buf_msg(buf), "|>DEF-PROT>");
@@ -1860,7 +1860,7 @@ u32 tipc_link_defer_pkt(struct sk_buff **head,
1860 struct sk_buff **tail, 1860 struct sk_buff **tail,
1861 struct sk_buff *buf) 1861 struct sk_buff *buf)
1862{ 1862{
1863 struct sk_buff *prev = 0; 1863 struct sk_buff *prev = NULL;
1864 struct sk_buff *crs = *head; 1864 struct sk_buff *crs = *head;
1865 u32 seq_no = msg_seqno(buf_msg(buf)); 1865 u32 seq_no = msg_seqno(buf_msg(buf));
1866 1866
@@ -1953,7 +1953,7 @@ static void link_handle_out_of_seq_msg(struct link *l_ptr,
1953void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg, 1953void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg,
1954 u32 gap, u32 tolerance, u32 priority, u32 ack_mtu) 1954 u32 gap, u32 tolerance, u32 priority, u32 ack_mtu)
1955{ 1955{
1956 struct sk_buff *buf = 0; 1956 struct sk_buff *buf = NULL;
1957 struct tipc_msg *msg = l_ptr->pmsg; 1957 struct tipc_msg *msg = l_ptr->pmsg;
1958 u32 msg_size = sizeof(l_ptr->proto_msg); 1958 u32 msg_size = sizeof(l_ptr->proto_msg);
1959 1959
@@ -2426,7 +2426,7 @@ static int link_recv_changeover_msg(struct link **l_ptr,
2426 } 2426 }
2427 } 2427 }
2428exit: 2428exit:
2429 *buf = 0; 2429 *buf = NULL;
2430 buf_discard(tunnel_buf); 2430 buf_discard(tunnel_buf);
2431 return 0; 2431 return 0;
2432} 2432}
@@ -2539,42 +2539,37 @@ exit:
2539 * pending message. This makes dynamic memory allocation unecessary. 2539 * pending message. This makes dynamic memory allocation unecessary.
2540 */ 2540 */
2541 2541
2542static inline u32 get_long_msg_seqno(struct sk_buff *buf) 2542static void set_long_msg_seqno(struct sk_buff *buf, u32 seqno)
2543{
2544 return msg_seqno(buf_msg(buf));
2545}
2546
2547static inline void set_long_msg_seqno(struct sk_buff *buf, u32 seqno)
2548{ 2543{
2549 msg_set_seqno(buf_msg(buf), seqno); 2544 msg_set_seqno(buf_msg(buf), seqno);
2550} 2545}
2551 2546
2552static inline u32 get_fragm_size(struct sk_buff *buf) 2547static u32 get_fragm_size(struct sk_buff *buf)
2553{ 2548{
2554 return msg_ack(buf_msg(buf)); 2549 return msg_ack(buf_msg(buf));
2555} 2550}
2556 2551
2557static inline void set_fragm_size(struct sk_buff *buf, u32 sz) 2552static void set_fragm_size(struct sk_buff *buf, u32 sz)
2558{ 2553{
2559 msg_set_ack(buf_msg(buf), sz); 2554 msg_set_ack(buf_msg(buf), sz);
2560} 2555}
2561 2556
2562static inline u32 get_expected_frags(struct sk_buff *buf) 2557static u32 get_expected_frags(struct sk_buff *buf)
2563{ 2558{
2564 return msg_bcast_ack(buf_msg(buf)); 2559 return msg_bcast_ack(buf_msg(buf));
2565} 2560}
2566 2561
2567static inline void set_expected_frags(struct sk_buff *buf, u32 exp) 2562static void set_expected_frags(struct sk_buff *buf, u32 exp)
2568{ 2563{
2569 msg_set_bcast_ack(buf_msg(buf), exp); 2564 msg_set_bcast_ack(buf_msg(buf), exp);
2570} 2565}
2571 2566
2572static inline u32 get_timer_cnt(struct sk_buff *buf) 2567static u32 get_timer_cnt(struct sk_buff *buf)
2573{ 2568{
2574 return msg_reroute_cnt(buf_msg(buf)); 2569 return msg_reroute_cnt(buf_msg(buf));
2575} 2570}
2576 2571
2577static inline void incr_timer_cnt(struct sk_buff *buf) 2572static void incr_timer_cnt(struct sk_buff *buf)
2578{ 2573{
2579 msg_incr_reroute_cnt(buf_msg(buf)); 2574 msg_incr_reroute_cnt(buf_msg(buf));
2580} 2575}
@@ -2586,13 +2581,13 @@ static inline void incr_timer_cnt(struct sk_buff *buf)
2586int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, 2581int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb,
2587 struct tipc_msg **m) 2582 struct tipc_msg **m)
2588{ 2583{
2589 struct sk_buff *prev = 0; 2584 struct sk_buff *prev = NULL;
2590 struct sk_buff *fbuf = *fb; 2585 struct sk_buff *fbuf = *fb;
2591 struct tipc_msg *fragm = buf_msg(fbuf); 2586 struct tipc_msg *fragm = buf_msg(fbuf);
2592 struct sk_buff *pbuf = *pending; 2587 struct sk_buff *pbuf = *pending;
2593 u32 long_msg_seq_no = msg_long_msgno(fragm); 2588 u32 long_msg_seq_no = msg_long_msgno(fragm);
2594 2589
2595 *fb = 0; 2590 *fb = NULL;
2596 msg_dbg(fragm,"FRG<REC<"); 2591 msg_dbg(fragm,"FRG<REC<");
2597 2592
2598 /* Is there an incomplete message waiting for this fragment? */ 2593 /* Is there an incomplete message waiting for this fragment? */
@@ -2670,8 +2665,8 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb,
2670 2665
2671static void link_check_defragm_bufs(struct link *l_ptr) 2666static void link_check_defragm_bufs(struct link *l_ptr)
2672{ 2667{
2673 struct sk_buff *prev = 0; 2668 struct sk_buff *prev = NULL;
2674 struct sk_buff *next = 0; 2669 struct sk_buff *next = NULL;
2675 struct sk_buff *buf = l_ptr->defragm_buf; 2670 struct sk_buff *buf = l_ptr->defragm_buf;
2676 2671
2677 if (!buf) 2672 if (!buf)
@@ -2750,19 +2745,19 @@ static struct link *link_find_link(const char *name, struct node **node)
2750 struct link *l_ptr; 2745 struct link *l_ptr;
2751 2746
2752 if (!link_name_validate(name, &link_name_parts)) 2747 if (!link_name_validate(name, &link_name_parts))
2753 return 0; 2748 return NULL;
2754 2749
2755 b_ptr = tipc_bearer_find_interface(link_name_parts.if_local); 2750 b_ptr = tipc_bearer_find_interface(link_name_parts.if_local);
2756 if (!b_ptr) 2751 if (!b_ptr)
2757 return 0; 2752 return NULL;
2758 2753
2759 *node = tipc_node_find(link_name_parts.addr_peer); 2754 *node = tipc_node_find(link_name_parts.addr_peer);
2760 if (!*node) 2755 if (!*node)
2761 return 0; 2756 return NULL;
2762 2757
2763 l_ptr = (*node)->links[b_ptr->identity]; 2758 l_ptr = (*node)->links[b_ptr->identity];
2764 if (!l_ptr || strcmp(l_ptr->name, name)) 2759 if (!l_ptr || strcmp(l_ptr->name, name))
2765 return 0; 2760 return NULL;
2766 2761
2767 return l_ptr; 2762 return l_ptr;
2768} 2763}
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index 830f90999041..953307a9df1d 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -168,8 +168,8 @@ void tipc_named_withdraw(struct publication *publ)
168void tipc_named_node_up(unsigned long node) 168void tipc_named_node_up(unsigned long node)
169{ 169{
170 struct publication *publ; 170 struct publication *publ;
171 struct distr_item *item = 0; 171 struct distr_item *item = NULL;
172 struct sk_buff *buf = 0; 172 struct sk_buff *buf = NULL;
173 u32 left = 0; 173 u32 left = 0;
174 u32 rest; 174 u32 rest;
175 u32 max_item_buf; 175 u32 max_item_buf;
@@ -200,7 +200,7 @@ void tipc_named_node_up(unsigned long node)
200 "<%u.%u.%u>\n", tipc_zone(node), 200 "<%u.%u.%u>\n", tipc_zone(node),
201 tipc_cluster(node), tipc_node(node)); 201 tipc_cluster(node), tipc_node(node));
202 tipc_link_send(buf, node, node); 202 tipc_link_send(buf, node, node);
203 buf = 0; 203 buf = NULL;
204 } 204 }
205 } 205 }
206exit: 206exit:
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index 3f4b23bd08f7..d129422fc5c2 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -46,7 +46,7 @@
46#include "cluster.h" 46#include "cluster.h"
47#include "bcast.h" 47#include "bcast.h"
48 48
49int tipc_nametbl_size = 1024; /* must be a power of 2 */ 49static int tipc_nametbl_size = 1024; /* must be a power of 2 */
50 50
51/** 51/**
52 * struct sub_seq - container for all published instances of a name sequence 52 * struct sub_seq - container for all published instances of a name sequence
@@ -104,7 +104,7 @@ static atomic_t rsv_publ_ok = ATOMIC_INIT(0);
104rwlock_t tipc_nametbl_lock = RW_LOCK_UNLOCKED; 104rwlock_t tipc_nametbl_lock = RW_LOCK_UNLOCKED;
105 105
106 106
107static inline int hash(int x) 107static int hash(int x)
108{ 108{
109 return(x & (tipc_nametbl_size - 1)); 109 return(x & (tipc_nametbl_size - 1));
110} 110}
@@ -121,7 +121,7 @@ static struct publication *publ_create(u32 type, u32 lower, u32 upper,
121 (struct publication *)kmalloc(sizeof(*publ), GFP_ATOMIC); 121 (struct publication *)kmalloc(sizeof(*publ), GFP_ATOMIC);
122 if (publ == NULL) { 122 if (publ == NULL) {
123 warn("Memory squeeze; failed to create publication\n"); 123 warn("Memory squeeze; failed to create publication\n");
124 return 0; 124 return NULL;
125 } 125 }
126 126
127 memset(publ, 0, sizeof(*publ)); 127 memset(publ, 0, sizeof(*publ));
@@ -142,7 +142,7 @@ static struct publication *publ_create(u32 type, u32 lower, u32 upper,
142 * tipc_subseq_alloc - allocate a specified number of sub-sequence structures 142 * tipc_subseq_alloc - allocate a specified number of sub-sequence structures
143 */ 143 */
144 144
145struct sub_seq *tipc_subseq_alloc(u32 cnt) 145static struct sub_seq *tipc_subseq_alloc(u32 cnt)
146{ 146{
147 u32 sz = cnt * sizeof(struct sub_seq); 147 u32 sz = cnt * sizeof(struct sub_seq);
148 struct sub_seq *sseq = (struct sub_seq *)kmalloc(sz, GFP_ATOMIC); 148 struct sub_seq *sseq = (struct sub_seq *)kmalloc(sz, GFP_ATOMIC);
@@ -158,7 +158,7 @@ struct sub_seq *tipc_subseq_alloc(u32 cnt)
158 * Allocates a single sub-sequence structure and sets it to all 0's. 158 * Allocates a single sub-sequence structure and sets it to all 0's.
159 */ 159 */
160 160
161struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_head) 161static struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_head)
162{ 162{
163 struct name_seq *nseq = 163 struct name_seq *nseq =
164 (struct name_seq *)kmalloc(sizeof(*nseq), GFP_ATOMIC); 164 (struct name_seq *)kmalloc(sizeof(*nseq), GFP_ATOMIC);
@@ -168,7 +168,7 @@ struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_head)
168 warn("Memory squeeze; failed to create name sequence\n"); 168 warn("Memory squeeze; failed to create name sequence\n");
169 kfree(nseq); 169 kfree(nseq);
170 kfree(sseq); 170 kfree(sseq);
171 return 0; 171 return NULL;
172 } 172 }
173 173
174 memset(nseq, 0, sizeof(*nseq)); 174 memset(nseq, 0, sizeof(*nseq));
@@ -190,8 +190,8 @@ struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_head)
190 * Very time-critical, so binary searches through sub-sequence array. 190 * Very time-critical, so binary searches through sub-sequence array.
191 */ 191 */
192 192
193static inline struct sub_seq *nameseq_find_subseq(struct name_seq *nseq, 193static struct sub_seq *nameseq_find_subseq(struct name_seq *nseq,
194 u32 instance) 194 u32 instance)
195{ 195{
196 struct sub_seq *sseqs = nseq->sseqs; 196 struct sub_seq *sseqs = nseq->sseqs;
197 int low = 0; 197 int low = 0;
@@ -207,7 +207,7 @@ static inline struct sub_seq *nameseq_find_subseq(struct name_seq *nseq,
207 else 207 else
208 return &sseqs[mid]; 208 return &sseqs[mid];
209 } 209 }
210 return 0; 210 return NULL;
211} 211}
212 212
213/** 213/**
@@ -243,9 +243,9 @@ static u32 nameseq_locate_subseq(struct name_seq *nseq, u32 instance)
243 * tipc_nameseq_insert_publ - 243 * tipc_nameseq_insert_publ -
244 */ 244 */
245 245
246struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, 246static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
247 u32 type, u32 lower, u32 upper, 247 u32 type, u32 lower, u32 upper,
248 u32 scope, u32 node, u32 port, u32 key) 248 u32 scope, u32 node, u32 port, u32 key)
249{ 249{
250 struct subscription *s; 250 struct subscription *s;
251 struct subscription *st; 251 struct subscription *st;
@@ -263,7 +263,7 @@ struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
263 263
264 if ((sseq->lower != lower) || (sseq->upper != upper)) { 264 if ((sseq->lower != lower) || (sseq->upper != upper)) {
265 warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper); 265 warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper);
266 return 0; 266 return NULL;
267 } 267 }
268 } else { 268 } else {
269 u32 inspos; 269 u32 inspos;
@@ -278,7 +278,7 @@ struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
278 if ((inspos < nseq->first_free) && 278 if ((inspos < nseq->first_free) &&
279 (upper >= nseq->sseqs[inspos].lower)) { 279 (upper >= nseq->sseqs[inspos].lower)) {
280 warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper); 280 warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper);
281 return 0; 281 return NULL;
282 } 282 }
283 283
284 /* Ensure there is space for new sub-sequence */ 284 /* Ensure there is space for new sub-sequence */
@@ -294,7 +294,7 @@ struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
294 nseq->alloc *= 2; 294 nseq->alloc *= 2;
295 } else { 295 } else {
296 warn("Memory squeeze; failed to create sub-sequence\n"); 296 warn("Memory squeeze; failed to create sub-sequence\n");
297 return 0; 297 return NULL;
298 } 298 }
299 } 299 }
300 dbg("Have %u sseqs for type %u\n", nseq->alloc, type); 300 dbg("Have %u sseqs for type %u\n", nseq->alloc, type);
@@ -319,7 +319,7 @@ struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
319 319
320 publ = publ_create(type, lower, upper, scope, node, port, key); 320 publ = publ_create(type, lower, upper, scope, node, port, key);
321 if (!publ) 321 if (!publ)
322 return 0; 322 return NULL;
323 dbg("inserting publ %x, node=%x publ->node=%x, subscr->node=%x\n", 323 dbg("inserting publ %x, node=%x publ->node=%x, subscr->node=%x\n",
324 publ, node, publ->node, publ->subscr.node); 324 publ, node, publ->node, publ->subscr.node);
325 325
@@ -369,8 +369,8 @@ struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
369 * tipc_nameseq_remove_publ - 369 * tipc_nameseq_remove_publ -
370 */ 370 */
371 371
372struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst, 372static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst,
373 u32 node, u32 ref, u32 key) 373 u32 node, u32 ref, u32 key)
374{ 374{
375 struct publication *publ; 375 struct publication *publ;
376 struct publication *prev; 376 struct publication *prev;
@@ -394,7 +394,7 @@ struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst,
394 i, &nseq->sseqs[i], nseq->sseqs[i].lower, 394 i, &nseq->sseqs[i], nseq->sseqs[i].lower,
395 nseq->sseqs[i].upper); 395 nseq->sseqs[i].upper);
396 } 396 }
397 return 0; 397 return NULL;
398 } 398 }
399 dbg("nameseq_remove: seq: %x, sseq %x, <%u,%u> key %u\n", 399 dbg("nameseq_remove: seq: %x, sseq %x, <%u,%u> key %u\n",
400 nseq, sseq, nseq->type, inst, key); 400 nseq, sseq, nseq->type, inst, key);
@@ -413,7 +413,7 @@ struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst,
413 prev->zone_list_next = publ->zone_list_next; 413 prev->zone_list_next = publ->zone_list_next;
414 sseq->zone_list = publ->zone_list_next; 414 sseq->zone_list = publ->zone_list_next;
415 } else { 415 } else {
416 sseq->zone_list = 0; 416 sseq->zone_list = NULL;
417 } 417 }
418 418
419 if (in_own_cluster(node)) { 419 if (in_own_cluster(node)) {
@@ -431,7 +431,7 @@ struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst,
431 prev->cluster_list_next = publ->cluster_list_next; 431 prev->cluster_list_next = publ->cluster_list_next;
432 sseq->cluster_list = publ->cluster_list_next; 432 sseq->cluster_list = publ->cluster_list_next;
433 } else { 433 } else {
434 sseq->cluster_list = 0; 434 sseq->cluster_list = NULL;
435 } 435 }
436 } 436 }
437 437
@@ -450,7 +450,7 @@ struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst,
450 prev->node_list_next = publ->node_list_next; 450 prev->node_list_next = publ->node_list_next;
451 sseq->node_list = publ->node_list_next; 451 sseq->node_list = publ->node_list_next;
452 } else { 452 } else {
453 sseq->node_list = 0; 453 sseq->node_list = NULL;
454 } 454 }
455 } 455 }
456 assert(!publ->node || (publ->node == node)); 456 assert(!publ->node || (publ->node == node));
@@ -535,7 +535,7 @@ static struct name_seq *nametbl_find_seq(u32 type)
535 } 535 }
536 } 536 }
537 537
538 return 0; 538 return NULL;
539}; 539};
540 540
541struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper, 541struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
@@ -547,7 +547,7 @@ struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
547 if (lower > upper) { 547 if (lower > upper) {
548 warn("Failed to publish illegal <%u,%u,%u>\n", 548 warn("Failed to publish illegal <%u,%u,%u>\n",
549 type, lower, upper); 549 type, lower, upper);
550 return 0; 550 return NULL;
551 } 551 }
552 552
553 dbg("Publishing <%u,%u,%u> from %x\n", type, lower, upper, node); 553 dbg("Publishing <%u,%u,%u> from %x\n", type, lower, upper, node);
@@ -556,7 +556,7 @@ struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
556 dbg("tipc_nametbl_insert_publ: created %x\n", seq); 556 dbg("tipc_nametbl_insert_publ: created %x\n", seq);
557 } 557 }
558 if (!seq) 558 if (!seq)
559 return 0; 559 return NULL;
560 560
561 assert(seq->type == type); 561 assert(seq->type == type);
562 return tipc_nameseq_insert_publ(seq, type, lower, upper, 562 return tipc_nameseq_insert_publ(seq, type, lower, upper,
@@ -570,7 +570,7 @@ struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
570 struct name_seq *seq = nametbl_find_seq(type); 570 struct name_seq *seq = nametbl_find_seq(type);
571 571
572 if (!seq) 572 if (!seq)
573 return 0; 573 return NULL;
574 574
575 dbg("Withdrawing <%u,%u> from %x\n", type, lower, node); 575 dbg("Withdrawing <%u,%u> from %x\n", type, lower, node);
576 publ = tipc_nameseq_remove_publ(seq, lower, node, ref, key); 576 publ = tipc_nameseq_remove_publ(seq, lower, node, ref, key);
@@ -594,7 +594,7 @@ struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
594u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode) 594u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
595{ 595{
596 struct sub_seq *sseq; 596 struct sub_seq *sseq;
597 struct publication *publ = 0; 597 struct publication *publ = NULL;
598 struct name_seq *seq; 598 struct name_seq *seq;
599 u32 ref; 599 u32 ref;
600 600
@@ -740,12 +740,12 @@ struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper,
740 if (table.local_publ_count >= tipc_max_publications) { 740 if (table.local_publ_count >= tipc_max_publications) {
741 warn("Failed publish: max %u local publication\n", 741 warn("Failed publish: max %u local publication\n",
742 tipc_max_publications); 742 tipc_max_publications);
743 return 0; 743 return NULL;
744 } 744 }
745 if ((type < TIPC_RESERVED_TYPES) && !atomic_read(&rsv_publ_ok)) { 745 if ((type < TIPC_RESERVED_TYPES) && !atomic_read(&rsv_publ_ok)) {
746 warn("Failed to publish reserved name <%u,%u,%u>\n", 746 warn("Failed to publish reserved name <%u,%u,%u>\n",
747 type, lower, upper); 747 type, lower, upper);
748 return 0; 748 return NULL;
749 } 749 }
750 750
751 write_lock_bh(&tipc_nametbl_lock); 751 write_lock_bh(&tipc_nametbl_lock);
@@ -983,6 +983,7 @@ static void nametbl_list(struct print_buf *buf, u32 depth_info,
983 } 983 }
984} 984}
985 985
986#if 0
986void tipc_nametbl_print(struct print_buf *buf, const char *str) 987void tipc_nametbl_print(struct print_buf *buf, const char *str)
987{ 988{
988 tipc_printf(buf, str); 989 tipc_printf(buf, str);
@@ -990,6 +991,7 @@ void tipc_nametbl_print(struct print_buf *buf, const char *str)
990 nametbl_list(buf, 0, 0, 0, 0); 991 nametbl_list(buf, 0, 0, 0, 0);
991 read_unlock_bh(&tipc_nametbl_lock); 992 read_unlock_bh(&tipc_nametbl_lock);
992} 993}
994#endif
993 995
994#define MAX_NAME_TBL_QUERY 32768 996#define MAX_NAME_TBL_QUERY 32768
995 997
@@ -1023,10 +1025,12 @@ struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space)
1023 return buf; 1025 return buf;
1024} 1026}
1025 1027
1028#if 0
1026void tipc_nametbl_dump(void) 1029void tipc_nametbl_dump(void)
1027{ 1030{
1028 nametbl_list(TIPC_CONS, 0, 0, 0, 0); 1031 nametbl_list(TIPC_CONS, 0, 0, 0, 0);
1029} 1032}
1033#endif
1030 1034
1031int tipc_nametbl_init(void) 1035int tipc_nametbl_init(void)
1032{ 1036{
diff --git a/net/tipc/net.c b/net/tipc/net.c
index 074891ad4f09..f7c8223ddf7d 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -116,7 +116,7 @@
116*/ 116*/
117 117
118rwlock_t tipc_net_lock = RW_LOCK_UNLOCKED; 118rwlock_t tipc_net_lock = RW_LOCK_UNLOCKED;
119struct network tipc_net = { 0 }; 119struct network tipc_net = { NULL };
120 120
121struct node *tipc_net_select_remote_node(u32 addr, u32 ref) 121struct node *tipc_net_select_remote_node(u32 addr, u32 ref)
122{ 122{
@@ -128,13 +128,14 @@ u32 tipc_net_select_router(u32 addr, u32 ref)
128 return tipc_zone_select_router(tipc_net.zones[tipc_zone(addr)], addr, ref); 128 return tipc_zone_select_router(tipc_net.zones[tipc_zone(addr)], addr, ref);
129} 129}
130 130
131 131#if 0
132u32 tipc_net_next_node(u32 a) 132u32 tipc_net_next_node(u32 a)
133{ 133{
134 if (tipc_net.zones[tipc_zone(a)]) 134 if (tipc_net.zones[tipc_zone(a)])
135 return tipc_zone_next_node(a); 135 return tipc_zone_next_node(a);
136 return 0; 136 return 0;
137} 137}
138#endif
138 139
139void tipc_net_remove_as_router(u32 router) 140void tipc_net_remove_as_router(u32 router)
140{ 141{
@@ -181,7 +182,7 @@ static void net_stop(void)
181 tipc_zone_delete(tipc_net.zones[z_num]); 182 tipc_zone_delete(tipc_net.zones[z_num]);
182 } 183 }
183 kfree(tipc_net.zones); 184 kfree(tipc_net.zones);
184 tipc_net.zones = 0; 185 tipc_net.zones = NULL;
185} 186}
186 187
187static void net_route_named_msg(struct sk_buff *buf) 188static void net_route_named_msg(struct sk_buff *buf)
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 6d65010e5fa1..0d5db06e203f 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -155,7 +155,7 @@ static void node_select_active_links(struct node *n_ptr)
155 u32 i; 155 u32 i;
156 u32 highest_prio = 0; 156 u32 highest_prio = 0;
157 157
158 active[0] = active[1] = 0; 158 active[0] = active[1] = NULL;
159 159
160 for (i = 0; i < MAX_BEARERS; i++) { 160 for (i = 0; i < MAX_BEARERS; i++) {
161 struct link *l_ptr = n_ptr->links[i]; 161 struct link *l_ptr = n_ptr->links[i];
@@ -214,7 +214,7 @@ int tipc_node_has_redundant_links(struct node *n_ptr)
214 (n_ptr->active_links[0] != n_ptr->active_links[1])); 214 (n_ptr->active_links[0] != n_ptr->active_links[1]));
215} 215}
216 216
217int tipc_node_has_active_routes(struct node *n_ptr) 217static int tipc_node_has_active_routes(struct node *n_ptr)
218{ 218{
219 return (n_ptr && (n_ptr->last_router >= 0)); 219 return (n_ptr && (n_ptr->last_router >= 0));
220} 220}
@@ -240,7 +240,7 @@ struct node *tipc_node_attach_link(struct link *l_ptr)
240 240
241 err("Attempt to create third link to %s\n", 241 err("Attempt to create third link to %s\n",
242 addr_string_fill(addr_string, n_ptr->addr)); 242 addr_string_fill(addr_string, n_ptr->addr));
243 return 0; 243 return NULL;
244 } 244 }
245 245
246 if (!n_ptr->links[bearer_id]) { 246 if (!n_ptr->links[bearer_id]) {
@@ -253,12 +253,12 @@ struct node *tipc_node_attach_link(struct link *l_ptr)
253 l_ptr->b_ptr->publ.name, 253 l_ptr->b_ptr->publ.name,
254 addr_string_fill(addr_string, l_ptr->addr)); 254 addr_string_fill(addr_string, l_ptr->addr));
255 } 255 }
256 return 0; 256 return NULL;
257} 257}
258 258
259void tipc_node_detach_link(struct node *n_ptr, struct link *l_ptr) 259void tipc_node_detach_link(struct node *n_ptr, struct link *l_ptr)
260{ 260{
261 n_ptr->links[l_ptr->b_ptr->identity] = 0; 261 n_ptr->links[l_ptr->b_ptr->identity] = NULL;
262 tipc_net.zones[tipc_zone(l_ptr->addr)]->links--; 262 tipc_net.zones[tipc_zone(l_ptr->addr)]->links--;
263 n_ptr->link_cnt--; 263 n_ptr->link_cnt--;
264} 264}
@@ -424,7 +424,7 @@ static void node_lost_contact(struct node *n_ptr)
424 424
425 /* Notify subscribers */ 425 /* Notify subscribers */
426 list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) { 426 list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) {
427 ns->node = 0; 427 ns->node = NULL;
428 list_del_init(&ns->nodesub_list); 428 list_del_init(&ns->nodesub_list);
429 tipc_k_signal((Handler)ns->handle_node_down, 429 tipc_k_signal((Handler)ns->handle_node_down,
430 (unsigned long)ns->usr_handle); 430 (unsigned long)ns->usr_handle);
@@ -443,7 +443,7 @@ struct node *tipc_node_select_next_hop(u32 addr, u32 selector)
443 u32 router_addr; 443 u32 router_addr;
444 444
445 if (!tipc_addr_domain_valid(addr)) 445 if (!tipc_addr_domain_valid(addr))
446 return 0; 446 return NULL;
447 447
448 /* Look for direct link to destination processsor */ 448 /* Look for direct link to destination processsor */
449 n_ptr = tipc_node_find(addr); 449 n_ptr = tipc_node_find(addr);
@@ -452,7 +452,7 @@ struct node *tipc_node_select_next_hop(u32 addr, u32 selector)
452 452
453 /* Cluster local system nodes *must* have direct links */ 453 /* Cluster local system nodes *must* have direct links */
454 if (!is_slave(addr) && in_own_cluster(addr)) 454 if (!is_slave(addr) && in_own_cluster(addr))
455 return 0; 455 return NULL;
456 456
457 /* Look for cluster local router with direct link to node */ 457 /* Look for cluster local router with direct link to node */
458 router_addr = tipc_node_select_router(n_ptr, selector); 458 router_addr = tipc_node_select_router(n_ptr, selector);
@@ -462,7 +462,7 @@ struct node *tipc_node_select_next_hop(u32 addr, u32 selector)
462 /* Slave nodes can only be accessed within own cluster via a 462 /* Slave nodes can only be accessed within own cluster via a
463 known router with direct link -- if no router was found,give up */ 463 known router with direct link -- if no router was found,give up */
464 if (is_slave(addr)) 464 if (is_slave(addr))
465 return 0; 465 return NULL;
466 466
467 /* Inter zone/cluster -- find any direct link to remote cluster */ 467 /* Inter zone/cluster -- find any direct link to remote cluster */
468 addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0); 468 addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0);
@@ -475,7 +475,7 @@ struct node *tipc_node_select_next_hop(u32 addr, u32 selector)
475 if (router_addr) 475 if (router_addr)
476 return tipc_node_select(router_addr, selector); 476 return tipc_node_select(router_addr, selector);
477 477
478 return 0; 478 return NULL;
479} 479}
480 480
481/** 481/**
diff --git a/net/tipc/node.h b/net/tipc/node.h
index 29f7ae6992d4..781126e084ae 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -121,7 +121,7 @@ static inline struct node *tipc_node_find(u32 addr)
121 if (c_ptr) 121 if (c_ptr)
122 return c_ptr->nodes[tipc_node(addr)]; 122 return c_ptr->nodes[tipc_node(addr)];
123 } 123 }
124 return 0; 124 return NULL;
125} 125}
126 126
127static inline struct node *tipc_node_select(u32 addr, u32 selector) 127static inline struct node *tipc_node_select(u32 addr, u32 selector)
diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c
index afeea121d8be..cff4068cc755 100644
--- a/net/tipc/node_subscr.c
+++ b/net/tipc/node_subscr.c
@@ -47,7 +47,7 @@
47void tipc_nodesub_subscribe(struct node_subscr *node_sub, u32 addr, 47void tipc_nodesub_subscribe(struct node_subscr *node_sub, u32 addr,
48 void *usr_handle, net_ev_handler handle_down) 48 void *usr_handle, net_ev_handler handle_down)
49{ 49{
50 node_sub->node = 0; 50 node_sub->node = NULL;
51 if (addr == tipc_own_addr) 51 if (addr == tipc_own_addr)
52 return; 52 return;
53 if (!tipc_addr_node_valid(addr)) { 53 if (!tipc_addr_node_valid(addr)) {
diff --git a/net/tipc/port.c b/net/tipc/port.c
index 72aae52bfec1..67e96cb1e825 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -54,8 +54,8 @@
54 54
55#define MAX_REJECT_SIZE 1024 55#define MAX_REJECT_SIZE 1024
56 56
57static struct sk_buff *msg_queue_head = 0; 57static struct sk_buff *msg_queue_head = NULL;
58static struct sk_buff *msg_queue_tail = 0; 58static struct sk_buff *msg_queue_tail = NULL;
59 59
60spinlock_t tipc_port_list_lock = SPIN_LOCK_UNLOCKED; 60spinlock_t tipc_port_list_lock = SPIN_LOCK_UNLOCKED;
61static spinlock_t queue_lock = SPIN_LOCK_UNLOCKED; 61static spinlock_t queue_lock = SPIN_LOCK_UNLOCKED;
@@ -67,27 +67,22 @@ static struct sk_buff* port_build_peer_abort_msg(struct port *,u32 err);
67static void port_timeout(unsigned long ref); 67static void port_timeout(unsigned long ref);
68 68
69 69
70static inline u32 port_peernode(struct port *p_ptr) 70static u32 port_peernode(struct port *p_ptr)
71{ 71{
72 return msg_destnode(&p_ptr->publ.phdr); 72 return msg_destnode(&p_ptr->publ.phdr);
73} 73}
74 74
75static inline u32 port_peerport(struct port *p_ptr) 75static u32 port_peerport(struct port *p_ptr)
76{ 76{
77 return msg_destport(&p_ptr->publ.phdr); 77 return msg_destport(&p_ptr->publ.phdr);
78} 78}
79 79
80static inline u32 port_out_seqno(struct port *p_ptr) 80static u32 port_out_seqno(struct port *p_ptr)
81{ 81{
82 return msg_transp_seqno(&p_ptr->publ.phdr); 82 return msg_transp_seqno(&p_ptr->publ.phdr);
83} 83}
84 84
85static inline void port_set_out_seqno(struct port *p_ptr, u32 seqno) 85static void port_incr_out_seqno(struct port *p_ptr)
86{
87 msg_set_transp_seqno(&p_ptr->publ.phdr,seqno);
88}
89
90static inline void port_incr_out_seqno(struct port *p_ptr)
91{ 86{
92 struct tipc_msg *m = &p_ptr->publ.phdr; 87 struct tipc_msg *m = &p_ptr->publ.phdr;
93 88
@@ -258,11 +253,11 @@ u32 tipc_createport_raw(void *usr_handle,
258 p_ptr->publ.usr_handle = usr_handle; 253 p_ptr->publ.usr_handle = usr_handle;
259 INIT_LIST_HEAD(&p_ptr->wait_list); 254 INIT_LIST_HEAD(&p_ptr->wait_list);
260 INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); 255 INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list);
261 p_ptr->congested_link = 0; 256 p_ptr->congested_link = NULL;
262 p_ptr->max_pkt = MAX_PKT_DEFAULT; 257 p_ptr->max_pkt = MAX_PKT_DEFAULT;
263 p_ptr->dispatcher = dispatcher; 258 p_ptr->dispatcher = dispatcher;
264 p_ptr->wakeup = wakeup; 259 p_ptr->wakeup = wakeup;
265 p_ptr->user_port = 0; 260 p_ptr->user_port = NULL;
266 k_init_timer(&p_ptr->timer, (Handler)port_timeout, ref); 261 k_init_timer(&p_ptr->timer, (Handler)port_timeout, ref);
267 spin_lock_bh(&tipc_port_list_lock); 262 spin_lock_bh(&tipc_port_list_lock);
268 INIT_LIST_HEAD(&p_ptr->publications); 263 INIT_LIST_HEAD(&p_ptr->publications);
@@ -276,9 +271,9 @@ u32 tipc_createport_raw(void *usr_handle,
276int tipc_deleteport(u32 ref) 271int tipc_deleteport(u32 ref)
277{ 272{
278 struct port *p_ptr; 273 struct port *p_ptr;
279 struct sk_buff *buf = 0; 274 struct sk_buff *buf = NULL;
280 275
281 tipc_withdraw(ref, 0, 0); 276 tipc_withdraw(ref, 0, NULL);
282 p_ptr = tipc_port_lock(ref); 277 p_ptr = tipc_port_lock(ref);
283 if (!p_ptr) 278 if (!p_ptr)
284 return -EINVAL; 279 return -EINVAL;
@@ -329,13 +324,13 @@ void *tipc_get_handle(const u32 ref)
329 324
330 p_ptr = tipc_port_lock(ref); 325 p_ptr = tipc_port_lock(ref);
331 if (!p_ptr) 326 if (!p_ptr)
332 return 0; 327 return NULL;
333 handle = p_ptr->publ.usr_handle; 328 handle = p_ptr->publ.usr_handle;
334 tipc_port_unlock(p_ptr); 329 tipc_port_unlock(p_ptr);
335 return handle; 330 return handle;
336} 331}
337 332
338static inline int port_unreliable(struct port *p_ptr) 333static int port_unreliable(struct port *p_ptr)
339{ 334{
340 return msg_src_droppable(&p_ptr->publ.phdr); 335 return msg_src_droppable(&p_ptr->publ.phdr);
341} 336}
@@ -364,7 +359,7 @@ int tipc_set_portunreliable(u32 ref, unsigned int isunreliable)
364 return TIPC_OK; 359 return TIPC_OK;
365} 360}
366 361
367static inline int port_unreturnable(struct port *p_ptr) 362static int port_unreturnable(struct port *p_ptr)
368{ 363{
369 return msg_dest_droppable(&p_ptr->publ.phdr); 364 return msg_dest_droppable(&p_ptr->publ.phdr);
370} 365}
@@ -475,7 +470,7 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err)
475 470
476 /* send self-abort message when rejecting on a connected port */ 471 /* send self-abort message when rejecting on a connected port */
477 if (msg_connected(msg)) { 472 if (msg_connected(msg)) {
478 struct sk_buff *abuf = 0; 473 struct sk_buff *abuf = NULL;
479 struct port *p_ptr = tipc_port_lock(msg_destport(msg)); 474 struct port *p_ptr = tipc_port_lock(msg_destport(msg));
480 475
481 if (p_ptr) { 476 if (p_ptr) {
@@ -510,7 +505,7 @@ int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr,
510static void port_timeout(unsigned long ref) 505static void port_timeout(unsigned long ref)
511{ 506{
512 struct port *p_ptr = tipc_port_lock(ref); 507 struct port *p_ptr = tipc_port_lock(ref);
513 struct sk_buff *buf = 0; 508 struct sk_buff *buf = NULL;
514 509
515 if (!p_ptr || !p_ptr->publ.connected) 510 if (!p_ptr || !p_ptr->publ.connected)
516 return; 511 return;
@@ -540,7 +535,7 @@ static void port_timeout(unsigned long ref)
540static void port_handle_node_down(unsigned long ref) 535static void port_handle_node_down(unsigned long ref)
541{ 536{
542 struct port *p_ptr = tipc_port_lock(ref); 537 struct port *p_ptr = tipc_port_lock(ref);
543 struct sk_buff* buf = 0; 538 struct sk_buff* buf = NULL;
544 539
545 if (!p_ptr) 540 if (!p_ptr)
546 return; 541 return;
@@ -555,7 +550,7 @@ static struct sk_buff *port_build_self_abort_msg(struct port *p_ptr, u32 err)
555 u32 imp = msg_importance(&p_ptr->publ.phdr); 550 u32 imp = msg_importance(&p_ptr->publ.phdr);
556 551
557 if (!p_ptr->publ.connected) 552 if (!p_ptr->publ.connected)
558 return 0; 553 return NULL;
559 if (imp < TIPC_CRITICAL_IMPORTANCE) 554 if (imp < TIPC_CRITICAL_IMPORTANCE)
560 imp++; 555 imp++;
561 return port_build_proto_msg(p_ptr->publ.ref, 556 return port_build_proto_msg(p_ptr->publ.ref,
@@ -575,7 +570,7 @@ static struct sk_buff *port_build_peer_abort_msg(struct port *p_ptr, u32 err)
575 u32 imp = msg_importance(&p_ptr->publ.phdr); 570 u32 imp = msg_importance(&p_ptr->publ.phdr);
576 571
577 if (!p_ptr->publ.connected) 572 if (!p_ptr->publ.connected)
578 return 0; 573 return NULL;
579 if (imp < TIPC_CRITICAL_IMPORTANCE) 574 if (imp < TIPC_CRITICAL_IMPORTANCE)
580 imp++; 575 imp++;
581 return port_build_proto_msg(port_peerport(p_ptr), 576 return port_build_proto_msg(port_peerport(p_ptr),
@@ -594,8 +589,8 @@ void tipc_port_recv_proto_msg(struct sk_buff *buf)
594 struct tipc_msg *msg = buf_msg(buf); 589 struct tipc_msg *msg = buf_msg(buf);
595 struct port *p_ptr = tipc_port_lock(msg_destport(msg)); 590 struct port *p_ptr = tipc_port_lock(msg_destport(msg));
596 u32 err = TIPC_OK; 591 u32 err = TIPC_OK;
597 struct sk_buff *r_buf = 0; 592 struct sk_buff *r_buf = NULL;
598 struct sk_buff *abort_buf = 0; 593 struct sk_buff *abort_buf = NULL;
599 594
600 msg_dbg(msg, "PORT<RECV<:"); 595 msg_dbg(msg, "PORT<RECV<:");
601 596
@@ -804,7 +799,7 @@ static void port_dispatcher_sigh(void *dummy)
804 799
805 spin_lock_bh(&queue_lock); 800 spin_lock_bh(&queue_lock);
806 buf = msg_queue_head; 801 buf = msg_queue_head;
807 msg_queue_head = 0; 802 msg_queue_head = NULL;
808 spin_unlock_bh(&queue_lock); 803 spin_unlock_bh(&queue_lock);
809 804
810 while (buf) { 805 while (buf) {
@@ -991,8 +986,8 @@ static void port_wakeup_sh(unsigned long ref)
991{ 986{
992 struct port *p_ptr; 987 struct port *p_ptr;
993 struct user_port *up_ptr; 988 struct user_port *up_ptr;
994 tipc_continue_event cb = 0; 989 tipc_continue_event cb = NULL;
995 void *uh = 0; 990 void *uh = NULL;
996 991
997 p_ptr = tipc_port_lock(ref); 992 p_ptr = tipc_port_lock(ref);
998 if (p_ptr) { 993 if (p_ptr) {
@@ -1016,7 +1011,7 @@ static void port_wakeup(struct tipc_port *p_ptr)
1016void tipc_acknowledge(u32 ref, u32 ack) 1011void tipc_acknowledge(u32 ref, u32 ack)
1017{ 1012{
1018 struct port *p_ptr; 1013 struct port *p_ptr;
1019 struct sk_buff *buf = 0; 1014 struct sk_buff *buf = NULL;
1020 1015
1021 p_ptr = tipc_port_lock(ref); 1016 p_ptr = tipc_port_lock(ref);
1022 if (!p_ptr) 1017 if (!p_ptr)
@@ -1062,7 +1057,7 @@ int tipc_createport(u32 user_ref,
1062 if (up_ptr == NULL) { 1057 if (up_ptr == NULL) {
1063 return -ENOMEM; 1058 return -ENOMEM;
1064 } 1059 }
1065 ref = tipc_createport_raw(0, port_dispatcher, port_wakeup, importance); 1060 ref = tipc_createport_raw(NULL, port_dispatcher, port_wakeup, importance);
1066 p_ptr = tipc_port_lock(ref); 1061 p_ptr = tipc_port_lock(ref);
1067 if (!p_ptr) { 1062 if (!p_ptr) {
1068 kfree(up_ptr); 1063 kfree(up_ptr);
@@ -1273,7 +1268,7 @@ int tipc_disconnect(u32 ref)
1273int tipc_shutdown(u32 ref) 1268int tipc_shutdown(u32 ref)
1274{ 1269{
1275 struct port *p_ptr; 1270 struct port *p_ptr;
1276 struct sk_buff *buf = 0; 1271 struct sk_buff *buf = NULL;
1277 1272
1278 p_ptr = tipc_port_lock(ref); 1273 p_ptr = tipc_port_lock(ref);
1279 if (!p_ptr) 1274 if (!p_ptr)
diff --git a/net/tipc/ref.c b/net/tipc/ref.c
index 5a13c2defe4a..33bbf5095094 100644
--- a/net/tipc/ref.c
+++ b/net/tipc/ref.c
@@ -61,7 +61,7 @@
61 * because entry 0's reference field has the form XXXX|1--1. 61 * because entry 0's reference field has the form XXXX|1--1.
62 */ 62 */
63 63
64struct ref_table tipc_ref_table = { 0 }; 64struct ref_table tipc_ref_table = { NULL };
65 65
66static rwlock_t ref_table_lock = RW_LOCK_UNLOCKED; 66static rwlock_t ref_table_lock = RW_LOCK_UNLOCKED;
67 67
@@ -86,7 +86,7 @@ int tipc_ref_table_init(u32 requested_size, u32 start)
86 write_lock_bh(&ref_table_lock); 86 write_lock_bh(&ref_table_lock);
87 index_mask = sz - 1; 87 index_mask = sz - 1;
88 for (i = sz - 1; i >= 0; i--) { 88 for (i = sz - 1; i >= 0; i--) {
89 table[i].object = 0; 89 table[i].object = NULL;
90 table[i].lock = SPIN_LOCK_UNLOCKED; 90 table[i].lock = SPIN_LOCK_UNLOCKED;
91 table[i].data.next_plus_upper = (start & ~index_mask) + i - 1; 91 table[i].data.next_plus_upper = (start & ~index_mask) + i - 1;
92 } 92 }
@@ -108,7 +108,7 @@ void tipc_ref_table_stop(void)
108 return; 108 return;
109 109
110 vfree(tipc_ref_table.entries); 110 vfree(tipc_ref_table.entries);
111 tipc_ref_table.entries = 0; 111 tipc_ref_table.entries = NULL;
112} 112}
113 113
114/** 114/**
@@ -173,7 +173,7 @@ void tipc_ref_discard(u32 ref)
173 assert(entry->data.reference == ref); 173 assert(entry->data.reference == ref);
174 174
175 /* mark entry as unused */ 175 /* mark entry as unused */
176 entry->object = 0; 176 entry->object = NULL;
177 if (tipc_ref_table.first_free == 0) 177 if (tipc_ref_table.first_free == 0)
178 tipc_ref_table.first_free = index; 178 tipc_ref_table.first_free = index;
179 else 179 else
diff --git a/net/tipc/ref.h b/net/tipc/ref.h
index 4f8f9f40dcac..6d20006be45b 100644
--- a/net/tipc/ref.h
+++ b/net/tipc/ref.h
@@ -92,7 +92,7 @@ static inline void *tipc_ref_lock(u32 ref)
92 return r->object; 92 return r->object;
93 spin_unlock_bh(&r->lock); 93 spin_unlock_bh(&r->lock);
94 } 94 }
95 return 0; 95 return NULL;
96} 96}
97 97
98/** 98/**
@@ -125,7 +125,7 @@ static inline void *tipc_ref_deref(u32 ref)
125 if (likely(r->data.reference == ref)) 125 if (likely(r->data.reference == ref))
126 return r->object; 126 return r->object;
127 } 127 }
128 return 0; 128 return NULL;
129} 129}
130 130
131#endif 131#endif
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 67253bfcd702..648a734e6044 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -88,7 +88,7 @@ static atomic_t tipc_queue_size = ATOMIC_INIT(0);
88 * with non-socket interfaces. 88 * with non-socket interfaces.
89 * See net.c for description of locking policy. 89 * See net.c for description of locking policy.
90 */ 90 */
91static inline void sock_lock(struct tipc_sock* tsock) 91static void sock_lock(struct tipc_sock* tsock)
92{ 92{
93 spin_lock_bh(tsock->p->lock); 93 spin_lock_bh(tsock->p->lock);
94} 94}
@@ -96,7 +96,7 @@ static inline void sock_lock(struct tipc_sock* tsock)
96/* 96/*
97 * sock_unlock(): Unlock a port/socket pair 97 * sock_unlock(): Unlock a port/socket pair
98 */ 98 */
99static inline void sock_unlock(struct tipc_sock* tsock) 99static void sock_unlock(struct tipc_sock* tsock)
100{ 100{
101 spin_unlock_bh(tsock->p->lock); 101 spin_unlock_bh(tsock->p->lock);
102} 102}
@@ -119,7 +119,7 @@ static inline void sock_unlock(struct tipc_sock* tsock)
119 * Returns pollmask value 119 * Returns pollmask value
120 */ 120 */
121 121
122static inline u32 pollmask(struct socket *sock) 122static u32 pollmask(struct socket *sock)
123{ 123{
124 u32 mask; 124 u32 mask;
125 125
@@ -144,7 +144,7 @@ static inline u32 pollmask(struct socket *sock)
144 * @tsock: TIPC socket 144 * @tsock: TIPC socket
145 */ 145 */
146 146
147static inline void advance_queue(struct tipc_sock *tsock) 147static void advance_queue(struct tipc_sock *tsock)
148{ 148{
149 sock_lock(tsock); 149 sock_lock(tsock);
150 buf_discard(skb_dequeue(&tsock->sk.sk_receive_queue)); 150 buf_discard(skb_dequeue(&tsock->sk.sk_receive_queue));
@@ -178,7 +178,7 @@ static int tipc_create(struct socket *sock, int protocol)
178 if (unlikely(protocol != 0)) 178 if (unlikely(protocol != 0))
179 return -EPROTONOSUPPORT; 179 return -EPROTONOSUPPORT;
180 180
181 ref = tipc_createport_raw(0, &dispatch, &wakeupdispatch, TIPC_LOW_IMPORTANCE); 181 ref = tipc_createport_raw(NULL, &dispatch, &wakeupdispatch, TIPC_LOW_IMPORTANCE);
182 if (unlikely(!ref)) 182 if (unlikely(!ref))
183 return -ENOMEM; 183 return -ENOMEM;
184 184
@@ -265,7 +265,7 @@ static int release(struct socket *sock)
265 sock_lock(tsock); 265 sock_lock(tsock);
266 buf = skb_dequeue(&sk->sk_receive_queue); 266 buf = skb_dequeue(&sk->sk_receive_queue);
267 if (!buf) 267 if (!buf)
268 tsock->p->usr_handle = 0; 268 tsock->p->usr_handle = NULL;
269 sock_unlock(tsock); 269 sock_unlock(tsock);
270 if (!buf) 270 if (!buf)
271 break; 271 break;
@@ -319,7 +319,7 @@ static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len)
319 return -ERESTARTSYS; 319 return -ERESTARTSYS;
320 320
321 if (unlikely(!uaddr_len)) { 321 if (unlikely(!uaddr_len)) {
322 res = tipc_withdraw(tsock->p->ref, 0, 0); 322 res = tipc_withdraw(tsock->p->ref, 0, NULL);
323 goto exit; 323 goto exit;
324 } 324 }
325 325
@@ -412,7 +412,7 @@ static unsigned int poll(struct file *file, struct socket *sock,
412 * Returns 0 if permission is granted, otherwise errno 412 * Returns 0 if permission is granted, otherwise errno
413 */ 413 */
414 414
415static inline int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) 415static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m)
416{ 416{
417 struct tipc_cfg_msg_hdr hdr; 417 struct tipc_cfg_msg_hdr hdr;
418 418
@@ -695,7 +695,7 @@ static int auto_connect(struct socket *sock, struct tipc_sock *tsock,
695 * Note: Address is not captured if not requested by receiver. 695 * Note: Address is not captured if not requested by receiver.
696 */ 696 */
697 697
698static inline void set_orig_addr(struct msghdr *m, struct tipc_msg *msg) 698static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg)
699{ 699{
700 struct sockaddr_tipc *addr = (struct sockaddr_tipc *)m->msg_name; 700 struct sockaddr_tipc *addr = (struct sockaddr_tipc *)m->msg_name;
701 701
@@ -721,7 +721,7 @@ static inline void set_orig_addr(struct msghdr *m, struct tipc_msg *msg)
721 * Returns 0 if successful, otherwise errno 721 * Returns 0 if successful, otherwise errno
722 */ 722 */
723 723
724static inline int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, 724static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
725 struct tipc_port *tport) 725 struct tipc_port *tport)
726{ 726{
727 u32 anc_data[3]; 727 u32 anc_data[3];
@@ -1226,7 +1226,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
1226{ 1226{
1227 struct tipc_sock *tsock = tipc_sk(sock->sk); 1227 struct tipc_sock *tsock = tipc_sk(sock->sk);
1228 struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; 1228 struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
1229 struct msghdr m = {0,}; 1229 struct msghdr m = {NULL,};
1230 struct sk_buff *buf; 1230 struct sk_buff *buf;
1231 struct tipc_msg *msg; 1231 struct tipc_msg *msg;
1232 int res; 1232 int res;
@@ -1251,7 +1251,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
1251 /* Send a 'SYN-' to destination */ 1251 /* Send a 'SYN-' to destination */
1252 1252
1253 m.msg_name = dest; 1253 m.msg_name = dest;
1254 if ((res = send_msg(0, sock, &m, 0)) < 0) { 1254 if ((res = send_msg(NULL, sock, &m, 0)) < 0) {
1255 sock->state = SS_DISCONNECTING; 1255 sock->state = SS_DISCONNECTING;
1256 return res; 1256 return res;
1257 } 1257 }
@@ -1367,9 +1367,9 @@ static int accept(struct socket *sock, struct socket *newsock, int flags)
1367 1367
1368 msg_dbg(msg,"<ACC<: "); 1368 msg_dbg(msg,"<ACC<: ");
1369 if (!msg_data_sz(msg)) { 1369 if (!msg_data_sz(msg)) {
1370 struct msghdr m = {0,}; 1370 struct msghdr m = {NULL,};
1371 1371
1372 send_packet(0, newsock, &m, 0); 1372 send_packet(NULL, newsock, &m, 0);
1373 advance_queue(tsock); 1373 advance_queue(tsock);
1374 } else { 1374 } else {
1375 sock_lock(tsock); 1375 sock_lock(tsock);
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
index 5ff38b9f3194..c5f026c7fd38 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -86,7 +86,7 @@ static struct top_srv topsrv = { 0 };
86 * Returns converted value 86 * Returns converted value
87 */ 87 */
88 88
89static inline u32 htohl(u32 in, int swap) 89static u32 htohl(u32 in, int swap)
90{ 90{
91 char *c = (char *)&in; 91 char *c = (char *)&in;
92 92
@@ -381,7 +381,7 @@ static void subscr_named_msg_event(void *usr_handle,
381 struct tipc_name_seq const *dest) 381 struct tipc_name_seq const *dest)
382{ 382{
383 struct subscriber *subscriber; 383 struct subscriber *subscriber;
384 struct iovec msg_sect = {0, 0}; 384 struct iovec msg_sect = {NULL, 0};
385 spinlock_t *subscriber_lock; 385 spinlock_t *subscriber_lock;
386 386
387 dbg("subscr_named_msg_event: orig = %x own = %x,\n", 387 dbg("subscr_named_msg_event: orig = %x own = %x,\n",
@@ -413,13 +413,13 @@ static void subscr_named_msg_event(void *usr_handle,
413 tipc_createport(topsrv.user_ref, 413 tipc_createport(topsrv.user_ref,
414 (void *)(unsigned long)subscriber->ref, 414 (void *)(unsigned long)subscriber->ref,
415 importance, 415 importance,
416 0, 416 NULL,
417 0, 417 NULL,
418 subscr_conn_shutdown_event, 418 subscr_conn_shutdown_event,
419 0, 419 NULL,
420 0, 420 NULL,
421 subscr_conn_msg_event, 421 subscr_conn_msg_event,
422 0, 422 NULL,
423 &subscriber->port_ref); 423 &subscriber->port_ref);
424 if (subscriber->port_ref == 0) { 424 if (subscriber->port_ref == 0) {
425 warn("Memory squeeze; failed to create subscription port\n"); 425 warn("Memory squeeze; failed to create subscription port\n");
@@ -461,22 +461,22 @@ int tipc_subscr_start(void)
461 INIT_LIST_HEAD(&topsrv.subscriber_list); 461 INIT_LIST_HEAD(&topsrv.subscriber_list);
462 462
463 spin_lock_bh(&topsrv.lock); 463 spin_lock_bh(&topsrv.lock);
464 res = tipc_attach(&topsrv.user_ref, 0, 0); 464 res = tipc_attach(&topsrv.user_ref, NULL, NULL);
465 if (res) { 465 if (res) {
466 spin_unlock_bh(&topsrv.lock); 466 spin_unlock_bh(&topsrv.lock);
467 return res; 467 return res;
468 } 468 }
469 469
470 res = tipc_createport(topsrv.user_ref, 470 res = tipc_createport(topsrv.user_ref,
471 0, 471 NULL,
472 TIPC_CRITICAL_IMPORTANCE, 472 TIPC_CRITICAL_IMPORTANCE,
473 0, 473 NULL,
474 0, 474 NULL,
475 0, 475 NULL,
476 0, 476 NULL,
477 subscr_named_msg_event, 477 subscr_named_msg_event,
478 0, 478 NULL,
479 0, 479 NULL,
480 &topsrv.setup_port); 480 &topsrv.setup_port);
481 if (res) 481 if (res)
482 goto failed; 482 goto failed;
diff --git a/net/tipc/user_reg.c b/net/tipc/user_reg.c
index 106200d76587..3f3f933976e9 100644
--- a/net/tipc/user_reg.c
+++ b/net/tipc/user_reg.c
@@ -65,7 +65,7 @@ struct tipc_user {
65#define MAX_USERID 64 65#define MAX_USERID 64
66#define USER_LIST_SIZE ((MAX_USERID + 1) * sizeof(struct tipc_user)) 66#define USER_LIST_SIZE ((MAX_USERID + 1) * sizeof(struct tipc_user))
67 67
68static struct tipc_user *users = 0; 68static struct tipc_user *users = NULL;
69static u32 next_free_user = MAX_USERID + 1; 69static u32 next_free_user = MAX_USERID + 1;
70static spinlock_t reg_lock = SPIN_LOCK_UNLOCKED; 70static spinlock_t reg_lock = SPIN_LOCK_UNLOCKED;
71 71
@@ -149,7 +149,7 @@ void tipc_reg_stop(void)
149 reg_callback(&users[id]); 149 reg_callback(&users[id]);
150 } 150 }
151 kfree(users); 151 kfree(users);
152 users = 0; 152 users = NULL;
153} 153}
154 154
155/** 155/**
diff --git a/net/tipc/zone.c b/net/tipc/zone.c
index 7c11f7f83a21..2803e1b4f170 100644
--- a/net/tipc/zone.c
+++ b/net/tipc/zone.c
@@ -44,11 +44,11 @@
44 44
45struct _zone *tipc_zone_create(u32 addr) 45struct _zone *tipc_zone_create(u32 addr)
46{ 46{
47 struct _zone *z_ptr = 0; 47 struct _zone *z_ptr = NULL;
48 u32 z_num; 48 u32 z_num;
49 49
50 if (!tipc_addr_domain_valid(addr)) 50 if (!tipc_addr_domain_valid(addr))
51 return 0; 51 return NULL;
52 52
53 z_ptr = (struct _zone *)kmalloc(sizeof(*z_ptr), GFP_ATOMIC); 53 z_ptr = (struct _zone *)kmalloc(sizeof(*z_ptr), GFP_ATOMIC);
54 if (z_ptr != NULL) { 54 if (z_ptr != NULL) {
@@ -114,10 +114,10 @@ struct node *tipc_zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref
114 u32 c_num; 114 u32 c_num;
115 115
116 if (!z_ptr) 116 if (!z_ptr)
117 return 0; 117 return NULL;
118 c_ptr = z_ptr->clusters[tipc_cluster(addr)]; 118 c_ptr = z_ptr->clusters[tipc_cluster(addr)];
119 if (!c_ptr) 119 if (!c_ptr)
120 return 0; 120 return NULL;
121 n_ptr = tipc_cltr_select_node(c_ptr, ref); 121 n_ptr = tipc_cltr_select_node(c_ptr, ref);
122 if (n_ptr) 122 if (n_ptr)
123 return n_ptr; 123 return n_ptr;
@@ -126,12 +126,12 @@ struct node *tipc_zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref
126 for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { 126 for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
127 c_ptr = z_ptr->clusters[c_num]; 127 c_ptr = z_ptr->clusters[c_num];
128 if (!c_ptr) 128 if (!c_ptr)
129 return 0; 129 return NULL;
130 n_ptr = tipc_cltr_select_node(c_ptr, ref); 130 n_ptr = tipc_cltr_select_node(c_ptr, ref);
131 if (n_ptr) 131 if (n_ptr)
132 return n_ptr; 132 return n_ptr;
133 } 133 }
134 return 0; 134 return NULL;
135} 135}
136 136
137u32 tipc_zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref) 137u32 tipc_zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index c323cc6a28b0..2b4cc2eea5b3 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -566,7 +566,7 @@ static struct sock * unix_create1(struct socket *sock)
566 u->mnt = NULL; 566 u->mnt = NULL;
567 spin_lock_init(&u->lock); 567 spin_lock_init(&u->lock);
568 atomic_set(&u->inflight, sock ? 0 : -1); 568 atomic_set(&u->inflight, sock ? 0 : -1);
569 init_MUTEX(&u->readsem); /* single task reading lock */ 569 mutex_init(&u->readlock); /* single task reading lock */
570 init_waitqueue_head(&u->peer_wait); 570 init_waitqueue_head(&u->peer_wait);
571 unix_insert_socket(unix_sockets_unbound, sk); 571 unix_insert_socket(unix_sockets_unbound, sk);
572out: 572out:
@@ -623,7 +623,7 @@ static int unix_autobind(struct socket *sock)
623 struct unix_address * addr; 623 struct unix_address * addr;
624 int err; 624 int err;
625 625
626 down(&u->readsem); 626 mutex_lock(&u->readlock);
627 627
628 err = 0; 628 err = 0;
629 if (u->addr) 629 if (u->addr)
@@ -661,7 +661,7 @@ retry:
661 spin_unlock(&unix_table_lock); 661 spin_unlock(&unix_table_lock);
662 err = 0; 662 err = 0;
663 663
664out: up(&u->readsem); 664out: mutex_unlock(&u->readlock);
665 return err; 665 return err;
666} 666}
667 667
@@ -744,7 +744,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
744 goto out; 744 goto out;
745 addr_len = err; 745 addr_len = err;
746 746
747 down(&u->readsem); 747 mutex_lock(&u->readlock);
748 748
749 err = -EINVAL; 749 err = -EINVAL;
750 if (u->addr) 750 if (u->addr)
@@ -816,7 +816,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
816out_unlock: 816out_unlock:
817 spin_unlock(&unix_table_lock); 817 spin_unlock(&unix_table_lock);
818out_up: 818out_up:
819 up(&u->readsem); 819 mutex_unlock(&u->readlock);
820out: 820out:
821 return err; 821 return err;
822 822
@@ -1427,15 +1427,15 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
1427 while(sent < len) 1427 while(sent < len)
1428 { 1428 {
1429 /* 1429 /*
1430 * Optimisation for the fact that under 0.01% of X messages typically 1430 * Optimisation for the fact that under 0.01% of X
1431 * need breaking up. 1431 * messages typically need breaking up.
1432 */ 1432 */
1433 1433
1434 size=len-sent; 1434 size = len-sent;
1435 1435
1436 /* Keep two messages in the pipe so it schedules better */ 1436 /* Keep two messages in the pipe so it schedules better */
1437 if (size > sk->sk_sndbuf / 2 - 64) 1437 if (size > ((sk->sk_sndbuf >> 1) - 64))
1438 size = sk->sk_sndbuf / 2 - 64; 1438 size = (sk->sk_sndbuf >> 1) - 64;
1439 1439
1440 if (size > SKB_MAX_ALLOC) 1440 if (size > SKB_MAX_ALLOC)
1441 size = SKB_MAX_ALLOC; 1441 size = SKB_MAX_ALLOC;
@@ -1545,7 +1545,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
1545 1545
1546 msg->msg_namelen = 0; 1546 msg->msg_namelen = 0;
1547 1547
1548 down(&u->readsem); 1548 mutex_lock(&u->readlock);
1549 1549
1550 skb = skb_recv_datagram(sk, flags, noblock, &err); 1550 skb = skb_recv_datagram(sk, flags, noblock, &err);
1551 if (!skb) 1551 if (!skb)
@@ -1600,7 +1600,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
1600out_free: 1600out_free:
1601 skb_free_datagram(sk,skb); 1601 skb_free_datagram(sk,skb);
1602out_unlock: 1602out_unlock:
1603 up(&u->readsem); 1603 mutex_unlock(&u->readlock);
1604out: 1604out:
1605 return err; 1605 return err;
1606} 1606}
@@ -1676,7 +1676,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1676 memset(&tmp_scm, 0, sizeof(tmp_scm)); 1676 memset(&tmp_scm, 0, sizeof(tmp_scm));
1677 } 1677 }
1678 1678
1679 down(&u->readsem); 1679 mutex_lock(&u->readlock);
1680 1680
1681 do 1681 do
1682 { 1682 {
@@ -1700,7 +1700,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1700 err = -EAGAIN; 1700 err = -EAGAIN;
1701 if (!timeo) 1701 if (!timeo)
1702 break; 1702 break;
1703 up(&u->readsem); 1703 mutex_unlock(&u->readlock);
1704 1704
1705 timeo = unix_stream_data_wait(sk, timeo); 1705 timeo = unix_stream_data_wait(sk, timeo);
1706 1706
@@ -1708,7 +1708,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1708 err = sock_intr_errno(timeo); 1708 err = sock_intr_errno(timeo);
1709 goto out; 1709 goto out;
1710 } 1710 }
1711 down(&u->readsem); 1711 mutex_lock(&u->readlock);
1712 continue; 1712 continue;
1713 } 1713 }
1714 1714
@@ -1774,7 +1774,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1774 } 1774 }
1775 } while (size); 1775 } while (size);
1776 1776
1777 up(&u->readsem); 1777 mutex_unlock(&u->readlock);
1778 scm_recv(sock, msg, siocb->scm, flags); 1778 scm_recv(sock, msg, siocb->scm, flags);
1779out: 1779out:
1780 return copied ? : err; 1780 return copied ? : err;
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index 411802bd4d37..746c2f4a5fa6 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -76,6 +76,7 @@
76#include <linux/netdevice.h> 76#include <linux/netdevice.h>
77#include <linux/file.h> 77#include <linux/file.h>
78#include <linux/proc_fs.h> 78#include <linux/proc_fs.h>
79#include <linux/mutex.h>
79 80
80#include <net/sock.h> 81#include <net/sock.h>
81#include <net/af_unix.h> 82#include <net/af_unix.h>
@@ -169,7 +170,7 @@ static void maybe_unmark_and_push(struct sock *x)
169 170
170void unix_gc(void) 171void unix_gc(void)
171{ 172{
172 static DECLARE_MUTEX(unix_gc_sem); 173 static DEFINE_MUTEX(unix_gc_sem);
173 int i; 174 int i;
174 struct sock *s; 175 struct sock *s;
175 struct sk_buff_head hitlist; 176 struct sk_buff_head hitlist;
@@ -179,7 +180,7 @@ void unix_gc(void)
179 * Avoid a recursive GC. 180 * Avoid a recursive GC.
180 */ 181 */
181 182
182 if (down_trylock(&unix_gc_sem)) 183 if (!mutex_trylock(&unix_gc_sem))
183 return; 184 return;
184 185
185 spin_lock(&unix_table_lock); 186 spin_lock(&unix_table_lock);
@@ -308,5 +309,5 @@ void unix_gc(void)
308 */ 309 */
309 310
310 __skb_queue_purge(&hitlist); 311 __skb_queue_purge(&hitlist);
311 up(&unix_gc_sem); 312 mutex_unlock(&unix_gc_sem);
312} 313}
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 72b6ff3299ba..282ce4e40d7b 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -54,7 +54,10 @@
54#include <linux/termios.h> /* For TIOCINQ/OUTQ */ 54#include <linux/termios.h> /* For TIOCINQ/OUTQ */
55#include <linux/notifier.h> 55#include <linux/notifier.h>
56#include <linux/init.h> 56#include <linux/init.h>
57#include <linux/compat.h>
58
57#include <net/x25.h> 59#include <net/x25.h>
60#include <net/compat.h>
58 61
59int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20; 62int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20;
60int sysctl_x25_call_request_timeout = X25_DEFAULT_T21; 63int sysctl_x25_call_request_timeout = X25_DEFAULT_T21;
@@ -69,6 +72,14 @@ static const struct proto_ops x25_proto_ops;
69 72
70static struct x25_address null_x25_address = {" "}; 73static struct x25_address null_x25_address = {" "};
71 74
75#ifdef CONFIG_COMPAT
76struct compat_x25_subscrip_struct {
77 char device[200-sizeof(compat_ulong_t)];
78 compat_ulong_t global_facil_mask;
79 compat_uint_t extended;
80};
81#endif
82
72int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr, 83int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr,
73 struct x25_address *calling_addr) 84 struct x25_address *calling_addr)
74{ 85{
@@ -514,6 +525,13 @@ static int x25_create(struct socket *sock, int protocol)
514 x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; 525 x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE;
515 x25->facilities.throughput = X25_DEFAULT_THROUGHPUT; 526 x25->facilities.throughput = X25_DEFAULT_THROUGHPUT;
516 x25->facilities.reverse = X25_DEFAULT_REVERSE; 527 x25->facilities.reverse = X25_DEFAULT_REVERSE;
528 x25->dte_facilities.calling_len = 0;
529 x25->dte_facilities.called_len = 0;
530 memset(x25->dte_facilities.called_ae, '\0',
531 sizeof(x25->dte_facilities.called_ae));
532 memset(x25->dte_facilities.calling_ae, '\0',
533 sizeof(x25->dte_facilities.calling_ae));
534
517 rc = 0; 535 rc = 0;
518out: 536out:
519 return rc; 537 return rc;
@@ -550,6 +568,7 @@ static struct sock *x25_make_new(struct sock *osk)
550 x25->t2 = ox25->t2; 568 x25->t2 = ox25->t2;
551 x25->facilities = ox25->facilities; 569 x25->facilities = ox25->facilities;
552 x25->qbitincl = ox25->qbitincl; 570 x25->qbitincl = ox25->qbitincl;
571 x25->dte_facilities = ox25->dte_facilities;
553 x25->cudmatchlength = ox25->cudmatchlength; 572 x25->cudmatchlength = ox25->cudmatchlength;
554 x25->accptapprv = ox25->accptapprv; 573 x25->accptapprv = ox25->accptapprv;
555 574
@@ -733,7 +752,7 @@ out:
733 return rc; 752 return rc;
734} 753}
735 754
736static int x25_wait_for_data(struct sock *sk, int timeout) 755static int x25_wait_for_data(struct sock *sk, long timeout)
737{ 756{
738 DECLARE_WAITQUEUE(wait, current); 757 DECLARE_WAITQUEUE(wait, current);
739 int rc = 0; 758 int rc = 0;
@@ -829,6 +848,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
829 struct x25_sock *makex25; 848 struct x25_sock *makex25;
830 struct x25_address source_addr, dest_addr; 849 struct x25_address source_addr, dest_addr;
831 struct x25_facilities facilities; 850 struct x25_facilities facilities;
851 struct x25_dte_facilities dte_facilities;
832 int len, rc; 852 int len, rc;
833 853
834 /* 854 /*
@@ -865,7 +885,8 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
865 /* 885 /*
866 * Try to reach a compromise on the requested facilities. 886 * Try to reach a compromise on the requested facilities.
867 */ 887 */
868 if ((len = x25_negotiate_facilities(skb, sk, &facilities)) == -1) 888 len = x25_negotiate_facilities(skb, sk, &facilities, &dte_facilities);
889 if (len == -1)
869 goto out_sock_put; 890 goto out_sock_put;
870 891
871 /* 892 /*
@@ -896,9 +917,12 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
896 makex25->source_addr = source_addr; 917 makex25->source_addr = source_addr;
897 makex25->neighbour = nb; 918 makex25->neighbour = nb;
898 makex25->facilities = facilities; 919 makex25->facilities = facilities;
920 makex25->dte_facilities= dte_facilities;
899 makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask; 921 makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask;
900 /* ensure no reverse facil on accept */ 922 /* ensure no reverse facil on accept */
901 makex25->vc_facil_mask &= ~X25_MASK_REVERSE; 923 makex25->vc_facil_mask &= ~X25_MASK_REVERSE;
924 /* ensure no calling address extension on accept */
925 makex25->vc_facil_mask &= ~X25_MASK_CALLING_AE;
902 makex25->cudmatchlength = x25_sk(sk)->cudmatchlength; 926 makex25->cudmatchlength = x25_sk(sk)->cudmatchlength;
903 927
904 /* Normally all calls are accepted immediatly */ 928 /* Normally all calls are accepted immediatly */
@@ -1305,6 +1329,36 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
1305 break; 1329 break;
1306 } 1330 }
1307 1331
1332 case SIOCX25GDTEFACILITIES: {
1333 rc = copy_to_user(argp, &x25->dte_facilities,
1334 sizeof(x25->dte_facilities));
1335 if (rc)
1336 rc = -EFAULT;
1337 break;
1338 }
1339
1340 case SIOCX25SDTEFACILITIES: {
1341 struct x25_dte_facilities dtefacs;
1342 rc = -EFAULT;
1343 if (copy_from_user(&dtefacs, argp, sizeof(dtefacs)))
1344 break;
1345 rc = -EINVAL;
1346 if (sk->sk_state != TCP_LISTEN &&
1347 sk->sk_state != TCP_CLOSE)
1348 break;
1349 if (dtefacs.calling_len > X25_MAX_AE_LEN)
1350 break;
1351 if (dtefacs.calling_ae == NULL)
1352 break;
1353 if (dtefacs.called_len > X25_MAX_AE_LEN)
1354 break;
1355 if (dtefacs.called_ae == NULL)
1356 break;
1357 x25->dte_facilities = dtefacs;
1358 rc = 0;
1359 break;
1360 }
1361
1308 case SIOCX25GCALLUSERDATA: { 1362 case SIOCX25GCALLUSERDATA: {
1309 struct x25_calluserdata cud = x25->calluserdata; 1363 struct x25_calluserdata cud = x25->calluserdata;
1310 rc = copy_to_user(argp, &cud, 1364 rc = copy_to_user(argp, &cud,
@@ -1387,6 +1441,118 @@ static struct net_proto_family x25_family_ops = {
1387 .owner = THIS_MODULE, 1441 .owner = THIS_MODULE,
1388}; 1442};
1389 1443
1444#ifdef CONFIG_COMPAT
1445static int compat_x25_subscr_ioctl(unsigned int cmd,
1446 struct compat_x25_subscrip_struct __user *x25_subscr32)
1447{
1448 struct compat_x25_subscrip_struct x25_subscr;
1449 struct x25_neigh *nb;
1450 struct net_device *dev;
1451 int rc = -EINVAL;
1452
1453 rc = -EFAULT;
1454 if (copy_from_user(&x25_subscr, x25_subscr32, sizeof(*x25_subscr32)))
1455 goto out;
1456
1457 rc = -EINVAL;
1458 dev = x25_dev_get(x25_subscr.device);
1459 if (dev == NULL)
1460 goto out;
1461
1462 nb = x25_get_neigh(dev);
1463 if (nb == NULL)
1464 goto out_dev_put;
1465
1466 dev_put(dev);
1467
1468 if (cmd == SIOCX25GSUBSCRIP) {
1469 x25_subscr.extended = nb->extended;
1470 x25_subscr.global_facil_mask = nb->global_facil_mask;
1471 rc = copy_to_user(x25_subscr32, &x25_subscr,
1472 sizeof(*x25_subscr32)) ? -EFAULT : 0;
1473 } else {
1474 rc = -EINVAL;
1475 if (x25_subscr.extended == 0 || x25_subscr.extended == 1) {
1476 rc = 0;
1477 nb->extended = x25_subscr.extended;
1478 nb->global_facil_mask = x25_subscr.global_facil_mask;
1479 }
1480 }
1481 x25_neigh_put(nb);
1482out:
1483 return rc;
1484out_dev_put:
1485 dev_put(dev);
1486 goto out;
1487}
1488
1489static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
1490 unsigned long arg)
1491{
1492 void __user *argp = compat_ptr(arg);
1493 struct sock *sk = sock->sk;
1494
1495 int rc = -ENOIOCTLCMD;
1496
1497 switch(cmd) {
1498 case TIOCOUTQ:
1499 case TIOCINQ:
1500 rc = x25_ioctl(sock, cmd, (unsigned long)argp);
1501 break;
1502 case SIOCGSTAMP:
1503 rc = -EINVAL;
1504 if (sk)
1505 rc = compat_sock_get_timestamp(sk,
1506 (struct timeval __user*)argp);
1507 break;
1508 case SIOCGIFADDR:
1509 case SIOCSIFADDR:
1510 case SIOCGIFDSTADDR:
1511 case SIOCSIFDSTADDR:
1512 case SIOCGIFBRDADDR:
1513 case SIOCSIFBRDADDR:
1514 case SIOCGIFNETMASK:
1515 case SIOCSIFNETMASK:
1516 case SIOCGIFMETRIC:
1517 case SIOCSIFMETRIC:
1518 rc = -EINVAL;
1519 break;
1520 case SIOCADDRT:
1521 case SIOCDELRT:
1522 rc = -EPERM;
1523 if (!capable(CAP_NET_ADMIN))
1524 break;
1525 rc = x25_route_ioctl(cmd, argp);
1526 break;
1527 case SIOCX25GSUBSCRIP:
1528 rc = compat_x25_subscr_ioctl(cmd, argp);
1529 break;
1530 case SIOCX25SSUBSCRIP:
1531 rc = -EPERM;
1532 if (!capable(CAP_NET_ADMIN))
1533 break;
1534 rc = compat_x25_subscr_ioctl(cmd, argp);
1535 break;
1536 case SIOCX25GFACILITIES:
1537 case SIOCX25SFACILITIES:
1538 case SIOCX25GDTEFACILITIES:
1539 case SIOCX25SDTEFACILITIES:
1540 case SIOCX25GCALLUSERDATA:
1541 case SIOCX25SCALLUSERDATA:
1542 case SIOCX25GCAUSEDIAG:
1543 case SIOCX25SCUDMATCHLEN:
1544 case SIOCX25CALLACCPTAPPRV:
1545 case SIOCX25SENDCALLACCPT:
1546 rc = x25_ioctl(sock, cmd, (unsigned long)argp);
1547 break;
1548 default:
1549 rc = -ENOIOCTLCMD;
1550 break;
1551 }
1552 return rc;
1553}
1554#endif
1555
1390static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { 1556static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
1391 .family = AF_X25, 1557 .family = AF_X25,
1392 .owner = THIS_MODULE, 1558 .owner = THIS_MODULE,
@@ -1398,6 +1564,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
1398 .getname = x25_getname, 1564 .getname = x25_getname,
1399 .poll = datagram_poll, 1565 .poll = datagram_poll,
1400 .ioctl = x25_ioctl, 1566 .ioctl = x25_ioctl,
1567#ifdef CONFIG_COMPAT
1568 .compat_ioctl = compat_x25_ioctl,
1569#endif
1401 .listen = x25_listen, 1570 .listen = x25_listen,
1402 .shutdown = sock_no_shutdown, 1571 .shutdown = sock_no_shutdown,
1403 .setsockopt = x25_setsockopt, 1572 .setsockopt = x25_setsockopt,
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c
index 54278b962f4c..9f42b9c9de37 100644
--- a/net/x25/x25_facilities.c
+++ b/net/x25/x25_facilities.c
@@ -28,18 +28,28 @@
28#include <net/x25.h> 28#include <net/x25.h>
29 29
30/* 30/*
31 * Parse a set of facilities into the facilities structure. Unrecognised 31 * Parse a set of facilities into the facilities structures. Unrecognised
32 * facilities are written to the debug log file. 32 * facilities are written to the debug log file.
33 */ 33 */
34int x25_parse_facilities(struct sk_buff *skb, 34int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,
35 struct x25_facilities *facilities, 35 struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask)
36 unsigned long *vc_fac_mask)
37{ 36{
38 unsigned char *p = skb->data; 37 unsigned char *p = skb->data;
39 unsigned int len = *p++; 38 unsigned int len = *p++;
40 39
41 *vc_fac_mask = 0; 40 *vc_fac_mask = 0;
42 41
42 /*
43 * The kernel knows which facilities were set on an incoming call but
44 * currently this information is not available to userspace. Here we
45 * give userspace who read incoming call facilities 0 length to indicate
46 * it wasn't set.
47 */
48 dte_facs->calling_len = 0;
49 dte_facs->called_len = 0;
50 memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae));
51 memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae));
52
43 while (len > 0) { 53 while (len > 0) {
44 switch (*p & X25_FAC_CLASS_MASK) { 54 switch (*p & X25_FAC_CLASS_MASK) {
45 case X25_FAC_CLASS_A: 55 case X25_FAC_CLASS_A:
@@ -74,6 +84,8 @@ int x25_parse_facilities(struct sk_buff *skb,
74 facilities->throughput = p[1]; 84 facilities->throughput = p[1];
75 *vc_fac_mask |= X25_MASK_THROUGHPUT; 85 *vc_fac_mask |= X25_MASK_THROUGHPUT;
76 break; 86 break;
87 case X25_MARKER:
88 break;
77 default: 89 default:
78 printk(KERN_DEBUG "X.25: unknown facility " 90 printk(KERN_DEBUG "X.25: unknown facility "
79 "%02X, value %02X\n", 91 "%02X, value %02X\n",
@@ -112,11 +124,30 @@ int x25_parse_facilities(struct sk_buff *skb,
112 len -= 4; 124 len -= 4;
113 break; 125 break;
114 case X25_FAC_CLASS_D: 126 case X25_FAC_CLASS_D:
115 printk(KERN_DEBUG "X.25: unknown facility %02X, " 127 switch (*p) {
116 "length %d, values %02X, %02X, %02X, %02X\n", 128 case X25_FAC_CALLING_AE:
117 p[0], p[1], p[2], p[3], p[4], p[5]); 129 if (p[1] > X25_MAX_DTE_FACIL_LEN)
130 break;
131 dte_facs->calling_len = p[2];
132 memcpy(dte_facs->calling_ae, &p[3], p[1] - 1);
133 *vc_fac_mask |= X25_MASK_CALLING_AE;
134 break;
135 case X25_FAC_CALLED_AE:
136 if (p[1] > X25_MAX_DTE_FACIL_LEN)
137 break;
138 dte_facs->called_len = p[2];
139 memcpy(dte_facs->called_ae, &p[3], p[1] - 1);
140 *vc_fac_mask |= X25_MASK_CALLED_AE;
141 break;
142 default:
143 printk(KERN_DEBUG "X.25: unknown facility %02X,"
144 "length %d, values %02X, %02X, "
145 "%02X, %02X\n",
146 p[0], p[1], p[2], p[3], p[4], p[5]);
147 break;
148 }
118 len -= p[1] + 2; 149 len -= p[1] + 2;
119 p += p[1] + 2; 150 p += p[1] + 2;
120 break; 151 break;
121 } 152 }
122 } 153 }
@@ -128,8 +159,8 @@ int x25_parse_facilities(struct sk_buff *skb,
128 * Create a set of facilities. 159 * Create a set of facilities.
129 */ 160 */
130int x25_create_facilities(unsigned char *buffer, 161int x25_create_facilities(unsigned char *buffer,
131 struct x25_facilities *facilities, 162 struct x25_facilities *facilities,
132 unsigned long facil_mask) 163 struct x25_dte_facilities *dte_facs, unsigned long facil_mask)
133{ 164{
134 unsigned char *p = buffer + 1; 165 unsigned char *p = buffer + 1;
135 int len; 166 int len;
@@ -168,6 +199,33 @@ int x25_create_facilities(unsigned char *buffer,
168 *p++ = facilities->winsize_out ? : facilities->winsize_in; 199 *p++ = facilities->winsize_out ? : facilities->winsize_in;
169 } 200 }
170 201
202 if (facil_mask & (X25_MASK_CALLING_AE|X25_MASK_CALLED_AE)) {
203 *p++ = X25_MARKER;
204 *p++ = X25_DTE_SERVICES;
205 }
206
207 if (dte_facs->calling_len && (facil_mask & X25_MASK_CALLING_AE)) {
208 unsigned bytecount = (dte_facs->calling_len % 2) ?
209 dte_facs->calling_len / 2 + 1 :
210 dte_facs->calling_len / 2;
211 *p++ = X25_FAC_CALLING_AE;
212 *p++ = 1 + bytecount;
213 *p++ = dte_facs->calling_len;
214 memcpy(p, dte_facs->calling_ae, bytecount);
215 p += bytecount;
216 }
217
218 if (dte_facs->called_len && (facil_mask & X25_MASK_CALLED_AE)) {
219 unsigned bytecount = (dte_facs->called_len % 2) ?
220 dte_facs->called_len / 2 + 1 :
221 dte_facs->called_len / 2;
222 *p++ = X25_FAC_CALLED_AE;
223 *p++ = 1 + bytecount;
224 *p++ = dte_facs->called_len;
225 memcpy(p, dte_facs->called_ae, bytecount);
226 p+=bytecount;
227 }
228
171 len = p - buffer; 229 len = p - buffer;
172 buffer[0] = len - 1; 230 buffer[0] = len - 1;
173 231
@@ -180,7 +238,7 @@ int x25_create_facilities(unsigned char *buffer,
180 * The only real problem is with reverse charging. 238 * The only real problem is with reverse charging.
181 */ 239 */
182int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, 240int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
183 struct x25_facilities *new) 241 struct x25_facilities *new, struct x25_dte_facilities *dte)
184{ 242{
185 struct x25_sock *x25 = x25_sk(sk); 243 struct x25_sock *x25 = x25_sk(sk);
186 struct x25_facilities *ours = &x25->facilities; 244 struct x25_facilities *ours = &x25->facilities;
@@ -190,7 +248,7 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
190 memset(&theirs, 0, sizeof(theirs)); 248 memset(&theirs, 0, sizeof(theirs));
191 memcpy(new, ours, sizeof(*new)); 249 memcpy(new, ours, sizeof(*new));
192 250
193 len = x25_parse_facilities(skb, &theirs, &x25->vc_facil_mask); 251 len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask);
194 252
195 /* 253 /*
196 * They want reverse charging, we won't accept it. 254 * They want reverse charging, we won't accept it.
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c
index 26146874b839..eed50e10f09b 100644
--- a/net/x25/x25_in.c
+++ b/net/x25/x25_in.c
@@ -106,7 +106,8 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp
106 skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr)); 106 skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr));
107 skb_pull(skb, 107 skb_pull(skb,
108 x25_parse_facilities(skb, &x25->facilities, 108 x25_parse_facilities(skb, &x25->facilities,
109 &x25->vc_facil_mask)); 109 &x25->dte_facilities,
110 &x25->vc_facil_mask));
110 /* 111 /*
111 * Copy any Call User Data. 112 * Copy any Call User Data.
112 */ 113 */
diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c
index 8be9b8fbc24d..8d6220aa5d0f 100644
--- a/net/x25/x25_subr.c
+++ b/net/x25/x25_subr.c
@@ -190,8 +190,9 @@ void x25_write_internal(struct sock *sk, int frametype)
190 dptr = skb_put(skb, len); 190 dptr = skb_put(skb, len);
191 memcpy(dptr, addresses, len); 191 memcpy(dptr, addresses, len);
192 len = x25_create_facilities(facilities, 192 len = x25_create_facilities(facilities,
193 &x25->facilities, 193 &x25->facilities,
194 x25->neighbour->global_facil_mask); 194 &x25->dte_facilities,
195 x25->neighbour->global_facil_mask);
195 dptr = skb_put(skb, len); 196 dptr = skb_put(skb, len);
196 memcpy(dptr, facilities, len); 197 memcpy(dptr, facilities, len);
197 dptr = skb_put(skb, x25->calluserdata.cudlength); 198 dptr = skb_put(skb, x25->calluserdata.cudlength);
@@ -206,6 +207,7 @@ void x25_write_internal(struct sock *sk, int frametype)
206 *dptr++ = 0x00; /* Address lengths */ 207 *dptr++ = 0x00; /* Address lengths */
207 len = x25_create_facilities(facilities, 208 len = x25_create_facilities(facilities,
208 &x25->facilities, 209 &x25->facilities,
210 &x25->dte_facilities,
209 x25->vc_facil_mask); 211 x25->vc_facil_mask);
210 dptr = skb_put(skb, len); 212 dptr = skb_put(skb, len);
211 memcpy(dptr, facilities, len); 213 memcpy(dptr, facilities, len);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index ae62054a9fc4..f5eae9febd26 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -26,8 +26,8 @@
26#include <net/xfrm.h> 26#include <net/xfrm.h>
27#include <net/ip.h> 27#include <net/ip.h>
28 28
29DECLARE_MUTEX(xfrm_cfg_sem); 29DEFINE_MUTEX(xfrm_cfg_mutex);
30EXPORT_SYMBOL(xfrm_cfg_sem); 30EXPORT_SYMBOL(xfrm_cfg_mutex);
31 31
32static DEFINE_RWLOCK(xfrm_policy_lock); 32static DEFINE_RWLOCK(xfrm_policy_lock);
33 33
@@ -203,7 +203,7 @@ static void xfrm_policy_timer(unsigned long data)
203 } 203 }
204 204
205 if (warn) 205 if (warn)
206 km_policy_expired(xp, dir, 0); 206 km_policy_expired(xp, dir, 0, 0);
207 if (next != LONG_MAX && 207 if (next != LONG_MAX &&
208 !mod_timer(&xp->timer, jiffies + make_jiffies(next))) 208 !mod_timer(&xp->timer, jiffies + make_jiffies(next)))
209 xfrm_pol_hold(xp); 209 xfrm_pol_hold(xp);
@@ -216,7 +216,7 @@ out:
216expired: 216expired:
217 read_unlock(&xp->lock); 217 read_unlock(&xp->lock);
218 if (!xfrm_policy_delete(xp, dir)) 218 if (!xfrm_policy_delete(xp, dir))
219 km_policy_expired(xp, dir, 1); 219 km_policy_expired(xp, dir, 1, 0);
220 xfrm_pol_put(xp); 220 xfrm_pol_put(xp);
221} 221}
222 222
@@ -621,6 +621,7 @@ int xfrm_policy_delete(struct xfrm_policy *pol, int dir)
621 } 621 }
622 return -ENOENT; 622 return -ENOENT;
623} 623}
624EXPORT_SYMBOL(xfrm_policy_delete);
624 625
625int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) 626int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol)
626{ 627{
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index c656cbaf35e8..a8e14dc1b04e 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -20,6 +20,15 @@
20#include <linux/module.h> 20#include <linux/module.h>
21#include <asm/uaccess.h> 21#include <asm/uaccess.h>
22 22
23struct sock *xfrm_nl;
24EXPORT_SYMBOL(xfrm_nl);
25
26u32 sysctl_xfrm_aevent_etime = XFRM_AE_ETIME;
27EXPORT_SYMBOL(sysctl_xfrm_aevent_etime);
28
29u32 sysctl_xfrm_aevent_rseqth = XFRM_AE_SEQT_SIZE;
30EXPORT_SYMBOL(sysctl_xfrm_aevent_rseqth);
31
23/* Each xfrm_state may be linked to two tables: 32/* Each xfrm_state may be linked to two tables:
24 33
25 1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl) 34 1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl)
@@ -50,18 +59,20 @@ static DEFINE_SPINLOCK(xfrm_state_gc_lock);
50 59
51static int xfrm_state_gc_flush_bundles; 60static int xfrm_state_gc_flush_bundles;
52 61
53static int __xfrm_state_delete(struct xfrm_state *x); 62int __xfrm_state_delete(struct xfrm_state *x);
54 63
55static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family); 64static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
56static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); 65static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
57 66
58static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); 67int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
59static void km_state_expired(struct xfrm_state *x, int hard); 68void km_state_expired(struct xfrm_state *x, int hard, u32 pid);
60 69
61static void xfrm_state_gc_destroy(struct xfrm_state *x) 70static void xfrm_state_gc_destroy(struct xfrm_state *x)
62{ 71{
63 if (del_timer(&x->timer)) 72 if (del_timer(&x->timer))
64 BUG(); 73 BUG();
74 if (del_timer(&x->rtimer))
75 BUG();
65 kfree(x->aalg); 76 kfree(x->aalg);
66 kfree(x->ealg); 77 kfree(x->ealg);
67 kfree(x->calg); 78 kfree(x->calg);
@@ -153,7 +164,7 @@ static void xfrm_timer_handler(unsigned long data)
153 164
154 x->km.dying = warn; 165 x->km.dying = warn;
155 if (warn) 166 if (warn)
156 km_state_expired(x, 0); 167 km_state_expired(x, 0, 0);
157resched: 168resched:
158 if (next != LONG_MAX && 169 if (next != LONG_MAX &&
159 !mod_timer(&x->timer, jiffies + make_jiffies(next))) 170 !mod_timer(&x->timer, jiffies + make_jiffies(next)))
@@ -168,13 +179,15 @@ expired:
168 goto resched; 179 goto resched;
169 } 180 }
170 if (!__xfrm_state_delete(x) && x->id.spi) 181 if (!__xfrm_state_delete(x) && x->id.spi)
171 km_state_expired(x, 1); 182 km_state_expired(x, 1, 0);
172 183
173out: 184out:
174 spin_unlock(&x->lock); 185 spin_unlock(&x->lock);
175 xfrm_state_put(x); 186 xfrm_state_put(x);
176} 187}
177 188
189static void xfrm_replay_timer_handler(unsigned long data);
190
178struct xfrm_state *xfrm_state_alloc(void) 191struct xfrm_state *xfrm_state_alloc(void)
179{ 192{
180 struct xfrm_state *x; 193 struct xfrm_state *x;
@@ -190,11 +203,16 @@ struct xfrm_state *xfrm_state_alloc(void)
190 init_timer(&x->timer); 203 init_timer(&x->timer);
191 x->timer.function = xfrm_timer_handler; 204 x->timer.function = xfrm_timer_handler;
192 x->timer.data = (unsigned long)x; 205 x->timer.data = (unsigned long)x;
206 init_timer(&x->rtimer);
207 x->rtimer.function = xfrm_replay_timer_handler;
208 x->rtimer.data = (unsigned long)x;
193 x->curlft.add_time = (unsigned long)xtime.tv_sec; 209 x->curlft.add_time = (unsigned long)xtime.tv_sec;
194 x->lft.soft_byte_limit = XFRM_INF; 210 x->lft.soft_byte_limit = XFRM_INF;
195 x->lft.soft_packet_limit = XFRM_INF; 211 x->lft.soft_packet_limit = XFRM_INF;
196 x->lft.hard_byte_limit = XFRM_INF; 212 x->lft.hard_byte_limit = XFRM_INF;
197 x->lft.hard_packet_limit = XFRM_INF; 213 x->lft.hard_packet_limit = XFRM_INF;
214 x->replay_maxage = 0;
215 x->replay_maxdiff = 0;
198 spin_lock_init(&x->lock); 216 spin_lock_init(&x->lock);
199 } 217 }
200 return x; 218 return x;
@@ -212,7 +230,7 @@ void __xfrm_state_destroy(struct xfrm_state *x)
212} 230}
213EXPORT_SYMBOL(__xfrm_state_destroy); 231EXPORT_SYMBOL(__xfrm_state_destroy);
214 232
215static int __xfrm_state_delete(struct xfrm_state *x) 233int __xfrm_state_delete(struct xfrm_state *x)
216{ 234{
217 int err = -ESRCH; 235 int err = -ESRCH;
218 236
@@ -228,6 +246,8 @@ static int __xfrm_state_delete(struct xfrm_state *x)
228 spin_unlock(&xfrm_state_lock); 246 spin_unlock(&xfrm_state_lock);
229 if (del_timer(&x->timer)) 247 if (del_timer(&x->timer))
230 __xfrm_state_put(x); 248 __xfrm_state_put(x);
249 if (del_timer(&x->rtimer))
250 __xfrm_state_put(x);
231 251
232 /* The number two in this test is the reference 252 /* The number two in this test is the reference
233 * mentioned in the comment below plus the reference 253 * mentioned in the comment below plus the reference
@@ -249,6 +269,7 @@ static int __xfrm_state_delete(struct xfrm_state *x)
249 269
250 return err; 270 return err;
251} 271}
272EXPORT_SYMBOL(__xfrm_state_delete);
252 273
253int xfrm_state_delete(struct xfrm_state *x) 274int xfrm_state_delete(struct xfrm_state *x)
254{ 275{
@@ -426,6 +447,10 @@ static void __xfrm_state_insert(struct xfrm_state *x)
426 if (!mod_timer(&x->timer, jiffies + HZ)) 447 if (!mod_timer(&x->timer, jiffies + HZ))
427 xfrm_state_hold(x); 448 xfrm_state_hold(x);
428 449
450 if (x->replay_maxage &&
451 !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
452 xfrm_state_hold(x);
453
429 wake_up(&km_waitq); 454 wake_up(&km_waitq);
430} 455}
431 456
@@ -580,7 +605,7 @@ int xfrm_state_check_expire(struct xfrm_state *x)
580 (x->curlft.bytes >= x->lft.soft_byte_limit || 605 (x->curlft.bytes >= x->lft.soft_byte_limit ||
581 x->curlft.packets >= x->lft.soft_packet_limit)) { 606 x->curlft.packets >= x->lft.soft_packet_limit)) {
582 x->km.dying = 1; 607 x->km.dying = 1;
583 km_state_expired(x, 0); 608 km_state_expired(x, 0, 0);
584 } 609 }
585 return 0; 610 return 0;
586} 611}
@@ -762,6 +787,61 @@ out:
762} 787}
763EXPORT_SYMBOL(xfrm_state_walk); 788EXPORT_SYMBOL(xfrm_state_walk);
764 789
790
791void xfrm_replay_notify(struct xfrm_state *x, int event)
792{
793 struct km_event c;
794 /* we send notify messages in case
795 * 1. we updated on of the sequence numbers, and the seqno difference
796 * is at least x->replay_maxdiff, in this case we also update the
797 * timeout of our timer function
798 * 2. if x->replay_maxage has elapsed since last update,
799 * and there were changes
800 *
801 * The state structure must be locked!
802 */
803
804 switch (event) {
805 case XFRM_REPLAY_UPDATE:
806 if (x->replay_maxdiff &&
807 (x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
808 (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff))
809 return;
810
811 break;
812
813 case XFRM_REPLAY_TIMEOUT:
814 if ((x->replay.seq == x->preplay.seq) &&
815 (x->replay.bitmap == x->preplay.bitmap) &&
816 (x->replay.oseq == x->preplay.oseq))
817 return;
818
819 break;
820 }
821
822 memcpy(&x->preplay, &x->replay, sizeof(struct xfrm_replay_state));
823 c.event = XFRM_MSG_NEWAE;
824 c.data.aevent = event;
825 km_state_notify(x, &c);
826
827 if (x->replay_maxage &&
828 !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
829 xfrm_state_hold(x);
830}
831EXPORT_SYMBOL(xfrm_replay_notify);
832
833static void xfrm_replay_timer_handler(unsigned long data)
834{
835 struct xfrm_state *x = (struct xfrm_state*)data;
836
837 spin_lock(&x->lock);
838
839 if (xfrm_aevent_is_on() && x->km.state == XFRM_STATE_VALID)
840 xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT);
841
842 spin_unlock(&x->lock);
843}
844
765int xfrm_replay_check(struct xfrm_state *x, u32 seq) 845int xfrm_replay_check(struct xfrm_state *x, u32 seq)
766{ 846{
767 u32 diff; 847 u32 diff;
@@ -805,6 +885,9 @@ void xfrm_replay_advance(struct xfrm_state *x, u32 seq)
805 diff = x->replay.seq - seq; 885 diff = x->replay.seq - seq;
806 x->replay.bitmap |= (1U << diff); 886 x->replay.bitmap |= (1U << diff);
807 } 887 }
888
889 if (xfrm_aevent_is_on())
890 xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
808} 891}
809EXPORT_SYMBOL(xfrm_replay_advance); 892EXPORT_SYMBOL(xfrm_replay_advance);
810 893
@@ -835,11 +918,12 @@ void km_state_notify(struct xfrm_state *x, struct km_event *c)
835EXPORT_SYMBOL(km_policy_notify); 918EXPORT_SYMBOL(km_policy_notify);
836EXPORT_SYMBOL(km_state_notify); 919EXPORT_SYMBOL(km_state_notify);
837 920
838static void km_state_expired(struct xfrm_state *x, int hard) 921void km_state_expired(struct xfrm_state *x, int hard, u32 pid)
839{ 922{
840 struct km_event c; 923 struct km_event c;
841 924
842 c.data.hard = hard; 925 c.data.hard = hard;
926 c.pid = pid;
843 c.event = XFRM_MSG_EXPIRE; 927 c.event = XFRM_MSG_EXPIRE;
844 km_state_notify(x, &c); 928 km_state_notify(x, &c);
845 929
@@ -847,11 +931,12 @@ static void km_state_expired(struct xfrm_state *x, int hard)
847 wake_up(&km_waitq); 931 wake_up(&km_waitq);
848} 932}
849 933
934EXPORT_SYMBOL(km_state_expired);
850/* 935/*
851 * We send to all registered managers regardless of failure 936 * We send to all registered managers regardless of failure
852 * We are happy with one success 937 * We are happy with one success
853*/ 938*/
854static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol) 939int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
855{ 940{
856 int err = -EINVAL, acqret; 941 int err = -EINVAL, acqret;
857 struct xfrm_mgr *km; 942 struct xfrm_mgr *km;
@@ -865,6 +950,7 @@ static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_polic
865 read_unlock(&xfrm_km_lock); 950 read_unlock(&xfrm_km_lock);
866 return err; 951 return err;
867} 952}
953EXPORT_SYMBOL(km_query);
868 954
869int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport) 955int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport)
870{ 956{
@@ -883,17 +969,19 @@ int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport)
883} 969}
884EXPORT_SYMBOL(km_new_mapping); 970EXPORT_SYMBOL(km_new_mapping);
885 971
886void km_policy_expired(struct xfrm_policy *pol, int dir, int hard) 972void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid)
887{ 973{
888 struct km_event c; 974 struct km_event c;
889 975
890 c.data.hard = hard; 976 c.data.hard = hard;
977 c.pid = pid;
891 c.event = XFRM_MSG_POLEXPIRE; 978 c.event = XFRM_MSG_POLEXPIRE;
892 km_policy_notify(pol, dir, &c); 979 km_policy_notify(pol, dir, &c);
893 980
894 if (hard) 981 if (hard)
895 wake_up(&km_waitq); 982 wake_up(&km_waitq);
896} 983}
984EXPORT_SYMBOL(km_policy_expired);
897 985
898int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen) 986int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen)
899{ 987{
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 7de17559249a..81d1005830f4 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -28,8 +28,6 @@
28#include <net/netlink.h> 28#include <net/netlink.h>
29#include <asm/uaccess.h> 29#include <asm/uaccess.h>
30 30
31static struct sock *xfrm_nl;
32
33static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type) 31static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type)
34{ 32{
35 struct rtattr *rt = xfrma[type - 1]; 33 struct rtattr *rt = xfrma[type - 1];
@@ -103,9 +101,6 @@ static inline int verify_sec_ctx_len(struct rtattr **xfrma)
103 101
104 uctx = RTA_DATA(rt); 102 uctx = RTA_DATA(rt);
105 103
106 if (uctx->ctx_len > PAGE_SIZE)
107 return -EINVAL;
108
109 len += sizeof(struct xfrm_user_sec_ctx); 104 len += sizeof(struct xfrm_user_sec_ctx);
110 len += uctx->ctx_len; 105 len += uctx->ctx_len;
111 106
@@ -276,6 +271,56 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
276 x->props.flags = p->flags; 271 x->props.flags = p->flags;
277} 272}
278 273
274/*
275 * someday when pfkey also has support, we could have the code
276 * somehow made shareable and move it to xfrm_state.c - JHS
277 *
278*/
279static int xfrm_update_ae_params(struct xfrm_state *x, struct rtattr **xfrma)
280{
281 int err = - EINVAL;
282 struct rtattr *rp = xfrma[XFRMA_REPLAY_VAL-1];
283 struct rtattr *lt = xfrma[XFRMA_LTIME_VAL-1];
284 struct rtattr *et = xfrma[XFRMA_ETIMER_THRESH-1];
285 struct rtattr *rt = xfrma[XFRMA_REPLAY_THRESH-1];
286
287 if (rp) {
288 struct xfrm_replay_state *replay;
289 if (RTA_PAYLOAD(rp) < sizeof(*replay))
290 goto error;
291 replay = RTA_DATA(rp);
292 memcpy(&x->replay, replay, sizeof(*replay));
293 memcpy(&x->preplay, replay, sizeof(*replay));
294 }
295
296 if (lt) {
297 struct xfrm_lifetime_cur *ltime;
298 if (RTA_PAYLOAD(lt) < sizeof(*ltime))
299 goto error;
300 ltime = RTA_DATA(lt);
301 x->curlft.bytes = ltime->bytes;
302 x->curlft.packets = ltime->packets;
303 x->curlft.add_time = ltime->add_time;
304 x->curlft.use_time = ltime->use_time;
305 }
306
307 if (et) {
308 if (RTA_PAYLOAD(et) < sizeof(u32))
309 goto error;
310 x->replay_maxage = *(u32*)RTA_DATA(et);
311 }
312
313 if (rt) {
314 if (RTA_PAYLOAD(rt) < sizeof(u32))
315 goto error;
316 x->replay_maxdiff = *(u32*)RTA_DATA(rt);
317 }
318
319 return 0;
320error:
321 return err;
322}
323
279static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, 324static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
280 struct rtattr **xfrma, 325 struct rtattr **xfrma,
281 int *errp) 326 int *errp)
@@ -311,6 +356,18 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
311 goto error; 356 goto error;
312 357
313 x->km.seq = p->seq; 358 x->km.seq = p->seq;
359 x->replay_maxdiff = sysctl_xfrm_aevent_rseqth;
360 /* sysctl_xfrm_aevent_etime is in 100ms units */
361 x->replay_maxage = (sysctl_xfrm_aevent_etime*HZ)/XFRM_AE_ETH_M;
362 x->preplay.bitmap = 0;
363 x->preplay.seq = x->replay.seq+x->replay_maxdiff;
364 x->preplay.oseq = x->replay.oseq +x->replay_maxdiff;
365
366 /* override default values from above */
367
368 err = xfrm_update_ae_params(x, (struct rtattr **)xfrma);
369 if (err < 0)
370 goto error;
314 371
315 return x; 372 return x;
316 373
@@ -1025,9 +1082,142 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma
1025 return 0; 1082 return 0;
1026} 1083}
1027 1084
1028static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) 1085
1086static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c)
1087{
1088 struct xfrm_aevent_id *id;
1089 struct nlmsghdr *nlh;
1090 struct xfrm_lifetime_cur ltime;
1091 unsigned char *b = skb->tail;
1092
1093 nlh = NLMSG_PUT(skb, c->pid, c->seq, XFRM_MSG_NEWAE, sizeof(*id));
1094 id = NLMSG_DATA(nlh);
1095 nlh->nlmsg_flags = 0;
1096
1097 id->sa_id.daddr = x->id.daddr;
1098 id->sa_id.spi = x->id.spi;
1099 id->sa_id.family = x->props.family;
1100 id->sa_id.proto = x->id.proto;
1101 id->flags = c->data.aevent;
1102
1103 RTA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay);
1104
1105 ltime.bytes = x->curlft.bytes;
1106 ltime.packets = x->curlft.packets;
1107 ltime.add_time = x->curlft.add_time;
1108 ltime.use_time = x->curlft.use_time;
1109
1110 RTA_PUT(skb, XFRMA_LTIME_VAL, sizeof(struct xfrm_lifetime_cur), &ltime);
1111
1112 if (id->flags&XFRM_AE_RTHR) {
1113 RTA_PUT(skb,XFRMA_REPLAY_THRESH,sizeof(u32),&x->replay_maxdiff);
1114 }
1115
1116 if (id->flags&XFRM_AE_ETHR) {
1117 u32 etimer = x->replay_maxage*10/HZ;
1118 RTA_PUT(skb,XFRMA_ETIMER_THRESH,sizeof(u32),&etimer);
1119 }
1120
1121 nlh->nlmsg_len = skb->tail - b;
1122 return skb->len;
1123
1124rtattr_failure:
1125nlmsg_failure:
1126 skb_trim(skb, b - skb->data);
1127 return -1;
1128}
1129
1130static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
1131{
1132 struct xfrm_state *x;
1133 struct sk_buff *r_skb;
1134 int err;
1135 struct km_event c;
1136 struct xfrm_aevent_id *p = NLMSG_DATA(nlh);
1137 int len = NLMSG_LENGTH(sizeof(struct xfrm_aevent_id));
1138 struct xfrm_usersa_id *id = &p->sa_id;
1139
1140 len += RTA_SPACE(sizeof(struct xfrm_replay_state));
1141 len += RTA_SPACE(sizeof(struct xfrm_lifetime_cur));
1142
1143 if (p->flags&XFRM_AE_RTHR)
1144 len+=RTA_SPACE(sizeof(u32));
1145
1146 if (p->flags&XFRM_AE_ETHR)
1147 len+=RTA_SPACE(sizeof(u32));
1148
1149 r_skb = alloc_skb(len, GFP_ATOMIC);
1150 if (r_skb == NULL)
1151 return -ENOMEM;
1152
1153 x = xfrm_state_lookup(&id->daddr, id->spi, id->proto, id->family);
1154 if (x == NULL) {
1155 kfree(r_skb);
1156 return -ESRCH;
1157 }
1158
1159 /*
1160 * XXX: is this lock really needed - none of the other
1161 * gets lock (the concern is things getting updated
1162 * while we are still reading) - jhs
1163 */
1164 spin_lock_bh(&x->lock);
1165 c.data.aevent = p->flags;
1166 c.seq = nlh->nlmsg_seq;
1167 c.pid = nlh->nlmsg_pid;
1168
1169 if (build_aevent(r_skb, x, &c) < 0)
1170 BUG();
1171 err = netlink_unicast(xfrm_nl, r_skb,
1172 NETLINK_CB(skb).pid, MSG_DONTWAIT);
1173 spin_unlock_bh(&x->lock);
1174 xfrm_state_put(x);
1175 return err;
1176}
1177
1178static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
1029{ 1179{
1180 struct xfrm_state *x;
1030 struct km_event c; 1181 struct km_event c;
1182 int err = - EINVAL;
1183 struct xfrm_aevent_id *p = NLMSG_DATA(nlh);
1184 struct rtattr *rp = xfrma[XFRMA_REPLAY_VAL-1];
1185 struct rtattr *lt = xfrma[XFRMA_LTIME_VAL-1];
1186
1187 if (!lt && !rp)
1188 return err;
1189
1190 /* pedantic mode - thou shalt sayeth replaceth */
1191 if (!(nlh->nlmsg_flags&NLM_F_REPLACE))
1192 return err;
1193
1194 x = xfrm_state_lookup(&p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family);
1195 if (x == NULL)
1196 return -ESRCH;
1197
1198 if (x->km.state != XFRM_STATE_VALID)
1199 goto out;
1200
1201 spin_lock_bh(&x->lock);
1202 err = xfrm_update_ae_params(x,(struct rtattr **)xfrma);
1203 spin_unlock_bh(&x->lock);
1204 if (err < 0)
1205 goto out;
1206
1207 c.event = nlh->nlmsg_type;
1208 c.seq = nlh->nlmsg_seq;
1209 c.pid = nlh->nlmsg_pid;
1210 c.data.aevent = XFRM_AE_CU;
1211 km_state_notify(x, &c);
1212 err = 0;
1213out:
1214 xfrm_state_put(x);
1215 return err;
1216}
1217
1218static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
1219{
1220struct km_event c;
1031 1221
1032 xfrm_policy_flush(); 1222 xfrm_policy_flush();
1033 c.event = nlh->nlmsg_type; 1223 c.event = nlh->nlmsg_type;
@@ -1037,6 +1227,139 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **x
1037 return 0; 1227 return 0;
1038} 1228}
1039 1229
1230static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
1231{
1232 struct xfrm_policy *xp;
1233 struct xfrm_user_polexpire *up = NLMSG_DATA(nlh);
1234 struct xfrm_userpolicy_info *p = &up->pol;
1235 int err = -ENOENT;
1236
1237 if (p->index)
1238 xp = xfrm_policy_byid(p->dir, p->index, 0);
1239 else {
1240 struct rtattr **rtattrs = (struct rtattr **)xfrma;
1241 struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1];
1242 struct xfrm_policy tmp;
1243
1244 err = verify_sec_ctx_len(rtattrs);
1245 if (err)
1246 return err;
1247
1248 memset(&tmp, 0, sizeof(struct xfrm_policy));
1249 if (rt) {
1250 struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt);
1251
1252 if ((err = security_xfrm_policy_alloc(&tmp, uctx)))
1253 return err;
1254 }
1255 xp = xfrm_policy_bysel_ctx(p->dir, &p->sel, tmp.security, 0);
1256 security_xfrm_policy_free(&tmp);
1257 }
1258
1259 if (xp == NULL)
1260 return err;
1261 read_lock(&xp->lock);
1262 if (xp->dead) {
1263 read_unlock(&xp->lock);
1264 goto out;
1265 }
1266
1267 read_unlock(&xp->lock);
1268 err = 0;
1269 if (up->hard) {
1270 xfrm_policy_delete(xp, p->dir);
1271 } else {
1272 // reset the timers here?
1273 printk("Dont know what to do with soft policy expire\n");
1274 }
1275 km_policy_expired(xp, p->dir, up->hard, current->pid);
1276
1277out:
1278 xfrm_pol_put(xp);
1279 return err;
1280}
1281
1282static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
1283{
1284 struct xfrm_state *x;
1285 int err;
1286 struct xfrm_user_expire *ue = NLMSG_DATA(nlh);
1287 struct xfrm_usersa_info *p = &ue->state;
1288
1289 x = xfrm_state_lookup(&p->id.daddr, p->id.spi, p->id.proto, p->family);
1290 err = -ENOENT;
1291
1292 if (x == NULL)
1293 return err;
1294
1295 err = -EINVAL;
1296
1297 spin_lock_bh(&x->lock);
1298 if (x->km.state != XFRM_STATE_VALID)
1299 goto out;
1300 km_state_expired(x, ue->hard, current->pid);
1301
1302 if (ue->hard)
1303 __xfrm_state_delete(x);
1304out:
1305 spin_unlock_bh(&x->lock);
1306 xfrm_state_put(x);
1307 return err;
1308}
1309
1310static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
1311{
1312 struct xfrm_policy *xp;
1313 struct xfrm_user_tmpl *ut;
1314 int i;
1315 struct rtattr *rt = xfrma[XFRMA_TMPL-1];
1316
1317 struct xfrm_user_acquire *ua = NLMSG_DATA(nlh);
1318 struct xfrm_state *x = xfrm_state_alloc();
1319 int err = -ENOMEM;
1320
1321 if (!x)
1322 return err;
1323
1324 err = verify_newpolicy_info(&ua->policy);
1325 if (err) {
1326 printk("BAD policy passed\n");
1327 kfree(x);
1328 return err;
1329 }
1330
1331 /* build an XP */
1332 xp = xfrm_policy_construct(&ua->policy, (struct rtattr **) xfrma, &err); if (!xp) {
1333 kfree(x);
1334 return err;
1335 }
1336
1337 memcpy(&x->id, &ua->id, sizeof(ua->id));
1338 memcpy(&x->props.saddr, &ua->saddr, sizeof(ua->saddr));
1339 memcpy(&x->sel, &ua->sel, sizeof(ua->sel));
1340
1341 ut = RTA_DATA(rt);
1342 /* extract the templates and for each call km_key */
1343 for (i = 0; i < xp->xfrm_nr; i++, ut++) {
1344 struct xfrm_tmpl *t = &xp->xfrm_vec[i];
1345 memcpy(&x->id, &t->id, sizeof(x->id));
1346 x->props.mode = t->mode;
1347 x->props.reqid = t->reqid;
1348 x->props.family = ut->family;
1349 t->aalgos = ua->aalgos;
1350 t->ealgos = ua->ealgos;
1351 t->calgos = ua->calgos;
1352 err = km_query(x, t, xp);
1353
1354 }
1355
1356 kfree(x);
1357 kfree(xp);
1358
1359 return 0;
1360}
1361
1362
1040#define XMSGSIZE(type) NLMSG_LENGTH(sizeof(struct type)) 1363#define XMSGSIZE(type) NLMSG_LENGTH(sizeof(struct type))
1041 1364
1042static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { 1365static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = {
@@ -1054,6 +1377,8 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = {
1054 [XFRM_MSG_POLEXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_polexpire), 1377 [XFRM_MSG_POLEXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_polexpire),
1055 [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush), 1378 [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush),
1056 [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = NLMSG_LENGTH(0), 1379 [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = NLMSG_LENGTH(0),
1380 [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id),
1381 [XFRM_MSG_GETAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id),
1057}; 1382};
1058 1383
1059#undef XMSGSIZE 1384#undef XMSGSIZE
@@ -1071,10 +1396,15 @@ static struct xfrm_link {
1071 [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy, 1396 [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy,
1072 .dump = xfrm_dump_policy }, 1397 .dump = xfrm_dump_policy },
1073 [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi }, 1398 [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi },
1399 [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_acquire },
1400 [XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_sa_expire },
1074 [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, 1401 [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy },
1075 [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, 1402 [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa },
1403 [XFRM_MSG_POLEXPIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_pol_expire},
1076 [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = { .doit = xfrm_flush_sa }, 1404 [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = { .doit = xfrm_flush_sa },
1077 [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy }, 1405 [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy },
1406 [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = { .doit = xfrm_new_ae },
1407 [XFRM_MSG_GETAE - XFRM_MSG_BASE] = { .doit = xfrm_get_ae },
1078}; 1408};
1079 1409
1080static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) 1410static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
@@ -1156,26 +1486,26 @@ static void xfrm_netlink_rcv(struct sock *sk, int len)
1156 unsigned int qlen = 0; 1486 unsigned int qlen = 0;
1157 1487
1158 do { 1488 do {
1159 down(&xfrm_cfg_sem); 1489 mutex_lock(&xfrm_cfg_mutex);
1160 netlink_run_queue(sk, &qlen, &xfrm_user_rcv_msg); 1490 netlink_run_queue(sk, &qlen, &xfrm_user_rcv_msg);
1161 up(&xfrm_cfg_sem); 1491 mutex_unlock(&xfrm_cfg_mutex);
1162 1492
1163 } while (qlen); 1493 } while (qlen);
1164} 1494}
1165 1495
1166static int build_expire(struct sk_buff *skb, struct xfrm_state *x, int hard) 1496static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c)
1167{ 1497{
1168 struct xfrm_user_expire *ue; 1498 struct xfrm_user_expire *ue;
1169 struct nlmsghdr *nlh; 1499 struct nlmsghdr *nlh;
1170 unsigned char *b = skb->tail; 1500 unsigned char *b = skb->tail;
1171 1501
1172 nlh = NLMSG_PUT(skb, 0, 0, XFRM_MSG_EXPIRE, 1502 nlh = NLMSG_PUT(skb, c->pid, 0, XFRM_MSG_EXPIRE,
1173 sizeof(*ue)); 1503 sizeof(*ue));
1174 ue = NLMSG_DATA(nlh); 1504 ue = NLMSG_DATA(nlh);
1175 nlh->nlmsg_flags = 0; 1505 nlh->nlmsg_flags = 0;
1176 1506
1177 copy_to_user_state(x, &ue->state); 1507 copy_to_user_state(x, &ue->state);
1178 ue->hard = (hard != 0) ? 1 : 0; 1508 ue->hard = (c->data.hard != 0) ? 1 : 0;
1179 1509
1180 nlh->nlmsg_len = skb->tail - b; 1510 nlh->nlmsg_len = skb->tail - b;
1181 return skb->len; 1511 return skb->len;
@@ -1194,13 +1524,31 @@ static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
1194 if (skb == NULL) 1524 if (skb == NULL)
1195 return -ENOMEM; 1525 return -ENOMEM;
1196 1526
1197 if (build_expire(skb, x, c->data.hard) < 0) 1527 if (build_expire(skb, x, c) < 0)
1198 BUG(); 1528 BUG();
1199 1529
1200 NETLINK_CB(skb).dst_group = XFRMNLGRP_EXPIRE; 1530 NETLINK_CB(skb).dst_group = XFRMNLGRP_EXPIRE;
1201 return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); 1531 return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
1202} 1532}
1203 1533
1534static int xfrm_aevent_state_notify(struct xfrm_state *x, struct km_event *c)
1535{
1536 struct sk_buff *skb;
1537 int len = NLMSG_LENGTH(sizeof(struct xfrm_aevent_id));
1538
1539 len += RTA_SPACE(sizeof(struct xfrm_replay_state));
1540 len += RTA_SPACE(sizeof(struct xfrm_lifetime_cur));
1541 skb = alloc_skb(len, GFP_ATOMIC);
1542 if (skb == NULL)
1543 return -ENOMEM;
1544
1545 if (build_aevent(skb, x, c) < 0)
1546 BUG();
1547
1548 NETLINK_CB(skb).dst_group = XFRMNLGRP_AEVENTS;
1549 return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_AEVENTS, GFP_ATOMIC);
1550}
1551
1204static int xfrm_notify_sa_flush(struct km_event *c) 1552static int xfrm_notify_sa_flush(struct km_event *c)
1205{ 1553{
1206 struct xfrm_usersa_flush *p; 1554 struct xfrm_usersa_flush *p;
@@ -1313,6 +1661,8 @@ static int xfrm_send_state_notify(struct xfrm_state *x, struct km_event *c)
1313 switch (c->event) { 1661 switch (c->event) {
1314 case XFRM_MSG_EXPIRE: 1662 case XFRM_MSG_EXPIRE:
1315 return xfrm_exp_state_notify(x, c); 1663 return xfrm_exp_state_notify(x, c);
1664 case XFRM_MSG_NEWAE:
1665 return xfrm_aevent_state_notify(x, c);
1316 case XFRM_MSG_DELSA: 1666 case XFRM_MSG_DELSA:
1317 case XFRM_MSG_UPDSA: 1667 case XFRM_MSG_UPDSA:
1318 case XFRM_MSG_NEWSA: 1668 case XFRM_MSG_NEWSA:
@@ -1443,13 +1793,14 @@ static struct xfrm_policy *xfrm_compile_policy(u16 family, int opt,
1443} 1793}
1444 1794
1445static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp, 1795static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp,
1446 int dir, int hard) 1796 int dir, struct km_event *c)
1447{ 1797{
1448 struct xfrm_user_polexpire *upe; 1798 struct xfrm_user_polexpire *upe;
1449 struct nlmsghdr *nlh; 1799 struct nlmsghdr *nlh;
1800 int hard = c->data.hard;
1450 unsigned char *b = skb->tail; 1801 unsigned char *b = skb->tail;
1451 1802
1452 nlh = NLMSG_PUT(skb, 0, 0, XFRM_MSG_POLEXPIRE, sizeof(*upe)); 1803 nlh = NLMSG_PUT(skb, c->pid, 0, XFRM_MSG_POLEXPIRE, sizeof(*upe));
1453 upe = NLMSG_DATA(nlh); 1804 upe = NLMSG_DATA(nlh);
1454 nlh->nlmsg_flags = 0; 1805 nlh->nlmsg_flags = 0;
1455 1806
@@ -1480,7 +1831,7 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve
1480 if (skb == NULL) 1831 if (skb == NULL)
1481 return -ENOMEM; 1832 return -ENOMEM;
1482 1833
1483 if (build_polexpire(skb, xp, dir, c->data.hard) < 0) 1834 if (build_polexpire(skb, xp, dir, c) < 0)
1484 BUG(); 1835 BUG();
1485 1836
1486 NETLINK_CB(skb).dst_group = XFRMNLGRP_EXPIRE; 1837 NETLINK_CB(skb).dst_group = XFRMNLGRP_EXPIRE;
@@ -1596,12 +1947,15 @@ static struct xfrm_mgr netlink_mgr = {
1596 1947
1597static int __init xfrm_user_init(void) 1948static int __init xfrm_user_init(void)
1598{ 1949{
1950 struct sock *nlsk;
1951
1599 printk(KERN_INFO "Initializing IPsec netlink socket\n"); 1952 printk(KERN_INFO "Initializing IPsec netlink socket\n");
1600 1953
1601 xfrm_nl = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX, 1954 nlsk = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX,
1602 xfrm_netlink_rcv, THIS_MODULE); 1955 xfrm_netlink_rcv, THIS_MODULE);
1603 if (xfrm_nl == NULL) 1956 if (nlsk == NULL)
1604 return -ENOMEM; 1957 return -ENOMEM;
1958 rcu_assign_pointer(xfrm_nl, nlsk);
1605 1959
1606 xfrm_register_km(&netlink_mgr); 1960 xfrm_register_km(&netlink_mgr);
1607 1961
@@ -1610,11 +1964,16 @@ static int __init xfrm_user_init(void)
1610 1964
1611static void __exit xfrm_user_exit(void) 1965static void __exit xfrm_user_exit(void)
1612{ 1966{
1967 struct sock *nlsk = xfrm_nl;
1968
1613 xfrm_unregister_km(&netlink_mgr); 1969 xfrm_unregister_km(&netlink_mgr);
1614 sock_release(xfrm_nl->sk_socket); 1970 rcu_assign_pointer(xfrm_nl, NULL);
1971 synchronize_rcu();
1972 sock_release(nlsk->sk_socket);
1615} 1973}
1616 1974
1617module_init(xfrm_user_init); 1975module_init(xfrm_user_init);
1618module_exit(xfrm_user_exit); 1976module_exit(xfrm_user_exit);
1619MODULE_LICENSE("GPL"); 1977MODULE_LICENSE("GPL");
1620MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM); 1978MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM);
1979