aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-03-21 12:31:48 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-21 12:31:48 -0500
commit3d1f337b3e7378923c89f37afb573a918ef40be5 (patch)
tree386798378567a10d1c7b24f599cb50f70298694c
parent2bf2154c6bb5599e3ec3f73c34861a0b12aa839e (diff)
parent5e35941d990123f155b02d5663e51a24f816b6f3 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (235 commits) [NETFILTER]: Add H.323 conntrack/NAT helper [TG3]: Don't mark tg3_test_registers() as returning const. [IPV6]: Cleanups for net/ipv6/addrconf.c (kzalloc, early exit) v2 [IPV6]: Nearly complete kzalloc cleanup for net/ipv6 [IPV6]: Cleanup of net/ipv6/reassambly.c [BRIDGE]: Remove duplicate const from is_link_local() argument type. [DECNET]: net/decnet/dn_route.c: fix inconsequent NULL checking [TG3]: make drivers/net/tg3.c:tg3_request_irq() static [BRIDGE]: use LLC to send STP [LLC]: llc_mac_hdr_init const arguments [BRIDGE]: allow show/store of group multicast address [BRIDGE]: use llc for receiving STP packets [BRIDGE]: stp timer to jiffies cleanup [BRIDGE]: forwarding remove unneeded preempt and bh diasables [BRIDGE]: netfilter inline cleanup [BRIDGE]: netfilter VLAN macro cleanup [BRIDGE]: netfilter dont use __constant_htons [BRIDGE]: netfilter whitespace [BRIDGE]: optimize frame pass up [BRIDGE]: use kzalloc ...
-rw-r--r--Documentation/connector/connector.txt5
-rw-r--r--Documentation/networking/ip-sysctl.txt49
-rw-r--r--drivers/atm/suni.c2
-rw-r--r--drivers/connector/connector.c7
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c16
-rw-r--r--drivers/net/8139too.c2
-rw-r--r--drivers/net/bnx2.c477
-rw-r--r--drivers/net/bnx2.h37
-rw-r--r--drivers/net/cassini.c40
-rw-r--r--drivers/net/cassini.h2
-rw-r--r--drivers/net/e1000/e1000_main.c2
-rw-r--r--drivers/net/irda/Kconfig8
-rw-r--r--drivers/net/irda/Makefile1
-rw-r--r--drivers/net/irda/donauboe.c2
-rw-r--r--drivers/net/irda/ep7211_ir.c11
-rw-r--r--drivers/net/irda/irtty-sir.c19
-rw-r--r--drivers/net/irda/nsc-ircc.c320
-rw-r--r--drivers/net/irda/nsc-ircc.h2
-rw-r--r--drivers/net/irda/sir_dongle.c19
-rw-r--r--drivers/net/irda/toim3232-sir.c375
-rw-r--r--drivers/net/irda/vlsi_ir.c2
-rw-r--r--drivers/net/ppp_generic.c4
-rw-r--r--drivers/net/pppoe.c3
-rw-r--r--drivers/net/sungem.c37
-rw-r--r--drivers/net/sungem.h6
-rw-r--r--drivers/net/tg3.c648
-rw-r--r--drivers/net/tg3.h19
-rw-r--r--drivers/net/wan/sbni.c3
-rw-r--r--include/asm-sparc/socket.h2
-rw-r--r--include/linux/dccp.h132
-rw-r--r--include/linux/dn.h44
-rw-r--r--include/linux/icmpv6.h11
-rw-r--r--include/linux/if.h26
-rw-r--r--include/linux/in.h1
-rw-r--r--include/linux/inetdevice.h1
-rw-r--r--include/linux/ipv6.h14
-rw-r--r--include/linux/ipv6_route.h10
-rw-r--r--include/linux/irda.h1
-rw-r--r--include/linux/list.h24
-rw-r--r--include/linux/net.h4
-rw-r--r--include/linux/netdevice.h41
-rw-r--r--include/linux/netfilter.h9
-rw-r--r--include/linux/netfilter/nfnetlink.h1
-rw-r--r--include/linux/netfilter/nfnetlink_log.h6
-rw-r--r--include/linux/netfilter/x_tables.h37
-rw-r--r--include/linux/netfilter/xt_policy.h58
-rw-r--r--include/linux/netfilter_bridge.h27
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack.h2
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_h323.h30
-rw-r--r--include/linux/netfilter_ipv4/ip_nat.h2
-rw-r--r--include/linux/netfilter_ipv4/ipt_policy.h69
-rw-r--r--include/linux/netfilter_ipv6/ip6t_policy.h69
-rw-r--r--include/linux/netlink.h1
-rw-r--r--include/linux/pci_ids.h6
-rw-r--r--include/linux/rtnetlink.h23
-rw-r--r--include/linux/security.h25
-rw-r--r--include/linux/skbuff.h47
-rw-r--r--include/linux/socket.h1
-rw-r--r--include/linux/sunrpc/svcsock.h2
-rw-r--r--include/linux/sysctl.h27
-rw-r--r--include/linux/tcp.h6
-rw-r--r--include/linux/xfrm.h30
-rw-r--r--include/net/af_unix.h3
-rw-r--r--include/net/dn.h105
-rw-r--r--include/net/dn_dev.h88
-rw-r--r--include/net/dn_fib.h22
-rw-r--r--include/net/dn_neigh.h4
-rw-r--r--include/net/dn_nsp.h72
-rw-r--r--include/net/dn_route.h12
-rw-r--r--include/net/flow.h8
-rw-r--r--include/net/if_inet6.h3
-rw-r--r--include/net/inet_connection_sock.h26
-rw-r--r--include/net/ip.h4
-rw-r--r--include/net/ip6_route.h24
-rw-r--r--include/net/ipv6.h22
-rw-r--r--include/net/llc.h2
-rw-r--r--include/net/ndisc.h2
-rw-r--r--include/net/neighbour.h2
-rw-r--r--include/net/netfilter/nf_conntrack.h56
-rw-r--r--include/net/scm.h10
-rw-r--r--include/net/sctp/structs.h10
-rw-r--r--include/net/sock.h12
-rw-r--r--include/net/tcp.h16
-rw-r--r--include/net/xfrm.h62
-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/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.c95
-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.c2842
-rw-r--r--net/core/rtnetlink.c78
-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/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/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.c113
-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_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.c21
-rw-r--r--net/ipv4/netfilter/arpt_mangle.c23
-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.c7
-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.c69
-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.c22
-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.c43
-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.c87
-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.c39
-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/Kconfig10
-rw-r--r--net/netfilter/Makefile1
-rw-r--r--net/netfilter/nf_conntrack_core.c135
-rw-r--r--net/netfilter/nf_conntrack_ftp.c2
-rw-r--r--net/netfilter/nf_conntrack_netlink.c46
-rw-r--r--net/netfilter/nf_conntrack_standalone.c1
-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/x_tables.c72
-rw-r--r--net/netfilter/xt_CLASSIFY.c42
-rw-r--r--net/netfilter/xt_CONNMARK.c27
-rw-r--r--net/netfilter/xt_MARK.c37
-rw-r--r--net/netfilter/xt_NFQUEUE.c24
-rw-r--r--net/netfilter/xt_NOTRACK.c45
-rw-r--r--net/netfilter/xt_comment.c18
-rw-r--r--net/netfilter/xt_connbytes.c15
-rw-r--r--net/netfilter/xt_connmark.c28
-rw-r--r--net/netfilter/xt_conntrack.c18
-rw-r--r--net/netfilter/xt_dccp.c45
-rw-r--r--net/netfilter/xt_helper.c26
-rw-r--r--net/netfilter/xt_length.c24
-rw-r--r--net/netfilter/xt_limit.c7
-rw-r--r--net/netfilter/xt_mac.c34
-rw-r--r--net/netfilter/xt_mark.c16
-rw-r--r--net/netfilter/xt_physdev.c14
-rw-r--r--net/netfilter/xt_pkttype.c23
-rw-r--r--net/netfilter/xt_policy.c209
-rw-r--r--net/netfilter/xt_realm.c27
-rw-r--r--net/netfilter/xt_sctp.c66
-rw-r--r--net/netfilter/xt_state.c21
-rw-r--r--net/netfilter/xt_string.c10
-rw-r--r--net/netfilter/xt_tcpmss.c52
-rw-r--r--net/netfilter/xt_tcpudp.c112
-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/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.c332
-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/xfrm/xfrm_policy.c9
-rw-r--r--net/xfrm/xfrm_state.c108
-rw-r--r--net/xfrm/xfrm_user.c397
-rw-r--r--security/dummy.c13
-rw-r--r--security/selinux/hooks.c46
-rw-r--r--security/selinux/include/xfrm.h12
-rw-r--r--security/selinux/nlmsgtab.c7
-rw-r--r--security/selinux/xfrm.c68
349 files changed, 18959 insertions, 7284 deletions
diff --git a/Documentation/connector/connector.txt b/Documentation/connector/connector.txt
index 57a314b14cf8..ad6e0ba7b38c 100644
--- a/Documentation/connector/connector.txt
+++ b/Documentation/connector/connector.txt
@@ -69,10 +69,11 @@ Unregisters new callback with connector core.
69 69
70struct cb_id *id - unique connector's user identifier. 70struct cb_id *id - unique connector's user identifier.
71 71
72void cn_netlink_send(struct cn_msg *msg, u32 __groups, int gfp_mask); 72int cn_netlink_send(struct cn_msg *msg, u32 __groups, int gfp_mask);
73 73
74Sends message to the specified groups. It can be safely called from 74Sends message to the specified groups. It can be safely called from
75any context, but may silently fail under strong memory pressure. 75softirq context, but may silently fail under strong memory pressure.
76If there are no listeners for given group -ESRCH can be returned.
76 77
77struct cn_msg * - message header(with attached data). 78struct cn_msg * - message header(with attached data).
78u32 __group - destination group. 79u32 __group - destination group.
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 26364d06ae92..f12007b80a46 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -355,6 +355,13 @@ somaxconn - INTEGER
355 Defaults to 128. See also tcp_max_syn_backlog for additional tuning 355 Defaults to 128. See also tcp_max_syn_backlog for additional tuning
356 for TCP sockets. 356 for TCP sockets.
357 357
358tcp_workaround_signed_windows - BOOLEAN
359 If set, assume no receipt of a window scaling option means the
360 remote TCP is broken and treats the window as a signed quantity.
361 If unset, assume the remote TCP is not broken even if we do
362 not receive a window scaling option from them.
363 Default: 0
364
358IP Variables: 365IP Variables:
359 366
360ip_local_port_range - 2 INTEGERS 367ip_local_port_range - 2 INTEGERS
@@ -619,6 +626,11 @@ arp_ignore - INTEGER
619 The max value from conf/{all,interface}/arp_ignore is used 626 The max value from conf/{all,interface}/arp_ignore is used
620 when ARP request is received on the {interface} 627 when ARP request is received on the {interface}
621 628
629arp_accept - BOOLEAN
630 Define behavior when gratuitous arp replies are received:
631 0 - drop gratuitous arp frames
632 1 - accept gratuitous arp frames
633
622app_solicit - INTEGER 634app_solicit - INTEGER
623 The maximum number of probes to send to the user space ARP daemon 635 The maximum number of probes to send to the user space ARP daemon
624 via netlink before dropping back to multicast probes (see 636 via netlink before dropping back to multicast probes (see
@@ -717,6 +729,33 @@ accept_ra - BOOLEAN
717 Functional default: enabled if local forwarding is disabled. 729 Functional default: enabled if local forwarding is disabled.
718 disabled if local forwarding is enabled. 730 disabled if local forwarding is enabled.
719 731
732accept_ra_defrtr - BOOLEAN
733 Learn default router in Router Advertisement.
734
735 Functional default: enabled if accept_ra is enabled.
736 disabled if accept_ra is disabled.
737
738accept_ra_pinfo - BOOLEAN
739 Learn Prefix Inforamtion in Router Advertisement.
740
741 Functional default: enabled if accept_ra is enabled.
742 disabled if accept_ra is disabled.
743
744accept_ra_rt_info_max_plen - INTEGER
745 Maximum prefix length of Route Information in RA.
746
747 Route Information w/ prefix larger than or equal to this
748 variable shall be ignored.
749
750 Functional default: 0 if accept_ra_rtr_pref is enabled.
751 -1 if accept_ra_rtr_pref is disabled.
752
753accept_ra_rtr_pref - BOOLEAN
754 Accept Router Preference in RA.
755
756 Functional default: enabled if accept_ra is enabled.
757 disabled if accept_ra is disabled.
758
720accept_redirects - BOOLEAN 759accept_redirects - BOOLEAN
721 Accept Redirects. 760 Accept Redirects.
722 761
@@ -727,8 +766,8 @@ autoconf - BOOLEAN
727 Autoconfigure addresses using Prefix Information in Router 766 Autoconfigure addresses using Prefix Information in Router
728 Advertisements. 767 Advertisements.
729 768
730 Functional default: enabled if accept_ra is enabled. 769 Functional default: enabled if accept_ra_pinfo is enabled.
731 disabled if accept_ra is disabled. 770 disabled if accept_ra_pinfo is disabled.
732 771
733dad_transmits - INTEGER 772dad_transmits - INTEGER
734 The amount of Duplicate Address Detection probes to send. 773 The amount of Duplicate Address Detection probes to send.
@@ -771,6 +810,12 @@ mtu - INTEGER
771 Default Maximum Transfer Unit 810 Default Maximum Transfer Unit
772 Default: 1280 (IPv6 required minimum) 811 Default: 1280 (IPv6 required minimum)
773 812
813router_probe_interval - INTEGER
814 Minimum interval (in seconds) between Router Probing described
815 in RFC4191.
816
817 Default: 60
818
774router_solicitation_delay - INTEGER 819router_solicitation_delay - INTEGER
775 Number of seconds to wait after interface is brought up 820 Number of seconds to wait after interface is brought up
776 before sending Router Solicitations. 821 before sending Router Solicitations.
diff --git a/drivers/atm/suni.c b/drivers/atm/suni.c
index 06817dec0c25..b1d063cc4fbe 100644
--- a/drivers/atm/suni.c
+++ b/drivers/atm/suni.c
@@ -188,7 +188,7 @@ static int suni_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg)
188 case SONET_GETDIAG: 188 case SONET_GETDIAG:
189 return get_diag(dev,arg); 189 return get_diag(dev,arg);
190 case SONET_SETFRAMING: 190 case SONET_SETFRAMING:
191 if (arg != SONET_FRAME_SONET) return -EINVAL; 191 if ((int)(unsigned long)arg != SONET_FRAME_SONET) return -EINVAL;
192 return 0; 192 return 0;
193 case SONET_GETFRAMING: 193 case SONET_GETFRAMING:
194 return put_user(SONET_FRAME_SONET,(int __user *)arg) ? 194 return put_user(SONET_FRAME_SONET,(int __user *)arg) ?
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index 505677fb3157..d7125f4d9113 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -97,6 +97,9 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, gfp_t gfp_mask)
97 group = __group; 97 group = __group;
98 } 98 }
99 99
100 if (!netlink_has_listeners(dev->nls, group))
101 return -ESRCH;
102
100 size = NLMSG_SPACE(sizeof(*msg) + msg->len); 103 size = NLMSG_SPACE(sizeof(*msg) + msg->len);
101 104
102 skb = alloc_skb(size, gfp_mask); 105 skb = alloc_skb(size, gfp_mask);
@@ -111,9 +114,7 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, gfp_t gfp_mask)
111 114
112 NETLINK_CB(skb).dst_group = group; 115 NETLINK_CB(skb).dst_group = group;
113 116
114 netlink_broadcast(dev->nls, skb, 0, group, gfp_mask); 117 return netlink_broadcast(dev->nls, skb, 0, group, gfp_mask);
115
116 return 0;
117 118
118nlmsg_failure: 119nlmsg_failure:
119 kfree_skb(skb); 120 kfree_skb(skb);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 0ebacd558ff6..37da8d3dc388 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -253,7 +253,6 @@ static void path_free(struct net_device *dev, struct ipoib_path *path)
253 if (neigh->ah) 253 if (neigh->ah)
254 ipoib_put_ah(neigh->ah); 254 ipoib_put_ah(neigh->ah);
255 *to_ipoib_neigh(neigh->neighbour) = NULL; 255 *to_ipoib_neigh(neigh->neighbour) = NULL;
256 neigh->neighbour->ops->destructor = NULL;
257 kfree(neigh); 256 kfree(neigh);
258 } 257 }
259 258
@@ -531,7 +530,6 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
531err: 530err:
532 *to_ipoib_neigh(skb->dst->neighbour) = NULL; 531 *to_ipoib_neigh(skb->dst->neighbour) = NULL;
533 list_del(&neigh->list); 532 list_del(&neigh->list);
534 neigh->neighbour->ops->destructor = NULL;
535 kfree(neigh); 533 kfree(neigh);
536 534
537 ++priv->stats.tx_dropped; 535 ++priv->stats.tx_dropped;
@@ -770,21 +768,9 @@ static void ipoib_neigh_destructor(struct neighbour *n)
770 ipoib_put_ah(ah); 768 ipoib_put_ah(ah);
771} 769}
772 770
773static int ipoib_neigh_setup(struct neighbour *neigh)
774{
775 /*
776 * Is this kosher? I can't find anybody in the kernel that
777 * sets neigh->destructor, so we should be able to set it here
778 * without trouble.
779 */
780 neigh->ops->destructor = ipoib_neigh_destructor;
781
782 return 0;
783}
784
785static int ipoib_neigh_setup_dev(struct net_device *dev, struct neigh_parms *parms) 771static int ipoib_neigh_setup_dev(struct net_device *dev, struct neigh_parms *parms)
786{ 772{
787 parms->neigh_setup = ipoib_neigh_setup; 773 parms->neigh_destructor = ipoib_neigh_destructor;
788 774
789 return 0; 775 return 0;
790} 776}
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index e58d4c50c2e1..f5ee064ab6b2 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -1605,7 +1605,7 @@ static void rtl8139_thread (void *_data)
1605 if (tp->watchdog_fired) { 1605 if (tp->watchdog_fired) {
1606 tp->watchdog_fired = 0; 1606 tp->watchdog_fired = 0;
1607 rtl8139_tx_timeout_task(_data); 1607 rtl8139_tx_timeout_task(_data);
1608 } else if (rtnl_shlock_nowait() == 0) { 1608 } else if (rtnl_trylock()) {
1609 rtl8139_thread_iter (dev, tp, tp->mmio_addr); 1609 rtl8139_thread_iter (dev, tp, tp->mmio_addr);
1610 rtnl_unlock (); 1610 rtnl_unlock ();
1611 } else { 1611 } else {
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index b787b6582e50..7d213707008a 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -14,8 +14,8 @@
14 14
15#define DRV_MODULE_NAME "bnx2" 15#define DRV_MODULE_NAME "bnx2"
16#define PFX DRV_MODULE_NAME ": " 16#define PFX DRV_MODULE_NAME ": "
17#define DRV_MODULE_VERSION "1.4.31" 17#define DRV_MODULE_VERSION "1.4.38"
18#define DRV_MODULE_RELDATE "January 19, 2006" 18#define DRV_MODULE_RELDATE "February 10, 2006"
19 19
20#define RUN_AT(x) (jiffies + (x)) 20#define RUN_AT(x) (jiffies + (x))
21 21
@@ -360,6 +360,8 @@ bnx2_netif_start(struct bnx2 *bp)
360static void 360static void
361bnx2_free_mem(struct bnx2 *bp) 361bnx2_free_mem(struct bnx2 *bp)
362{ 362{
363 int i;
364
363 if (bp->stats_blk) { 365 if (bp->stats_blk) {
364 pci_free_consistent(bp->pdev, sizeof(struct statistics_block), 366 pci_free_consistent(bp->pdev, sizeof(struct statistics_block),
365 bp->stats_blk, bp->stats_blk_mapping); 367 bp->stats_blk, bp->stats_blk_mapping);
@@ -378,19 +380,23 @@ bnx2_free_mem(struct bnx2 *bp)
378 } 380 }
379 kfree(bp->tx_buf_ring); 381 kfree(bp->tx_buf_ring);
380 bp->tx_buf_ring = NULL; 382 bp->tx_buf_ring = NULL;
381 if (bp->rx_desc_ring) { 383 for (i = 0; i < bp->rx_max_ring; i++) {
382 pci_free_consistent(bp->pdev, 384 if (bp->rx_desc_ring[i])
383 sizeof(struct rx_bd) * RX_DESC_CNT, 385 pci_free_consistent(bp->pdev,
384 bp->rx_desc_ring, bp->rx_desc_mapping); 386 sizeof(struct rx_bd) * RX_DESC_CNT,
385 bp->rx_desc_ring = NULL; 387 bp->rx_desc_ring[i],
386 } 388 bp->rx_desc_mapping[i]);
387 kfree(bp->rx_buf_ring); 389 bp->rx_desc_ring[i] = NULL;
390 }
391 vfree(bp->rx_buf_ring);
388 bp->rx_buf_ring = NULL; 392 bp->rx_buf_ring = NULL;
389} 393}
390 394
391static int 395static int
392bnx2_alloc_mem(struct bnx2 *bp) 396bnx2_alloc_mem(struct bnx2 *bp)
393{ 397{
398 int i;
399
394 bp->tx_buf_ring = kmalloc(sizeof(struct sw_bd) * TX_DESC_CNT, 400 bp->tx_buf_ring = kmalloc(sizeof(struct sw_bd) * TX_DESC_CNT,
395 GFP_KERNEL); 401 GFP_KERNEL);
396 if (bp->tx_buf_ring == NULL) 402 if (bp->tx_buf_ring == NULL)
@@ -404,18 +410,23 @@ bnx2_alloc_mem(struct bnx2 *bp)
404 if (bp->tx_desc_ring == NULL) 410 if (bp->tx_desc_ring == NULL)
405 goto alloc_mem_err; 411 goto alloc_mem_err;
406 412
407 bp->rx_buf_ring = kmalloc(sizeof(struct sw_bd) * RX_DESC_CNT, 413 bp->rx_buf_ring = vmalloc(sizeof(struct sw_bd) * RX_DESC_CNT *
408 GFP_KERNEL); 414 bp->rx_max_ring);
409 if (bp->rx_buf_ring == NULL) 415 if (bp->rx_buf_ring == NULL)
410 goto alloc_mem_err; 416 goto alloc_mem_err;
411 417
412 memset(bp->rx_buf_ring, 0, sizeof(struct sw_bd) * RX_DESC_CNT); 418 memset(bp->rx_buf_ring, 0, sizeof(struct sw_bd) * RX_DESC_CNT *
413 bp->rx_desc_ring = pci_alloc_consistent(bp->pdev, 419 bp->rx_max_ring);
414 sizeof(struct rx_bd) * 420
415 RX_DESC_CNT, 421 for (i = 0; i < bp->rx_max_ring; i++) {
416 &bp->rx_desc_mapping); 422 bp->rx_desc_ring[i] =
417 if (bp->rx_desc_ring == NULL) 423 pci_alloc_consistent(bp->pdev,
418 goto alloc_mem_err; 424 sizeof(struct rx_bd) * RX_DESC_CNT,
425 &bp->rx_desc_mapping[i]);
426 if (bp->rx_desc_ring[i] == NULL)
427 goto alloc_mem_err;
428
429 }
419 430
420 bp->status_blk = pci_alloc_consistent(bp->pdev, 431 bp->status_blk = pci_alloc_consistent(bp->pdev,
421 sizeof(struct status_block), 432 sizeof(struct status_block),
@@ -1520,7 +1531,7 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index)
1520 struct sk_buff *skb; 1531 struct sk_buff *skb;
1521 struct sw_bd *rx_buf = &bp->rx_buf_ring[index]; 1532 struct sw_bd *rx_buf = &bp->rx_buf_ring[index];
1522 dma_addr_t mapping; 1533 dma_addr_t mapping;
1523 struct rx_bd *rxbd = &bp->rx_desc_ring[index]; 1534 struct rx_bd *rxbd = &bp->rx_desc_ring[RX_RING(index)][RX_IDX(index)];
1524 unsigned long align; 1535 unsigned long align;
1525 1536
1526 skb = dev_alloc_skb(bp->rx_buf_size); 1537 skb = dev_alloc_skb(bp->rx_buf_size);
@@ -1656,23 +1667,30 @@ static inline void
1656bnx2_reuse_rx_skb(struct bnx2 *bp, struct sk_buff *skb, 1667bnx2_reuse_rx_skb(struct bnx2 *bp, struct sk_buff *skb,
1657 u16 cons, u16 prod) 1668 u16 cons, u16 prod)
1658{ 1669{
1659 struct sw_bd *cons_rx_buf = &bp->rx_buf_ring[cons]; 1670 struct sw_bd *cons_rx_buf, *prod_rx_buf;
1660 struct sw_bd *prod_rx_buf = &bp->rx_buf_ring[prod]; 1671 struct rx_bd *cons_bd, *prod_bd;
1661 struct rx_bd *cons_bd = &bp->rx_desc_ring[cons]; 1672
1662 struct rx_bd *prod_bd = &bp->rx_desc_ring[prod]; 1673 cons_rx_buf = &bp->rx_buf_ring[cons];
1674 prod_rx_buf = &bp->rx_buf_ring[prod];
1663 1675
1664 pci_dma_sync_single_for_device(bp->pdev, 1676 pci_dma_sync_single_for_device(bp->pdev,
1665 pci_unmap_addr(cons_rx_buf, mapping), 1677 pci_unmap_addr(cons_rx_buf, mapping),
1666 bp->rx_offset + RX_COPY_THRESH, PCI_DMA_FROMDEVICE); 1678 bp->rx_offset + RX_COPY_THRESH, PCI_DMA_FROMDEVICE);
1667 1679
1668 prod_rx_buf->skb = cons_rx_buf->skb; 1680 bp->rx_prod_bseq += bp->rx_buf_use_size;
1669 pci_unmap_addr_set(prod_rx_buf, mapping,
1670 pci_unmap_addr(cons_rx_buf, mapping));
1671 1681
1672 memcpy(prod_bd, cons_bd, 8); 1682 prod_rx_buf->skb = skb;
1673 1683
1674 bp->rx_prod_bseq += bp->rx_buf_use_size; 1684 if (cons == prod)
1685 return;
1675 1686
1687 pci_unmap_addr_set(prod_rx_buf, mapping,
1688 pci_unmap_addr(cons_rx_buf, mapping));
1689
1690 cons_bd = &bp->rx_desc_ring[RX_RING(cons)][RX_IDX(cons)];
1691 prod_bd = &bp->rx_desc_ring[RX_RING(prod)][RX_IDX(prod)];
1692 prod_bd->rx_bd_haddr_hi = cons_bd->rx_bd_haddr_hi;
1693 prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo;
1676} 1694}
1677 1695
1678static int 1696static int
@@ -1699,14 +1717,19 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
1699 u32 status; 1717 u32 status;
1700 struct sw_bd *rx_buf; 1718 struct sw_bd *rx_buf;
1701 struct sk_buff *skb; 1719 struct sk_buff *skb;
1720 dma_addr_t dma_addr;
1702 1721
1703 sw_ring_cons = RX_RING_IDX(sw_cons); 1722 sw_ring_cons = RX_RING_IDX(sw_cons);
1704 sw_ring_prod = RX_RING_IDX(sw_prod); 1723 sw_ring_prod = RX_RING_IDX(sw_prod);
1705 1724
1706 rx_buf = &bp->rx_buf_ring[sw_ring_cons]; 1725 rx_buf = &bp->rx_buf_ring[sw_ring_cons];
1707 skb = rx_buf->skb; 1726 skb = rx_buf->skb;
1708 pci_dma_sync_single_for_cpu(bp->pdev, 1727
1709 pci_unmap_addr(rx_buf, mapping), 1728 rx_buf->skb = NULL;
1729
1730 dma_addr = pci_unmap_addr(rx_buf, mapping);
1731
1732 pci_dma_sync_single_for_cpu(bp->pdev, dma_addr,
1710 bp->rx_offset + RX_COPY_THRESH, PCI_DMA_FROMDEVICE); 1733 bp->rx_offset + RX_COPY_THRESH, PCI_DMA_FROMDEVICE);
1711 1734
1712 rx_hdr = (struct l2_fhdr *) skb->data; 1735 rx_hdr = (struct l2_fhdr *) skb->data;
@@ -1747,8 +1770,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
1747 skb = new_skb; 1770 skb = new_skb;
1748 } 1771 }
1749 else if (bnx2_alloc_rx_skb(bp, sw_ring_prod) == 0) { 1772 else if (bnx2_alloc_rx_skb(bp, sw_ring_prod) == 0) {
1750 pci_unmap_single(bp->pdev, 1773 pci_unmap_single(bp->pdev, dma_addr,
1751 pci_unmap_addr(rx_buf, mapping),
1752 bp->rx_buf_use_size, PCI_DMA_FROMDEVICE); 1774 bp->rx_buf_use_size, PCI_DMA_FROMDEVICE);
1753 1775
1754 skb_reserve(skb, bp->rx_offset); 1776 skb_reserve(skb, bp->rx_offset);
@@ -1794,8 +1816,6 @@ reuse_rx:
1794 rx_pkt++; 1816 rx_pkt++;
1795 1817
1796next_rx: 1818next_rx:
1797 rx_buf->skb = NULL;
1798
1799 sw_cons = NEXT_RX_BD(sw_cons); 1819 sw_cons = NEXT_RX_BD(sw_cons);
1800 sw_prod = NEXT_RX_BD(sw_prod); 1820 sw_prod = NEXT_RX_BD(sw_prod);
1801 1821
@@ -3340,27 +3360,35 @@ bnx2_init_rx_ring(struct bnx2 *bp)
3340 bp->hw_rx_cons = 0; 3360 bp->hw_rx_cons = 0;
3341 bp->rx_prod_bseq = 0; 3361 bp->rx_prod_bseq = 0;
3342 3362
3343 rxbd = &bp->rx_desc_ring[0]; 3363 for (i = 0; i < bp->rx_max_ring; i++) {
3344 for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) { 3364 int j;
3345 rxbd->rx_bd_len = bp->rx_buf_use_size;
3346 rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END;
3347 }
3348 3365
3349 rxbd->rx_bd_haddr_hi = (u64) bp->rx_desc_mapping >> 32; 3366 rxbd = &bp->rx_desc_ring[i][0];
3350 rxbd->rx_bd_haddr_lo = (u64) bp->rx_desc_mapping & 0xffffffff; 3367 for (j = 0; j < MAX_RX_DESC_CNT; j++, rxbd++) {
3368 rxbd->rx_bd_len = bp->rx_buf_use_size;
3369 rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END;
3370 }
3371 if (i == (bp->rx_max_ring - 1))
3372 j = 0;
3373 else
3374 j = i + 1;
3375 rxbd->rx_bd_haddr_hi = (u64) bp->rx_desc_mapping[j] >> 32;
3376 rxbd->rx_bd_haddr_lo = (u64) bp->rx_desc_mapping[j] &
3377 0xffffffff;
3378 }
3351 3379
3352 val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE; 3380 val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE;
3353 val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2; 3381 val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2;
3354 val |= 0x02 << 8; 3382 val |= 0x02 << 8;
3355 CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_CTX_TYPE, val); 3383 CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_CTX_TYPE, val);
3356 3384
3357 val = (u64) bp->rx_desc_mapping >> 32; 3385 val = (u64) bp->rx_desc_mapping[0] >> 32;
3358 CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_HI, val); 3386 CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_HI, val);
3359 3387
3360 val = (u64) bp->rx_desc_mapping & 0xffffffff; 3388 val = (u64) bp->rx_desc_mapping[0] & 0xffffffff;
3361 CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_LO, val); 3389 CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_LO, val);
3362 3390
3363 for ( ;ring_prod < bp->rx_ring_size; ) { 3391 for (i = 0; i < bp->rx_ring_size; i++) {
3364 if (bnx2_alloc_rx_skb(bp, ring_prod) < 0) { 3392 if (bnx2_alloc_rx_skb(bp, ring_prod) < 0) {
3365 break; 3393 break;
3366 } 3394 }
@@ -3375,6 +3403,29 @@ bnx2_init_rx_ring(struct bnx2 *bp)
3375} 3403}
3376 3404
3377static void 3405static void
3406bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size)
3407{
3408 u32 num_rings, max;
3409
3410 bp->rx_ring_size = size;
3411 num_rings = 1;
3412 while (size > MAX_RX_DESC_CNT) {
3413 size -= MAX_RX_DESC_CNT;
3414 num_rings++;
3415 }
3416 /* round to next power of 2 */
3417 max = MAX_RX_RINGS;
3418 while ((max & num_rings) == 0)
3419 max >>= 1;
3420
3421 if (num_rings != max)
3422 max <<= 1;
3423
3424 bp->rx_max_ring = max;
3425 bp->rx_max_ring_idx = (bp->rx_max_ring * RX_DESC_CNT) - 1;
3426}
3427
3428static void
3378bnx2_free_tx_skbs(struct bnx2 *bp) 3429bnx2_free_tx_skbs(struct bnx2 *bp)
3379{ 3430{
3380 int i; 3431 int i;
@@ -3419,7 +3470,7 @@ bnx2_free_rx_skbs(struct bnx2 *bp)
3419 if (bp->rx_buf_ring == NULL) 3470 if (bp->rx_buf_ring == NULL)
3420 return; 3471 return;
3421 3472
3422 for (i = 0; i < RX_DESC_CNT; i++) { 3473 for (i = 0; i < bp->rx_max_ring_idx; i++) {
3423 struct sw_bd *rx_buf = &bp->rx_buf_ring[i]; 3474 struct sw_bd *rx_buf = &bp->rx_buf_ring[i];
3424 struct sk_buff *skb = rx_buf->skb; 3475 struct sk_buff *skb = rx_buf->skb;
3425 3476
@@ -3506,74 +3557,9 @@ bnx2_test_registers(struct bnx2 *bp)
3506 { 0x0c00, 0, 0x00000000, 0x00000001 }, 3557 { 0x0c00, 0, 0x00000000, 0x00000001 },
3507 { 0x0c04, 0, 0x00000000, 0x03ff0001 }, 3558 { 0x0c04, 0, 0x00000000, 0x03ff0001 },
3508 { 0x0c08, 0, 0x0f0ff073, 0x00000000 }, 3559 { 0x0c08, 0, 0x0f0ff073, 0x00000000 },
3509 { 0x0c0c, 0, 0x00ffffff, 0x00000000 },
3510 { 0x0c30, 0, 0x00000000, 0xffffffff },
3511 { 0x0c34, 0, 0x00000000, 0xffffffff },
3512 { 0x0c38, 0, 0x00000000, 0xffffffff },
3513 { 0x0c3c, 0, 0x00000000, 0xffffffff },
3514 { 0x0c40, 0, 0x00000000, 0xffffffff },
3515 { 0x0c44, 0, 0x00000000, 0xffffffff },
3516 { 0x0c48, 0, 0x00000000, 0x0007ffff },
3517 { 0x0c4c, 0, 0x00000000, 0xffffffff },
3518 { 0x0c50, 0, 0x00000000, 0xffffffff },
3519 { 0x0c54, 0, 0x00000000, 0xffffffff },
3520 { 0x0c58, 0, 0x00000000, 0xffffffff },
3521 { 0x0c5c, 0, 0x00000000, 0xffffffff },
3522 { 0x0c60, 0, 0x00000000, 0xffffffff },
3523 { 0x0c64, 0, 0x00000000, 0xffffffff },
3524 { 0x0c68, 0, 0x00000000, 0xffffffff },
3525 { 0x0c6c, 0, 0x00000000, 0xffffffff },
3526 { 0x0c70, 0, 0x00000000, 0xffffffff },
3527 { 0x0c74, 0, 0x00000000, 0xffffffff },
3528 { 0x0c78, 0, 0x00000000, 0xffffffff },
3529 { 0x0c7c, 0, 0x00000000, 0xffffffff },
3530 { 0x0c80, 0, 0x00000000, 0xffffffff },
3531 { 0x0c84, 0, 0x00000000, 0xffffffff },
3532 { 0x0c88, 0, 0x00000000, 0xffffffff },
3533 { 0x0c8c, 0, 0x00000000, 0xffffffff },
3534 { 0x0c90, 0, 0x00000000, 0xffffffff },
3535 { 0x0c94, 0, 0x00000000, 0xffffffff },
3536 { 0x0c98, 0, 0x00000000, 0xffffffff },
3537 { 0x0c9c, 0, 0x00000000, 0xffffffff },
3538 { 0x0ca0, 0, 0x00000000, 0xffffffff },
3539 { 0x0ca4, 0, 0x00000000, 0xffffffff },
3540 { 0x0ca8, 0, 0x00000000, 0x0007ffff },
3541 { 0x0cac, 0, 0x00000000, 0xffffffff },
3542 { 0x0cb0, 0, 0x00000000, 0xffffffff },
3543 { 0x0cb4, 0, 0x00000000, 0xffffffff },
3544 { 0x0cb8, 0, 0x00000000, 0xffffffff },
3545 { 0x0cbc, 0, 0x00000000, 0xffffffff },
3546 { 0x0cc0, 0, 0x00000000, 0xffffffff },
3547 { 0x0cc4, 0, 0x00000000, 0xffffffff },
3548 { 0x0cc8, 0, 0x00000000, 0xffffffff },
3549 { 0x0ccc, 0, 0x00000000, 0xffffffff },
3550 { 0x0cd0, 0, 0x00000000, 0xffffffff },
3551 { 0x0cd4, 0, 0x00000000, 0xffffffff },
3552 { 0x0cd8, 0, 0x00000000, 0xffffffff },
3553 { 0x0cdc, 0, 0x00000000, 0xffffffff },
3554 { 0x0ce0, 0, 0x00000000, 0xffffffff },
3555 { 0x0ce4, 0, 0x00000000, 0xffffffff },
3556 { 0x0ce8, 0, 0x00000000, 0xffffffff },
3557 { 0x0cec, 0, 0x00000000, 0xffffffff },
3558 { 0x0cf0, 0, 0x00000000, 0xffffffff },
3559 { 0x0cf4, 0, 0x00000000, 0xffffffff },
3560 { 0x0cf8, 0, 0x00000000, 0xffffffff },
3561 { 0x0cfc, 0, 0x00000000, 0xffffffff },
3562 { 0x0d00, 0, 0x00000000, 0xffffffff },
3563 { 0x0d04, 0, 0x00000000, 0xffffffff },
3564 3560
3565 { 0x1000, 0, 0x00000000, 0x00000001 }, 3561 { 0x1000, 0, 0x00000000, 0x00000001 },
3566 { 0x1004, 0, 0x00000000, 0x000f0001 }, 3562 { 0x1004, 0, 0x00000000, 0x000f0001 },
3567 { 0x1044, 0, 0x00000000, 0xffc003ff },
3568 { 0x1080, 0, 0x00000000, 0x0001ffff },
3569 { 0x1084, 0, 0x00000000, 0xffffffff },
3570 { 0x1088, 0, 0x00000000, 0xffffffff },
3571 { 0x108c, 0, 0x00000000, 0xffffffff },
3572 { 0x1090, 0, 0x00000000, 0xffffffff },
3573 { 0x1094, 0, 0x00000000, 0xffffffff },
3574 { 0x1098, 0, 0x00000000, 0xffffffff },
3575 { 0x109c, 0, 0x00000000, 0xffffffff },
3576 { 0x10a0, 0, 0x00000000, 0xffffffff },
3577 3563
3578 { 0x1408, 0, 0x01c00800, 0x00000000 }, 3564 { 0x1408, 0, 0x01c00800, 0x00000000 },
3579 { 0x149c, 0, 0x8000ffff, 0x00000000 }, 3565 { 0x149c, 0, 0x8000ffff, 0x00000000 },
@@ -3585,111 +3571,9 @@ bnx2_test_registers(struct bnx2 *bp)
3585 { 0x14c4, 0, 0x00003fff, 0x00000000 }, 3571 { 0x14c4, 0, 0x00003fff, 0x00000000 },
3586 { 0x14cc, 0, 0x00000000, 0x00000001 }, 3572 { 0x14cc, 0, 0x00000000, 0x00000001 },
3587 { 0x14d0, 0, 0xffffffff, 0x00000000 }, 3573 { 0x14d0, 0, 0xffffffff, 0x00000000 },
3588 { 0x1500, 0, 0x00000000, 0xffffffff },
3589 { 0x1504, 0, 0x00000000, 0xffffffff },
3590 { 0x1508, 0, 0x00000000, 0xffffffff },
3591 { 0x150c, 0, 0x00000000, 0xffffffff },
3592 { 0x1510, 0, 0x00000000, 0xffffffff },
3593 { 0x1514, 0, 0x00000000, 0xffffffff },
3594 { 0x1518, 0, 0x00000000, 0xffffffff },
3595 { 0x151c, 0, 0x00000000, 0xffffffff },
3596 { 0x1520, 0, 0x00000000, 0xffffffff },
3597 { 0x1524, 0, 0x00000000, 0xffffffff },
3598 { 0x1528, 0, 0x00000000, 0xffffffff },
3599 { 0x152c, 0, 0x00000000, 0xffffffff },
3600 { 0x1530, 0, 0x00000000, 0xffffffff },
3601 { 0x1534, 0, 0x00000000, 0xffffffff },
3602 { 0x1538, 0, 0x00000000, 0xffffffff },
3603 { 0x153c, 0, 0x00000000, 0xffffffff },
3604 { 0x1540, 0, 0x00000000, 0xffffffff },
3605 { 0x1544, 0, 0x00000000, 0xffffffff },
3606 { 0x1548, 0, 0x00000000, 0xffffffff },
3607 { 0x154c, 0, 0x00000000, 0xffffffff },
3608 { 0x1550, 0, 0x00000000, 0xffffffff },
3609 { 0x1554, 0, 0x00000000, 0xffffffff },
3610 { 0x1558, 0, 0x00000000, 0xffffffff },
3611 { 0x1600, 0, 0x00000000, 0xffffffff },
3612 { 0x1604, 0, 0x00000000, 0xffffffff },
3613 { 0x1608, 0, 0x00000000, 0xffffffff },
3614 { 0x160c, 0, 0x00000000, 0xffffffff },
3615 { 0x1610, 0, 0x00000000, 0xffffffff },
3616 { 0x1614, 0, 0x00000000, 0xffffffff },
3617 { 0x1618, 0, 0x00000000, 0xffffffff },
3618 { 0x161c, 0, 0x00000000, 0xffffffff },
3619 { 0x1620, 0, 0x00000000, 0xffffffff },
3620 { 0x1624, 0, 0x00000000, 0xffffffff },
3621 { 0x1628, 0, 0x00000000, 0xffffffff },
3622 { 0x162c, 0, 0x00000000, 0xffffffff },
3623 { 0x1630, 0, 0x00000000, 0xffffffff },
3624 { 0x1634, 0, 0x00000000, 0xffffffff },
3625 { 0x1638, 0, 0x00000000, 0xffffffff },
3626 { 0x163c, 0, 0x00000000, 0xffffffff },
3627 { 0x1640, 0, 0x00000000, 0xffffffff },
3628 { 0x1644, 0, 0x00000000, 0xffffffff },
3629 { 0x1648, 0, 0x00000000, 0xffffffff },
3630 { 0x164c, 0, 0x00000000, 0xffffffff },
3631 { 0x1650, 0, 0x00000000, 0xffffffff },
3632 { 0x1654, 0, 0x00000000, 0xffffffff },
3633 3574
3634 { 0x1800, 0, 0x00000000, 0x00000001 }, 3575 { 0x1800, 0, 0x00000000, 0x00000001 },
3635 { 0x1804, 0, 0x00000000, 0x00000003 }, 3576 { 0x1804, 0, 0x00000000, 0x00000003 },
3636 { 0x1840, 0, 0x00000000, 0xffffffff },
3637 { 0x1844, 0, 0x00000000, 0xffffffff },
3638 { 0x1848, 0, 0x00000000, 0xffffffff },
3639 { 0x184c, 0, 0x00000000, 0xffffffff },
3640 { 0x1850, 0, 0x00000000, 0xffffffff },
3641 { 0x1900, 0, 0x7ffbffff, 0x00000000 },
3642 { 0x1904, 0, 0xffffffff, 0x00000000 },
3643 { 0x190c, 0, 0xffffffff, 0x00000000 },
3644 { 0x1914, 0, 0xffffffff, 0x00000000 },
3645 { 0x191c, 0, 0xffffffff, 0x00000000 },
3646 { 0x1924, 0, 0xffffffff, 0x00000000 },
3647 { 0x192c, 0, 0xffffffff, 0x00000000 },
3648 { 0x1934, 0, 0xffffffff, 0x00000000 },
3649 { 0x193c, 0, 0xffffffff, 0x00000000 },
3650 { 0x1944, 0, 0xffffffff, 0x00000000 },
3651 { 0x194c, 0, 0xffffffff, 0x00000000 },
3652 { 0x1954, 0, 0xffffffff, 0x00000000 },
3653 { 0x195c, 0, 0xffffffff, 0x00000000 },
3654 { 0x1964, 0, 0xffffffff, 0x00000000 },
3655 { 0x196c, 0, 0xffffffff, 0x00000000 },
3656 { 0x1974, 0, 0xffffffff, 0x00000000 },
3657 { 0x197c, 0, 0xffffffff, 0x00000000 },
3658 { 0x1980, 0, 0x0700ffff, 0x00000000 },
3659
3660 { 0x1c00, 0, 0x00000000, 0x00000001 },
3661 { 0x1c04, 0, 0x00000000, 0x00000003 },
3662 { 0x1c08, 0, 0x0000000f, 0x00000000 },
3663 { 0x1c40, 0, 0x00000000, 0xffffffff },
3664 { 0x1c44, 0, 0x00000000, 0xffffffff },
3665 { 0x1c48, 0, 0x00000000, 0xffffffff },
3666 { 0x1c4c, 0, 0x00000000, 0xffffffff },
3667 { 0x1c50, 0, 0x00000000, 0xffffffff },
3668 { 0x1d00, 0, 0x7ffbffff, 0x00000000 },
3669 { 0x1d04, 0, 0xffffffff, 0x00000000 },
3670 { 0x1d0c, 0, 0xffffffff, 0x00000000 },
3671 { 0x1d14, 0, 0xffffffff, 0x00000000 },
3672 { 0x1d1c, 0, 0xffffffff, 0x00000000 },
3673 { 0x1d24, 0, 0xffffffff, 0x00000000 },
3674 { 0x1d2c, 0, 0xffffffff, 0x00000000 },
3675 { 0x1d34, 0, 0xffffffff, 0x00000000 },
3676 { 0x1d3c, 0, 0xffffffff, 0x00000000 },
3677 { 0x1d44, 0, 0xffffffff, 0x00000000 },
3678 { 0x1d4c, 0, 0xffffffff, 0x00000000 },
3679 { 0x1d54, 0, 0xffffffff, 0x00000000 },
3680 { 0x1d5c, 0, 0xffffffff, 0x00000000 },
3681 { 0x1d64, 0, 0xffffffff, 0x00000000 },
3682 { 0x1d6c, 0, 0xffffffff, 0x00000000 },
3683 { 0x1d74, 0, 0xffffffff, 0x00000000 },
3684 { 0x1d7c, 0, 0xffffffff, 0x00000000 },
3685 { 0x1d80, 0, 0x0700ffff, 0x00000000 },
3686
3687 { 0x2004, 0, 0x00000000, 0x0337000f },
3688 { 0x2008, 0, 0xffffffff, 0x00000000 },
3689 { 0x200c, 0, 0xffffffff, 0x00000000 },
3690 { 0x2010, 0, 0xffffffff, 0x00000000 },
3691 { 0x2014, 0, 0x801fff80, 0x00000000 },
3692 { 0x2018, 0, 0x000003ff, 0x00000000 },
3693 3577
3694 { 0x2800, 0, 0x00000000, 0x00000001 }, 3578 { 0x2800, 0, 0x00000000, 0x00000001 },
3695 { 0x2804, 0, 0x00000000, 0x00003f01 }, 3579 { 0x2804, 0, 0x00000000, 0x00003f01 },
@@ -3707,16 +3591,6 @@ bnx2_test_registers(struct bnx2 *bp)
3707 { 0x2c00, 0, 0x00000000, 0x00000011 }, 3591 { 0x2c00, 0, 0x00000000, 0x00000011 },
3708 { 0x2c04, 0, 0x00000000, 0x00030007 }, 3592 { 0x2c04, 0, 0x00000000, 0x00030007 },
3709 3593
3710 { 0x3000, 0, 0x00000000, 0x00000001 },
3711 { 0x3004, 0, 0x00000000, 0x007007ff },
3712 { 0x3008, 0, 0x00000003, 0x00000000 },
3713 { 0x300c, 0, 0xffffffff, 0x00000000 },
3714 { 0x3010, 0, 0xffffffff, 0x00000000 },
3715 { 0x3014, 0, 0xffffffff, 0x00000000 },
3716 { 0x3034, 0, 0xffffffff, 0x00000000 },
3717 { 0x3038, 0, 0xffffffff, 0x00000000 },
3718 { 0x3050, 0, 0x00000001, 0x00000000 },
3719
3720 { 0x3c00, 0, 0x00000000, 0x00000001 }, 3594 { 0x3c00, 0, 0x00000000, 0x00000001 },
3721 { 0x3c04, 0, 0x00000000, 0x00070000 }, 3595 { 0x3c04, 0, 0x00000000, 0x00070000 },
3722 { 0x3c08, 0, 0x00007f71, 0x07f00000 }, 3596 { 0x3c08, 0, 0x00007f71, 0x07f00000 },
@@ -3726,88 +3600,11 @@ bnx2_test_registers(struct bnx2 *bp)
3726 { 0x3c18, 0, 0x00000000, 0xffffffff }, 3600 { 0x3c18, 0, 0x00000000, 0xffffffff },
3727 { 0x3c1c, 0, 0xfffff000, 0x00000000 }, 3601 { 0x3c1c, 0, 0xfffff000, 0x00000000 },
3728 { 0x3c20, 0, 0xffffff00, 0x00000000 }, 3602 { 0x3c20, 0, 0xffffff00, 0x00000000 },
3729 { 0x3c24, 0, 0xffffffff, 0x00000000 },
3730 { 0x3c28, 0, 0xffffffff, 0x00000000 },
3731 { 0x3c2c, 0, 0xffffffff, 0x00000000 },
3732 { 0x3c30, 0, 0xffffffff, 0x00000000 },
3733 { 0x3c34, 0, 0xffffffff, 0x00000000 },
3734 { 0x3c38, 0, 0xffffffff, 0x00000000 },
3735 { 0x3c3c, 0, 0xffffffff, 0x00000000 },
3736 { 0x3c40, 0, 0xffffffff, 0x00000000 },
3737 { 0x3c44, 0, 0xffffffff, 0x00000000 },
3738 { 0x3c48, 0, 0xffffffff, 0x00000000 },
3739 { 0x3c4c, 0, 0xffffffff, 0x00000000 },
3740 { 0x3c50, 0, 0xffffffff, 0x00000000 },
3741 { 0x3c54, 0, 0xffffffff, 0x00000000 },
3742 { 0x3c58, 0, 0xffffffff, 0x00000000 },
3743 { 0x3c5c, 0, 0xffffffff, 0x00000000 },
3744 { 0x3c60, 0, 0xffffffff, 0x00000000 },
3745 { 0x3c64, 0, 0xffffffff, 0x00000000 },
3746 { 0x3c68, 0, 0xffffffff, 0x00000000 },
3747 { 0x3c6c, 0, 0xffffffff, 0x00000000 },
3748 { 0x3c70, 0, 0xffffffff, 0x00000000 },
3749 { 0x3c74, 0, 0x0000003f, 0x00000000 },
3750 { 0x3c78, 0, 0x00000000, 0x00000000 },
3751 { 0x3c7c, 0, 0x00000000, 0x00000000 },
3752 { 0x3c80, 0, 0x3fffffff, 0x00000000 },
3753 { 0x3c84, 0, 0x0000003f, 0x00000000 },
3754 { 0x3c88, 0, 0x00000000, 0xffffffff },
3755 { 0x3c8c, 0, 0x00000000, 0xffffffff },
3756
3757 { 0x4000, 0, 0x00000000, 0x00000001 },
3758 { 0x4004, 0, 0x00000000, 0x00030000 },
3759 { 0x4008, 0, 0x00000ff0, 0x00000000 },
3760 { 0x400c, 0, 0xffffffff, 0x00000000 },
3761 { 0x4088, 0, 0x00000000, 0x00070303 },
3762
3763 { 0x4400, 0, 0x00000000, 0x00000001 },
3764 { 0x4404, 0, 0x00000000, 0x00003f01 },
3765 { 0x4408, 0, 0x7fff00ff, 0x00000000 },
3766 { 0x440c, 0, 0xffffffff, 0x00000000 },
3767 { 0x4410, 0, 0xffff, 0x0000 },
3768 { 0x4414, 0, 0xffff, 0x0000 },
3769 { 0x4418, 0, 0xffff, 0x0000 },
3770 { 0x441c, 0, 0xffff, 0x0000 },
3771 { 0x4428, 0, 0xffffffff, 0x00000000 },
3772 { 0x442c, 0, 0xffffffff, 0x00000000 },
3773 { 0x4430, 0, 0xffffffff, 0x00000000 },
3774 { 0x4434, 0, 0xffffffff, 0x00000000 },
3775 { 0x4438, 0, 0xffffffff, 0x00000000 },
3776 { 0x443c, 0, 0xffffffff, 0x00000000 },
3777 { 0x4440, 0, 0xffffffff, 0x00000000 },
3778 { 0x4444, 0, 0xffffffff, 0x00000000 },
3779
3780 { 0x4c00, 0, 0x00000000, 0x00000001 },
3781 { 0x4c04, 0, 0x00000000, 0x0000003f },
3782 { 0x4c08, 0, 0xffffffff, 0x00000000 },
3783 { 0x4c0c, 0, 0x0007fc00, 0x00000000 },
3784 { 0x4c10, 0, 0x80003fe0, 0x00000000 },
3785 { 0x4c14, 0, 0xffffffff, 0x00000000 },
3786 { 0x4c44, 0, 0x00000000, 0x9fff9fff },
3787 { 0x4c48, 0, 0x00000000, 0xb3009fff },
3788 { 0x4c4c, 0, 0x00000000, 0x77f33b30 },
3789 { 0x4c50, 0, 0x00000000, 0xffffffff },
3790 3603
3791 { 0x5004, 0, 0x00000000, 0x0000007f }, 3604 { 0x5004, 0, 0x00000000, 0x0000007f },
3792 { 0x5008, 0, 0x0f0007ff, 0x00000000 }, 3605 { 0x5008, 0, 0x0f0007ff, 0x00000000 },
3793 { 0x500c, 0, 0xf800f800, 0x07ff07ff }, 3606 { 0x500c, 0, 0xf800f800, 0x07ff07ff },
3794 3607
3795 { 0x5400, 0, 0x00000008, 0x00000001 },
3796 { 0x5404, 0, 0x00000000, 0x0000003f },
3797 { 0x5408, 0, 0x0000001f, 0x00000000 },
3798 { 0x540c, 0, 0xffffffff, 0x00000000 },
3799 { 0x5410, 0, 0xffffffff, 0x00000000 },
3800 { 0x5414, 0, 0x0000ffff, 0x00000000 },
3801 { 0x5418, 0, 0x0000ffff, 0x00000000 },
3802 { 0x541c, 0, 0x0000ffff, 0x00000000 },
3803 { 0x5420, 0, 0x0000ffff, 0x00000000 },
3804 { 0x5428, 0, 0x000000ff, 0x00000000 },
3805 { 0x542c, 0, 0xff00ffff, 0x00000000 },
3806 { 0x5430, 0, 0x001fff80, 0x00000000 },
3807 { 0x5438, 0, 0xffffffff, 0x00000000 },
3808 { 0x543c, 0, 0xffffffff, 0x00000000 },
3809 { 0x5440, 0, 0xf800f800, 0x07ff07ff },
3810
3811 { 0x5c00, 0, 0x00000000, 0x00000001 }, 3608 { 0x5c00, 0, 0x00000000, 0x00000001 },
3812 { 0x5c04, 0, 0x00000000, 0x0003000f }, 3609 { 0x5c04, 0, 0x00000000, 0x0003000f },
3813 { 0x5c08, 0, 0x00000003, 0x00000000 }, 3610 { 0x5c08, 0, 0x00000003, 0x00000000 },
@@ -4794,6 +4591,64 @@ bnx2_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
4794 info->fw_version[5] = 0; 4591 info->fw_version[5] = 0;
4795} 4592}
4796 4593
4594#define BNX2_REGDUMP_LEN (32 * 1024)
4595
4596static int
4597bnx2_get_regs_len(struct net_device *dev)
4598{
4599 return BNX2_REGDUMP_LEN;
4600}
4601
4602static void
4603bnx2_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *_p)
4604{
4605 u32 *p = _p, i, offset;
4606 u8 *orig_p = _p;
4607 struct bnx2 *bp = netdev_priv(dev);
4608 u32 reg_boundaries[] = { 0x0000, 0x0098, 0x0400, 0x045c,
4609 0x0800, 0x0880, 0x0c00, 0x0c10,
4610 0x0c30, 0x0d08, 0x1000, 0x101c,
4611 0x1040, 0x1048, 0x1080, 0x10a4,
4612 0x1400, 0x1490, 0x1498, 0x14f0,
4613 0x1500, 0x155c, 0x1580, 0x15dc,
4614 0x1600, 0x1658, 0x1680, 0x16d8,
4615 0x1800, 0x1820, 0x1840, 0x1854,
4616 0x1880, 0x1894, 0x1900, 0x1984,
4617 0x1c00, 0x1c0c, 0x1c40, 0x1c54,
4618 0x1c80, 0x1c94, 0x1d00, 0x1d84,
4619 0x2000, 0x2030, 0x23c0, 0x2400,
4620 0x2800, 0x2820, 0x2830, 0x2850,
4621 0x2b40, 0x2c10, 0x2fc0, 0x3058,
4622 0x3c00, 0x3c94, 0x4000, 0x4010,
4623 0x4080, 0x4090, 0x43c0, 0x4458,
4624 0x4c00, 0x4c18, 0x4c40, 0x4c54,
4625 0x4fc0, 0x5010, 0x53c0, 0x5444,
4626 0x5c00, 0x5c18, 0x5c80, 0x5c90,
4627 0x5fc0, 0x6000, 0x6400, 0x6428,
4628 0x6800, 0x6848, 0x684c, 0x6860,
4629 0x6888, 0x6910, 0x8000 };
4630
4631 regs->version = 0;
4632
4633 memset(p, 0, BNX2_REGDUMP_LEN);
4634
4635 if (!netif_running(bp->dev))
4636 return;
4637
4638 i = 0;
4639 offset = reg_boundaries[0];
4640 p += offset;
4641 while (offset < BNX2_REGDUMP_LEN) {
4642 *p++ = REG_RD(bp, offset);
4643 offset += 4;
4644 if (offset == reg_boundaries[i + 1]) {
4645 offset = reg_boundaries[i + 2];
4646 p = (u32 *) (orig_p + offset);
4647 i += 2;
4648 }
4649 }
4650}
4651
4797static void 4652static void
4798bnx2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) 4653bnx2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
4799{ 4654{
@@ -4979,7 +4834,7 @@ bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
4979{ 4834{
4980 struct bnx2 *bp = netdev_priv(dev); 4835 struct bnx2 *bp = netdev_priv(dev);
4981 4836
4982 ering->rx_max_pending = MAX_RX_DESC_CNT; 4837 ering->rx_max_pending = MAX_TOTAL_RX_DESC_CNT;
4983 ering->rx_mini_max_pending = 0; 4838 ering->rx_mini_max_pending = 0;
4984 ering->rx_jumbo_max_pending = 0; 4839 ering->rx_jumbo_max_pending = 0;
4985 4840
@@ -4996,17 +4851,28 @@ bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
4996{ 4851{
4997 struct bnx2 *bp = netdev_priv(dev); 4852 struct bnx2 *bp = netdev_priv(dev);
4998 4853
4999 if ((ering->rx_pending > MAX_RX_DESC_CNT) || 4854 if ((ering->rx_pending > MAX_TOTAL_RX_DESC_CNT) ||
5000 (ering->tx_pending > MAX_TX_DESC_CNT) || 4855 (ering->tx_pending > MAX_TX_DESC_CNT) ||
5001 (ering->tx_pending <= MAX_SKB_FRAGS)) { 4856 (ering->tx_pending <= MAX_SKB_FRAGS)) {
5002 4857
5003 return -EINVAL; 4858 return -EINVAL;
5004 } 4859 }
5005 bp->rx_ring_size = ering->rx_pending; 4860 if (netif_running(bp->dev)) {
4861 bnx2_netif_stop(bp);
4862 bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
4863 bnx2_free_skbs(bp);
4864 bnx2_free_mem(bp);
4865 }
4866
4867 bnx2_set_rx_ring_size(bp, ering->rx_pending);
5006 bp->tx_ring_size = ering->tx_pending; 4868 bp->tx_ring_size = ering->tx_pending;
5007 4869
5008 if (netif_running(bp->dev)) { 4870 if (netif_running(bp->dev)) {
5009 bnx2_netif_stop(bp); 4871 int rc;
4872
4873 rc = bnx2_alloc_mem(bp);
4874 if (rc)
4875 return rc;
5010 bnx2_init_nic(bp); 4876 bnx2_init_nic(bp);
5011 bnx2_netif_start(bp); 4877 bnx2_netif_start(bp);
5012 } 4878 }
@@ -5360,6 +5226,8 @@ static struct ethtool_ops bnx2_ethtool_ops = {
5360 .get_settings = bnx2_get_settings, 5226 .get_settings = bnx2_get_settings,
5361 .set_settings = bnx2_set_settings, 5227 .set_settings = bnx2_set_settings,
5362 .get_drvinfo = bnx2_get_drvinfo, 5228 .get_drvinfo = bnx2_get_drvinfo,
5229 .get_regs_len = bnx2_get_regs_len,
5230 .get_regs = bnx2_get_regs,
5363 .get_wol = bnx2_get_wol, 5231 .get_wol = bnx2_get_wol,
5364 .set_wol = bnx2_set_wol, 5232 .set_wol = bnx2_set_wol,
5365 .nway_reset = bnx2_nway_reset, 5233 .nway_reset = bnx2_nway_reset,
@@ -5678,7 +5546,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
5678 bp->mac_addr[5] = (u8) reg; 5546 bp->mac_addr[5] = (u8) reg;
5679 5547
5680 bp->tx_ring_size = MAX_TX_DESC_CNT; 5548 bp->tx_ring_size = MAX_TX_DESC_CNT;
5681 bp->rx_ring_size = 100; 5549 bnx2_set_rx_ring_size(bp, 100);
5682 5550
5683 bp->rx_csum = 1; 5551 bp->rx_csum = 1;
5684 5552
@@ -5897,6 +5765,7 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state)
5897 if (!netif_running(dev)) 5765 if (!netif_running(dev))
5898 return 0; 5766 return 0;
5899 5767
5768 flush_scheduled_work();
5900 bnx2_netif_stop(bp); 5769 bnx2_netif_stop(bp);
5901 netif_device_detach(dev); 5770 netif_device_detach(dev);
5902 del_timer_sync(&bp->timer); 5771 del_timer_sync(&bp->timer);
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 9f691cbd666b..fd4b7f2eb477 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -23,6 +23,7 @@
23#include <linux/errno.h> 23#include <linux/errno.h>
24#include <linux/ioport.h> 24#include <linux/ioport.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/vmalloc.h>
26#include <linux/interrupt.h> 27#include <linux/interrupt.h>
27#include <linux/pci.h> 28#include <linux/pci.h>
28#include <linux/init.h> 29#include <linux/init.h>
@@ -3792,8 +3793,10 @@ struct l2_fhdr {
3792#define TX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct tx_bd)) 3793#define TX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct tx_bd))
3793#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1) 3794#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
3794 3795
3796#define MAX_RX_RINGS 4
3795#define RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct rx_bd)) 3797#define RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct rx_bd))
3796#define MAX_RX_DESC_CNT (RX_DESC_CNT - 1) 3798#define MAX_RX_DESC_CNT (RX_DESC_CNT - 1)
3799#define MAX_TOTAL_RX_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_RINGS)
3797 3800
3798#define NEXT_TX_BD(x) (((x) & (MAX_TX_DESC_CNT - 1)) == \ 3801#define NEXT_TX_BD(x) (((x) & (MAX_TX_DESC_CNT - 1)) == \
3799 (MAX_TX_DESC_CNT - 1)) ? \ 3802 (MAX_TX_DESC_CNT - 1)) ? \
@@ -3805,8 +3808,10 @@ struct l2_fhdr {
3805 (MAX_RX_DESC_CNT - 1)) ? \ 3808 (MAX_RX_DESC_CNT - 1)) ? \
3806 (x) + 2 : (x) + 1 3809 (x) + 2 : (x) + 1
3807 3810
3808#define RX_RING_IDX(x) ((x) & MAX_RX_DESC_CNT) 3811#define RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx)
3809 3812
3813#define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> 8)
3814#define RX_IDX(x) ((x) & MAX_RX_DESC_CNT)
3810 3815
3811/* Context size. */ 3816/* Context size. */
3812#define CTX_SHIFT 7 3817#define CTX_SHIFT 7
@@ -3903,6 +3908,15 @@ struct bnx2 {
3903 struct status_block *status_blk; 3908 struct status_block *status_blk;
3904 u32 last_status_idx; 3909 u32 last_status_idx;
3905 3910
3911 u32 flags;
3912#define PCIX_FLAG 1
3913#define PCI_32BIT_FLAG 2
3914#define ONE_TDMA_FLAG 4 /* no longer used */
3915#define NO_WOL_FLAG 8
3916#define USING_DAC_FLAG 0x10
3917#define USING_MSI_FLAG 0x20
3918#define ASF_ENABLE_FLAG 0x40
3919
3906 struct tx_bd *tx_desc_ring; 3920 struct tx_bd *tx_desc_ring;
3907 struct sw_bd *tx_buf_ring; 3921 struct sw_bd *tx_buf_ring;
3908 u32 tx_prod_bseq; 3922 u32 tx_prod_bseq;
@@ -3920,19 +3934,22 @@ struct bnx2 {
3920 u32 rx_offset; 3934 u32 rx_offset;
3921 u32 rx_buf_use_size; /* useable size */ 3935 u32 rx_buf_use_size; /* useable size */
3922 u32 rx_buf_size; /* with alignment */ 3936 u32 rx_buf_size; /* with alignment */
3923 struct rx_bd *rx_desc_ring; 3937 u32 rx_max_ring_idx;
3924 struct sw_bd *rx_buf_ring; 3938
3925 u32 rx_prod_bseq; 3939 u32 rx_prod_bseq;
3926 u16 rx_prod; 3940 u16 rx_prod;
3927 u16 rx_cons; 3941 u16 rx_cons;
3928 3942
3929 u32 rx_csum; 3943 u32 rx_csum;
3930 3944
3945 struct sw_bd *rx_buf_ring;
3946 struct rx_bd *rx_desc_ring[MAX_RX_RINGS];
3947
3931 /* Only used to synchronize netif_stop_queue/wake_queue when tx */ 3948 /* Only used to synchronize netif_stop_queue/wake_queue when tx */
3932 /* ring is full */ 3949 /* ring is full */
3933 spinlock_t tx_lock; 3950 spinlock_t tx_lock;
3934 3951
3935 /* End of fileds used in the performance code paths. */ 3952 /* End of fields used in the performance code paths. */
3936 3953
3937 char *name; 3954 char *name;
3938 3955
@@ -3945,15 +3962,6 @@ struct bnx2 {
3945 /* Used to synchronize phy accesses. */ 3962 /* Used to synchronize phy accesses. */
3946 spinlock_t phy_lock; 3963 spinlock_t phy_lock;
3947 3964
3948 u32 flags;
3949#define PCIX_FLAG 1
3950#define PCI_32BIT_FLAG 2
3951#define ONE_TDMA_FLAG 4 /* no longer used */
3952#define NO_WOL_FLAG 8
3953#define USING_DAC_FLAG 0x10
3954#define USING_MSI_FLAG 0x20
3955#define ASF_ENABLE_FLAG 0x40
3956
3957 u32 phy_flags; 3965 u32 phy_flags;
3958#define PHY_SERDES_FLAG 1 3966#define PHY_SERDES_FLAG 1
3959#define PHY_CRC_FIX_FLAG 2 3967#define PHY_CRC_FIX_FLAG 2
@@ -4004,8 +4012,9 @@ struct bnx2 {
4004 dma_addr_t tx_desc_mapping; 4012 dma_addr_t tx_desc_mapping;
4005 4013
4006 4014
4015 int rx_max_ring;
4007 int rx_ring_size; 4016 int rx_ring_size;
4008 dma_addr_t rx_desc_mapping; 4017 dma_addr_t rx_desc_mapping[MAX_RX_RINGS];
4009 4018
4010 u16 tx_quick_cons_trip; 4019 u16 tx_quick_cons_trip;
4011 u16 tx_quick_cons_trip_int; 4020 u16 tx_quick_cons_trip_int;
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 6e295fce5c6f..8f1573e658a5 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -91,6 +91,7 @@
91#include <linux/mii.h> 91#include <linux/mii.h>
92#include <linux/ip.h> 92#include <linux/ip.h>
93#include <linux/tcp.h> 93#include <linux/tcp.h>
94#include <linux/mutex.h>
94 95
95#include <net/checksum.h> 96#include <net/checksum.h>
96 97
@@ -3892,7 +3893,7 @@ static void cas_reset(struct cas *cp, int blkflag)
3892 spin_unlock(&cp->stat_lock[N_TX_RINGS]); 3893 spin_unlock(&cp->stat_lock[N_TX_RINGS]);
3893} 3894}
3894 3895
3895/* Shut down the chip, must be called with pm_sem held. */ 3896/* Shut down the chip, must be called with pm_mutex held. */
3896static void cas_shutdown(struct cas *cp) 3897static void cas_shutdown(struct cas *cp)
3897{ 3898{
3898 unsigned long flags; 3899 unsigned long flags;
@@ -4311,11 +4312,11 @@ static int cas_open(struct net_device *dev)
4311 int hw_was_up, err; 4312 int hw_was_up, err;
4312 unsigned long flags; 4313 unsigned long flags;
4313 4314
4314 down(&cp->pm_sem); 4315 mutex_lock(&cp->pm_mutex);
4315 4316
4316 hw_was_up = cp->hw_running; 4317 hw_was_up = cp->hw_running;
4317 4318
4318 /* The power-management semaphore protects the hw_running 4319 /* The power-management mutex protects the hw_running
4319 * etc. state so it is safe to do this bit without cp->lock 4320 * etc. state so it is safe to do this bit without cp->lock
4320 */ 4321 */
4321 if (!cp->hw_running) { 4322 if (!cp->hw_running) {
@@ -4364,7 +4365,7 @@ static int cas_open(struct net_device *dev)
4364 cas_unlock_all_restore(cp, flags); 4365 cas_unlock_all_restore(cp, flags);
4365 4366
4366 netif_start_queue(dev); 4367 netif_start_queue(dev);
4367 up(&cp->pm_sem); 4368 mutex_unlock(&cp->pm_mutex);
4368 return 0; 4369 return 0;
4369 4370
4370err_spare: 4371err_spare:
@@ -4372,7 +4373,7 @@ err_spare:
4372 cas_free_rxds(cp); 4373 cas_free_rxds(cp);
4373err_tx_tiny: 4374err_tx_tiny:
4374 cas_tx_tiny_free(cp); 4375 cas_tx_tiny_free(cp);
4375 up(&cp->pm_sem); 4376 mutex_unlock(&cp->pm_mutex);
4376 return err; 4377 return err;
4377} 4378}
4378 4379
@@ -4382,7 +4383,7 @@ static int cas_close(struct net_device *dev)
4382 struct cas *cp = netdev_priv(dev); 4383 struct cas *cp = netdev_priv(dev);
4383 4384
4384 /* Make sure we don't get distracted by suspend/resume */ 4385 /* Make sure we don't get distracted by suspend/resume */
4385 down(&cp->pm_sem); 4386 mutex_lock(&cp->pm_mutex);
4386 4387
4387 netif_stop_queue(dev); 4388 netif_stop_queue(dev);
4388 4389
@@ -4399,7 +4400,7 @@ static int cas_close(struct net_device *dev)
4399 cas_spare_free(cp); 4400 cas_spare_free(cp);
4400 cas_free_rxds(cp); 4401 cas_free_rxds(cp);
4401 cas_tx_tiny_free(cp); 4402 cas_tx_tiny_free(cp);
4402 up(&cp->pm_sem); 4403 mutex_unlock(&cp->pm_mutex);
4403 return 0; 4404 return 0;
4404} 4405}
4405 4406
@@ -4834,10 +4835,10 @@ static int cas_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
4834 unsigned long flags; 4835 unsigned long flags;
4835 int rc = -EOPNOTSUPP; 4836 int rc = -EOPNOTSUPP;
4836 4837
4837 /* Hold the PM semaphore while doing ioctl's or we may collide 4838 /* Hold the PM mutex while doing ioctl's or we may collide
4838 * with open/close and power management and oops. 4839 * with open/close and power management and oops.
4839 */ 4840 */
4840 down(&cp->pm_sem); 4841 mutex_lock(&cp->pm_mutex);
4841 switch (cmd) { 4842 switch (cmd) {
4842 case SIOCGMIIPHY: /* Get address of MII PHY in use. */ 4843 case SIOCGMIIPHY: /* Get address of MII PHY in use. */
4843 data->phy_id = cp->phy_addr; 4844 data->phy_id = cp->phy_addr;
@@ -4867,7 +4868,7 @@ static int cas_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
4867 break; 4868 break;
4868 }; 4869 };
4869 4870
4870 up(&cp->pm_sem); 4871 mutex_unlock(&cp->pm_mutex);
4871 return rc; 4872 return rc;
4872} 4873}
4873 4874
@@ -4994,7 +4995,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
4994 spin_lock_init(&cp->tx_lock[i]); 4995 spin_lock_init(&cp->tx_lock[i]);
4995 } 4996 }
4996 spin_lock_init(&cp->stat_lock[N_TX_RINGS]); 4997 spin_lock_init(&cp->stat_lock[N_TX_RINGS]);
4997 init_MUTEX(&cp->pm_sem); 4998 mutex_init(&cp->pm_mutex);
4998 4999
4999 init_timer(&cp->link_timer); 5000 init_timer(&cp->link_timer);
5000 cp->link_timer.function = cas_link_timer; 5001 cp->link_timer.function = cas_link_timer;
@@ -5116,10 +5117,10 @@ err_out_free_consistent:
5116 cp->init_block, cp->block_dvma); 5117 cp->init_block, cp->block_dvma);
5117 5118
5118err_out_iounmap: 5119err_out_iounmap:
5119 down(&cp->pm_sem); 5120 mutex_lock(&cp->pm_mutex);
5120 if (cp->hw_running) 5121 if (cp->hw_running)
5121 cas_shutdown(cp); 5122 cas_shutdown(cp);
5122 up(&cp->pm_sem); 5123 mutex_unlock(&cp->pm_mutex);
5123 5124
5124 iounmap(cp->regs); 5125 iounmap(cp->regs);
5125 5126
@@ -5152,11 +5153,11 @@ static void __devexit cas_remove_one(struct pci_dev *pdev)
5152 cp = netdev_priv(dev); 5153 cp = netdev_priv(dev);
5153 unregister_netdev(dev); 5154 unregister_netdev(dev);
5154 5155
5155 down(&cp->pm_sem); 5156 mutex_lock(&cp->pm_mutex);
5156 flush_scheduled_work(); 5157 flush_scheduled_work();
5157 if (cp->hw_running) 5158 if (cp->hw_running)
5158 cas_shutdown(cp); 5159 cas_shutdown(cp);
5159 up(&cp->pm_sem); 5160 mutex_unlock(&cp->pm_mutex);
5160 5161
5161#if 1 5162#if 1
5162 if (cp->orig_cacheline_size) { 5163 if (cp->orig_cacheline_size) {
@@ -5183,10 +5184,7 @@ static int cas_suspend(struct pci_dev *pdev, pm_message_t state)
5183 struct cas *cp = netdev_priv(dev); 5184 struct cas *cp = netdev_priv(dev);
5184 unsigned long flags; 5185 unsigned long flags;
5185 5186
5186 /* We hold the PM semaphore during entire driver 5187 mutex_lock(&cp->pm_mutex);
5187 * sleep time
5188 */
5189 down(&cp->pm_sem);
5190 5188
5191 /* If the driver is opened, we stop the DMA */ 5189 /* If the driver is opened, we stop the DMA */
5192 if (cp->opened) { 5190 if (cp->opened) {
@@ -5206,6 +5204,7 @@ static int cas_suspend(struct pci_dev *pdev, pm_message_t state)
5206 5204
5207 if (cp->hw_running) 5205 if (cp->hw_running)
5208 cas_shutdown(cp); 5206 cas_shutdown(cp);
5207 mutex_unlock(&cp->pm_mutex);
5209 5208
5210 return 0; 5209 return 0;
5211} 5210}
@@ -5217,6 +5216,7 @@ static int cas_resume(struct pci_dev *pdev)
5217 5216
5218 printk(KERN_INFO "%s: resuming\n", dev->name); 5217 printk(KERN_INFO "%s: resuming\n", dev->name);
5219 5218
5219 mutex_lock(&cp->pm_mutex);
5220 cas_hard_reset(cp); 5220 cas_hard_reset(cp);
5221 if (cp->opened) { 5221 if (cp->opened) {
5222 unsigned long flags; 5222 unsigned long flags;
@@ -5229,7 +5229,7 @@ static int cas_resume(struct pci_dev *pdev)
5229 5229
5230 netif_device_attach(dev); 5230 netif_device_attach(dev);
5231 } 5231 }
5232 up(&cp->pm_sem); 5232 mutex_unlock(&cp->pm_mutex);
5233 return 0; 5233 return 0;
5234} 5234}
5235#endif /* CONFIG_PM */ 5235#endif /* CONFIG_PM */
diff --git a/drivers/net/cassini.h b/drivers/net/cassini.h
index 88063ef16cf6..ab55c7ee1012 100644
--- a/drivers/net/cassini.h
+++ b/drivers/net/cassini.h
@@ -4284,7 +4284,7 @@ struct cas {
4284 * (ie. not power managed) */ 4284 * (ie. not power managed) */
4285 int hw_running; 4285 int hw_running;
4286 int opened; 4286 int opened;
4287 struct semaphore pm_sem; /* open/close/suspend/resume */ 4287 struct mutex pm_mutex; /* open/close/suspend/resume */
4288 4288
4289 struct cas_init_block *init_block; 4289 struct cas_init_block *init_block;
4290 struct cas_tx_desc *init_txds[MAX_TX_RINGS]; 4290 struct cas_tx_desc *init_txds[MAX_TX_RINGS];
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index f39de16e6b97..49cd096a3c3d 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -920,7 +920,7 @@ e1000_remove(struct pci_dev *pdev)
920 unregister_netdev(netdev); 920 unregister_netdev(netdev);
921#ifdef CONFIG_E1000_NAPI 921#ifdef CONFIG_E1000_NAPI
922 for (i = 0; i < adapter->num_rx_queues; i++) 922 for (i = 0; i < adapter->num_rx_queues; i++)
923 __dev_put(&adapter->polling_netdev[i]); 923 dev_put(&adapter->polling_netdev[i]);
924#endif 924#endif
925 925
926 if (!e1000_check_phy_reset_block(&adapter->hw)) 926 if (!e1000_check_phy_reset_block(&adapter->hw))
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index c81fe1c382d5..5e6d00752990 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -64,6 +64,14 @@ config TEKRAM_DONGLE
64 dongles you will have to start irattach like this: 64 dongles you will have to start irattach like this:
65 "irattach -d tekram". 65 "irattach -d tekram".
66 66
67config TOIM3232_DONGLE
68 tristate "TOIM3232 IrDa dongle"
69 depends on DONGLE && IRDA
70 help
71 Say Y here if you want to build support for the Vishay/Temic
72 TOIM3232 and TOIM4232 based dongles.
73 To compile it as a module, choose M here.
74
67config LITELINK_DONGLE 75config LITELINK_DONGLE
68 tristate "Parallax LiteLink dongle" 76 tristate "Parallax LiteLink dongle"
69 depends on DONGLE && IRDA 77 depends on DONGLE && IRDA
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index 72cbfdc9cfcc..27ab75f20799 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_OLD_BELKIN_DONGLE) += old_belkin-sir.o
43obj-$(CONFIG_MCP2120_DONGLE) += mcp2120-sir.o 43obj-$(CONFIG_MCP2120_DONGLE) += mcp2120-sir.o
44obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o 44obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o
45obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o 45obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o
46obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o
46 47
47# The SIR helper module 48# The SIR helper module
48sir-dev-objs := sir_dev.o sir_dongle.o sir_kthread.o 49sir-dev-objs := sir_dev.o sir_dongle.o sir_kthread.o
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 3137592d60c0..910c0cab35b0 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -1778,7 +1778,7 @@ static struct pci_driver donauboe_pci_driver = {
1778static int __init 1778static int __init
1779donauboe_init (void) 1779donauboe_init (void)
1780{ 1780{
1781 return pci_module_init(&donauboe_pci_driver); 1781 return pci_register_driver(&donauboe_pci_driver);
1782} 1782}
1783 1783
1784static void __exit 1784static void __exit
diff --git a/drivers/net/irda/ep7211_ir.c b/drivers/net/irda/ep7211_ir.c
index 31896262d21c..4cba38f7e4a8 100644
--- a/drivers/net/irda/ep7211_ir.c
+++ b/drivers/net/irda/ep7211_ir.c
@@ -8,6 +8,7 @@
8#include <linux/delay.h> 8#include <linux/delay.h>
9#include <linux/tty.h> 9#include <linux/tty.h>
10#include <linux/init.h> 10#include <linux/init.h>
11#include <linux/spinlock.h>
11 12
12#include <net/irda/irda.h> 13#include <net/irda/irda.h>
13#include <net/irda/irda_device.h> 14#include <net/irda/irda_device.h>
@@ -23,6 +24,8 @@ static void ep7211_ir_close(dongle_t *self);
23static int ep7211_ir_change_speed(struct irda_task *task); 24static int ep7211_ir_change_speed(struct irda_task *task);
24static int ep7211_ir_reset(struct irda_task *task); 25static int ep7211_ir_reset(struct irda_task *task);
25 26
27static DEFINE_SPINLOCK(ep7211_lock);
28
26static struct dongle_reg dongle = { 29static struct dongle_reg dongle = {
27 .type = IRDA_EP7211_IR, 30 .type = IRDA_EP7211_IR,
28 .open = ep7211_ir_open, 31 .open = ep7211_ir_open,
@@ -36,7 +39,7 @@ static void ep7211_ir_open(dongle_t *self, struct qos_info *qos)
36{ 39{
37 unsigned int syscon1, flags; 40 unsigned int syscon1, flags;
38 41
39 save_flags(flags); cli(); 42 spin_lock_irqsave(&ep7211_lock, flags);
40 43
41 /* Turn on the SIR encoder. */ 44 /* Turn on the SIR encoder. */
42 syscon1 = clps_readl(SYSCON1); 45 syscon1 = clps_readl(SYSCON1);
@@ -46,14 +49,14 @@ static void ep7211_ir_open(dongle_t *self, struct qos_info *qos)
46 /* XXX: We should disable modem status interrupts on the first 49 /* XXX: We should disable modem status interrupts on the first
47 UART (interrupt #14). */ 50 UART (interrupt #14). */
48 51
49 restore_flags(flags); 52 spin_unlock_irqrestore(&ep7211_lock, flags);
50} 53}
51 54
52static void ep7211_ir_close(dongle_t *self) 55static void ep7211_ir_close(dongle_t *self)
53{ 56{
54 unsigned int syscon1, flags; 57 unsigned int syscon1, flags;
55 58
56 save_flags(flags); cli(); 59 spin_lock_irqsave(&ep7211_lock, flags);
57 60
58 /* Turn off the SIR encoder. */ 61 /* Turn off the SIR encoder. */
59 syscon1 = clps_readl(SYSCON1); 62 syscon1 = clps_readl(SYSCON1);
@@ -63,7 +66,7 @@ static void ep7211_ir_close(dongle_t *self)
63 /* XXX: If we've disabled the modem status interrupts, we should 66 /* XXX: If we've disabled the modem status interrupts, we should
64 reset them back to their original state. */ 67 reset them back to their original state. */
65 68
66 restore_flags(flags); 69 spin_unlock_irqrestore(&ep7211_lock, flags);
67} 70}
68 71
69/* 72/*
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index 101750bf210f..6a98b7ae4975 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -33,6 +33,7 @@
33#include <asm/uaccess.h> 33#include <asm/uaccess.h>
34#include <linux/smp_lock.h> 34#include <linux/smp_lock.h>
35#include <linux/delay.h> 35#include <linux/delay.h>
36#include <linux/mutex.h>
36 37
37#include <net/irda/irda.h> 38#include <net/irda/irda.h>
38#include <net/irda/irda_device.h> 39#include <net/irda/irda_device.h>
@@ -338,7 +339,7 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop)
338/*****************************************************************/ 339/*****************************************************************/
339 340
340/* serialize ldisc open/close with sir_dev */ 341/* serialize ldisc open/close with sir_dev */
341static DECLARE_MUTEX(irtty_sem); 342static DEFINE_MUTEX(irtty_mutex);
342 343
343/* notifier from sir_dev when irda% device gets opened (ifup) */ 344/* notifier from sir_dev when irda% device gets opened (ifup) */
344 345
@@ -348,11 +349,11 @@ static int irtty_start_dev(struct sir_dev *dev)
348 struct tty_struct *tty; 349 struct tty_struct *tty;
349 350
350 /* serialize with ldisc open/close */ 351 /* serialize with ldisc open/close */
351 down(&irtty_sem); 352 mutex_lock(&irtty_mutex);
352 353
353 priv = dev->priv; 354 priv = dev->priv;
354 if (unlikely(!priv || priv->magic!=IRTTY_MAGIC)) { 355 if (unlikely(!priv || priv->magic!=IRTTY_MAGIC)) {
355 up(&irtty_sem); 356 mutex_unlock(&irtty_mutex);
356 return -ESTALE; 357 return -ESTALE;
357 } 358 }
358 359
@@ -363,7 +364,7 @@ static int irtty_start_dev(struct sir_dev *dev)
363 /* Make sure we can receive more data */ 364 /* Make sure we can receive more data */
364 irtty_stop_receiver(tty, FALSE); 365 irtty_stop_receiver(tty, FALSE);
365 366
366 up(&irtty_sem); 367 mutex_unlock(&irtty_mutex);
367 return 0; 368 return 0;
368} 369}
369 370
@@ -375,11 +376,11 @@ static int irtty_stop_dev(struct sir_dev *dev)
375 struct tty_struct *tty; 376 struct tty_struct *tty;
376 377
377 /* serialize with ldisc open/close */ 378 /* serialize with ldisc open/close */
378 down(&irtty_sem); 379 mutex_lock(&irtty_mutex);
379 380
380 priv = dev->priv; 381 priv = dev->priv;
381 if (unlikely(!priv || priv->magic!=IRTTY_MAGIC)) { 382 if (unlikely(!priv || priv->magic!=IRTTY_MAGIC)) {
382 up(&irtty_sem); 383 mutex_unlock(&irtty_mutex);
383 return -ESTALE; 384 return -ESTALE;
384 } 385 }
385 386
@@ -390,7 +391,7 @@ static int irtty_stop_dev(struct sir_dev *dev)
390 if (tty->driver->stop) 391 if (tty->driver->stop)
391 tty->driver->stop(tty); 392 tty->driver->stop(tty);
392 393
393 up(&irtty_sem); 394 mutex_unlock(&irtty_mutex);
394 395
395 return 0; 396 return 0;
396} 397}
@@ -514,13 +515,13 @@ static int irtty_open(struct tty_struct *tty)
514 priv->dev = dev; 515 priv->dev = dev;
515 516
516 /* serialize with start_dev - in case we were racing with ifup */ 517 /* serialize with start_dev - in case we were racing with ifup */
517 down(&irtty_sem); 518 mutex_lock(&irtty_mutex);
518 519
519 dev->priv = priv; 520 dev->priv = priv;
520 tty->disc_data = priv; 521 tty->disc_data = priv;
521 tty->receive_room = 65536; 522 tty->receive_room = 65536;
522 523
523 up(&irtty_sem); 524 mutex_unlock(&irtty_mutex);
524 525
525 IRDA_DEBUG(0, "%s - %s: irda line discipline opened\n", __FUNCTION__, tty->name); 526 IRDA_DEBUG(0, "%s - %s: irda line discipline opened\n", __FUNCTION__, tty->name);
526 527
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index ee717d0e939e..83141a3ff546 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -12,6 +12,7 @@
12 * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no> 12 * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
13 * Copyright (c) 1998 Lichen Wang, <lwang@actisys.com> 13 * Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
14 * Copyright (c) 1998 Actisys Corp., www.actisys.com 14 * Copyright (c) 1998 Actisys Corp., www.actisys.com
15 * Copyright (c) 2000-2004 Jean Tourrilhes <jt@hpl.hp.com>
15 * All Rights Reserved 16 * All Rights Reserved
16 * 17 *
17 * This program is free software; you can redistribute it and/or 18 * This program is free software; you can redistribute it and/or
@@ -53,14 +54,13 @@
53#include <linux/init.h> 54#include <linux/init.h>
54#include <linux/rtnetlink.h> 55#include <linux/rtnetlink.h>
55#include <linux/dma-mapping.h> 56#include <linux/dma-mapping.h>
57#include <linux/pnp.h>
58#include <linux/platform_device.h>
56 59
57#include <asm/io.h> 60#include <asm/io.h>
58#include <asm/dma.h> 61#include <asm/dma.h>
59#include <asm/byteorder.h> 62#include <asm/byteorder.h>
60 63
61#include <linux/pm.h>
62#include <linux/pm_legacy.h>
63
64#include <net/irda/wrapper.h> 64#include <net/irda/wrapper.h>
65#include <net/irda/irda.h> 65#include <net/irda/irda.h>
66#include <net/irda/irda_device.h> 66#include <net/irda/irda_device.h>
@@ -72,14 +72,27 @@
72 72
73static char *driver_name = "nsc-ircc"; 73static char *driver_name = "nsc-ircc";
74 74
75/* Power Management */
76#define NSC_IRCC_DRIVER_NAME "nsc-ircc"
77static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state);
78static int nsc_ircc_resume(struct platform_device *dev);
79
80static struct platform_driver nsc_ircc_driver = {
81 .suspend = nsc_ircc_suspend,
82 .resume = nsc_ircc_resume,
83 .driver = {
84 .name = NSC_IRCC_DRIVER_NAME,
85 },
86};
87
75/* Module parameters */ 88/* Module parameters */
76static int qos_mtt_bits = 0x07; /* 1 ms or more */ 89static int qos_mtt_bits = 0x07; /* 1 ms or more */
77static int dongle_id; 90static int dongle_id;
78 91
79/* Use BIOS settions by default, but user may supply module parameters */ 92/* Use BIOS settions by default, but user may supply module parameters */
80static unsigned int io[] = { ~0, ~0, ~0, ~0 }; 93static unsigned int io[] = { ~0, ~0, ~0, ~0, ~0 };
81static unsigned int irq[] = { 0, 0, 0, 0, 0 }; 94static unsigned int irq[] = { 0, 0, 0, 0, 0 };
82static unsigned int dma[] = { 0, 0, 0, 0, 0 }; 95static unsigned int dma[] = { 0, 0, 0, 0, 0 };
83 96
84static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info); 97static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info);
85static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info); 98static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info);
@@ -87,6 +100,7 @@ static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info);
87static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info); 100static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info);
88static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info); 101static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info);
89static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info); 102static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info);
103static int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id);
90 104
91/* These are the known NSC chips */ 105/* These are the known NSC chips */
92static nsc_chip_t chips[] = { 106static nsc_chip_t chips[] = {
@@ -101,11 +115,12 @@ static nsc_chip_t chips[] = {
101 /* Contributed by Jan Frey - IBM A30/A31 */ 115 /* Contributed by Jan Frey - IBM A30/A31 */
102 { "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff, 116 { "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff,
103 nsc_ircc_probe_39x, nsc_ircc_init_39x }, 117 nsc_ircc_probe_39x, nsc_ircc_init_39x },
118 { "IBM", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff,
119 nsc_ircc_probe_39x, nsc_ircc_init_39x },
104 { NULL } 120 { NULL }
105}; 121};
106 122
107/* Max 4 instances for now */ 123static struct nsc_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL, NULL };
108static struct nsc_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL };
109 124
110static char *dongle_types[] = { 125static char *dongle_types[] = {
111 "Differential serial interface", 126 "Differential serial interface",
@@ -126,8 +141,24 @@ static char *dongle_types[] = {
126 "No dongle connected", 141 "No dongle connected",
127}; 142};
128 143
144/* PNP probing */
145static chipio_t pnp_info;
146static const struct pnp_device_id nsc_ircc_pnp_table[] = {
147 { .id = "NSC6001", .driver_data = 0 },
148 { .id = "IBM0071", .driver_data = 0 },
149 { }
150};
151
152MODULE_DEVICE_TABLE(pnp, nsc_ircc_pnp_table);
153
154static struct pnp_driver nsc_ircc_pnp_driver = {
155 .name = "nsc-ircc",
156 .id_table = nsc_ircc_pnp_table,
157 .probe = nsc_ircc_pnp_probe,
158};
159
129/* Some prototypes */ 160/* Some prototypes */
130static int nsc_ircc_open(int i, chipio_t *info); 161static int nsc_ircc_open(chipio_t *info);
131static int nsc_ircc_close(struct nsc_ircc_cb *self); 162static int nsc_ircc_close(struct nsc_ircc_cb *self);
132static int nsc_ircc_setup(chipio_t *info); 163static int nsc_ircc_setup(chipio_t *info);
133static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self); 164static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self);
@@ -146,7 +177,10 @@ static int nsc_ircc_net_open(struct net_device *dev);
146static int nsc_ircc_net_close(struct net_device *dev); 177static int nsc_ircc_net_close(struct net_device *dev);
147static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); 178static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
148static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev); 179static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev);
149static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data); 180
181/* Globals */
182static int pnp_registered;
183static int pnp_succeeded;
150 184
151/* 185/*
152 * Function nsc_ircc_init () 186 * Function nsc_ircc_init ()
@@ -158,28 +192,36 @@ static int __init nsc_ircc_init(void)
158{ 192{
159 chipio_t info; 193 chipio_t info;
160 nsc_chip_t *chip; 194 nsc_chip_t *chip;
161 int ret = -ENODEV; 195 int ret;
162 int cfg_base; 196 int cfg_base;
163 int cfg, id; 197 int cfg, id;
164 int reg; 198 int reg;
165 int i = 0; 199 int i = 0;
166 200
201 ret = platform_driver_register(&nsc_ircc_driver);
202 if (ret) {
203 IRDA_ERROR("%s, Can't register driver!\n", driver_name);
204 return ret;
205 }
206
207 /* Register with PnP subsystem to detect disable ports */
208 ret = pnp_register_driver(&nsc_ircc_pnp_driver);
209
210 if (ret >= 0)
211 pnp_registered = 1;
212
213 ret = -ENODEV;
214
167 /* Probe for all the NSC chipsets we know about */ 215 /* Probe for all the NSC chipsets we know about */
168 for (chip=chips; chip->name ; chip++) { 216 for (chip = chips; chip->name ; chip++) {
169 IRDA_DEBUG(2, "%s(), Probing for %s ...\n", __FUNCTION__, 217 IRDA_DEBUG(2, "%s(), Probing for %s ...\n", __FUNCTION__,
170 chip->name); 218 chip->name);
171 219
172 /* Try all config registers for this chip */ 220 /* Try all config registers for this chip */
173 for (cfg=0; cfg<3; cfg++) { 221 for (cfg = 0; cfg < ARRAY_SIZE(chip->cfg); cfg++) {
174 cfg_base = chip->cfg[cfg]; 222 cfg_base = chip->cfg[cfg];
175 if (!cfg_base) 223 if (!cfg_base)
176 continue; 224 continue;
177
178 memset(&info, 0, sizeof(chipio_t));
179 info.cfg_base = cfg_base;
180 info.fir_base = io[i];
181 info.dma = dma[i];
182 info.irq = irq[i];
183 225
184 /* Read index register */ 226 /* Read index register */
185 reg = inb(cfg_base); 227 reg = inb(cfg_base);
@@ -194,24 +236,65 @@ static int __init nsc_ircc_init(void)
194 if ((id & chip->cid_mask) == chip->cid_value) { 236 if ((id & chip->cid_mask) == chip->cid_value) {
195 IRDA_DEBUG(2, "%s() Found %s chip, revision=%d\n", 237 IRDA_DEBUG(2, "%s() Found %s chip, revision=%d\n",
196 __FUNCTION__, chip->name, id & ~chip->cid_mask); 238 __FUNCTION__, chip->name, id & ~chip->cid_mask);
197 /*
198 * If the user supplies the base address, then
199 * we init the chip, if not we probe the values
200 * set by the BIOS
201 */
202 if (io[i] < 0x2000) {
203 chip->init(chip, &info);
204 } else
205 chip->probe(chip, &info);
206 239
207 if (nsc_ircc_open(i, &info) == 0) 240 /*
208 ret = 0; 241 * If we found a correct PnP setting,
242 * we first try it.
243 */
244 if (pnp_succeeded) {
245 memset(&info, 0, sizeof(chipio_t));
246 info.cfg_base = cfg_base;
247 info.fir_base = pnp_info.fir_base;
248 info.dma = pnp_info.dma;
249 info.irq = pnp_info.irq;
250
251 if (info.fir_base < 0x2000) {
252 IRDA_MESSAGE("%s, chip->init\n", driver_name);
253 chip->init(chip, &info);
254 } else
255 chip->probe(chip, &info);
256
257 if (nsc_ircc_open(&info) >= 0)
258 ret = 0;
259 }
260
261 /*
262 * Opening based on PnP values failed.
263 * Let's fallback to user values, or probe
264 * the chip.
265 */
266 if (ret) {
267 IRDA_DEBUG(2, "%s, PnP init failed\n", driver_name);
268 memset(&info, 0, sizeof(chipio_t));
269 info.cfg_base = cfg_base;
270 info.fir_base = io[i];
271 info.dma = dma[i];
272 info.irq = irq[i];
273
274 /*
275 * If the user supplies the base address, then
276 * we init the chip, if not we probe the values
277 * set by the BIOS
278 */
279 if (io[i] < 0x2000) {
280 chip->init(chip, &info);
281 } else
282 chip->probe(chip, &info);
283
284 if (nsc_ircc_open(&info) >= 0)
285 ret = 0;
286 }
209 i++; 287 i++;
210 } else { 288 } else {
211 IRDA_DEBUG(2, "%s(), Wrong chip id=0x%02x\n", __FUNCTION__, id); 289 IRDA_DEBUG(2, "%s(), Wrong chip id=0x%02x\n", __FUNCTION__, id);
212 } 290 }
213 } 291 }
214 292 }
293
294 if (ret) {
295 platform_driver_unregister(&nsc_ircc_driver);
296 pnp_unregister_driver(&nsc_ircc_pnp_driver);
297 pnp_registered = 0;
215 } 298 }
216 299
217 return ret; 300 return ret;
@@ -227,12 +310,17 @@ static void __exit nsc_ircc_cleanup(void)
227{ 310{
228 int i; 311 int i;
229 312
230 pm_unregister_all(nsc_ircc_pmproc); 313 for (i = 0; i < ARRAY_SIZE(dev_self); i++) {
231
232 for (i=0; i < 4; i++) {
233 if (dev_self[i]) 314 if (dev_self[i])
234 nsc_ircc_close(dev_self[i]); 315 nsc_ircc_close(dev_self[i]);
235 } 316 }
317
318 platform_driver_unregister(&nsc_ircc_driver);
319
320 if (pnp_registered)
321 pnp_unregister_driver(&nsc_ircc_pnp_driver);
322
323 pnp_registered = 0;
236} 324}
237 325
238/* 326/*
@@ -241,16 +329,26 @@ static void __exit nsc_ircc_cleanup(void)
241 * Open driver instance 329 * Open driver instance
242 * 330 *
243 */ 331 */
244static int __init nsc_ircc_open(int i, chipio_t *info) 332static int __init nsc_ircc_open(chipio_t *info)
245{ 333{
246 struct net_device *dev; 334 struct net_device *dev;
247 struct nsc_ircc_cb *self; 335 struct nsc_ircc_cb *self;
248 struct pm_dev *pmdev;
249 void *ret; 336 void *ret;
250 int err; 337 int err, chip_index;
251 338
252 IRDA_DEBUG(2, "%s()\n", __FUNCTION__); 339 IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
253 340
341
342 for (chip_index = 0; chip_index < ARRAY_SIZE(dev_self); chip_index++) {
343 if (!dev_self[chip_index])
344 break;
345 }
346
347 if (chip_index == ARRAY_SIZE(dev_self)) {
348 IRDA_ERROR("%s(), maximum number of supported chips reached!\n", __FUNCTION__);
349 return -ENOMEM;
350 }
351
254 IRDA_MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, 352 IRDA_MESSAGE("%s, Found chip at base=0x%03x\n", driver_name,
255 info->cfg_base); 353 info->cfg_base);
256 354
@@ -271,8 +369,8 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
271 spin_lock_init(&self->lock); 369 spin_lock_init(&self->lock);
272 370
273 /* Need to store self somewhere */ 371 /* Need to store self somewhere */
274 dev_self[i] = self; 372 dev_self[chip_index] = self;
275 self->index = i; 373 self->index = chip_index;
276 374
277 /* Initialize IO */ 375 /* Initialize IO */
278 self->io.cfg_base = info->cfg_base; 376 self->io.cfg_base = info->cfg_base;
@@ -351,7 +449,7 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
351 449
352 /* Check if user has supplied a valid dongle id or not */ 450 /* Check if user has supplied a valid dongle id or not */
353 if ((dongle_id <= 0) || 451 if ((dongle_id <= 0) ||
354 (dongle_id >= (sizeof(dongle_types) / sizeof(dongle_types[0]))) ) { 452 (dongle_id >= ARRAY_SIZE(dongle_types))) {
355 dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base); 453 dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base);
356 454
357 IRDA_MESSAGE("%s, Found dongle: %s\n", driver_name, 455 IRDA_MESSAGE("%s, Found dongle: %s\n", driver_name,
@@ -364,11 +462,18 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
364 self->io.dongle_id = dongle_id; 462 self->io.dongle_id = dongle_id;
365 nsc_ircc_init_dongle_interface(self->io.fir_base, dongle_id); 463 nsc_ircc_init_dongle_interface(self->io.fir_base, dongle_id);
366 464
367 pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, nsc_ircc_pmproc); 465 self->pldev = platform_device_register_simple(NSC_IRCC_DRIVER_NAME,
368 if (pmdev) 466 self->index, NULL, 0);
369 pmdev->data = self; 467 if (IS_ERR(self->pldev)) {
468 err = PTR_ERR(self->pldev);
469 goto out5;
470 }
471 platform_set_drvdata(self->pldev, self);
370 472
371 return 0; 473 return chip_index;
474
475 out5:
476 unregister_netdev(dev);
372 out4: 477 out4:
373 dma_free_coherent(NULL, self->tx_buff.truesize, 478 dma_free_coherent(NULL, self->tx_buff.truesize,
374 self->tx_buff.head, self->tx_buff_dma); 479 self->tx_buff.head, self->tx_buff_dma);
@@ -379,7 +484,7 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
379 release_region(self->io.fir_base, self->io.fir_ext); 484 release_region(self->io.fir_base, self->io.fir_ext);
380 out1: 485 out1:
381 free_netdev(dev); 486 free_netdev(dev);
382 dev_self[i] = NULL; 487 dev_self[chip_index] = NULL;
383 return err; 488 return err;
384} 489}
385 490
@@ -399,6 +504,8 @@ static int __exit nsc_ircc_close(struct nsc_ircc_cb *self)
399 504
400 iobase = self->io.fir_base; 505 iobase = self->io.fir_base;
401 506
507 platform_device_unregister(self->pldev);
508
402 /* Remove netdevice */ 509 /* Remove netdevice */
403 unregister_netdev(self->netdev); 510 unregister_netdev(self->netdev);
404 511
@@ -806,6 +913,43 @@ static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info)
806 return 0; 913 return 0;
807} 914}
808 915
916/* PNP probing */
917static int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id)
918{
919 memset(&pnp_info, 0, sizeof(chipio_t));
920 pnp_info.irq = -1;
921 pnp_info.dma = -1;
922 pnp_succeeded = 1;
923
924 /* There don't seem to be any way to get the cfg_base.
925 * On my box, cfg_base is in the PnP descriptor of the
926 * motherboard. Oh well... Jean II */
927
928 if (pnp_port_valid(dev, 0) &&
929 !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED))
930 pnp_info.fir_base = pnp_port_start(dev, 0);
931
932 if (pnp_irq_valid(dev, 0) &&
933 !(pnp_irq_flags(dev, 0) & IORESOURCE_DISABLED))
934 pnp_info.irq = pnp_irq(dev, 0);
935
936 if (pnp_dma_valid(dev, 0) &&
937 !(pnp_dma_flags(dev, 0) & IORESOURCE_DISABLED))
938 pnp_info.dma = pnp_dma(dev, 0);
939
940 IRDA_DEBUG(0, "%s() : From PnP, found firbase 0x%03X ; irq %d ; dma %d.\n",
941 __FUNCTION__, pnp_info.fir_base, pnp_info.irq, pnp_info.dma);
942
943 if((pnp_info.fir_base == 0) ||
944 (pnp_info.irq == -1) || (pnp_info.dma == -1)) {
945 /* Returning an error will disable the device. Yuck ! */
946 //return -EINVAL;
947 pnp_succeeded = 0;
948 }
949
950 return 0;
951}
952
809/* 953/*
810 * Function nsc_ircc_setup (info) 954 * Function nsc_ircc_setup (info)
811 * 955 *
@@ -2161,45 +2305,83 @@ static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev)
2161 return &self->stats; 2305 return &self->stats;
2162} 2306}
2163 2307
2164static void nsc_ircc_suspend(struct nsc_ircc_cb *self) 2308static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state)
2165{ 2309{
2166 IRDA_MESSAGE("%s, Suspending\n", driver_name); 2310 struct nsc_ircc_cb *self = platform_get_drvdata(dev);
2311 int bank;
2312 unsigned long flags;
2313 int iobase = self->io.fir_base;
2167 2314
2168 if (self->io.suspended) 2315 if (self->io.suspended)
2169 return; 2316 return 0;
2170 2317
2171 nsc_ircc_net_close(self->netdev); 2318 IRDA_DEBUG(1, "%s, Suspending\n", driver_name);
2172 2319
2320 rtnl_lock();
2321 if (netif_running(self->netdev)) {
2322 netif_device_detach(self->netdev);
2323 spin_lock_irqsave(&self->lock, flags);
2324 /* Save current bank */
2325 bank = inb(iobase+BSR);
2326
2327 /* Disable interrupts */
2328 switch_bank(iobase, BANK0);
2329 outb(0, iobase+IER);
2330
2331 /* Restore bank register */
2332 outb(bank, iobase+BSR);
2333
2334 spin_unlock_irqrestore(&self->lock, flags);
2335 free_irq(self->io.irq, self->netdev);
2336 disable_dma(self->io.dma);
2337 }
2173 self->io.suspended = 1; 2338 self->io.suspended = 1;
2339 rtnl_unlock();
2340
2341 return 0;
2174} 2342}
2175 2343
2176static void nsc_ircc_wakeup(struct nsc_ircc_cb *self) 2344static int nsc_ircc_resume(struct platform_device *dev)
2177{ 2345{
2346 struct nsc_ircc_cb *self = platform_get_drvdata(dev);
2347 unsigned long flags;
2348
2178 if (!self->io.suspended) 2349 if (!self->io.suspended)
2179 return; 2350 return 0;
2180 2351
2352 IRDA_DEBUG(1, "%s, Waking up\n", driver_name);
2353
2354 rtnl_lock();
2181 nsc_ircc_setup(&self->io); 2355 nsc_ircc_setup(&self->io);
2182 nsc_ircc_net_open(self->netdev); 2356 nsc_ircc_init_dongle_interface(self->io.fir_base, self->io.dongle_id);
2183
2184 IRDA_MESSAGE("%s, Waking up\n", driver_name);
2185 2357
2358 if (netif_running(self->netdev)) {
2359 if (request_irq(self->io.irq, nsc_ircc_interrupt, 0,
2360 self->netdev->name, self->netdev)) {
2361 IRDA_WARNING("%s, unable to allocate irq=%d\n",
2362 driver_name, self->io.irq);
2363
2364 /*
2365 * Don't fail resume process, just kill this
2366 * network interface
2367 */
2368 unregister_netdevice(self->netdev);
2369 } else {
2370 spin_lock_irqsave(&self->lock, flags);
2371 nsc_ircc_change_speed(self, self->io.speed);
2372 spin_unlock_irqrestore(&self->lock, flags);
2373 netif_device_attach(self->netdev);
2374 }
2375
2376 } else {
2377 spin_lock_irqsave(&self->lock, flags);
2378 nsc_ircc_change_speed(self, 9600);
2379 spin_unlock_irqrestore(&self->lock, flags);
2380 }
2186 self->io.suspended = 0; 2381 self->io.suspended = 0;
2187} 2382 rtnl_unlock();
2188 2383
2189static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data) 2384 return 0;
2190{
2191 struct nsc_ircc_cb *self = (struct nsc_ircc_cb*) dev->data;
2192 if (self) {
2193 switch (rqst) {
2194 case PM_SUSPEND:
2195 nsc_ircc_suspend(self);
2196 break;
2197 case PM_RESUME:
2198 nsc_ircc_wakeup(self);
2199 break;
2200 }
2201 }
2202 return 0;
2203} 2385}
2204 2386
2205MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); 2387MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
diff --git a/drivers/net/irda/nsc-ircc.h b/drivers/net/irda/nsc-ircc.h
index 6edf7e514624..dacf671abcd6 100644
--- a/drivers/net/irda/nsc-ircc.h
+++ b/drivers/net/irda/nsc-ircc.h
@@ -269,7 +269,7 @@ struct nsc_ircc_cb {
269 __u32 new_speed; 269 __u32 new_speed;
270 int index; /* Instance index */ 270 int index; /* Instance index */
271 271
272 struct pm_dev *dev; 272 struct platform_device *pldev;
273}; 273};
274 274
275static inline void switch_bank(int iobase, int bank) 275static inline void switch_bank(int iobase, int bank)
diff --git a/drivers/net/irda/sir_dongle.c b/drivers/net/irda/sir_dongle.c
index 8d225921ae7b..d7e32d9554fc 100644
--- a/drivers/net/irda/sir_dongle.c
+++ b/drivers/net/irda/sir_dongle.c
@@ -16,6 +16,7 @@
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/smp_lock.h> 17#include <linux/smp_lock.h>
18#include <linux/kmod.h> 18#include <linux/kmod.h>
19#include <linux/mutex.h>
19 20
20#include <net/irda/irda.h> 21#include <net/irda/irda.h>
21 22
@@ -28,7 +29,7 @@
28 */ 29 */
29 30
30static LIST_HEAD(dongle_list); /* list of registered dongle drivers */ 31static LIST_HEAD(dongle_list); /* list of registered dongle drivers */
31static DECLARE_MUTEX(dongle_list_lock); /* protects the list */ 32static DEFINE_MUTEX(dongle_list_lock); /* protects the list */
32 33
33int irda_register_dongle(struct dongle_driver *new) 34int irda_register_dongle(struct dongle_driver *new)
34{ 35{
@@ -38,25 +39,25 @@ int irda_register_dongle(struct dongle_driver *new)
38 IRDA_DEBUG(0, "%s : registering dongle \"%s\" (%d).\n", 39 IRDA_DEBUG(0, "%s : registering dongle \"%s\" (%d).\n",
39 __FUNCTION__, new->driver_name, new->type); 40 __FUNCTION__, new->driver_name, new->type);
40 41
41 down(&dongle_list_lock); 42 mutex_lock(&dongle_list_lock);
42 list_for_each(entry, &dongle_list) { 43 list_for_each(entry, &dongle_list) {
43 drv = list_entry(entry, struct dongle_driver, dongle_list); 44 drv = list_entry(entry, struct dongle_driver, dongle_list);
44 if (new->type == drv->type) { 45 if (new->type == drv->type) {
45 up(&dongle_list_lock); 46 mutex_unlock(&dongle_list_lock);
46 return -EEXIST; 47 return -EEXIST;
47 } 48 }
48 } 49 }
49 list_add(&new->dongle_list, &dongle_list); 50 list_add(&new->dongle_list, &dongle_list);
50 up(&dongle_list_lock); 51 mutex_unlock(&dongle_list_lock);
51 return 0; 52 return 0;
52} 53}
53EXPORT_SYMBOL(irda_register_dongle); 54EXPORT_SYMBOL(irda_register_dongle);
54 55
55int irda_unregister_dongle(struct dongle_driver *drv) 56int irda_unregister_dongle(struct dongle_driver *drv)
56{ 57{
57 down(&dongle_list_lock); 58 mutex_lock(&dongle_list_lock);
58 list_del(&drv->dongle_list); 59 list_del(&drv->dongle_list);
59 up(&dongle_list_lock); 60 mutex_unlock(&dongle_list_lock);
60 return 0; 61 return 0;
61} 62}
62EXPORT_SYMBOL(irda_unregister_dongle); 63EXPORT_SYMBOL(irda_unregister_dongle);
@@ -75,7 +76,7 @@ int sirdev_get_dongle(struct sir_dev *dev, IRDA_DONGLE type)
75 return -EBUSY; 76 return -EBUSY;
76 77
77 /* serialize access to the list of registered dongles */ 78 /* serialize access to the list of registered dongles */
78 down(&dongle_list_lock); 79 mutex_lock(&dongle_list_lock);
79 80
80 list_for_each(entry, &dongle_list) { 81 list_for_each(entry, &dongle_list) {
81 drv = list_entry(entry, struct dongle_driver, dongle_list); 82 drv = list_entry(entry, struct dongle_driver, dongle_list);
@@ -109,14 +110,14 @@ int sirdev_get_dongle(struct sir_dev *dev, IRDA_DONGLE type)
109 if (!drv->open || (err=drv->open(dev))!=0) 110 if (!drv->open || (err=drv->open(dev))!=0)
110 goto out_reject; /* failed to open driver */ 111 goto out_reject; /* failed to open driver */
111 112
112 up(&dongle_list_lock); 113 mutex_unlock(&dongle_list_lock);
113 return 0; 114 return 0;
114 115
115out_reject: 116out_reject:
116 dev->dongle_drv = NULL; 117 dev->dongle_drv = NULL;
117 module_put(drv->owner); 118 module_put(drv->owner);
118out_unlock: 119out_unlock:
119 up(&dongle_list_lock); 120 mutex_unlock(&dongle_list_lock);
120 return err; 121 return err;
121} 122}
122 123
diff --git a/drivers/net/irda/toim3232-sir.c b/drivers/net/irda/toim3232-sir.c
new file mode 100644
index 000000000000..aa1a9b0ed83e
--- /dev/null
+++ b/drivers/net/irda/toim3232-sir.c
@@ -0,0 +1,375 @@
1/*********************************************************************
2 *
3 * Filename: toim3232-sir.c
4 * Version: 1.0
5 * Description: Implementation of dongles based on the Vishay/Temic
6 * TOIM3232 SIR Endec chipset. Currently only the
7 * IRWave IR320ST-2 is tested, although it should work
8 * with any TOIM3232 or TOIM4232 chipset based RS232
9 * dongle with minimal modification.
10 * Based heavily on the Tekram driver (tekram.c),
11 * with thanks to Dag Brattli and Martin Diehl.
12 * Status: Experimental.
13 * Author: David Basden <davidb-irda@rcpt.to>
14 * Created at: Thu Feb 09 23:47:32 2006
15 *
16 * Copyright (c) 2006 David Basden.
17 * Copyright (c) 1998-1999 Dag Brattli,
18 * Copyright (c) 2002 Martin Diehl,
19 * All Rights Reserved.
20 *
21 * This program is free software; you can redistribute it and/or
22 * modify it under the terms of the GNU General Public License as
23 * published by the Free Software Foundation; either version 2 of
24 * the License, or (at your option) any later version.
25 *
26 * Neither Dag Brattli nor University of Tromsø admit liability nor
27 * provide warranty for any of this software. This material is
28 * provided "AS-IS" and at no charge.
29 *
30 ********************************************************************/
31
32/*
33 * This driver has currently only been tested on the IRWave IR320ST-2
34 *
35 * PROTOCOL:
36 *
37 * The protocol for talking to the TOIM3232 is quite easy, and is
38 * designed to interface with RS232 with only level convertors. The
39 * BR/~D line on the chip is brought high to signal 'command mode',
40 * where a command byte is sent to select the baudrate of the RS232
41 * interface and the pulse length of the IRDA output. When BR/~D
42 * is brought low, the dongle then changes to the selected baudrate,
43 * and the RS232 interface is used for data until BR/~D is brought
44 * high again. The initial speed for the TOIMx323 after RESET is
45 * 9600 baud. The baudrate for command-mode is the last selected
46 * baud-rate, or 9600 after a RESET.
47 *
48 * The dongle I have (below) adds some extra hardware on the front end,
49 * but this is mostly directed towards pariasitic power from the RS232
50 * line rather than changing very much about how to communicate with
51 * the TOIM3232.
52 *
53 * The protocol to talk to the TOIM4232 chipset seems to be almost
54 * identical to the TOIM3232 (and the 4232 datasheet is more detailed)
55 * so this code will probably work on that as well, although I haven't
56 * tested it on that hardware.
57 *
58 * Target dongle variations that might be common:
59 *
60 * DTR and RTS function:
61 * The data sheet for the 4232 has a sample implementation that hooks the
62 * DTR and RTS lines to the RESET and BaudRate/~Data lines of the
63 * chip (through line-converters). Given both DTR and RTS would have to
64 * be held low in normal operation, and the TOIMx232 requires +5V to
65 * signal ground, most dongle designers would almost certainly choose
66 * an implementation that kept at least one of DTR or RTS high in
67 * normal operation to provide power to the dongle, but will likely
68 * vary between designs.
69 *
70 * User specified command bits:
71 * There are two user-controllable output lines from the TOIMx232 that
72 * can be set low or high by setting the appropriate bits in the
73 * high-nibble of the command byte (when setting speed and pulse length).
74 * These might be used to switch on and off added hardware or extra
75 * dongle features.
76 *
77 *
78 * Target hardware: IRWave IR320ST-2
79 *
80 * The IRWave IR320ST-2 is a simple dongle based on the Vishay/Temic
81 * TOIM3232 SIR Endec and the Vishay/Temic TFDS4500 SIR IRDA transciever.
82 * It uses a hex inverter and some discrete components to buffer and
83 * line convert the RS232 down to 5V.
84 *
85 * The dongle is powered through a voltage regulator, fed by a large
86 * capacitor. To switch the dongle on, DTR is brought high to charge
87 * the capacitor and drive the voltage regulator. DTR isn't associated
88 * with any control lines on the TOIM3232. Parisitic power is also taken
89 * from the RTS, TD and RD lines when brought high, but through resistors.
90 * When DTR is low, the circuit might lose power even with RTS high.
91 *
92 * RTS is inverted and attached to the BR/~D input pin. When RTS
93 * is high, BR/~D is low, and the TOIM3232 is in the normal 'data' mode.
94 * RTS is brought low, BR/~D is high, and the TOIM3232 is in 'command
95 * mode'.
96 *
97 * For some unknown reason, the RESET line isn't actually connected
98 * to anything. This means to reset the dongle to get it to a known
99 * state (9600 baud) you must drop DTR and RTS low, wait for the power
100 * capacitor to discharge, and then bring DTR (and RTS for data mode)
101 * high again, and wait for the capacitor to charge, the power supply
102 * to stabilise, and the oscillator clock to stabilise.
103 *
104 * Fortunately, if the current baudrate is known, the chipset can
105 * easily change speed by entering command mode without having to
106 * reset the dongle first.
107 *
108 * Major Components:
109 *
110 * - Vishay/Temic TOIM3232 SIR Endec to change RS232 pulse timings
111 * to IRDA pulse timings
112 * - 3.6864MHz crystal to drive TOIM3232 clock oscillator
113 * - DM74lS04M Inverting Hex line buffer for RS232 input buffering
114 * and level conversion
115 * - PJ2951AC 150mA voltage regulator
116 * - Vishay/Temic TFDS4500 SIR IRDA front-end transceiver
117 *
118 */
119
120#include <linux/module.h>
121#include <linux/delay.h>
122#include <linux/init.h>
123
124#include <net/irda/irda.h>
125
126#include "sir-dev.h"
127
128static int toim3232delay = 150; /* default is 150 ms */
129module_param(toim3232delay, int, 0);
130MODULE_PARM_DESC(toim3232delay, "toim3232 dongle write complete delay");
131
132#if 0
133static int toim3232flipdtr = 0; /* default is DTR high to reset */
134module_param(toim3232flipdtr, int, 0);
135MODULE_PARM_DESC(toim3232flipdtr, "toim3232 dongle invert DTR (Reset)");
136
137static int toim3232fliprts = 0; /* default is RTS high for baud change */
138module_param(toim3232fliptrs, int, 0);
139MODULE_PARM_DESC(toim3232fliprts, "toim3232 dongle invert RTS (BR/D)");
140#endif
141
142static int toim3232_open(struct sir_dev *);
143static int toim3232_close(struct sir_dev *);
144static int toim3232_change_speed(struct sir_dev *, unsigned);
145static int toim3232_reset(struct sir_dev *);
146
147#define TOIM3232_115200 0x00
148#define TOIM3232_57600 0x01
149#define TOIM3232_38400 0x02
150#define TOIM3232_19200 0x03
151#define TOIM3232_9600 0x06
152#define TOIM3232_2400 0x0A
153
154#define TOIM3232_PW 0x10 /* Pulse select bit */
155
156static struct dongle_driver toim3232 = {
157 .owner = THIS_MODULE,
158 .driver_name = "Vishay TOIM3232",
159 .type = IRDA_TOIM3232_DONGLE,
160 .open = toim3232_open,
161 .close = toim3232_close,
162 .reset = toim3232_reset,
163 .set_speed = toim3232_change_speed,
164};
165
166static int __init toim3232_sir_init(void)
167{
168 if (toim3232delay < 1 || toim3232delay > 500)
169 toim3232delay = 200;
170 IRDA_DEBUG(1, "%s - using %d ms delay\n",
171 toim3232.driver_name, toim3232delay);
172 return irda_register_dongle(&toim3232);
173}
174
175static void __exit toim3232_sir_cleanup(void)
176{
177 irda_unregister_dongle(&toim3232);
178}
179
180static int toim3232_open(struct sir_dev *dev)
181{
182 struct qos_info *qos = &dev->qos;
183
184 IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
185
186 /* Pull the lines high to start with.
187 *
188 * For the IR320ST-2, we need to charge the main supply capacitor to
189 * switch the device on. We keep DTR high throughout to do this.
190 * When RTS, TD and RD are high, they will also trickle-charge the
191 * cap. RTS is high for data transmission, and low for baud rate select.
192 * -- DGB
193 */
194 sirdev_set_dtr_rts(dev, TRUE, TRUE);
195
196 /* The TOI3232 supports many speeds between 1200bps and 115000bps.
197 * We really only care about those supported by the IRDA spec, but
198 * 38400 seems to be implemented in many places */
199 qos->baud_rate.bits &= IR_2400|IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
200
201 /* From the tekram driver. Not sure what a reasonable value is -- DGB */
202 qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */
203 irda_qos_bits_to_value(qos);
204
205 /* irda thread waits 50 msec for power settling */
206
207 return 0;
208}
209
210static int toim3232_close(struct sir_dev *dev)
211{
212 IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
213
214 /* Power off dongle */
215 sirdev_set_dtr_rts(dev, FALSE, FALSE);
216
217 return 0;
218}
219
220/*
221 * Function toim3232change_speed (dev, state, speed)
222 *
223 * Set the speed for the TOIM3232 based dongle. Warning, this
224 * function must be called with a process context!
225 *
226 * Algorithm
227 * 1. keep DTR high but clear RTS to bring into baud programming mode
228 * 2. wait at least 7us to enter programming mode
229 * 3. send control word to set baud rate and timing
230 * 4. wait at least 1us
231 * 5. bring RTS high to enter DATA mode (RS232 is passed through to transceiver)
232 * 6. should take effect immediately (although probably worth waiting)
233 */
234
235#define TOIM3232_STATE_WAIT_SPEED (SIRDEV_STATE_DONGLE_SPEED + 1)
236
237static int toim3232_change_speed(struct sir_dev *dev, unsigned speed)
238{
239 unsigned state = dev->fsm.substate;
240 unsigned delay = 0;
241 u8 byte;
242 static int ret = 0;
243
244 IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
245
246 switch(state) {
247 case SIRDEV_STATE_DONGLE_SPEED:
248
249 /* Figure out what we are going to send as a control byte */
250 switch (speed) {
251 case 2400:
252 byte = TOIM3232_PW|TOIM3232_2400;
253 break;
254 default:
255 speed = 9600;
256 ret = -EINVAL;
257 /* fall thru */
258 case 9600:
259 byte = TOIM3232_PW|TOIM3232_9600;
260 break;
261 case 19200:
262 byte = TOIM3232_PW|TOIM3232_19200;
263 break;
264 case 38400:
265 byte = TOIM3232_PW|TOIM3232_38400;
266 break;
267 case 57600:
268 byte = TOIM3232_PW|TOIM3232_57600;
269 break;
270 case 115200:
271 byte = TOIM3232_115200;
272 break;
273 }
274
275 /* Set DTR, Clear RTS: Go into baud programming mode */
276 sirdev_set_dtr_rts(dev, TRUE, FALSE);
277
278 /* Wait at least 7us */
279 udelay(14);
280
281 /* Write control byte */
282 sirdev_raw_write(dev, &byte, 1);
283
284 dev->speed = speed;
285
286 state = TOIM3232_STATE_WAIT_SPEED;
287 delay = toim3232delay;
288 break;
289
290 case TOIM3232_STATE_WAIT_SPEED:
291 /* Have transmitted control byte * Wait for 'at least 1us' */
292 udelay(14);
293
294 /* Set DTR, Set RTS: Go into normal data mode */
295 sirdev_set_dtr_rts(dev, TRUE, TRUE);
296
297 /* Wait (TODO: check this is needed) */
298 udelay(50);
299 break;
300
301 default:
302 printk(KERN_ERR "%s - undefined state %d\n", __FUNCTION__, state);
303 ret = -EINVAL;
304 break;
305 }
306
307 dev->fsm.substate = state;
308 return (delay > 0) ? delay : ret;
309}
310
311/*
312 * Function toim3232reset (driver)
313 *
314 * This function resets the toim3232 dongle. Warning, this function
315 * must be called with a process context!!
316 *
317 * What we should do is:
318 * 0. Pull RESET high
319 * 1. Wait for at least 7us
320 * 2. Pull RESET low
321 * 3. Wait for at least 7us
322 * 4. Pull BR/~D high
323 * 5. Wait for at least 7us
324 * 6. Send control byte to set baud rate
325 * 7. Wait at least 1us after stop bit
326 * 8. Pull BR/~D low
327 * 9. Should then be in data mode
328 *
329 * Because the IR320ST-2 doesn't have the RESET line connected for some reason,
330 * we'll have to do something else.
331 *
332 * The default speed after a RESET is 9600, so lets try just bringing it up in
333 * data mode after switching it off, waiting for the supply capacitor to
334 * discharge, and then switch it back on. This isn't actually pulling RESET
335 * high, but it seems to have the same effect.
336 *
337 * This behaviour will probably work on dongles that have the RESET line connected,
338 * but if not, add a flag for the IR320ST-2, and implment the above-listed proper
339 * behaviour.
340 *
341 * RTS is inverted and then fed to BR/~D, so to put it in programming mode, we
342 * need to have pull RTS low
343 */
344
345static int toim3232_reset(struct sir_dev *dev)
346{
347 IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
348
349 /* Switch off both DTR and RTS to switch off dongle */
350 sirdev_set_dtr_rts(dev, FALSE, FALSE);
351
352 /* Should sleep a while. This might be evil doing it this way.*/
353 set_current_state(TASK_UNINTERRUPTIBLE);
354 schedule_timeout(msecs_to_jiffies(50));
355
356 /* Set DTR, Set RTS (data mode) */
357 sirdev_set_dtr_rts(dev, TRUE, TRUE);
358
359 /* Wait at least 10 ms for power to stabilize again */
360 set_current_state(TASK_UNINTERRUPTIBLE);
361 schedule_timeout(msecs_to_jiffies(10));
362
363 /* Speed should now be 9600 */
364 dev->speed = 9600;
365
366 return 0;
367}
368
369MODULE_AUTHOR("David Basden <davidb-linux@rcpt.to>");
370MODULE_DESCRIPTION("Vishay/Temic TOIM3232 based dongle driver");
371MODULE_LICENSE("GPL");
372MODULE_ALIAS("irda-dongle-12"); /* IRDA_TOIM3232_DONGLE */
373
374module_init(toim3232_sir_init);
375module_exit(toim3232_sir_cleanup);
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index a9f49f058cfb..97a49e0be76b 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -1887,7 +1887,7 @@ static int __init vlsi_mod_init(void)
1887 vlsi_proc_root->owner = THIS_MODULE; 1887 vlsi_proc_root->owner = THIS_MODULE;
1888 } 1888 }
1889 1889
1890 ret = pci_module_init(&vlsi_irda_driver); 1890 ret = pci_register_driver(&vlsi_irda_driver);
1891 1891
1892 if (ret && vlsi_proc_root) 1892 if (ret && vlsi_proc_root)
1893 remove_proc_entry(PROC_DIR, NULL); 1893 remove_proc_entry(PROC_DIR, NULL);
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 0245e40b51a1..f608c12e3e8b 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -1691,8 +1691,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
1691 || ppp->npmode[npi] != NPMODE_PASS) { 1691 || ppp->npmode[npi] != NPMODE_PASS) {
1692 kfree_skb(skb); 1692 kfree_skb(skb);
1693 } else { 1693 } else {
1694 skb_pull(skb, 2); /* chop off protocol */ 1694 /* chop off protocol */
1695 skb_postpull_rcsum(skb, skb->data - 2, 2); 1695 skb_pull_rcsum(skb, 2);
1696 skb->dev = ppp->dev; 1696 skb->dev = ppp->dev;
1697 skb->protocol = htons(npindex_to_ethertype[npi]); 1697 skb->protocol = htons(npindex_to_ethertype[npi]);
1698 skb->mac.raw = skb->data; 1698 skb->mac.raw = skb->data;
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index 9369f811075d..475dc930380f 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -337,8 +337,7 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
337 if (sk->sk_state & PPPOX_BOUND) { 337 if (sk->sk_state & PPPOX_BOUND) {
338 struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw; 338 struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw;
339 int len = ntohs(ph->length); 339 int len = ntohs(ph->length);
340 skb_pull(skb, sizeof(struct pppoe_hdr)); 340 skb_pull_rcsum(skb, sizeof(struct pppoe_hdr));
341 skb_postpull_rcsum(skb, ph, sizeof(*ph));
342 if (pskb_trim_rcsum(skb, len)) 341 if (pskb_trim_rcsum(skb, len))
343 goto abort_kfree; 342 goto abort_kfree;
344 343
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 28ce47a02408..38cd30cb7c75 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -55,6 +55,7 @@
55#include <linux/workqueue.h> 55#include <linux/workqueue.h>
56#include <linux/if_vlan.h> 56#include <linux/if_vlan.h>
57#include <linux/bitops.h> 57#include <linux/bitops.h>
58#include <linux/mutex.h>
58 59
59#include <asm/system.h> 60#include <asm/system.h>
60#include <asm/io.h> 61#include <asm/io.h>
@@ -2284,7 +2285,7 @@ static void gem_reset_task(void *data)
2284{ 2285{
2285 struct gem *gp = (struct gem *) data; 2286 struct gem *gp = (struct gem *) data;
2286 2287
2287 down(&gp->pm_sem); 2288 mutex_lock(&gp->pm_mutex);
2288 2289
2289 netif_poll_disable(gp->dev); 2290 netif_poll_disable(gp->dev);
2290 2291
@@ -2311,7 +2312,7 @@ static void gem_reset_task(void *data)
2311 2312
2312 netif_poll_enable(gp->dev); 2313 netif_poll_enable(gp->dev);
2313 2314
2314 up(&gp->pm_sem); 2315 mutex_unlock(&gp->pm_mutex);
2315} 2316}
2316 2317
2317 2318
@@ -2320,14 +2321,14 @@ static int gem_open(struct net_device *dev)
2320 struct gem *gp = dev->priv; 2321 struct gem *gp = dev->priv;
2321 int rc = 0; 2322 int rc = 0;
2322 2323
2323 down(&gp->pm_sem); 2324 mutex_lock(&gp->pm_mutex);
2324 2325
2325 /* We need the cell enabled */ 2326 /* We need the cell enabled */
2326 if (!gp->asleep) 2327 if (!gp->asleep)
2327 rc = gem_do_start(dev); 2328 rc = gem_do_start(dev);
2328 gp->opened = (rc == 0); 2329 gp->opened = (rc == 0);
2329 2330
2330 up(&gp->pm_sem); 2331 mutex_unlock(&gp->pm_mutex);
2331 2332
2332 return rc; 2333 return rc;
2333} 2334}
@@ -2340,13 +2341,13 @@ static int gem_close(struct net_device *dev)
2340 * our caller (dev_close) already did it for us 2341 * our caller (dev_close) already did it for us
2341 */ 2342 */
2342 2343
2343 down(&gp->pm_sem); 2344 mutex_lock(&gp->pm_mutex);
2344 2345
2345 gp->opened = 0; 2346 gp->opened = 0;
2346 if (!gp->asleep) 2347 if (!gp->asleep)
2347 gem_do_stop(dev, 0); 2348 gem_do_stop(dev, 0);
2348 2349
2349 up(&gp->pm_sem); 2350 mutex_unlock(&gp->pm_mutex);
2350 2351
2351 return 0; 2352 return 0;
2352} 2353}
@@ -2358,7 +2359,7 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state)
2358 struct gem *gp = dev->priv; 2359 struct gem *gp = dev->priv;
2359 unsigned long flags; 2360 unsigned long flags;
2360 2361
2361 down(&gp->pm_sem); 2362 mutex_lock(&gp->pm_mutex);
2362 2363
2363 netif_poll_disable(dev); 2364 netif_poll_disable(dev);
2364 2365
@@ -2391,11 +2392,11 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state)
2391 /* Stop the link timer */ 2392 /* Stop the link timer */
2392 del_timer_sync(&gp->link_timer); 2393 del_timer_sync(&gp->link_timer);
2393 2394
2394 /* Now we release the semaphore to not block the reset task who 2395 /* Now we release the mutex to not block the reset task who
2395 * can take it too. We are marked asleep, so there will be no 2396 * can take it too. We are marked asleep, so there will be no
2396 * conflict here 2397 * conflict here
2397 */ 2398 */
2398 up(&gp->pm_sem); 2399 mutex_unlock(&gp->pm_mutex);
2399 2400
2400 /* Wait for a pending reset task to complete */ 2401 /* Wait for a pending reset task to complete */
2401 while (gp->reset_task_pending) 2402 while (gp->reset_task_pending)
@@ -2424,7 +2425,7 @@ static int gem_resume(struct pci_dev *pdev)
2424 2425
2425 printk(KERN_INFO "%s: resuming\n", dev->name); 2426 printk(KERN_INFO "%s: resuming\n", dev->name);
2426 2427
2427 down(&gp->pm_sem); 2428 mutex_lock(&gp->pm_mutex);
2428 2429
2429 /* Keep the cell enabled during the entire operation, no need to 2430 /* Keep the cell enabled during the entire operation, no need to
2430 * take a lock here tho since nothing else can happen while we are 2431 * take a lock here tho since nothing else can happen while we are
@@ -2440,7 +2441,7 @@ static int gem_resume(struct pci_dev *pdev)
2440 * still asleep, a new sleep cycle may bring it back 2441 * still asleep, a new sleep cycle may bring it back
2441 */ 2442 */
2442 gem_put_cell(gp); 2443 gem_put_cell(gp);
2443 up(&gp->pm_sem); 2444 mutex_unlock(&gp->pm_mutex);
2444 return 0; 2445 return 0;
2445 } 2446 }
2446 pci_set_master(gp->pdev); 2447 pci_set_master(gp->pdev);
@@ -2486,7 +2487,7 @@ static int gem_resume(struct pci_dev *pdev)
2486 2487
2487 netif_poll_enable(dev); 2488 netif_poll_enable(dev);
2488 2489
2489 up(&gp->pm_sem); 2490 mutex_unlock(&gp->pm_mutex);
2490 2491
2491 return 0; 2492 return 0;
2492} 2493}
@@ -2591,7 +2592,7 @@ static int gem_change_mtu(struct net_device *dev, int new_mtu)
2591 return 0; 2592 return 0;
2592 } 2593 }
2593 2594
2594 down(&gp->pm_sem); 2595 mutex_lock(&gp->pm_mutex);
2595 spin_lock_irq(&gp->lock); 2596 spin_lock_irq(&gp->lock);
2596 spin_lock(&gp->tx_lock); 2597 spin_lock(&gp->tx_lock);
2597 dev->mtu = new_mtu; 2598 dev->mtu = new_mtu;
@@ -2602,7 +2603,7 @@ static int gem_change_mtu(struct net_device *dev, int new_mtu)
2602 } 2603 }
2603 spin_unlock(&gp->tx_lock); 2604 spin_unlock(&gp->tx_lock);
2604 spin_unlock_irq(&gp->lock); 2605 spin_unlock_irq(&gp->lock);
2605 up(&gp->pm_sem); 2606 mutex_unlock(&gp->pm_mutex);
2606 2607
2607 return 0; 2608 return 0;
2608} 2609}
@@ -2771,10 +2772,10 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
2771 int rc = -EOPNOTSUPP; 2772 int rc = -EOPNOTSUPP;
2772 unsigned long flags; 2773 unsigned long flags;
2773 2774
2774 /* Hold the PM semaphore while doing ioctl's or we may collide 2775 /* Hold the PM mutex while doing ioctl's or we may collide
2775 * with power management. 2776 * with power management.
2776 */ 2777 */
2777 down(&gp->pm_sem); 2778 mutex_lock(&gp->pm_mutex);
2778 2779
2779 spin_lock_irqsave(&gp->lock, flags); 2780 spin_lock_irqsave(&gp->lock, flags);
2780 gem_get_cell(gp); 2781 gem_get_cell(gp);
@@ -2812,7 +2813,7 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
2812 gem_put_cell(gp); 2813 gem_put_cell(gp);
2813 spin_unlock_irqrestore(&gp->lock, flags); 2814 spin_unlock_irqrestore(&gp->lock, flags);
2814 2815
2815 up(&gp->pm_sem); 2816 mutex_unlock(&gp->pm_mutex);
2816 2817
2817 return rc; 2818 return rc;
2818} 2819}
@@ -3033,7 +3034,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
3033 3034
3034 spin_lock_init(&gp->lock); 3035 spin_lock_init(&gp->lock);
3035 spin_lock_init(&gp->tx_lock); 3036 spin_lock_init(&gp->tx_lock);
3036 init_MUTEX(&gp->pm_sem); 3037 mutex_init(&gp->pm_mutex);
3037 3038
3038 init_timer(&gp->link_timer); 3039 init_timer(&gp->link_timer);
3039 gp->link_timer.function = gem_link_timer; 3040 gp->link_timer.function = gem_link_timer;
diff --git a/drivers/net/sungem.h b/drivers/net/sungem.h
index 13006d759ad8..89847215d006 100644
--- a/drivers/net/sungem.h
+++ b/drivers/net/sungem.h
@@ -980,15 +980,15 @@ struct gem {
980 int tx_new, tx_old; 980 int tx_new, tx_old;
981 981
982 unsigned int has_wol : 1; /* chip supports wake-on-lan */ 982 unsigned int has_wol : 1; /* chip supports wake-on-lan */
983 unsigned int asleep : 1; /* chip asleep, protected by pm_sem */ 983 unsigned int asleep : 1; /* chip asleep, protected by pm_mutex */
984 unsigned int asleep_wol : 1; /* was asleep with WOL enabled */ 984 unsigned int asleep_wol : 1; /* was asleep with WOL enabled */
985 unsigned int opened : 1; /* driver opened, protected by pm_sem */ 985 unsigned int opened : 1; /* driver opened, protected by pm_mutex */
986 unsigned int running : 1; /* chip running, protected by lock */ 986 unsigned int running : 1; /* chip running, protected by lock */
987 987
988 /* cell enable count, protected by lock */ 988 /* cell enable count, protected by lock */
989 int cell_enabled; 989 int cell_enabled;
990 990
991 struct semaphore pm_sem; 991 struct mutex pm_mutex;
992 992
993 u32 msg_enable; 993 u32 msg_enable;
994 u32 status; 994 u32 status;
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 6c6c5498899f..e03d1ae50c3e 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -69,8 +69,8 @@
69 69
70#define DRV_MODULE_NAME "tg3" 70#define DRV_MODULE_NAME "tg3"
71#define PFX DRV_MODULE_NAME ": " 71#define PFX DRV_MODULE_NAME ": "
72#define DRV_MODULE_VERSION "3.49" 72#define DRV_MODULE_VERSION "3.52"
73#define DRV_MODULE_RELDATE "Feb 2, 2006" 73#define DRV_MODULE_RELDATE "Mar 06, 2006"
74 74
75#define TG3_DEF_MAC_MODE 0 75#define TG3_DEF_MAC_MODE 0
76#define TG3_DEF_RX_MODE 0 76#define TG3_DEF_RX_MODE 0
@@ -221,10 +221,22 @@ static struct pci_device_id tg3_pci_tbl[] = {
221 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, 221 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
222 { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F, 222 { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F,
223 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, 223 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
224 { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754,
225 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
226 { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M,
227 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
228 { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787,
229 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
230 { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M,
231 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
224 { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714, 232 { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714,
225 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, 233 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
234 { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S,
235 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
226 { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715, 236 { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715,
227 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, 237 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
238 { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715S,
239 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
228 { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780, 240 { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780,
229 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, 241 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
230 { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S, 242 { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S,
@@ -534,6 +546,9 @@ static void tg3_enable_ints(struct tg3 *tp)
534 (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT)); 546 (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
535 tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 547 tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
536 (tp->last_tag << 24)); 548 (tp->last_tag << 24));
549 if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)
550 tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
551 (tp->last_tag << 24));
537 tg3_cond_int(tp); 552 tg3_cond_int(tp);
538} 553}
539 554
@@ -1038,9 +1053,11 @@ static void tg3_frob_aux_power(struct tg3 *tp)
1038 struct net_device *dev_peer; 1053 struct net_device *dev_peer;
1039 1054
1040 dev_peer = pci_get_drvdata(tp->pdev_peer); 1055 dev_peer = pci_get_drvdata(tp->pdev_peer);
1056 /* remove_one() may have been run on the peer. */
1041 if (!dev_peer) 1057 if (!dev_peer)
1042 BUG(); 1058 tp_peer = tp;
1043 tp_peer = netdev_priv(dev_peer); 1059 else
1060 tp_peer = netdev_priv(dev_peer);
1044 } 1061 }
1045 1062
1046 if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0 || 1063 if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0 ||
@@ -1131,7 +1148,7 @@ static int tg3_halt_cpu(struct tg3 *, u32);
1131static int tg3_nvram_lock(struct tg3 *); 1148static int tg3_nvram_lock(struct tg3 *);
1132static void tg3_nvram_unlock(struct tg3 *); 1149static void tg3_nvram_unlock(struct tg3 *);
1133 1150
1134static int tg3_set_power_state(struct tg3 *tp, int state) 1151static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
1135{ 1152{
1136 u32 misc_host_ctrl; 1153 u32 misc_host_ctrl;
1137 u16 power_control, power_caps; 1154 u16 power_control, power_caps;
@@ -1150,7 +1167,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
1150 power_control |= PCI_PM_CTRL_PME_STATUS; 1167 power_control |= PCI_PM_CTRL_PME_STATUS;
1151 power_control &= ~(PCI_PM_CTRL_STATE_MASK); 1168 power_control &= ~(PCI_PM_CTRL_STATE_MASK);
1152 switch (state) { 1169 switch (state) {
1153 case 0: 1170 case PCI_D0:
1154 power_control |= 0; 1171 power_control |= 0;
1155 pci_write_config_word(tp->pdev, 1172 pci_write_config_word(tp->pdev,
1156 pm + PCI_PM_CTRL, 1173 pm + PCI_PM_CTRL,
@@ -1163,15 +1180,15 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
1163 1180
1164 return 0; 1181 return 0;
1165 1182
1166 case 1: 1183 case PCI_D1:
1167 power_control |= 1; 1184 power_control |= 1;
1168 break; 1185 break;
1169 1186
1170 case 2: 1187 case PCI_D2:
1171 power_control |= 2; 1188 power_control |= 2;
1172 break; 1189 break;
1173 1190
1174 case 3: 1191 case PCI_D3hot:
1175 power_control |= 3; 1192 power_control |= 3;
1176 break; 1193 break;
1177 1194
@@ -2680,6 +2697,12 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
2680 2697
2681 err |= tg3_readphy(tp, MII_BMSR, &bmsr); 2698 err |= tg3_readphy(tp, MII_BMSR, &bmsr);
2682 err |= tg3_readphy(tp, MII_BMSR, &bmsr); 2699 err |= tg3_readphy(tp, MII_BMSR, &bmsr);
2700 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
2701 if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP)
2702 bmsr |= BMSR_LSTATUS;
2703 else
2704 bmsr &= ~BMSR_LSTATUS;
2705 }
2683 2706
2684 err |= tg3_readphy(tp, MII_BMCR, &bmcr); 2707 err |= tg3_readphy(tp, MII_BMCR, &bmcr);
2685 2708
@@ -2748,6 +2771,13 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
2748 bmcr = new_bmcr; 2771 bmcr = new_bmcr;
2749 err |= tg3_readphy(tp, MII_BMSR, &bmsr); 2772 err |= tg3_readphy(tp, MII_BMSR, &bmsr);
2750 err |= tg3_readphy(tp, MII_BMSR, &bmsr); 2773 err |= tg3_readphy(tp, MII_BMSR, &bmsr);
2774 if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
2775 ASIC_REV_5714) {
2776 if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP)
2777 bmsr |= BMSR_LSTATUS;
2778 else
2779 bmsr &= ~BMSR_LSTATUS;
2780 }
2751 tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; 2781 tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
2752 } 2782 }
2753 } 2783 }
@@ -3338,6 +3368,23 @@ static inline void tg3_full_unlock(struct tg3 *tp)
3338 spin_unlock_bh(&tp->lock); 3368 spin_unlock_bh(&tp->lock);
3339} 3369}
3340 3370
3371/* One-shot MSI handler - Chip automatically disables interrupt
3372 * after sending MSI so driver doesn't have to do it.
3373 */
3374static irqreturn_t tg3_msi_1shot(int irq, void *dev_id, struct pt_regs *regs)
3375{
3376 struct net_device *dev = dev_id;
3377 struct tg3 *tp = netdev_priv(dev);
3378
3379 prefetch(tp->hw_status);
3380 prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
3381
3382 if (likely(!tg3_irq_sync(tp)))
3383 netif_rx_schedule(dev); /* schedule NAPI poll */
3384
3385 return IRQ_HANDLED;
3386}
3387
3341/* MSI ISR - No need to check for interrupt sharing and no need to 3388/* MSI ISR - No need to check for interrupt sharing and no need to
3342 * flush status block and interrupt mailbox. PCI ordering rules 3389 * flush status block and interrupt mailbox. PCI ordering rules
3343 * guarantee that MSI will arrive after the status block. 3390 * guarantee that MSI will arrive after the status block.
@@ -3628,11 +3675,139 @@ static void tg3_set_txd(struct tg3 *tp, int entry,
3628 txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT; 3675 txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
3629} 3676}
3630 3677
3678/* hard_start_xmit for devices that don't have any bugs and
3679 * support TG3_FLG2_HW_TSO_2 only.
3680 */
3631static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) 3681static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
3632{ 3682{
3633 struct tg3 *tp = netdev_priv(dev); 3683 struct tg3 *tp = netdev_priv(dev);
3634 dma_addr_t mapping; 3684 dma_addr_t mapping;
3635 u32 len, entry, base_flags, mss; 3685 u32 len, entry, base_flags, mss;
3686
3687 len = skb_headlen(skb);
3688
3689 /* No BH disabling for tx_lock here. We are running in BH disabled
3690 * context and TX reclaim runs via tp->poll inside of a software
3691 * interrupt. Furthermore, IRQ processing runs lockless so we have
3692 * no IRQ context deadlocks to worry about either. Rejoice!
3693 */
3694 if (!spin_trylock(&tp->tx_lock))
3695 return NETDEV_TX_LOCKED;
3696
3697 if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
3698 if (!netif_queue_stopped(dev)) {
3699 netif_stop_queue(dev);
3700
3701 /* This is a hard error, log it. */
3702 printk(KERN_ERR PFX "%s: BUG! Tx Ring full when "
3703 "queue awake!\n", dev->name);
3704 }
3705 spin_unlock(&tp->tx_lock);
3706 return NETDEV_TX_BUSY;
3707 }
3708
3709 entry = tp->tx_prod;
3710 base_flags = 0;
3711#if TG3_TSO_SUPPORT != 0
3712 mss = 0;
3713 if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
3714 (mss = skb_shinfo(skb)->tso_size) != 0) {
3715 int tcp_opt_len, ip_tcp_len;
3716
3717 if (skb_header_cloned(skb) &&
3718 pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
3719 dev_kfree_skb(skb);
3720 goto out_unlock;
3721 }
3722
3723 tcp_opt_len = ((skb->h.th->doff - 5) * 4);
3724 ip_tcp_len = (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr);
3725
3726 base_flags |= (TXD_FLAG_CPU_PRE_DMA |
3727 TXD_FLAG_CPU_POST_DMA);
3728
3729 skb->nh.iph->check = 0;
3730 skb->nh.iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
3731
3732 skb->h.th->check = 0;
3733
3734 mss |= (ip_tcp_len + tcp_opt_len) << 9;
3735 }
3736 else if (skb->ip_summed == CHECKSUM_HW)
3737 base_flags |= TXD_FLAG_TCPUDP_CSUM;
3738#else
3739 mss = 0;
3740 if (skb->ip_summed == CHECKSUM_HW)
3741 base_flags |= TXD_FLAG_TCPUDP_CSUM;
3742#endif
3743#if TG3_VLAN_TAG_USED
3744 if (tp->vlgrp != NULL && vlan_tx_tag_present(skb))
3745 base_flags |= (TXD_FLAG_VLAN |
3746 (vlan_tx_tag_get(skb) << 16));
3747#endif
3748
3749 /* Queue skb data, a.k.a. the main skb fragment. */
3750 mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE);
3751
3752 tp->tx_buffers[entry].skb = skb;
3753 pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
3754
3755 tg3_set_txd(tp, entry, mapping, len, base_flags,
3756 (skb_shinfo(skb)->nr_frags == 0) | (mss << 1));
3757
3758 entry = NEXT_TX(entry);
3759
3760 /* Now loop through additional data fragments, and queue them. */
3761 if (skb_shinfo(skb)->nr_frags > 0) {
3762 unsigned int i, last;
3763
3764 last = skb_shinfo(skb)->nr_frags - 1;
3765 for (i = 0; i <= last; i++) {
3766 skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
3767
3768 len = frag->size;
3769 mapping = pci_map_page(tp->pdev,
3770 frag->page,
3771 frag->page_offset,
3772 len, PCI_DMA_TODEVICE);
3773
3774 tp->tx_buffers[entry].skb = NULL;
3775 pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
3776
3777 tg3_set_txd(tp, entry, mapping, len,
3778 base_flags, (i == last) | (mss << 1));
3779
3780 entry = NEXT_TX(entry);
3781 }
3782 }
3783
3784 /* Packets are ready, update Tx producer idx local and on card. */
3785 tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
3786
3787 tp->tx_prod = entry;
3788 if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) {
3789 netif_stop_queue(dev);
3790 if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)
3791 netif_wake_queue(tp->dev);
3792 }
3793
3794out_unlock:
3795 mmiowb();
3796 spin_unlock(&tp->tx_lock);
3797
3798 dev->trans_start = jiffies;
3799
3800 return NETDEV_TX_OK;
3801}
3802
3803/* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and
3804 * support TG3_FLG2_HW_TSO_1 or firmware TSO only.
3805 */
3806static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
3807{
3808 struct tg3 *tp = netdev_priv(dev);
3809 dma_addr_t mapping;
3810 u32 len, entry, base_flags, mss;
3636 int would_hit_hwbug; 3811 int would_hit_hwbug;
3637 3812
3638 len = skb_headlen(skb); 3813 len = skb_headlen(skb);
@@ -4369,6 +4544,10 @@ static int tg3_chip_reset(struct tg3 *tp)
4369 tp->nvram_lock_cnt = 0; 4544 tp->nvram_lock_cnt = 0;
4370 } 4545 }
4371 4546
4547 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
4548 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
4549 tw32(GRC_FASTBOOT_PC, 0);
4550
4372 /* 4551 /*
4373 * We must avoid the readl() that normally takes place. 4552 * We must avoid the readl() that normally takes place.
4374 * It locks machines, causes machine checks, and other 4553 * It locks machines, causes machine checks, and other
@@ -5518,6 +5697,9 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
5518 5697
5519 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); 5698 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
5520 5699
5700 if (!netif_running(dev))
5701 return 0;
5702
5521 spin_lock_bh(&tp->lock); 5703 spin_lock_bh(&tp->lock);
5522 __tg3_set_mac_addr(tp); 5704 __tg3_set_mac_addr(tp);
5523 spin_unlock_bh(&tp->lock); 5705 spin_unlock_bh(&tp->lock);
@@ -5585,6 +5767,9 @@ static int tg3_reset_hw(struct tg3 *tp)
5585 tg3_abort_hw(tp, 1); 5767 tg3_abort_hw(tp, 1);
5586 } 5768 }
5587 5769
5770 if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)
5771 tg3_phy_reset(tp);
5772
5588 err = tg3_chip_reset(tp); 5773 err = tg3_chip_reset(tp);
5589 if (err) 5774 if (err)
5590 return err; 5775 return err;
@@ -5993,6 +6178,10 @@ static int tg3_reset_hw(struct tg3 *tp)
5993 } 6178 }
5994 } 6179 }
5995 6180
6181 /* Enable host coalescing bug fix */
6182 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
6183 val |= (1 << 29);
6184
5996 tw32_f(WDMAC_MODE, val); 6185 tw32_f(WDMAC_MODE, val);
5997 udelay(40); 6186 udelay(40);
5998 6187
@@ -6097,6 +6286,17 @@ static int tg3_reset_hw(struct tg3 *tp)
6097 tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG; 6286 tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG;
6098 } 6287 }
6099 6288
6289 if ((tp->tg3_flags2 & TG3_FLG2_MII_SERDES) &&
6290 (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)) {
6291 u32 tmp;
6292
6293 tmp = tr32(SERDES_RX_CTRL);
6294 tw32(SERDES_RX_CTRL, tmp | SERDES_RX_SIG_DETECT);
6295 tp->grc_local_ctrl &= ~GRC_LCLCTRL_USE_EXT_SIG_DETECT;
6296 tp->grc_local_ctrl |= GRC_LCLCTRL_USE_SIG_DETECT;
6297 tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
6298 }
6299
6100 err = tg3_setup_phy(tp, 1); 6300 err = tg3_setup_phy(tp, 1);
6101 if (err) 6301 if (err)
6102 return err; 6302 return err;
@@ -6175,7 +6375,7 @@ static int tg3_init_hw(struct tg3 *tp)
6175 int err; 6375 int err;
6176 6376
6177 /* Force the chip into D0. */ 6377 /* Force the chip into D0. */
6178 err = tg3_set_power_state(tp, 0); 6378 err = tg3_set_power_state(tp, PCI_D0);
6179 if (err) 6379 if (err)
6180 goto out; 6380 goto out;
6181 6381
@@ -6331,6 +6531,26 @@ static void tg3_timer(unsigned long __opaque)
6331 add_timer(&tp->timer); 6531 add_timer(&tp->timer);
6332} 6532}
6333 6533
6534static int tg3_request_irq(struct tg3 *tp)
6535{
6536 irqreturn_t (*fn)(int, void *, struct pt_regs *);
6537 unsigned long flags;
6538 struct net_device *dev = tp->dev;
6539
6540 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
6541 fn = tg3_msi;
6542 if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)
6543 fn = tg3_msi_1shot;
6544 flags = SA_SAMPLE_RANDOM;
6545 } else {
6546 fn = tg3_interrupt;
6547 if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
6548 fn = tg3_interrupt_tagged;
6549 flags = SA_SHIRQ | SA_SAMPLE_RANDOM;
6550 }
6551 return (request_irq(tp->pdev->irq, fn, flags, dev->name, dev));
6552}
6553
6334static int tg3_test_interrupt(struct tg3 *tp) 6554static int tg3_test_interrupt(struct tg3 *tp)
6335{ 6555{
6336 struct net_device *dev = tp->dev; 6556 struct net_device *dev = tp->dev;
@@ -6367,16 +6587,7 @@ static int tg3_test_interrupt(struct tg3 *tp)
6367 6587
6368 free_irq(tp->pdev->irq, dev); 6588 free_irq(tp->pdev->irq, dev);
6369 6589
6370 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) 6590 err = tg3_request_irq(tp);
6371 err = request_irq(tp->pdev->irq, tg3_msi,
6372 SA_SAMPLE_RANDOM, dev->name, dev);
6373 else {
6374 irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt;
6375 if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
6376 fn = tg3_interrupt_tagged;
6377 err = request_irq(tp->pdev->irq, fn,
6378 SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
6379 }
6380 6591
6381 if (err) 6592 if (err)
6382 return err; 6593 return err;
@@ -6428,14 +6639,7 @@ static int tg3_test_msi(struct tg3 *tp)
6428 6639
6429 tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; 6640 tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
6430 6641
6431 { 6642 err = tg3_request_irq(tp);
6432 irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt;
6433 if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
6434 fn = tg3_interrupt_tagged;
6435
6436 err = request_irq(tp->pdev->irq, fn,
6437 SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
6438 }
6439 if (err) 6643 if (err)
6440 return err; 6644 return err;
6441 6645
@@ -6462,6 +6666,10 @@ static int tg3_open(struct net_device *dev)
6462 6666
6463 tg3_full_lock(tp, 0); 6667 tg3_full_lock(tp, 0);
6464 6668
6669 err = tg3_set_power_state(tp, PCI_D0);
6670 if (err)
6671 return err;
6672
6465 tg3_disable_ints(tp); 6673 tg3_disable_ints(tp);
6466 tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE; 6674 tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
6467 6675
@@ -6476,7 +6684,9 @@ static int tg3_open(struct net_device *dev)
6476 6684
6477 if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && 6685 if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
6478 (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_AX) && 6686 (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_AX) &&
6479 (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_BX)) { 6687 (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_BX) &&
6688 !((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) &&
6689 (tp->pdev_peer == tp->pdev))) {
6480 /* All MSI supporting chips should support tagged 6690 /* All MSI supporting chips should support tagged
6481 * status. Assert that this is the case. 6691 * status. Assert that this is the case.
6482 */ 6692 */
@@ -6491,17 +6701,7 @@ static int tg3_open(struct net_device *dev)
6491 tp->tg3_flags2 |= TG3_FLG2_USING_MSI; 6701 tp->tg3_flags2 |= TG3_FLG2_USING_MSI;
6492 } 6702 }
6493 } 6703 }
6494 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) 6704 err = tg3_request_irq(tp);
6495 err = request_irq(tp->pdev->irq, tg3_msi,
6496 SA_SAMPLE_RANDOM, dev->name, dev);
6497 else {
6498 irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt;
6499 if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
6500 fn = tg3_interrupt_tagged;
6501
6502 err = request_irq(tp->pdev->irq, fn,
6503 SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
6504 }
6505 6705
6506 if (err) { 6706 if (err) {
6507 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { 6707 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
@@ -6566,6 +6766,14 @@ static int tg3_open(struct net_device *dev)
6566 6766
6567 return err; 6767 return err;
6568 } 6768 }
6769
6770 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
6771 if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) {
6772 u32 val = tr32(0x7c04);
6773
6774 tw32(0x7c04, val | (1 << 29));
6775 }
6776 }
6569 } 6777 }
6570 6778
6571 tg3_full_lock(tp, 0); 6779 tg3_full_lock(tp, 0);
@@ -6839,7 +7047,6 @@ static int tg3_close(struct net_device *dev)
6839 tp->tg3_flags &= 7047 tp->tg3_flags &=
6840 ~(TG3_FLAG_INIT_COMPLETE | 7048 ~(TG3_FLAG_INIT_COMPLETE |
6841 TG3_FLAG_GOT_SERDES_FLOWCTL); 7049 TG3_FLAG_GOT_SERDES_FLOWCTL);
6842 netif_carrier_off(tp->dev);
6843 7050
6844 tg3_full_unlock(tp); 7051 tg3_full_unlock(tp);
6845 7052
@@ -6856,6 +7063,10 @@ static int tg3_close(struct net_device *dev)
6856 7063
6857 tg3_free_consistent(tp); 7064 tg3_free_consistent(tp);
6858 7065
7066 tg3_set_power_state(tp, PCI_D3hot);
7067
7068 netif_carrier_off(tp->dev);
7069
6859 return 0; 7070 return 0;
6860} 7071}
6861 7072
@@ -7150,6 +7361,9 @@ static void tg3_set_rx_mode(struct net_device *dev)
7150{ 7361{
7151 struct tg3 *tp = netdev_priv(dev); 7362 struct tg3 *tp = netdev_priv(dev);
7152 7363
7364 if (!netif_running(dev))
7365 return;
7366
7153 tg3_full_lock(tp, 0); 7367 tg3_full_lock(tp, 0);
7154 __tg3_set_rx_mode(dev); 7368 __tg3_set_rx_mode(dev);
7155 tg3_full_unlock(tp); 7369 tg3_full_unlock(tp);
@@ -7174,6 +7388,9 @@ static void tg3_get_regs(struct net_device *dev,
7174 7388
7175 memset(p, 0, TG3_REGDUMP_LEN); 7389 memset(p, 0, TG3_REGDUMP_LEN);
7176 7390
7391 if (tp->link_config.phy_is_low_power)
7392 return;
7393
7177 tg3_full_lock(tp, 0); 7394 tg3_full_lock(tp, 0);
7178 7395
7179#define __GET_REG32(reg) (*(p)++ = tr32(reg)) 7396#define __GET_REG32(reg) (*(p)++ = tr32(reg))
@@ -7240,6 +7457,7 @@ static int tg3_get_eeprom_len(struct net_device *dev)
7240} 7457}
7241 7458
7242static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val); 7459static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val);
7460static int tg3_nvram_read_swab(struct tg3 *tp, u32 offset, u32 *val);
7243 7461
7244static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) 7462static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
7245{ 7463{
@@ -7248,6 +7466,9 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
7248 u8 *pd; 7466 u8 *pd;
7249 u32 i, offset, len, val, b_offset, b_count; 7467 u32 i, offset, len, val, b_offset, b_count;
7250 7468
7469 if (tp->link_config.phy_is_low_power)
7470 return -EAGAIN;
7471
7251 offset = eeprom->offset; 7472 offset = eeprom->offset;
7252 len = eeprom->len; 7473 len = eeprom->len;
7253 eeprom->len = 0; 7474 eeprom->len = 0;
@@ -7309,6 +7530,9 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
7309 u32 offset, len, b_offset, odd_len, start, end; 7530 u32 offset, len, b_offset, odd_len, start, end;
7310 u8 *buf; 7531 u8 *buf;
7311 7532
7533 if (tp->link_config.phy_is_low_power)
7534 return -EAGAIN;
7535
7312 if (eeprom->magic != TG3_EEPROM_MAGIC) 7536 if (eeprom->magic != TG3_EEPROM_MAGIC)
7313 return -EINVAL; 7537 return -EINVAL;
7314 7538
@@ -7442,6 +7666,7 @@ static void tg3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info
7442 7666
7443 strcpy(info->driver, DRV_MODULE_NAME); 7667 strcpy(info->driver, DRV_MODULE_NAME);
7444 strcpy(info->version, DRV_MODULE_VERSION); 7668 strcpy(info->version, DRV_MODULE_VERSION);
7669 strcpy(info->fw_version, tp->fw_ver);
7445 strcpy(info->bus_info, pci_name(tp->pdev)); 7670 strcpy(info->bus_info, pci_name(tp->pdev));
7446} 7671}
7447 7672
@@ -7536,11 +7761,20 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam *
7536 7761
7537 ering->rx_max_pending = TG3_RX_RING_SIZE - 1; 7762 ering->rx_max_pending = TG3_RX_RING_SIZE - 1;
7538 ering->rx_mini_max_pending = 0; 7763 ering->rx_mini_max_pending = 0;
7539 ering->rx_jumbo_max_pending = TG3_RX_JUMBO_RING_SIZE - 1; 7764 if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE)
7765 ering->rx_jumbo_max_pending = TG3_RX_JUMBO_RING_SIZE - 1;
7766 else
7767 ering->rx_jumbo_max_pending = 0;
7768
7769 ering->tx_max_pending = TG3_TX_RING_SIZE - 1;
7540 7770
7541 ering->rx_pending = tp->rx_pending; 7771 ering->rx_pending = tp->rx_pending;
7542 ering->rx_mini_pending = 0; 7772 ering->rx_mini_pending = 0;
7543 ering->rx_jumbo_pending = tp->rx_jumbo_pending; 7773 if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE)
7774 ering->rx_jumbo_pending = tp->rx_jumbo_pending;
7775 else
7776 ering->rx_jumbo_pending = 0;
7777
7544 ering->tx_pending = tp->tx_pending; 7778 ering->tx_pending = tp->tx_pending;
7545} 7779}
7546 7780
@@ -7661,10 +7895,10 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data)
7661 return 0; 7895 return 0;
7662 } 7896 }
7663 7897
7664 if (data) 7898 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
7665 dev->features |= NETIF_F_IP_CSUM; 7899 ethtool_op_set_tx_hw_csum(dev, data);
7666 else 7900 else
7667 dev->features &= ~NETIF_F_IP_CSUM; 7901 ethtool_op_set_tx_csum(dev, data);
7668 7902
7669 return 0; 7903 return 0;
7670} 7904}
@@ -7734,29 +7968,52 @@ static void tg3_get_ethtool_stats (struct net_device *dev,
7734} 7968}
7735 7969
7736#define NVRAM_TEST_SIZE 0x100 7970#define NVRAM_TEST_SIZE 0x100
7971#define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14
7737 7972
7738static int tg3_test_nvram(struct tg3 *tp) 7973static int tg3_test_nvram(struct tg3 *tp)
7739{ 7974{
7740 u32 *buf, csum; 7975 u32 *buf, csum, magic;
7741 int i, j, err = 0; 7976 int i, j, err = 0, size;
7742 7977
7743 buf = kmalloc(NVRAM_TEST_SIZE, GFP_KERNEL); 7978 if (tg3_nvram_read_swab(tp, 0, &magic) != 0)
7979 return -EIO;
7980
7981 if (magic == TG3_EEPROM_MAGIC)
7982 size = NVRAM_TEST_SIZE;
7983 else if ((magic & 0xff000000) == 0xa5000000) {
7984 if ((magic & 0xe00000) == 0x200000)
7985 size = NVRAM_SELFBOOT_FORMAT1_SIZE;
7986 else
7987 return 0;
7988 } else
7989 return -EIO;
7990
7991 buf = kmalloc(size, GFP_KERNEL);
7744 if (buf == NULL) 7992 if (buf == NULL)
7745 return -ENOMEM; 7993 return -ENOMEM;
7746 7994
7747 for (i = 0, j = 0; i < NVRAM_TEST_SIZE; i += 4, j++) { 7995 err = -EIO;
7996 for (i = 0, j = 0; i < size; i += 4, j++) {
7748 u32 val; 7997 u32 val;
7749 7998
7750 if ((err = tg3_nvram_read(tp, i, &val)) != 0) 7999 if ((err = tg3_nvram_read(tp, i, &val)) != 0)
7751 break; 8000 break;
7752 buf[j] = cpu_to_le32(val); 8001 buf[j] = cpu_to_le32(val);
7753 } 8002 }
7754 if (i < NVRAM_TEST_SIZE) 8003 if (i < size)
7755 goto out; 8004 goto out;
7756 8005
7757 err = -EIO; 8006 /* Selfboot format */
7758 if (cpu_to_be32(buf[0]) != TG3_EEPROM_MAGIC) 8007 if (cpu_to_be32(buf[0]) != TG3_EEPROM_MAGIC) {
7759 goto out; 8008 u8 *buf8 = (u8 *) buf, csum8 = 0;
8009
8010 for (i = 0; i < size; i++)
8011 csum8 += buf8[i];
8012
8013 if (csum8 == 0)
8014 return 0;
8015 return -EIO;
8016 }
7760 8017
7761 /* Bootstrap checksum at offset 0x10 */ 8018 /* Bootstrap checksum at offset 0x10 */
7762 csum = calc_crc((unsigned char *) buf, 0x10); 8019 csum = calc_crc((unsigned char *) buf, 0x10);
@@ -7802,7 +8059,7 @@ static int tg3_test_link(struct tg3 *tp)
7802} 8059}
7803 8060
7804/* Only test the commonly used registers */ 8061/* Only test the commonly used registers */
7805static const int tg3_test_registers(struct tg3 *tp) 8062static int tg3_test_registers(struct tg3 *tp)
7806{ 8063{
7807 int i, is_5705; 8064 int i, is_5705;
7808 u32 offset, read_mask, write_mask, val, save_val, read_val; 8065 u32 offset, read_mask, write_mask, val, save_val, read_val;
@@ -8050,14 +8307,24 @@ static int tg3_test_memory(struct tg3 *tp)
8050 { 0x00008000, 0x02000}, 8307 { 0x00008000, 0x02000},
8051 { 0x00010000, 0x0e000}, 8308 { 0x00010000, 0x0e000},
8052 { 0xffffffff, 0x00000} 8309 { 0xffffffff, 0x00000}
8310 }, mem_tbl_5755[] = {
8311 { 0x00000200, 0x00008},
8312 { 0x00004000, 0x00800},
8313 { 0x00006000, 0x00800},
8314 { 0x00008000, 0x02000},
8315 { 0x00010000, 0x0c000},
8316 { 0xffffffff, 0x00000}
8053 }; 8317 };
8054 struct mem_entry *mem_tbl; 8318 struct mem_entry *mem_tbl;
8055 int err = 0; 8319 int err = 0;
8056 int i; 8320 int i;
8057 8321
8058 if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) 8322 if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
8059 mem_tbl = mem_tbl_5705; 8323 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
8060 else 8324 mem_tbl = mem_tbl_5755;
8325 else
8326 mem_tbl = mem_tbl_5705;
8327 } else
8061 mem_tbl = mem_tbl_570x; 8328 mem_tbl = mem_tbl_570x;
8062 8329
8063 for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) { 8330 for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) {
@@ -8229,6 +8496,9 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
8229{ 8496{
8230 struct tg3 *tp = netdev_priv(dev); 8497 struct tg3 *tp = netdev_priv(dev);
8231 8498
8499 if (tp->link_config.phy_is_low_power)
8500 tg3_set_power_state(tp, PCI_D0);
8501
8232 memset(data, 0, sizeof(u64) * TG3_NUM_TEST); 8502 memset(data, 0, sizeof(u64) * TG3_NUM_TEST);
8233 8503
8234 if (tg3_test_nvram(tp) != 0) { 8504 if (tg3_test_nvram(tp) != 0) {
@@ -8257,6 +8527,9 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
8257 if (!err) 8527 if (!err)
8258 tg3_nvram_unlock(tp); 8528 tg3_nvram_unlock(tp);
8259 8529
8530 if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)
8531 tg3_phy_reset(tp);
8532
8260 if (tg3_test_registers(tp) != 0) { 8533 if (tg3_test_registers(tp) != 0) {
8261 etest->flags |= ETH_TEST_FL_FAILED; 8534 etest->flags |= ETH_TEST_FL_FAILED;
8262 data[2] = 1; 8535 data[2] = 1;
@@ -8286,6 +8559,9 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
8286 8559
8287 tg3_full_unlock(tp); 8560 tg3_full_unlock(tp);
8288 } 8561 }
8562 if (tp->link_config.phy_is_low_power)
8563 tg3_set_power_state(tp, PCI_D3hot);
8564
8289} 8565}
8290 8566
8291static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 8567static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -8305,6 +8581,9 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
8305 if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) 8581 if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
8306 break; /* We have no PHY */ 8582 break; /* We have no PHY */
8307 8583
8584 if (tp->link_config.phy_is_low_power)
8585 return -EAGAIN;
8586
8308 spin_lock_bh(&tp->lock); 8587 spin_lock_bh(&tp->lock);
8309 err = tg3_readphy(tp, data->reg_num & 0x1f, &mii_regval); 8588 err = tg3_readphy(tp, data->reg_num & 0x1f, &mii_regval);
8310 spin_unlock_bh(&tp->lock); 8589 spin_unlock_bh(&tp->lock);
@@ -8321,6 +8600,9 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
8321 if (!capable(CAP_NET_ADMIN)) 8600 if (!capable(CAP_NET_ADMIN))
8322 return -EPERM; 8601 return -EPERM;
8323 8602
8603 if (tp->link_config.phy_is_low_power)
8604 return -EAGAIN;
8605
8324 spin_lock_bh(&tp->lock); 8606 spin_lock_bh(&tp->lock);
8325 err = tg3_writephy(tp, data->reg_num & 0x1f, data->val_in); 8607 err = tg3_writephy(tp, data->reg_num & 0x1f, data->val_in);
8326 spin_unlock_bh(&tp->lock); 8608 spin_unlock_bh(&tp->lock);
@@ -8464,14 +8746,14 @@ static struct ethtool_ops tg3_ethtool_ops = {
8464 8746
8465static void __devinit tg3_get_eeprom_size(struct tg3 *tp) 8747static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
8466{ 8748{
8467 u32 cursize, val; 8749 u32 cursize, val, magic;
8468 8750
8469 tp->nvram_size = EEPROM_CHIP_SIZE; 8751 tp->nvram_size = EEPROM_CHIP_SIZE;
8470 8752
8471 if (tg3_nvram_read(tp, 0, &val) != 0) 8753 if (tg3_nvram_read_swab(tp, 0, &magic) != 0)
8472 return; 8754 return;
8473 8755
8474 if (swab32(val) != TG3_EEPROM_MAGIC) 8756 if ((magic != TG3_EEPROM_MAGIC) && ((magic & 0xff000000) != 0xa5000000))
8475 return; 8757 return;
8476 8758
8477 /* 8759 /*
@@ -8479,13 +8761,13 @@ static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
8479 * When we encounter our validation signature, we know the addressing 8761 * When we encounter our validation signature, we know the addressing
8480 * has wrapped around, and thus have our chip size. 8762 * has wrapped around, and thus have our chip size.
8481 */ 8763 */
8482 cursize = 0x800; 8764 cursize = 0x10;
8483 8765
8484 while (cursize < tp->nvram_size) { 8766 while (cursize < tp->nvram_size) {
8485 if (tg3_nvram_read(tp, cursize, &val) != 0) 8767 if (tg3_nvram_read_swab(tp, cursize, &val) != 0)
8486 return; 8768 return;
8487 8769
8488 if (swab32(val) == TG3_EEPROM_MAGIC) 8770 if (val == magic)
8489 break; 8771 break;
8490 8772
8491 cursize <<= 1; 8773 cursize <<= 1;
@@ -8498,6 +8780,15 @@ static void __devinit tg3_get_nvram_size(struct tg3 *tp)
8498{ 8780{
8499 u32 val; 8781 u32 val;
8500 8782
8783 if (tg3_nvram_read_swab(tp, 0, &val) != 0)
8784 return;
8785
8786 /* Selfboot format */
8787 if (val != TG3_EEPROM_MAGIC) {
8788 tg3_get_eeprom_size(tp);
8789 return;
8790 }
8791
8501 if (tg3_nvram_read(tp, 0xf0, &val) == 0) { 8792 if (tg3_nvram_read(tp, 0xf0, &val) == 0) {
8502 if (val != 0) { 8793 if (val != 0) {
8503 tp->nvram_size = (val >> 16) * 1024; 8794 tp->nvram_size = (val >> 16) * 1024;
@@ -8621,6 +8912,44 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
8621 } 8912 }
8622} 8913}
8623 8914
8915static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp)
8916{
8917 u32 nvcfg1;
8918
8919 nvcfg1 = tr32(NVRAM_CFG1);
8920
8921 switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
8922 case FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ:
8923 case FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ:
8924 case FLASH_5787VENDOR_MICRO_EEPROM_64KHZ:
8925 case FLASH_5787VENDOR_MICRO_EEPROM_376KHZ:
8926 tp->nvram_jedecnum = JEDEC_ATMEL;
8927 tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
8928 tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
8929
8930 nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
8931 tw32(NVRAM_CFG1, nvcfg1);
8932 break;
8933 case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED:
8934 case FLASH_5755VENDOR_ATMEL_FLASH_1:
8935 case FLASH_5755VENDOR_ATMEL_FLASH_2:
8936 case FLASH_5755VENDOR_ATMEL_FLASH_3:
8937 tp->nvram_jedecnum = JEDEC_ATMEL;
8938 tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
8939 tp->tg3_flags2 |= TG3_FLG2_FLASH;
8940 tp->nvram_pagesize = 264;
8941 break;
8942 case FLASH_5752VENDOR_ST_M45PE10:
8943 case FLASH_5752VENDOR_ST_M45PE20:
8944 case FLASH_5752VENDOR_ST_M45PE40:
8945 tp->nvram_jedecnum = JEDEC_ST;
8946 tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
8947 tp->tg3_flags2 |= TG3_FLG2_FLASH;
8948 tp->nvram_pagesize = 256;
8949 break;
8950 }
8951}
8952
8624/* Chips other than 5700/5701 use the NVRAM for fetching info. */ 8953/* Chips other than 5700/5701 use the NVRAM for fetching info. */
8625static void __devinit tg3_nvram_init(struct tg3 *tp) 8954static void __devinit tg3_nvram_init(struct tg3 *tp)
8626{ 8955{
@@ -8656,6 +8985,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
8656 8985
8657 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) 8986 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
8658 tg3_get_5752_nvram_info(tp); 8987 tg3_get_5752_nvram_info(tp);
8988 else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
8989 tg3_get_5787_nvram_info(tp);
8659 else 8990 else
8660 tg3_get_nvram_info(tp); 8991 tg3_get_nvram_info(tp);
8661 8992
@@ -8725,6 +9056,34 @@ static int tg3_nvram_exec_cmd(struct tg3 *tp, u32 nvram_cmd)
8725 return 0; 9056 return 0;
8726} 9057}
8727 9058
9059static u32 tg3_nvram_phys_addr(struct tg3 *tp, u32 addr)
9060{
9061 if ((tp->tg3_flags & TG3_FLAG_NVRAM) &&
9062 (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) &&
9063 (tp->tg3_flags2 & TG3_FLG2_FLASH) &&
9064 (tp->nvram_jedecnum == JEDEC_ATMEL))
9065
9066 addr = ((addr / tp->nvram_pagesize) <<
9067 ATMEL_AT45DB0X1B_PAGE_POS) +
9068 (addr % tp->nvram_pagesize);
9069
9070 return addr;
9071}
9072
9073static u32 tg3_nvram_logical_addr(struct tg3 *tp, u32 addr)
9074{
9075 if ((tp->tg3_flags & TG3_FLAG_NVRAM) &&
9076 (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) &&
9077 (tp->tg3_flags2 & TG3_FLG2_FLASH) &&
9078 (tp->nvram_jedecnum == JEDEC_ATMEL))
9079
9080 addr = ((addr >> ATMEL_AT45DB0X1B_PAGE_POS) *
9081 tp->nvram_pagesize) +
9082 (addr & ((1 << ATMEL_AT45DB0X1B_PAGE_POS) - 1));
9083
9084 return addr;
9085}
9086
8728static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val) 9087static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val)
8729{ 9088{
8730 int ret; 9089 int ret;
@@ -8737,14 +9096,7 @@ static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val)
8737 if (!(tp->tg3_flags & TG3_FLAG_NVRAM)) 9096 if (!(tp->tg3_flags & TG3_FLAG_NVRAM))
8738 return tg3_nvram_read_using_eeprom(tp, offset, val); 9097 return tg3_nvram_read_using_eeprom(tp, offset, val);
8739 9098
8740 if ((tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) && 9099 offset = tg3_nvram_phys_addr(tp, offset);
8741 (tp->tg3_flags2 & TG3_FLG2_FLASH) &&
8742 (tp->nvram_jedecnum == JEDEC_ATMEL)) {
8743
8744 offset = ((offset / tp->nvram_pagesize) <<
8745 ATMEL_AT45DB0X1B_PAGE_POS) +
8746 (offset % tp->nvram_pagesize);
8747 }
8748 9100
8749 if (offset > NVRAM_ADDR_MSK) 9101 if (offset > NVRAM_ADDR_MSK)
8750 return -EINVAL; 9102 return -EINVAL;
@@ -8769,6 +9121,16 @@ static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val)
8769 return ret; 9121 return ret;
8770} 9122}
8771 9123
9124static int tg3_nvram_read_swab(struct tg3 *tp, u32 offset, u32 *val)
9125{
9126 int err;
9127 u32 tmp;
9128
9129 err = tg3_nvram_read(tp, offset, &tmp);
9130 *val = swab32(tmp);
9131 return err;
9132}
9133
8772static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp, 9134static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp,
8773 u32 offset, u32 len, u8 *buf) 9135 u32 offset, u32 len, u8 *buf)
8774{ 9136{
@@ -8921,15 +9283,7 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len,
8921 9283
8922 page_off = offset % tp->nvram_pagesize; 9284 page_off = offset % tp->nvram_pagesize;
8923 9285
8924 if ((tp->tg3_flags2 & TG3_FLG2_FLASH) && 9286 phy_addr = tg3_nvram_phys_addr(tp, offset);
8925 (tp->nvram_jedecnum == JEDEC_ATMEL)) {
8926
8927 phy_addr = ((offset / tp->nvram_pagesize) <<
8928 ATMEL_AT45DB0X1B_PAGE_POS) + page_off;
8929 }
8930 else {
8931 phy_addr = offset;
8932 }
8933 9287
8934 tw32(NVRAM_ADDR, phy_addr); 9288 tw32(NVRAM_ADDR, phy_addr);
8935 9289
@@ -8944,6 +9298,7 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len,
8944 nvram_cmd |= NVRAM_CMD_LAST; 9298 nvram_cmd |= NVRAM_CMD_LAST;
8945 9299
8946 if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) && 9300 if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) &&
9301 (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) &&
8947 (tp->nvram_jedecnum == JEDEC_ST) && 9302 (tp->nvram_jedecnum == JEDEC_ST) &&
8948 (nvram_cmd & NVRAM_CMD_FIRST)) { 9303 (nvram_cmd & NVRAM_CMD_FIRST)) {
8949 9304
@@ -9347,6 +9702,7 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
9347{ 9702{
9348 unsigned char vpd_data[256]; 9703 unsigned char vpd_data[256];
9349 int i; 9704 int i;
9705 u32 magic;
9350 9706
9351 if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) { 9707 if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
9352 /* Sun decided not to put the necessary bits in the 9708 /* Sun decided not to put the necessary bits in the
@@ -9356,16 +9712,43 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
9356 return; 9712 return;
9357 } 9713 }
9358 9714
9359 for (i = 0; i < 256; i += 4) { 9715 if (tg3_nvram_read_swab(tp, 0x0, &magic))
9360 u32 tmp; 9716 return;
9361 9717
9362 if (tg3_nvram_read(tp, 0x100 + i, &tmp)) 9718 if (magic == TG3_EEPROM_MAGIC) {
9363 goto out_not_found; 9719 for (i = 0; i < 256; i += 4) {
9720 u32 tmp;
9721
9722 if (tg3_nvram_read(tp, 0x100 + i, &tmp))
9723 goto out_not_found;
9364 9724
9365 vpd_data[i + 0] = ((tmp >> 0) & 0xff); 9725 vpd_data[i + 0] = ((tmp >> 0) & 0xff);
9366 vpd_data[i + 1] = ((tmp >> 8) & 0xff); 9726 vpd_data[i + 1] = ((tmp >> 8) & 0xff);
9367 vpd_data[i + 2] = ((tmp >> 16) & 0xff); 9727 vpd_data[i + 2] = ((tmp >> 16) & 0xff);
9368 vpd_data[i + 3] = ((tmp >> 24) & 0xff); 9728 vpd_data[i + 3] = ((tmp >> 24) & 0xff);
9729 }
9730 } else {
9731 int vpd_cap;
9732
9733 vpd_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_VPD);
9734 for (i = 0; i < 256; i += 4) {
9735 u32 tmp, j = 0;
9736 u16 tmp16;
9737
9738 pci_write_config_word(tp->pdev, vpd_cap + PCI_VPD_ADDR,
9739 i);
9740 while (j++ < 100) {
9741 pci_read_config_word(tp->pdev, vpd_cap +
9742 PCI_VPD_ADDR, &tmp16);
9743 if (tmp16 & 0x8000)
9744 break;
9745 msleep(1);
9746 }
9747 pci_read_config_dword(tp->pdev, vpd_cap + PCI_VPD_DATA,
9748 &tmp);
9749 tmp = cpu_to_le32(tmp);
9750 memcpy(&vpd_data[i], &tmp, 4);
9751 }
9369 } 9752 }
9370 9753
9371 /* Now parse and find the part number. */ 9754 /* Now parse and find the part number. */
@@ -9412,6 +9795,46 @@ out_not_found:
9412 strcpy(tp->board_part_number, "none"); 9795 strcpy(tp->board_part_number, "none");
9413} 9796}
9414 9797
9798static void __devinit tg3_read_fw_ver(struct tg3 *tp)
9799{
9800 u32 val, offset, start;
9801
9802 if (tg3_nvram_read_swab(tp, 0, &val))
9803 return;
9804
9805 if (val != TG3_EEPROM_MAGIC)
9806 return;
9807
9808 if (tg3_nvram_read_swab(tp, 0xc, &offset) ||
9809 tg3_nvram_read_swab(tp, 0x4, &start))
9810 return;
9811
9812 offset = tg3_nvram_logical_addr(tp, offset);
9813 if (tg3_nvram_read_swab(tp, offset, &val))
9814 return;
9815
9816 if ((val & 0xfc000000) == 0x0c000000) {
9817 u32 ver_offset, addr;
9818 int i;
9819
9820 if (tg3_nvram_read_swab(tp, offset + 4, &val) ||
9821 tg3_nvram_read_swab(tp, offset + 8, &ver_offset))
9822 return;
9823
9824 if (val != 0)
9825 return;
9826
9827 addr = offset + ver_offset - start;
9828 for (i = 0; i < 16; i += 4) {
9829 if (tg3_nvram_read(tp, addr + i, &val))
9830 return;
9831
9832 val = cpu_to_le32(val);
9833 memcpy(tp->fw_ver + i, &val, 4);
9834 }
9835 }
9836}
9837
9415#ifdef CONFIG_SPARC64 9838#ifdef CONFIG_SPARC64
9416static int __devinit tg3_is_sun_570X(struct tg3 *tp) 9839static int __devinit tg3_is_sun_570X(struct tg3 *tp)
9417{ 9840{
@@ -9603,6 +10026,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
9603 10026
9604 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || 10027 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
9605 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || 10028 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
10029 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
9606 (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) 10030 (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
9607 tp->tg3_flags2 |= TG3_FLG2_5750_PLUS; 10031 tp->tg3_flags2 |= TG3_FLG2_5750_PLUS;
9608 10032
@@ -9610,12 +10034,18 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
9610 (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)) 10034 (tp->tg3_flags2 & TG3_FLG2_5750_PLUS))
9611 tp->tg3_flags2 |= TG3_FLG2_5705_PLUS; 10035 tp->tg3_flags2 |= TG3_FLG2_5705_PLUS;
9612 10036
9613 if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) 10037 if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
9614 tp->tg3_flags2 |= TG3_FLG2_HW_TSO; 10038 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
10039 tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2;
10040 tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI;
10041 } else
10042 tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1;
10043 }
9615 10044
9616 if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && 10045 if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
9617 GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 && 10046 GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 &&
9618 GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) 10047 GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 &&
10048 GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787)
9619 tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE; 10049 tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE;
9620 10050
9621 if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0) 10051 if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0)
@@ -9772,7 +10202,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
9772 tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3; 10202 tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3;
9773 10203
9774 /* Force the chip into D0. */ 10204 /* Force the chip into D0. */
9775 err = tg3_set_power_state(tp, 0); 10205 err = tg3_set_power_state(tp, PCI_D0);
9776 if (err) { 10206 if (err) {
9777 printk(KERN_ERR PFX "(%s) transition to D0 failed\n", 10207 printk(KERN_ERR PFX "(%s) transition to D0 failed\n",
9778 pci_name(tp->pdev)); 10208 pci_name(tp->pdev));
@@ -9825,7 +10255,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
9825 if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) 10255 if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0)
9826 tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG; 10256 tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG;
9827 10257
9828 if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) 10258 if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
10259 (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787))
9829 tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG; 10260 tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
9830 10261
9831 tp->coalesce_mode = 0; 10262 tp->coalesce_mode = 0;
@@ -9925,6 +10356,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
9925 } 10356 }
9926 10357
9927 tg3_read_partno(tp); 10358 tg3_read_partno(tp);
10359 tg3_read_fw_ver(tp);
9928 10360
9929 if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { 10361 if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
9930 tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT; 10362 tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT;
@@ -9960,10 +10392,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
9960 else 10392 else
9961 tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES; 10393 tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES;
9962 10394
9963 /* It seems all chips can get confused if TX buffers 10395 /* All chips before 5787 can get confused if TX buffers
9964 * straddle the 4GB address boundary in some cases. 10396 * straddle the 4GB address boundary in some cases.
9965 */ 10397 */
9966 tp->dev->hard_start_xmit = tg3_start_xmit; 10398 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
10399 tp->dev->hard_start_xmit = tg3_start_xmit;
10400 else
10401 tp->dev->hard_start_xmit = tg3_start_xmit_dma_bug;
9967 10402
9968 tp->rx_offset = 2; 10403 tp->rx_offset = 2;
9969 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 && 10404 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 &&
@@ -10491,7 +10926,6 @@ static void __devinit tg3_init_link_config(struct tg3 *tp)
10491 tp->link_config.speed = SPEED_INVALID; 10926 tp->link_config.speed = SPEED_INVALID;
10492 tp->link_config.duplex = DUPLEX_INVALID; 10927 tp->link_config.duplex = DUPLEX_INVALID;
10493 tp->link_config.autoneg = AUTONEG_ENABLE; 10928 tp->link_config.autoneg = AUTONEG_ENABLE;
10494 netif_carrier_off(tp->dev);
10495 tp->link_config.active_speed = SPEED_INVALID; 10929 tp->link_config.active_speed = SPEED_INVALID;
10496 tp->link_config.active_duplex = DUPLEX_INVALID; 10930 tp->link_config.active_duplex = DUPLEX_INVALID;
10497 tp->link_config.phy_is_low_power = 0; 10931 tp->link_config.phy_is_low_power = 0;
@@ -10550,6 +10984,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
10550 case PHY_ID_BCM5752: return "5752"; 10984 case PHY_ID_BCM5752: return "5752";
10551 case PHY_ID_BCM5714: return "5714"; 10985 case PHY_ID_BCM5714: return "5714";
10552 case PHY_ID_BCM5780: return "5780"; 10986 case PHY_ID_BCM5780: return "5780";
10987 case PHY_ID_BCM5787: return "5787";
10553 case PHY_ID_BCM8002: return "8002/serdes"; 10988 case PHY_ID_BCM8002: return "8002/serdes";
10554 case 0: return "serdes"; 10989 case 0: return "serdes";
10555 default: return "unknown"; 10990 default: return "unknown";
@@ -10848,11 +11283,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
10848 tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; 11283 tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE;
10849 } 11284 }
10850 11285
10851 /* TSO is off by default, user can enable using ethtool. */ 11286 /* TSO is on by default on chips that support hardware TSO.
10852#if 0 11287 * Firmware TSO on older chips gives lower performance, so it
10853 if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) 11288 * is off by default, but can be enabled using ethtool.
11289 */
11290 if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
10854 dev->features |= NETIF_F_TSO; 11291 dev->features |= NETIF_F_TSO;
10855#endif
10856 11292
10857#endif 11293#endif
10858 11294
@@ -10896,7 +11332,11 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
10896 * checksumming. 11332 * checksumming.
10897 */ 11333 */
10898 if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) { 11334 if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) {
10899 dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; 11335 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
11336 dev->features |= NETIF_F_HW_CSUM;
11337 else
11338 dev->features |= NETIF_F_IP_CSUM;
11339 dev->features |= NETIF_F_SG;
10900 tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS; 11340 tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
10901 } else 11341 } else
10902 tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS; 11342 tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
@@ -10949,6 +11389,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
10949 (pdev->dma_mask == DMA_32BIT_MASK) ? 32 : 11389 (pdev->dma_mask == DMA_32BIT_MASK) ? 32 :
10950 (((u64) pdev->dma_mask == DMA_40BIT_MASK) ? 40 : 64)); 11390 (((u64) pdev->dma_mask == DMA_40BIT_MASK) ? 40 : 64));
10951 11391
11392 netif_carrier_off(tp->dev);
11393
10952 return 0; 11394 return 0;
10953 11395
10954err_out_iounmap: 11396err_out_iounmap:
@@ -11044,7 +11486,7 @@ static int tg3_resume(struct pci_dev *pdev)
11044 11486
11045 pci_restore_state(tp->pdev); 11487 pci_restore_state(tp->pdev);
11046 11488
11047 err = tg3_set_power_state(tp, 0); 11489 err = tg3_set_power_state(tp, PCI_D0);
11048 if (err) 11490 if (err)
11049 return err; 11491 return err;
11050 11492
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 7e3b613afb29..baa34c4721db 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -138,6 +138,7 @@
138#define ASIC_REV_5752 0x06 138#define ASIC_REV_5752 0x06
139#define ASIC_REV_5780 0x08 139#define ASIC_REV_5780 0x08
140#define ASIC_REV_5714 0x09 140#define ASIC_REV_5714 0x09
141#define ASIC_REV_5787 0x0b
141#define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8) 142#define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8)
142#define CHIPREV_5700_AX 0x70 143#define CHIPREV_5700_AX 0x70
143#define CHIPREV_5700_BX 0x71 144#define CHIPREV_5700_BX 0x71
@@ -1393,6 +1394,7 @@
1393#define GRC_MDI_CTRL 0x00006844 1394#define GRC_MDI_CTRL 0x00006844
1394#define GRC_SEEPROM_DELAY 0x00006848 1395#define GRC_SEEPROM_DELAY 0x00006848
1395/* 0x684c --> 0x6c00 unused */ 1396/* 0x684c --> 0x6c00 unused */
1397#define GRC_FASTBOOT_PC 0x00006894 /* 5752, 5755, 5787 */
1396 1398
1397/* 0x6c00 --> 0x7000 unused */ 1399/* 0x6c00 --> 0x7000 unused */
1398 1400
@@ -1436,6 +1438,13 @@
1436#define FLASH_5752VENDOR_ST_M45PE10 0x02400000 1438#define FLASH_5752VENDOR_ST_M45PE10 0x02400000
1437#define FLASH_5752VENDOR_ST_M45PE20 0x02400002 1439#define FLASH_5752VENDOR_ST_M45PE20 0x02400002
1438#define FLASH_5752VENDOR_ST_M45PE40 0x02400001 1440#define FLASH_5752VENDOR_ST_M45PE40 0x02400001
1441#define FLASH_5755VENDOR_ATMEL_FLASH_1 0x03400001
1442#define FLASH_5755VENDOR_ATMEL_FLASH_2 0x03400002
1443#define FLASH_5755VENDOR_ATMEL_FLASH_3 0x03400000
1444#define FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ 0x03000003
1445#define FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ 0x03000002
1446#define FLASH_5787VENDOR_MICRO_EEPROM_64KHZ 0x03000000
1447#define FLASH_5787VENDOR_MICRO_EEPROM_376KHZ 0x02000000
1439#define NVRAM_CFG1_5752PAGE_SIZE_MASK 0x70000000 1448#define NVRAM_CFG1_5752PAGE_SIZE_MASK 0x70000000
1440#define FLASH_5752PAGE_SIZE_256 0x00000000 1449#define FLASH_5752PAGE_SIZE_256 0x00000000
1441#define FLASH_5752PAGE_SIZE_512 0x10000000 1450#define FLASH_5752PAGE_SIZE_512 0x10000000
@@ -2185,7 +2194,7 @@ struct tg3 {
2185#define TG3_FLG2_PHY_SERDES 0x00002000 2194#define TG3_FLG2_PHY_SERDES 0x00002000
2186#define TG3_FLG2_CAPACITIVE_COUPLING 0x00004000 2195#define TG3_FLG2_CAPACITIVE_COUPLING 0x00004000
2187#define TG3_FLG2_FLASH 0x00008000 2196#define TG3_FLG2_FLASH 0x00008000
2188#define TG3_FLG2_HW_TSO 0x00010000 2197#define TG3_FLG2_HW_TSO_1 0x00010000
2189#define TG3_FLG2_SERDES_PREEMPHASIS 0x00020000 2198#define TG3_FLG2_SERDES_PREEMPHASIS 0x00020000
2190#define TG3_FLG2_5705_PLUS 0x00040000 2199#define TG3_FLG2_5705_PLUS 0x00040000
2191#define TG3_FLG2_5750_PLUS 0x00080000 2200#define TG3_FLG2_5750_PLUS 0x00080000
@@ -2198,6 +2207,9 @@ struct tg3 {
2198#define TG3_FLG2_PARALLEL_DETECT 0x01000000 2207#define TG3_FLG2_PARALLEL_DETECT 0x01000000
2199#define TG3_FLG2_ICH_WORKAROUND 0x02000000 2208#define TG3_FLG2_ICH_WORKAROUND 0x02000000
2200#define TG3_FLG2_5780_CLASS 0x04000000 2209#define TG3_FLG2_5780_CLASS 0x04000000
2210#define TG3_FLG2_HW_TSO_2 0x08000000
2211#define TG3_FLG2_HW_TSO (TG3_FLG2_HW_TSO_1 | TG3_FLG2_HW_TSO_2)
2212#define TG3_FLG2_1SHOT_MSI 0x10000000
2201 2213
2202 u32 split_mode_max_reqs; 2214 u32 split_mode_max_reqs;
2203#define SPLIT_MODE_5704_MAX_REQ 3 2215#define SPLIT_MODE_5704_MAX_REQ 3
@@ -2247,6 +2259,7 @@ struct tg3 {
2247#define PHY_ID_BCM5752 0x60008100 2259#define PHY_ID_BCM5752 0x60008100
2248#define PHY_ID_BCM5714 0x60008340 2260#define PHY_ID_BCM5714 0x60008340
2249#define PHY_ID_BCM5780 0x60008350 2261#define PHY_ID_BCM5780 0x60008350
2262#define PHY_ID_BCM5787 0xbc050ce0
2250#define PHY_ID_BCM8002 0x60010140 2263#define PHY_ID_BCM8002 0x60010140
2251#define PHY_ID_INVALID 0xffffffff 2264#define PHY_ID_INVALID 0xffffffff
2252#define PHY_ID_REV_MASK 0x0000000f 2265#define PHY_ID_REV_MASK 0x0000000f
@@ -2258,6 +2271,7 @@ struct tg3 {
2258 u32 led_ctrl; 2271 u32 led_ctrl;
2259 2272
2260 char board_part_number[24]; 2273 char board_part_number[24];
2274 char fw_ver[16];
2261 u32 nic_sram_data_cfg; 2275 u32 nic_sram_data_cfg;
2262 u32 pci_clock_ctrl; 2276 u32 pci_clock_ctrl;
2263 struct pci_dev *pdev_peer; 2277 struct pci_dev *pdev_peer;
@@ -2271,7 +2285,8 @@ struct tg3 {
2271 (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \ 2285 (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \
2272 (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \ 2286 (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \
2273 (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5714 || \ 2287 (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5714 || \
2274 (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM8002) 2288 (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM5787 || \
2289 (X) == PHY_ID_BCM8002)
2275 2290
2276 struct tg3_hw_stats *hw_stats; 2291 struct tg3_hw_stats *hw_stats;
2277 dma_addr_t stats_mapping; 2292 dma_addr_t stats_mapping;
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index db2c798ba89e..175ba13bce41 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -1495,8 +1495,7 @@ module_param(skip_pci_probe, bool, 0);
1495MODULE_LICENSE("GPL"); 1495MODULE_LICENSE("GPL");
1496 1496
1497 1497
1498int 1498int __init init_module( void )
1499init_module( void )
1500{ 1499{
1501 struct net_device *dev; 1500 struct net_device *dev;
1502 int err; 1501 int err;
diff --git a/include/asm-sparc/socket.h b/include/asm-sparc/socket.h
index 09575b608adb..4e0ce3a35ea9 100644
--- a/include/asm-sparc/socket.h
+++ b/include/asm-sparc/socket.h
@@ -47,7 +47,7 @@
47#define SO_TIMESTAMP 0x001d 47#define SO_TIMESTAMP 0x001d
48#define SCM_TIMESTAMP SO_TIMESTAMP 48#define SCM_TIMESTAMP SO_TIMESTAMP
49 49
50#define SO_PEERSEC 0x100e 50#define SO_PEERSEC 0x001e
51 51
52/* Security levels - as per NRL IPv6 - don't actually do anything */ 52/* Security levels - as per NRL IPv6 - don't actually do anything */
53#define SO_SECURITY_AUTHENTICATION 0x5001 53#define SO_SECURITY_AUTHENTICATION 0x5001
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index 088529f54965..676333b9fad0 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -18,7 +18,7 @@
18 * @dccph_seq - sequence number high or low order 24 bits, depends on dccph_x 18 * @dccph_seq - sequence number high or low order 24 bits, depends on dccph_x
19 */ 19 */
20struct dccp_hdr { 20struct dccp_hdr {
21 __u16 dccph_sport, 21 __be16 dccph_sport,
22 dccph_dport; 22 dccph_dport;
23 __u8 dccph_doff; 23 __u8 dccph_doff;
24#if defined(__LITTLE_ENDIAN_BITFIELD) 24#if defined(__LITTLE_ENDIAN_BITFIELD)
@@ -32,18 +32,18 @@ struct dccp_hdr {
32#endif 32#endif
33 __u16 dccph_checksum; 33 __u16 dccph_checksum;
34#if defined(__LITTLE_ENDIAN_BITFIELD) 34#if defined(__LITTLE_ENDIAN_BITFIELD)
35 __u32 dccph_x:1, 35 __u8 dccph_x:1,
36 dccph_type:4, 36 dccph_type:4,
37 dccph_reserved:3, 37 dccph_reserved:3;
38 dccph_seq:24;
39#elif defined(__BIG_ENDIAN_BITFIELD) 38#elif defined(__BIG_ENDIAN_BITFIELD)
40 __u32 dccph_reserved:3, 39 __u8 dccph_reserved:3,
41 dccph_type:4, 40 dccph_type:4,
42 dccph_x:1, 41 dccph_x:1;
43 dccph_seq:24;
44#else 42#else
45#error "Adjust your <asm/byteorder.h> defines" 43#error "Adjust your <asm/byteorder.h> defines"
46#endif 44#endif
45 __u8 dccph_seq2;
46 __be16 dccph_seq;
47}; 47};
48 48
49/** 49/**
@@ -52,7 +52,7 @@ struct dccp_hdr {
52 * @dccph_seq_low - low 24 bits of a 48 bit seq packet 52 * @dccph_seq_low - low 24 bits of a 48 bit seq packet
53 */ 53 */
54struct dccp_hdr_ext { 54struct dccp_hdr_ext {
55 __u32 dccph_seq_low; 55 __be32 dccph_seq_low;
56}; 56};
57 57
58/** 58/**
@@ -62,7 +62,7 @@ struct dccp_hdr_ext {
62 * @dccph_req_options - list of options (must be a multiple of 32 bits 62 * @dccph_req_options - list of options (must be a multiple of 32 bits
63 */ 63 */
64struct dccp_hdr_request { 64struct dccp_hdr_request {
65 __u32 dccph_req_service; 65 __be32 dccph_req_service;
66}; 66};
67/** 67/**
68 * struct dccp_hdr_ack_bits - acknowledgment bits common to most packets 68 * struct dccp_hdr_ack_bits - acknowledgment bits common to most packets
@@ -71,9 +71,9 @@ struct dccp_hdr_request {
71 * @dccph_resp_ack_nr_low - 48 bit ack number low order bits, contains GSR 71 * @dccph_resp_ack_nr_low - 48 bit ack number low order bits, contains GSR
72 */ 72 */
73struct dccp_hdr_ack_bits { 73struct dccp_hdr_ack_bits {
74 __u32 dccph_reserved1:8, 74 __be16 dccph_reserved1;
75 dccph_ack_nr_high:24; 75 __be16 dccph_ack_nr_high;
76 __u32 dccph_ack_nr_low; 76 __be32 dccph_ack_nr_low;
77}; 77};
78/** 78/**
79 * struct dccp_hdr_response - Conection initiation response header 79 * struct dccp_hdr_response - Conection initiation response header
@@ -85,7 +85,7 @@ struct dccp_hdr_ack_bits {
85 */ 85 */
86struct dccp_hdr_response { 86struct dccp_hdr_response {
87 struct dccp_hdr_ack_bits dccph_resp_ack; 87 struct dccp_hdr_ack_bits dccph_resp_ack;
88 __u32 dccph_resp_service; 88 __be32 dccph_resp_service;
89}; 89};
90 90
91/** 91/**
@@ -154,6 +154,10 @@ enum {
154 DCCPO_MANDATORY = 1, 154 DCCPO_MANDATORY = 1,
155 DCCPO_MIN_RESERVED = 3, 155 DCCPO_MIN_RESERVED = 3,
156 DCCPO_MAX_RESERVED = 31, 156 DCCPO_MAX_RESERVED = 31,
157 DCCPO_CHANGE_L = 32,
158 DCCPO_CONFIRM_L = 33,
159 DCCPO_CHANGE_R = 34,
160 DCCPO_CONFIRM_R = 35,
157 DCCPO_NDP_COUNT = 37, 161 DCCPO_NDP_COUNT = 37,
158 DCCPO_ACK_VECTOR_0 = 38, 162 DCCPO_ACK_VECTOR_0 = 38,
159 DCCPO_ACK_VECTOR_1 = 39, 163 DCCPO_ACK_VECTOR_1 = 39,
@@ -168,7 +172,9 @@ enum {
168/* DCCP features */ 172/* DCCP features */
169enum { 173enum {
170 DCCPF_RESERVED = 0, 174 DCCPF_RESERVED = 0,
175 DCCPF_CCID = 1,
171 DCCPF_SEQUENCE_WINDOW = 3, 176 DCCPF_SEQUENCE_WINDOW = 3,
177 DCCPF_ACK_RATIO = 5,
172 DCCPF_SEND_ACK_VECTOR = 6, 178 DCCPF_SEND_ACK_VECTOR = 6,
173 DCCPF_SEND_NDP_COUNT = 7, 179 DCCPF_SEND_NDP_COUNT = 7,
174 /* 10-127 reserved */ 180 /* 10-127 reserved */
@@ -176,9 +182,18 @@ enum {
176 DCCPF_MAX_CCID_SPECIFIC = 255, 182 DCCPF_MAX_CCID_SPECIFIC = 255,
177}; 183};
178 184
185/* this structure is argument to DCCP_SOCKOPT_CHANGE_X */
186struct dccp_so_feat {
187 __u8 dccpsf_feat;
188 __u8 *dccpsf_val;
189 __u8 dccpsf_len;
190};
191
179/* DCCP socket options */ 192/* DCCP socket options */
180#define DCCP_SOCKOPT_PACKET_SIZE 1 193#define DCCP_SOCKOPT_PACKET_SIZE 1
181#define DCCP_SOCKOPT_SERVICE 2 194#define DCCP_SOCKOPT_SERVICE 2
195#define DCCP_SOCKOPT_CHANGE_L 3
196#define DCCP_SOCKOPT_CHANGE_R 4
182#define DCCP_SOCKOPT_CCID_RX_INFO 128 197#define DCCP_SOCKOPT_CCID_RX_INFO 128
183#define DCCP_SOCKOPT_CCID_TX_INFO 192 198#define DCCP_SOCKOPT_CCID_TX_INFO 192
184 199
@@ -254,16 +269,12 @@ static inline unsigned int dccp_basic_hdr_len(const struct sk_buff *skb)
254static inline __u64 dccp_hdr_seq(const struct sk_buff *skb) 269static inline __u64 dccp_hdr_seq(const struct sk_buff *skb)
255{ 270{
256 const struct dccp_hdr *dh = dccp_hdr(skb); 271 const struct dccp_hdr *dh = dccp_hdr(skb);
257#if defined(__LITTLE_ENDIAN_BITFIELD) 272 __u64 seq_nr = ntohs(dh->dccph_seq);
258 __u64 seq_nr = ntohl(dh->dccph_seq << 8);
259#elif defined(__BIG_ENDIAN_BITFIELD)
260 __u64 seq_nr = ntohl(dh->dccph_seq);
261#else
262#error "Adjust your <asm/byteorder.h> defines"
263#endif
264 273
265 if (dh->dccph_x != 0) 274 if (dh->dccph_x != 0)
266 seq_nr = (seq_nr << 32) + ntohl(dccp_hdrx(skb)->dccph_seq_low); 275 seq_nr = (seq_nr << 32) + ntohl(dccp_hdrx(skb)->dccph_seq_low);
276 else
277 seq_nr += (u32)dh->dccph_seq2 << 16;
267 278
268 return seq_nr; 279 return seq_nr;
269} 280}
@@ -281,13 +292,7 @@ static inline struct dccp_hdr_ack_bits *dccp_hdr_ack_bits(const struct sk_buff *
281static inline u64 dccp_hdr_ack_seq(const struct sk_buff *skb) 292static inline u64 dccp_hdr_ack_seq(const struct sk_buff *skb)
282{ 293{
283 const struct dccp_hdr_ack_bits *dhack = dccp_hdr_ack_bits(skb); 294 const struct dccp_hdr_ack_bits *dhack = dccp_hdr_ack_bits(skb);
284#if defined(__LITTLE_ENDIAN_BITFIELD) 295 return ((u64)ntohs(dhack->dccph_ack_nr_high) << 32) + ntohl(dhack->dccph_ack_nr_low);
285 return (((u64)ntohl(dhack->dccph_ack_nr_high << 8)) << 32) + ntohl(dhack->dccph_ack_nr_low);
286#elif defined(__BIG_ENDIAN_BITFIELD)
287 return (((u64)ntohl(dhack->dccph_ack_nr_high)) << 32) + ntohl(dhack->dccph_ack_nr_low);
288#else
289#error "Adjust your <asm/byteorder.h> defines"
290#endif
291} 296}
292 297
293static inline struct dccp_hdr_response *dccp_hdr_response(struct sk_buff *skb) 298static inline struct dccp_hdr_response *dccp_hdr_response(struct sk_buff *skb)
@@ -314,38 +319,60 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb)
314 319
315/* initial values for each feature */ 320/* initial values for each feature */
316#define DCCPF_INITIAL_SEQUENCE_WINDOW 100 321#define DCCPF_INITIAL_SEQUENCE_WINDOW 100
317/* FIXME: for now we're using CCID 3 (TFRC) */ 322#define DCCPF_INITIAL_ACK_RATIO 2
318#define DCCPF_INITIAL_CCID 3 323#define DCCPF_INITIAL_CCID 2
319#define DCCPF_INITIAL_SEND_ACK_VECTOR 0 324#define DCCPF_INITIAL_SEND_ACK_VECTOR 1
320/* FIXME: for now we're default to 1 but it should really be 0 */ 325/* FIXME: for now we're default to 1 but it should really be 0 */
321#define DCCPF_INITIAL_SEND_NDP_COUNT 1 326#define DCCPF_INITIAL_SEND_NDP_COUNT 1
322 327
323#define DCCP_NDP_LIMIT 0xFFFFFF 328#define DCCP_NDP_LIMIT 0xFFFFFF
324 329
325/** 330/**
326 * struct dccp_options - option values for a DCCP connection 331 * struct dccp_minisock - Minimal DCCP connection representation
327 * @dccpo_sequence_window - Sequence Window Feature (section 7.5.2) 332 *
328 * @dccpo_ccid - Congestion Control Id (CCID) (section 10) 333 * Will be used to pass the state from dccp_request_sock to dccp_sock.
329 * @dccpo_send_ack_vector - Send Ack Vector Feature (section 11.5) 334 *
330 * @dccpo_send_ndp_count - Send NDP Count Feature (7.7.2) 335 * @dccpms_sequence_window - Sequence Window Feature (section 7.5.2)
336 * @dccpms_ccid - Congestion Control Id (CCID) (section 10)
337 * @dccpms_send_ack_vector - Send Ack Vector Feature (section 11.5)
338 * @dccpms_send_ndp_count - Send NDP Count Feature (7.7.2)
331 */ 339 */
332struct dccp_options { 340struct dccp_minisock {
333 __u64 dccpo_sequence_window; 341 __u64 dccpms_sequence_window;
334 __u8 dccpo_rx_ccid; 342 __u8 dccpms_rx_ccid;
335 __u8 dccpo_tx_ccid; 343 __u8 dccpms_tx_ccid;
336 __u8 dccpo_send_ack_vector; 344 __u8 dccpms_send_ack_vector;
337 __u8 dccpo_send_ndp_count; 345 __u8 dccpms_send_ndp_count;
346 __u8 dccpms_ack_ratio;
347 struct list_head dccpms_pending;
348 struct list_head dccpms_conf;
349};
350
351struct dccp_opt_conf {
352 __u8 *dccpoc_val;
353 __u8 dccpoc_len;
354};
355
356struct dccp_opt_pend {
357 struct list_head dccpop_node;
358 __u8 dccpop_type;
359 __u8 dccpop_feat;
360 __u8 *dccpop_val;
361 __u8 dccpop_len;
362 int dccpop_conf;
363 struct dccp_opt_conf *dccpop_sc;
338}; 364};
339 365
340extern void __dccp_options_init(struct dccp_options *dccpo); 366extern void __dccp_minisock_init(struct dccp_minisock *dmsk);
341extern void dccp_options_init(struct dccp_options *dccpo); 367extern void dccp_minisock_init(struct dccp_minisock *dmsk);
368
342extern int dccp_parse_options(struct sock *sk, struct sk_buff *skb); 369extern int dccp_parse_options(struct sock *sk, struct sk_buff *skb);
343 370
344struct dccp_request_sock { 371struct dccp_request_sock {
345 struct inet_request_sock dreq_inet_rsk; 372 struct inet_request_sock dreq_inet_rsk;
346 __u64 dreq_iss; 373 __u64 dreq_iss;
347 __u64 dreq_isr; 374 __u64 dreq_isr;
348 __u32 dreq_service; 375 __be32 dreq_service;
349}; 376};
350 377
351static inline struct dccp_request_sock *dccp_rsk(const struct request_sock *req) 378static inline struct dccp_request_sock *dccp_rsk(const struct request_sock *req)
@@ -373,13 +400,13 @@ enum dccp_role {
373 400
374struct dccp_service_list { 401struct dccp_service_list {
375 __u32 dccpsl_nr; 402 __u32 dccpsl_nr;
376 __u32 dccpsl_list[0]; 403 __be32 dccpsl_list[0];
377}; 404};
378 405
379#define DCCP_SERVICE_INVALID_VALUE htonl((__u32)-1) 406#define DCCP_SERVICE_INVALID_VALUE htonl((__u32)-1)
380 407
381static inline int dccp_list_has_service(const struct dccp_service_list *sl, 408static inline int dccp_list_has_service(const struct dccp_service_list *sl,
382 const u32 service) 409 const __be32 service)
383{ 410{
384 if (likely(sl != NULL)) { 411 if (likely(sl != NULL)) {
385 u32 i = sl->dccpsl_nr; 412 u32 i = sl->dccpsl_nr;
@@ -425,17 +452,17 @@ struct dccp_sock {
425 __u64 dccps_gss; 452 __u64 dccps_gss;
426 __u64 dccps_gsr; 453 __u64 dccps_gsr;
427 __u64 dccps_gar; 454 __u64 dccps_gar;
428 __u32 dccps_service; 455 __be32 dccps_service;
429 struct dccp_service_list *dccps_service_list; 456 struct dccp_service_list *dccps_service_list;
430 struct timeval dccps_timestamp_time; 457 struct timeval dccps_timestamp_time;
431 __u32 dccps_timestamp_echo; 458 __u32 dccps_timestamp_echo;
432 __u32 dccps_packet_size; 459 __u32 dccps_packet_size;
460 __u16 dccps_l_ack_ratio;
461 __u16 dccps_r_ack_ratio;
433 unsigned long dccps_ndp_count; 462 unsigned long dccps_ndp_count;
434 __u32 dccps_mss_cache; 463 __u32 dccps_mss_cache;
435 struct dccp_options dccps_options; 464 struct dccp_minisock dccps_minisock;
436 struct dccp_ackvec *dccps_hc_rx_ackvec; 465 struct dccp_ackvec *dccps_hc_rx_ackvec;
437 void *dccps_hc_rx_ccid_private;
438 void *dccps_hc_tx_ccid_private;
439 struct ccid *dccps_hc_rx_ccid; 466 struct ccid *dccps_hc_rx_ccid;
440 struct ccid *dccps_hc_tx_ccid; 467 struct ccid *dccps_hc_tx_ccid;
441 struct dccp_options_received dccps_options_received; 468 struct dccp_options_received dccps_options_received;
@@ -450,6 +477,11 @@ static inline struct dccp_sock *dccp_sk(const struct sock *sk)
450 return (struct dccp_sock *)sk; 477 return (struct dccp_sock *)sk;
451} 478}
452 479
480static inline struct dccp_minisock *dccp_msk(const struct sock *sk)
481{
482 return (struct dccp_minisock *)&dccp_sk(sk)->dccps_minisock;
483}
484
453static inline int dccp_service_not_initialized(const struct sock *sk) 485static inline int dccp_service_not_initialized(const struct sock *sk)
454{ 486{
455 return dccp_sk(sk)->dccps_service == DCCP_SERVICE_INVALID_VALUE; 487 return dccp_sk(sk)->dccps_service == DCCP_SERVICE_INVALID_VALUE;
diff --git a/include/linux/dn.h b/include/linux/dn.h
index 782cae49e64c..10b6a6fd5837 100644
--- a/include/linux/dn.h
+++ b/include/linux/dn.h
@@ -71,17 +71,17 @@
71 71
72struct dn_naddr 72struct dn_naddr
73{ 73{
74 unsigned short a_len; 74 __le16 a_len;
75 unsigned char a_addr[DN_MAXADDL]; 75 __u8 a_addr[DN_MAXADDL]; /* Two bytes little endian */
76}; 76};
77 77
78struct sockaddr_dn 78struct sockaddr_dn
79{ 79{
80 unsigned short sdn_family; 80 __u16 sdn_family;
81 unsigned char sdn_flags; 81 __u8 sdn_flags;
82 unsigned char sdn_objnum; 82 __u8 sdn_objnum;
83 unsigned short sdn_objnamel; 83 __le16 sdn_objnamel;
84 unsigned char sdn_objname[DN_MAXOBJL]; 84 __u8 sdn_objname[DN_MAXOBJL];
85 struct dn_naddr sdn_add; 85 struct dn_naddr sdn_add;
86}; 86};
87#define sdn_nodeaddrl sdn_add.a_len /* Node address length */ 87#define sdn_nodeaddrl sdn_add.a_len /* Node address length */
@@ -93,38 +93,38 @@ struct sockaddr_dn
93 * DECnet set/get DSO_CONDATA, DSO_DISDATA (optional data) structure 93 * DECnet set/get DSO_CONDATA, DSO_DISDATA (optional data) structure
94 */ 94 */
95struct optdata_dn { 95struct optdata_dn {
96 unsigned short opt_status; /* Extended status return */ 96 __le16 opt_status; /* Extended status return */
97#define opt_sts opt_status 97#define opt_sts opt_status
98 unsigned short opt_optl; /* Length of user data */ 98 __le16 opt_optl; /* Length of user data */
99 unsigned char opt_data[16]; /* User data */ 99 __u8 opt_data[16]; /* User data */
100}; 100};
101 101
102struct accessdata_dn 102struct accessdata_dn
103{ 103{
104 unsigned char acc_accl; 104 __u8 acc_accl;
105 unsigned char acc_acc[DN_MAXACCL]; 105 __u8 acc_acc[DN_MAXACCL];
106 unsigned char acc_passl; 106 __u8 acc_passl;
107 unsigned char acc_pass[DN_MAXACCL]; 107 __u8 acc_pass[DN_MAXACCL];
108 unsigned char acc_userl; 108 __u8 acc_userl;
109 unsigned char acc_user[DN_MAXACCL]; 109 __u8 acc_user[DN_MAXACCL];
110}; 110};
111 111
112/* 112/*
113 * DECnet logical link information structure 113 * DECnet logical link information structure
114 */ 114 */
115struct linkinfo_dn { 115struct linkinfo_dn {
116 unsigned short idn_segsize; /* Segment size for link */ 116 __le16 idn_segsize; /* Segment size for link */
117 unsigned char idn_linkstate; /* Logical link state */ 117 __u8 idn_linkstate; /* Logical link state */
118}; 118};
119 119
120/* 120/*
121 * Ethernet address format (for DECnet) 121 * Ethernet address format (for DECnet)
122 */ 122 */
123union etheraddress { 123union etheraddress {
124 unsigned char dne_addr[6]; /* Full ethernet address */ 124 __u8 dne_addr[6]; /* Full ethernet address */
125 struct { 125 struct {
126 unsigned char dne_hiord[4]; /* DECnet HIORD prefix */ 126 __u8 dne_hiord[4]; /* DECnet HIORD prefix */
127 unsigned char dne_nodeaddr[2]; /* DECnet node address */ 127 __u8 dne_nodeaddr[2]; /* DECnet node address */
128 } dne_remote; 128 } dne_remote;
129}; 129};
130 130
@@ -133,7 +133,7 @@ union etheraddress {
133 * DECnet physical socket address format 133 * DECnet physical socket address format
134 */ 134 */
135struct dn_addr { 135struct dn_addr {
136 unsigned short dna_family; /* AF_DECnet */ 136 __le16 dna_family; /* AF_DECnet */
137 union etheraddress dna_netaddr; /* DECnet ethernet address */ 137 union etheraddress dna_netaddr; /* DECnet ethernet address */
138}; 138};
139 139
diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h
index 0cf6c8b12caf..c771a7db9871 100644
--- a/include/linux/icmpv6.h
+++ b/include/linux/icmpv6.h
@@ -40,14 +40,16 @@ struct icmp6hdr {
40 struct icmpv6_nd_ra { 40 struct icmpv6_nd_ra {
41 __u8 hop_limit; 41 __u8 hop_limit;
42#if defined(__LITTLE_ENDIAN_BITFIELD) 42#if defined(__LITTLE_ENDIAN_BITFIELD)
43 __u8 reserved:6, 43 __u8 reserved:4,
44 router_pref:2,
44 other:1, 45 other:1,
45 managed:1; 46 managed:1;
46 47
47#elif defined(__BIG_ENDIAN_BITFIELD) 48#elif defined(__BIG_ENDIAN_BITFIELD)
48 __u8 managed:1, 49 __u8 managed:1,
49 other:1, 50 other:1,
50 reserved:6; 51 router_pref:2,
52 reserved:4;
51#else 53#else
52#error "Please fix <asm/byteorder.h>" 54#error "Please fix <asm/byteorder.h>"
53#endif 55#endif
@@ -70,8 +72,13 @@ struct icmp6hdr {
70#define icmp6_addrconf_managed icmp6_dataun.u_nd_ra.managed 72#define icmp6_addrconf_managed icmp6_dataun.u_nd_ra.managed
71#define icmp6_addrconf_other icmp6_dataun.u_nd_ra.other 73#define icmp6_addrconf_other icmp6_dataun.u_nd_ra.other
72#define icmp6_rt_lifetime icmp6_dataun.u_nd_ra.rt_lifetime 74#define icmp6_rt_lifetime icmp6_dataun.u_nd_ra.rt_lifetime
75#define icmp6_router_pref icmp6_dataun.u_nd_ra.router_pref
73}; 76};
74 77
78#define ICMPV6_ROUTER_PREF_LOW 0x3
79#define ICMPV6_ROUTER_PREF_MEDIUM 0x0
80#define ICMPV6_ROUTER_PREF_HIGH 0x1
81#define ICMPV6_ROUTER_PREF_INVALID 0x2
75 82
76#define ICMPV6_DEST_UNREACH 1 83#define ICMPV6_DEST_UNREACH 1
77#define ICMPV6_PKT_TOOBIG 2 84#define ICMPV6_PKT_TOOBIG 2
diff --git a/include/linux/if.h b/include/linux/if.h
index 12c6f6d157c3..374e20ad8b0d 100644
--- a/include/linux/if.h
+++ b/include/linux/if.h
@@ -33,7 +33,7 @@
33#define IFF_LOOPBACK 0x8 /* is a loopback net */ 33#define IFF_LOOPBACK 0x8 /* is a loopback net */
34#define IFF_POINTOPOINT 0x10 /* interface is has p-p link */ 34#define IFF_POINTOPOINT 0x10 /* interface is has p-p link */
35#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */ 35#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */
36#define IFF_RUNNING 0x40 /* interface running and carrier ok */ 36#define IFF_RUNNING 0x40 /* interface RFC2863 OPER_UP */
37#define IFF_NOARP 0x80 /* no ARP protocol */ 37#define IFF_NOARP 0x80 /* no ARP protocol */
38#define IFF_PROMISC 0x100 /* receive all packets */ 38#define IFF_PROMISC 0x100 /* receive all packets */
39#define IFF_ALLMULTI 0x200 /* receive all multicast packets*/ 39#define IFF_ALLMULTI 0x200 /* receive all multicast packets*/
@@ -43,12 +43,16 @@
43 43
44#define IFF_MULTICAST 0x1000 /* Supports multicast */ 44#define IFF_MULTICAST 0x1000 /* Supports multicast */
45 45
46#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_MASTER|IFF_SLAVE|IFF_RUNNING)
47
48#define IFF_PORTSEL 0x2000 /* can set media type */ 46#define IFF_PORTSEL 0x2000 /* can set media type */
49#define IFF_AUTOMEDIA 0x4000 /* auto media select active */ 47#define IFF_AUTOMEDIA 0x4000 /* auto media select active */
50#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/ 48#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/
51 49
50#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */
51#define IFF_DORMANT 0x20000 /* driver signals dormant */
52
53#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|\
54 IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT)
55
52/* Private (from user) interface flags (netdevice->priv_flags). */ 56/* Private (from user) interface flags (netdevice->priv_flags). */
53#define IFF_802_1Q_VLAN 0x1 /* 802.1Q VLAN device. */ 57#define IFF_802_1Q_VLAN 0x1 /* 802.1Q VLAN device. */
54#define IFF_EBRIDGE 0x2 /* Ethernet bridging device. */ 58#define IFF_EBRIDGE 0x2 /* Ethernet bridging device. */
@@ -83,6 +87,22 @@
83#define IF_PROTO_FR_ETH_PVC 0x200B 87#define IF_PROTO_FR_ETH_PVC 0x200B
84#define IF_PROTO_RAW 0x200C /* RAW Socket */ 88#define IF_PROTO_RAW 0x200C /* RAW Socket */
85 89
90/* RFC 2863 operational status */
91enum {
92 IF_OPER_UNKNOWN,
93 IF_OPER_NOTPRESENT,
94 IF_OPER_DOWN,
95 IF_OPER_LOWERLAYERDOWN,
96 IF_OPER_TESTING,
97 IF_OPER_DORMANT,
98 IF_OPER_UP,
99};
100
101/* link modes */
102enum {
103 IF_LINK_MODE_DEFAULT,
104 IF_LINK_MODE_DORMANT, /* limit upward transition to dormant */
105};
86 106
87/* 107/*
88 * Device mapping structure. I'd just gone off and designed a 108 * Device mapping structure. I'd just gone off and designed a
diff --git a/include/linux/in.h b/include/linux/in.h
index ba355384016a..94f557fa4636 100644
--- a/include/linux/in.h
+++ b/include/linux/in.h
@@ -72,6 +72,7 @@ struct in_addr {
72#define IP_FREEBIND 15 72#define IP_FREEBIND 15
73#define IP_IPSEC_POLICY 16 73#define IP_IPSEC_POLICY 16
74#define IP_XFRM_POLICY 17 74#define IP_XFRM_POLICY 17
75#define IP_PASSSEC 18
75 76
76/* BSD compatibility */ 77/* BSD compatibility */
77#define IP_RECVRETOPTS IP_RETOPTS 78#define IP_RECVRETOPTS IP_RETOPTS
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index fd7af86151b1..92297ff24e85 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -25,6 +25,7 @@ struct ipv4_devconf
25 int arp_filter; 25 int arp_filter;
26 int arp_announce; 26 int arp_announce;
27 int arp_ignore; 27 int arp_ignore;
28 int arp_accept;
28 int medium_id; 29 int medium_id;
29 int no_xfrm; 30 int no_xfrm;
30 int no_policy; 31 int no_policy;
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 9c8f4c9ed429..1263d8cb3c18 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -145,6 +145,15 @@ struct ipv6_devconf {
145 __s32 max_desync_factor; 145 __s32 max_desync_factor;
146#endif 146#endif
147 __s32 max_addresses; 147 __s32 max_addresses;
148 __s32 accept_ra_defrtr;
149 __s32 accept_ra_pinfo;
150#ifdef CONFIG_IPV6_ROUTER_PREF
151 __s32 accept_ra_rtr_pref;
152 __s32 rtr_probe_interval;
153#ifdef CONFIG_IPV6_ROUTE_INFO
154 __s32 accept_ra_rt_info_max_plen;
155#endif
156#endif
148 void *sysctl; 157 void *sysctl;
149}; 158};
150 159
@@ -167,6 +176,11 @@ enum {
167 DEVCONF_MAX_DESYNC_FACTOR, 176 DEVCONF_MAX_DESYNC_FACTOR,
168 DEVCONF_MAX_ADDRESSES, 177 DEVCONF_MAX_ADDRESSES,
169 DEVCONF_FORCE_MLD_VERSION, 178 DEVCONF_FORCE_MLD_VERSION,
179 DEVCONF_ACCEPT_RA_DEFRTR,
180 DEVCONF_ACCEPT_RA_PINFO,
181 DEVCONF_ACCEPT_RA_RTR_PREF,
182 DEVCONF_RTR_PROBE_INTERVAL,
183 DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN,
170 DEVCONF_MAX 184 DEVCONF_MAX
171}; 185};
172 186
diff --git a/include/linux/ipv6_route.h b/include/linux/ipv6_route.h
index d7c41d1d706a..b323ff577967 100644
--- a/include/linux/ipv6_route.h
+++ b/include/linux/ipv6_route.h
@@ -23,12 +23,22 @@
23#define RTF_NONEXTHOP 0x00200000 /* route with no nexthop */ 23#define RTF_NONEXTHOP 0x00200000 /* route with no nexthop */
24#define RTF_EXPIRES 0x00400000 24#define RTF_EXPIRES 0x00400000
25 25
26#define RTF_ROUTEINFO 0x00800000 /* route information - RA */
27
26#define RTF_CACHE 0x01000000 /* cache entry */ 28#define RTF_CACHE 0x01000000 /* cache entry */
27#define RTF_FLOW 0x02000000 /* flow significant route */ 29#define RTF_FLOW 0x02000000 /* flow significant route */
28#define RTF_POLICY 0x04000000 /* policy route */ 30#define RTF_POLICY 0x04000000 /* policy route */
29 31
32#define RTF_PREF(pref) ((pref) << 27)
33#define RTF_PREF_MASK 0x18000000
34
30#define RTF_LOCAL 0x80000000 35#define RTF_LOCAL 0x80000000
31 36
37#ifdef __KERNEL__
38#define IPV6_EXTRACT_PREF(flag) (((flag) & RTF_PREF_MASK) >> 27)
39#define IPV6_DECODE_PREF(pref) ((pref) ^ 2) /* 1:low,2:med,3:high */
40#endif
41
32struct in6_rtmsg { 42struct in6_rtmsg {
33 struct in6_addr rtmsg_dst; 43 struct in6_addr rtmsg_dst;
34 struct in6_addr rtmsg_src; 44 struct in6_addr rtmsg_src;
diff --git a/include/linux/irda.h b/include/linux/irda.h
index 95dee174cdc5..09d8f105a5a8 100644
--- a/include/linux/irda.h
+++ b/include/linux/irda.h
@@ -76,6 +76,7 @@ typedef enum {
76 IRDA_MCP2120_DONGLE = 9, 76 IRDA_MCP2120_DONGLE = 9,
77 IRDA_ACT200L_DONGLE = 10, 77 IRDA_ACT200L_DONGLE = 10,
78 IRDA_MA600_DONGLE = 11, 78 IRDA_MA600_DONGLE = 11,
79 IRDA_TOIM3232_DONGLE = 12,
79} IRDA_DONGLE; 80} IRDA_DONGLE;
80 81
81/* Protocol types to be used for SOCK_DGRAM */ 82/* Protocol types to be used for SOCK_DGRAM */
diff --git a/include/linux/list.h b/include/linux/list.h
index 47208bd99f9e..67258b47e9ca 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -411,6 +411,17 @@ static inline void list_splice_init(struct list_head *list,
411 pos = list_entry(pos->member.next, typeof(*pos), member)) 411 pos = list_entry(pos->member.next, typeof(*pos), member))
412 412
413/** 413/**
414 * list_for_each_entry_from - iterate over list of given type
415 * continuing from existing point
416 * @pos: the type * to use as a loop counter.
417 * @head: the head for your list.
418 * @member: the name of the list_struct within the struct.
419 */
420#define list_for_each_entry_from(pos, head, member) \
421 for (; prefetch(pos->member.next), &pos->member != (head); \
422 pos = list_entry(pos->member.next, typeof(*pos), member))
423
424/**
414 * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry 425 * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
415 * @pos: the type * to use as a loop counter. 426 * @pos: the type * to use as a loop counter.
416 * @n: another type * to use as temporary storage 427 * @n: another type * to use as temporary storage
@@ -438,6 +449,19 @@ static inline void list_splice_init(struct list_head *list,
438 pos = n, n = list_entry(n->member.next, typeof(*n), member)) 449 pos = n, n = list_entry(n->member.next, typeof(*n), member))
439 450
440/** 451/**
452 * list_for_each_entry_safe_from - iterate over list of given type
453 * from existing point safe against removal of list entry
454 * @pos: the type * to use as a loop counter.
455 * @n: another type * to use as temporary storage
456 * @head: the head for your list.
457 * @member: the name of the list_struct within the struct.
458 */
459#define list_for_each_entry_safe_from(pos, n, head, member) \
460 for (n = list_entry(pos->member.next, typeof(*pos), member); \
461 &pos->member != (head); \
462 pos = n, n = list_entry(n->member.next, typeof(*n), member))
463
464/**
441 * list_for_each_entry_safe_reverse - iterate backwards over list of given type safe against 465 * list_for_each_entry_safe_reverse - iterate backwards over list of given type safe against
442 * removal of list entry 466 * removal of list entry
443 * @pos: the type * to use as a loop counter. 467 * @pos: the type * to use as a loop counter.
diff --git a/include/linux/net.h b/include/linux/net.h
index 28195a2d8ff0..152fa6551fd8 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -149,6 +149,10 @@ struct proto_ops {
149 int optname, char __user *optval, int optlen); 149 int optname, char __user *optval, int optlen);
150 int (*getsockopt)(struct socket *sock, int level, 150 int (*getsockopt)(struct socket *sock, int level,
151 int optname, char __user *optval, int __user *optlen); 151 int optname, char __user *optval, int __user *optlen);
152 int (*compat_setsockopt)(struct socket *sock, int level,
153 int optname, char __user *optval, int optlen);
154 int (*compat_getsockopt)(struct socket *sock, int level,
155 int optname, char __user *optval, int __user *optlen);
152 int (*sendmsg) (struct kiocb *iocb, struct socket *sock, 156 int (*sendmsg) (struct kiocb *iocb, struct socket *sock,
153 struct msghdr *m, size_t total_len); 157 struct msghdr *m, size_t total_len);
154 int (*recvmsg) (struct kiocb *iocb, struct socket *sock, 158 int (*recvmsg) (struct kiocb *iocb, struct socket *sock,
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 7fda03d338d1..950dc55e5192 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -230,7 +230,8 @@ enum netdev_state_t
230 __LINK_STATE_SCHED, 230 __LINK_STATE_SCHED,
231 __LINK_STATE_NOCARRIER, 231 __LINK_STATE_NOCARRIER,
232 __LINK_STATE_RX_SCHED, 232 __LINK_STATE_RX_SCHED,
233 __LINK_STATE_LINKWATCH_PENDING 233 __LINK_STATE_LINKWATCH_PENDING,
234 __LINK_STATE_DORMANT,
234}; 235};
235 236
236 237
@@ -335,11 +336,14 @@ struct net_device
335 */ 336 */
336 337
337 338
338 unsigned short flags; /* interface flags (a la BSD) */ 339 unsigned int flags; /* interface flags (a la BSD) */
339 unsigned short gflags; 340 unsigned short gflags;
340 unsigned short priv_flags; /* Like 'flags' but invisible to userspace. */ 341 unsigned short priv_flags; /* Like 'flags' but invisible to userspace. */
341 unsigned short padded; /* How much padding added by alloc_netdev() */ 342 unsigned short padded; /* How much padding added by alloc_netdev() */
342 343
344 unsigned char operstate; /* RFC2863 operstate */
345 unsigned char link_mode; /* mapping policy to operstate */
346
343 unsigned mtu; /* interface MTU value */ 347 unsigned mtu; /* interface MTU value */
344 unsigned short type; /* interface hardware type */ 348 unsigned short type; /* interface hardware type */
345 unsigned short hard_header_len; /* hardware hdr length */ 349 unsigned short hard_header_len; /* hardware hdr length */
@@ -708,12 +712,18 @@ static inline void dev_put(struct net_device *dev)
708 atomic_dec(&dev->refcnt); 712 atomic_dec(&dev->refcnt);
709} 713}
710 714
711#define __dev_put(dev) atomic_dec(&(dev)->refcnt) 715static inline void dev_hold(struct net_device *dev)
712#define dev_hold(dev) atomic_inc(&(dev)->refcnt) 716{
717 atomic_inc(&dev->refcnt);
718}
713 719
714/* Carrier loss detection, dial on demand. The functions netif_carrier_on 720/* Carrier loss detection, dial on demand. The functions netif_carrier_on
715 * and _off may be called from IRQ context, but it is caller 721 * and _off may be called from IRQ context, but it is caller
716 * who is responsible for serialization of these calls. 722 * who is responsible for serialization of these calls.
723 *
724 * The name carrier is inappropriate, these functions should really be
725 * called netif_lowerlayer_*() because they represent the state of any
726 * kind of lower layer not just hardware media.
717 */ 727 */
718 728
719extern void linkwatch_fire_event(struct net_device *dev); 729extern void linkwatch_fire_event(struct net_device *dev);
@@ -729,6 +739,29 @@ extern void netif_carrier_on(struct net_device *dev);
729 739
730extern void netif_carrier_off(struct net_device *dev); 740extern void netif_carrier_off(struct net_device *dev);
731 741
742static inline void netif_dormant_on(struct net_device *dev)
743{
744 if (!test_and_set_bit(__LINK_STATE_DORMANT, &dev->state))
745 linkwatch_fire_event(dev);
746}
747
748static inline void netif_dormant_off(struct net_device *dev)
749{
750 if (test_and_clear_bit(__LINK_STATE_DORMANT, &dev->state))
751 linkwatch_fire_event(dev);
752}
753
754static inline int netif_dormant(const struct net_device *dev)
755{
756 return test_bit(__LINK_STATE_DORMANT, &dev->state);
757}
758
759
760static inline int netif_oper_up(const struct net_device *dev) {
761 return (dev->operstate == IF_OPER_UP ||
762 dev->operstate == IF_OPER_UNKNOWN /* backward compat */);
763}
764
732/* Hot-plugging. */ 765/* Hot-plugging. */
733static inline int netif_device_present(struct net_device *dev) 766static inline int netif_device_present(struct net_device *dev)
734{ 767{
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 468896939843..412e52ca9720 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -80,10 +80,14 @@ struct nf_sockopt_ops
80 int set_optmin; 80 int set_optmin;
81 int set_optmax; 81 int set_optmax;
82 int (*set)(struct sock *sk, int optval, void __user *user, unsigned int len); 82 int (*set)(struct sock *sk, int optval, void __user *user, unsigned int len);
83 int (*compat_set)(struct sock *sk, int optval,
84 void __user *user, unsigned int len);
83 85
84 int get_optmin; 86 int get_optmin;
85 int get_optmax; 87 int get_optmax;
86 int (*get)(struct sock *sk, int optval, void __user *user, int *len); 88 int (*get)(struct sock *sk, int optval, void __user *user, int *len);
89 int (*compat_get)(struct sock *sk, int optval,
90 void __user *user, int *len);
87 91
88 /* Number of users inside set() or get(). */ 92 /* Number of users inside set() or get(). */
89 unsigned int use; 93 unsigned int use;
@@ -246,6 +250,11 @@ int nf_setsockopt(struct sock *sk, int pf, int optval, char __user *opt,
246int nf_getsockopt(struct sock *sk, int pf, int optval, char __user *opt, 250int nf_getsockopt(struct sock *sk, int pf, int optval, char __user *opt,
247 int *len); 251 int *len);
248 252
253int compat_nf_setsockopt(struct sock *sk, int pf, int optval,
254 char __user *opt, int len);
255int compat_nf_getsockopt(struct sock *sk, int pf, int optval,
256 char __user *opt, int *len);
257
249/* Packet queuing */ 258/* Packet queuing */
250struct nf_queue_handler { 259struct nf_queue_handler {
251 int (*outfn)(struct sk_buff *skb, struct nf_info *info, 260 int (*outfn)(struct sk_buff *skb, struct nf_info *info,
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h
index 934a2479f160..9f5b12cf489b 100644
--- a/include/linux/netfilter/nfnetlink.h
+++ b/include/linux/netfilter/nfnetlink.h
@@ -164,6 +164,7 @@ extern void nfattr_parse(struct nfattr *tb[], int maxattr,
164 __res; \ 164 __res; \
165}) 165})
166 166
167extern int nfnetlink_has_listeners(unsigned int group);
167extern int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, 168extern int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group,
168 int echo); 169 int echo);
169extern int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags); 170extern int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags);
diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h
index b04b03880595..a7497c7436df 100644
--- a/include/linux/netfilter/nfnetlink_log.h
+++ b/include/linux/netfilter/nfnetlink_log.h
@@ -47,6 +47,8 @@ enum nfulnl_attr_type {
47 NFULA_PAYLOAD, /* opaque data payload */ 47 NFULA_PAYLOAD, /* opaque data payload */
48 NFULA_PREFIX, /* string prefix */ 48 NFULA_PREFIX, /* string prefix */
49 NFULA_UID, /* user id of socket */ 49 NFULA_UID, /* user id of socket */
50 NFULA_SEQ, /* instance-local sequence number */
51 NFULA_SEQ_GLOBAL, /* global sequence number */
50 52
51 __NFULA_MAX 53 __NFULA_MAX
52}; 54};
@@ -77,6 +79,7 @@ enum nfulnl_attr_config {
77 NFULA_CFG_NLBUFSIZ, /* u_int32_t buffer size */ 79 NFULA_CFG_NLBUFSIZ, /* u_int32_t buffer size */
78 NFULA_CFG_TIMEOUT, /* u_int32_t in 1/100 s */ 80 NFULA_CFG_TIMEOUT, /* u_int32_t in 1/100 s */
79 NFULA_CFG_QTHRESH, /* u_int32_t */ 81 NFULA_CFG_QTHRESH, /* u_int32_t */
82 NFULA_CFG_FLAGS, /* u_int16_t */
80 __NFULA_CFG_MAX 83 __NFULA_CFG_MAX
81}; 84};
82#define NFULA_CFG_MAX (__NFULA_CFG_MAX -1) 85#define NFULA_CFG_MAX (__NFULA_CFG_MAX -1)
@@ -85,4 +88,7 @@ enum nfulnl_attr_config {
85#define NFULNL_COPY_META 0x01 88#define NFULNL_COPY_META 0x01
86#define NFULNL_COPY_PACKET 0x02 89#define NFULNL_COPY_PACKET 0x02
87 90
91#define NFULNL_CFG_F_SEQ 0x0001
92#define NFULNL_CFG_F_SEQ_GLOBAL 0x0002
93
88#endif /* _NFNETLINK_LOG_H */ 94#endif /* _NFNETLINK_LOG_H */
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 6500d4e59d46..46a0f974f87c 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -92,8 +92,6 @@ struct xt_match
92 92
93 const char name[XT_FUNCTION_MAXNAMELEN-1]; 93 const char name[XT_FUNCTION_MAXNAMELEN-1];
94 94
95 u_int8_t revision;
96
97 /* Return true or false: return FALSE and set *hotdrop = 1 to 95 /* Return true or false: return FALSE and set *hotdrop = 1 to
98 force immediate packet drop. */ 96 force immediate packet drop. */
99 /* Arguments changed since 2.6.9, as this must now handle 97 /* Arguments changed since 2.6.9, as this must now handle
@@ -102,6 +100,7 @@ struct xt_match
102 int (*match)(const struct sk_buff *skb, 100 int (*match)(const struct sk_buff *skb,
103 const struct net_device *in, 101 const struct net_device *in,
104 const struct net_device *out, 102 const struct net_device *out,
103 const struct xt_match *match,
105 const void *matchinfo, 104 const void *matchinfo,
106 int offset, 105 int offset,
107 unsigned int protoff, 106 unsigned int protoff,
@@ -111,15 +110,25 @@ struct xt_match
111 /* Should return true or false. */ 110 /* Should return true or false. */
112 int (*checkentry)(const char *tablename, 111 int (*checkentry)(const char *tablename,
113 const void *ip, 112 const void *ip,
113 const struct xt_match *match,
114 void *matchinfo, 114 void *matchinfo,
115 unsigned int matchinfosize, 115 unsigned int matchinfosize,
116 unsigned int hook_mask); 116 unsigned int hook_mask);
117 117
118 /* Called when entry of this type deleted. */ 118 /* Called when entry of this type deleted. */
119 void (*destroy)(void *matchinfo, unsigned int matchinfosize); 119 void (*destroy)(const struct xt_match *match, void *matchinfo,
120 unsigned int matchinfosize);
120 121
121 /* Set this to THIS_MODULE if you are a module, otherwise NULL */ 122 /* Set this to THIS_MODULE if you are a module, otherwise NULL */
122 struct module *me; 123 struct module *me;
124
125 char *table;
126 unsigned int matchsize;
127 unsigned int hooks;
128 unsigned short proto;
129
130 unsigned short family;
131 u_int8_t revision;
123}; 132};
124 133
125/* Registration hooks for targets. */ 134/* Registration hooks for targets. */
@@ -129,8 +138,6 @@ struct xt_target
129 138
130 const char name[XT_FUNCTION_MAXNAMELEN-1]; 139 const char name[XT_FUNCTION_MAXNAMELEN-1];
131 140
132 u_int8_t revision;
133
134 /* Returns verdict. Argument order changed since 2.6.9, as this 141 /* Returns verdict. Argument order changed since 2.6.9, as this
135 must now handle non-linear skbs, using skb_copy_bits and 142 must now handle non-linear skbs, using skb_copy_bits and
136 skb_ip_make_writable. */ 143 skb_ip_make_writable. */
@@ -138,6 +145,7 @@ struct xt_target
138 const struct net_device *in, 145 const struct net_device *in,
139 const struct net_device *out, 146 const struct net_device *out,
140 unsigned int hooknum, 147 unsigned int hooknum,
148 const struct xt_target *target,
141 const void *targinfo, 149 const void *targinfo,
142 void *userdata); 150 void *userdata);
143 151
@@ -147,15 +155,25 @@ struct xt_target
147 /* Should return true or false. */ 155 /* Should return true or false. */
148 int (*checkentry)(const char *tablename, 156 int (*checkentry)(const char *tablename,
149 const void *entry, 157 const void *entry,
158 const struct xt_target *target,
150 void *targinfo, 159 void *targinfo,
151 unsigned int targinfosize, 160 unsigned int targinfosize,
152 unsigned int hook_mask); 161 unsigned int hook_mask);
153 162
154 /* Called when entry of this type deleted. */ 163 /* Called when entry of this type deleted. */
155 void (*destroy)(void *targinfo, unsigned int targinfosize); 164 void (*destroy)(const struct xt_target *target, void *targinfo,
165 unsigned int targinfosize);
156 166
157 /* Set this to THIS_MODULE if you are a module, otherwise NULL */ 167 /* Set this to THIS_MODULE if you are a module, otherwise NULL */
158 struct module *me; 168 struct module *me;
169
170 char *table;
171 unsigned int targetsize;
172 unsigned int hooks;
173 unsigned short proto;
174
175 unsigned short family;
176 u_int8_t revision;
159}; 177};
160 178
161/* Furniture shopping... */ 179/* Furniture shopping... */
@@ -207,6 +225,13 @@ extern void xt_unregister_target(int af, struct xt_target *target);
207extern int xt_register_match(int af, struct xt_match *target); 225extern int xt_register_match(int af, struct xt_match *target);
208extern void xt_unregister_match(int af, struct xt_match *target); 226extern void xt_unregister_match(int af, struct xt_match *target);
209 227
228extern int xt_check_match(const struct xt_match *match, unsigned short family,
229 unsigned int size, const char *table, unsigned int hook,
230 unsigned short proto, int inv_proto);
231extern int xt_check_target(const struct xt_target *target, unsigned short family,
232 unsigned int size, const char *table, unsigned int hook,
233 unsigned short proto, int inv_proto);
234
210extern int xt_register_table(struct xt_table *table, 235extern int xt_register_table(struct xt_table *table,
211 struct xt_table_info *bootstrap, 236 struct xt_table_info *bootstrap,
212 struct xt_table_info *newinfo); 237 struct xt_table_info *newinfo);
diff --git a/include/linux/netfilter/xt_policy.h b/include/linux/netfilter/xt_policy.h
new file mode 100644
index 000000000000..a8132ec076fb
--- /dev/null
+++ b/include/linux/netfilter/xt_policy.h
@@ -0,0 +1,58 @@
1#ifndef _XT_POLICY_H
2#define _XT_POLICY_H
3
4#define XT_POLICY_MAX_ELEM 4
5
6enum xt_policy_flags
7{
8 XT_POLICY_MATCH_IN = 0x1,
9 XT_POLICY_MATCH_OUT = 0x2,
10 XT_POLICY_MATCH_NONE = 0x4,
11 XT_POLICY_MATCH_STRICT = 0x8,
12};
13
14enum xt_policy_modes
15{
16 XT_POLICY_MODE_TRANSPORT,
17 XT_POLICY_MODE_TUNNEL
18};
19
20struct xt_policy_spec
21{
22 u_int8_t saddr:1,
23 daddr:1,
24 proto:1,
25 mode:1,
26 spi:1,
27 reqid:1;
28};
29
30union xt_policy_addr
31{
32 struct in_addr a4;
33 struct in6_addr a6;
34};
35
36struct xt_policy_elem
37{
38 union xt_policy_addr saddr;
39 union xt_policy_addr smask;
40 union xt_policy_addr daddr;
41 union xt_policy_addr dmask;
42 u_int32_t spi;
43 u_int32_t reqid;
44 u_int8_t proto;
45 u_int8_t mode;
46
47 struct xt_policy_spec match;
48 struct xt_policy_spec invert;
49};
50
51struct xt_policy_info
52{
53 struct xt_policy_elem pol[XT_POLICY_MAX_ELEM];
54 u_int16_t flags;
55 u_int16_t len;
56};
57
58#endif /* _XT_POLICY_H */
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
index de4d397865ce..a75b84bb9a88 100644
--- a/include/linux/netfilter_bridge.h
+++ b/include/linux/netfilter_bridge.h
@@ -47,22 +47,6 @@ enum nf_br_hook_priorities {
47#define BRNF_BRIDGED 0x08 47#define BRNF_BRIDGED 0x08
48#define BRNF_NF_BRIDGE_PREROUTING 0x10 48#define BRNF_NF_BRIDGE_PREROUTING 0x10
49 49
50static inline
51struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb)
52{
53 struct nf_bridge_info **nf_bridge = &(skb->nf_bridge);
54
55 if ((*nf_bridge = kmalloc(sizeof(**nf_bridge), GFP_ATOMIC)) != NULL) {
56 atomic_set(&(*nf_bridge)->use, 1);
57 (*nf_bridge)->mask = 0;
58 (*nf_bridge)->physindev = (*nf_bridge)->physoutdev = NULL;
59#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
60 (*nf_bridge)->netoutdev = NULL;
61#endif
62 }
63
64 return *nf_bridge;
65}
66 50
67/* Only used in br_forward.c */ 51/* Only used in br_forward.c */
68static inline 52static inline
@@ -77,17 +61,6 @@ void nf_bridge_maybe_copy_header(struct sk_buff *skb)
77 } 61 }
78} 62}
79 63
80static inline
81void nf_bridge_save_header(struct sk_buff *skb)
82{
83 int header_size = 16;
84
85 if (skb->protocol == __constant_htons(ETH_P_8021Q))
86 header_size = 18;
87
88 memcpy(skb->nf_bridge->data, skb->data - header_size, header_size);
89}
90
91/* This is called by the IP fragmenting code and it ensures there is 64/* This is called by the IP fragmenting code and it ensures there is
92 * enough room for the encapsulating header (if there is one). */ 65 * enough room for the encapsulating header (if there is one). */
93static inline 66static inline
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
index 215765f043e6..f32d75c4f4cf 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -29,6 +29,7 @@ union ip_conntrack_expect_proto {
29}; 29};
30 30
31/* Add protocol helper include file here */ 31/* Add protocol helper include file here */
32#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
32#include <linux/netfilter_ipv4/ip_conntrack_pptp.h> 33#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
33#include <linux/netfilter_ipv4/ip_conntrack_amanda.h> 34#include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
34#include <linux/netfilter_ipv4/ip_conntrack_ftp.h> 35#include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
@@ -37,6 +38,7 @@ union ip_conntrack_expect_proto {
37/* per conntrack: application helper private data */ 38/* per conntrack: application helper private data */
38union ip_conntrack_help { 39union ip_conntrack_help {
39 /* insert conntrack helper private data (master) here */ 40 /* insert conntrack helper private data (master) here */
41 struct ip_ct_h323_master ct_h323_info;
40 struct ip_ct_pptp_master ct_pptp_info; 42 struct ip_ct_pptp_master ct_pptp_info;
41 struct ip_ct_ftp_master ct_ftp_info; 43 struct ip_ct_ftp_master ct_ftp_info;
42 struct ip_ct_irc_master ct_irc_info; 44 struct ip_ct_irc_master ct_irc_info;
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_h323.h b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
new file mode 100644
index 000000000000..0987cea53840
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
@@ -0,0 +1,30 @@
1#ifndef _IP_CONNTRACK_H323_H
2#define _IP_CONNTRACK_H323_H
3
4#ifdef __KERNEL__
5
6#define RAS_PORT 1719
7#define Q931_PORT 1720
8#define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */
9
10/* This structure exists only once per master */
11struct ip_ct_h323_master {
12
13 /* Original and NATed Q.931 or H.245 signal ports */
14 u_int16_t sig_port[IP_CT_DIR_MAX];
15
16 /* Original and NATed RTP ports */
17 u_int16_t rtp_port[H323_RTP_CHANNEL_MAX][IP_CT_DIR_MAX];
18
19 union {
20 /* RAS connection timeout */
21 u_int32_t timeout;
22
23 /* Next TPKT length (for separate TPKT header and data) */
24 u_int16_t tpkt_len[IP_CT_DIR_MAX];
25 };
26};
27
28#endif
29
30#endif
diff --git a/include/linux/netfilter_ipv4/ip_nat.h b/include/linux/netfilter_ipv4/ip_nat.h
index 41a107de17cf..e9f5ed1d9f68 100644
--- a/include/linux/netfilter_ipv4/ip_nat.h
+++ b/include/linux/netfilter_ipv4/ip_nat.h
@@ -23,7 +23,7 @@ struct ip_nat_seq {
23 * modification (if any) */ 23 * modification (if any) */
24 u_int32_t correction_pos; 24 u_int32_t correction_pos;
25 /* sequence number offset before and after last modification */ 25 /* sequence number offset before and after last modification */
26 int32_t offset_before, offset_after; 26 int16_t offset_before, offset_after;
27}; 27};
28 28
29/* Single range specification. */ 29/* Single range specification. */
diff --git a/include/linux/netfilter_ipv4/ipt_policy.h b/include/linux/netfilter_ipv4/ipt_policy.h
index a3f6eff39d33..b9478a255301 100644
--- a/include/linux/netfilter_ipv4/ipt_policy.h
+++ b/include/linux/netfilter_ipv4/ipt_policy.h
@@ -1,58 +1,21 @@
1#ifndef _IPT_POLICY_H 1#ifndef _IPT_POLICY_H
2#define _IPT_POLICY_H 2#define _IPT_POLICY_H
3 3
4#define IPT_POLICY_MAX_ELEM 4 4#define IPT_POLICY_MAX_ELEM XT_POLICY_MAX_ELEM
5 5
6enum ipt_policy_flags 6/* ipt_policy_flags */
7{ 7#define IPT_POLICY_MATCH_IN XT_POLICY_MATCH_IN
8 IPT_POLICY_MATCH_IN = 0x1, 8#define IPT_POLICY_MATCH_OUT XT_POLICY_MATCH_OUT
9 IPT_POLICY_MATCH_OUT = 0x2, 9#define IPT_POLICY_MATCH_NONE XT_POLICY_MATCH_NONE
10 IPT_POLICY_MATCH_NONE = 0x4, 10#define IPT_POLICY_MATCH_STRICT XT_POLICY_MATCH_STRICT
11 IPT_POLICY_MATCH_STRICT = 0x8, 11
12}; 12/* ipt_policy_modes */
13 13#define IPT_POLICY_MODE_TRANSPORT XT_POLICY_MODE_TRANSPORT
14enum ipt_policy_modes 14#define IPT_POLICY_MODE_TUNNEL XT_POLICY_MODE_TUNNEL
15{ 15
16 IPT_POLICY_MODE_TRANSPORT, 16#define ipt_policy_spec xt_policy_spec
17 IPT_POLICY_MODE_TUNNEL 17#define ipt_policy_addr xt_policy_addr
18}; 18#define ipt_policy_elem xt_policy_elem
19 19#define ipt_policy_info xt_policy_info
20struct ipt_policy_spec
21{
22 u_int8_t saddr:1,
23 daddr:1,
24 proto:1,
25 mode:1,
26 spi:1,
27 reqid:1;
28};
29
30union ipt_policy_addr
31{
32 struct in_addr a4;
33 struct in6_addr a6;
34};
35
36struct ipt_policy_elem
37{
38 union ipt_policy_addr saddr;
39 union ipt_policy_addr smask;
40 union ipt_policy_addr daddr;
41 union ipt_policy_addr dmask;
42 u_int32_t spi;
43 u_int32_t reqid;
44 u_int8_t proto;
45 u_int8_t mode;
46
47 struct ipt_policy_spec match;
48 struct ipt_policy_spec invert;
49};
50
51struct ipt_policy_info
52{
53 struct ipt_policy_elem pol[IPT_POLICY_MAX_ELEM];
54 u_int16_t flags;
55 u_int16_t len;
56};
57 20
58#endif /* _IPT_POLICY_H */ 21#endif /* _IPT_POLICY_H */
diff --git a/include/linux/netfilter_ipv6/ip6t_policy.h b/include/linux/netfilter_ipv6/ip6t_policy.h
index 671bd818300f..6bab3163d2fb 100644
--- a/include/linux/netfilter_ipv6/ip6t_policy.h
+++ b/include/linux/netfilter_ipv6/ip6t_policy.h
@@ -1,58 +1,21 @@
1#ifndef _IP6T_POLICY_H 1#ifndef _IP6T_POLICY_H
2#define _IP6T_POLICY_H 2#define _IP6T_POLICY_H
3 3
4#define IP6T_POLICY_MAX_ELEM 4 4#define IP6T_POLICY_MAX_ELEM XT_POLICY_MAX_ELEM
5 5
6enum ip6t_policy_flags 6/* ip6t_policy_flags */
7{ 7#define IP6T_POLICY_MATCH_IN XT_POLICY_MATCH_IN
8 IP6T_POLICY_MATCH_IN = 0x1, 8#define IP6T_POLICY_MATCH_OUT XT_POLICY_MATCH_OUT
9 IP6T_POLICY_MATCH_OUT = 0x2, 9#define IP6T_POLICY_MATCH_NONE XT_POLICY_MATCH_NONE
10 IP6T_POLICY_MATCH_NONE = 0x4, 10#define IP6T_POLICY_MATCH_STRICT XT_POLICY_MATCH_STRICT
11 IP6T_POLICY_MATCH_STRICT = 0x8, 11
12}; 12/* ip6t_policy_modes */
13 13#define IP6T_POLICY_MODE_TRANSPORT XT_POLICY_MODE_TRANSPORT
14enum ip6t_policy_modes 14#define IP6T_POLICY_MODE_TUNNEL XT_POLICY_MODE_TUNNEL
15{ 15
16 IP6T_POLICY_MODE_TRANSPORT, 16#define ip6t_policy_spec xt_policy_spec
17 IP6T_POLICY_MODE_TUNNEL 17#define ip6t_policy_addr xt_policy_addr
18}; 18#define ip6t_policy_elem xt_policy_elem
19 19#define ip6t_policy_info xt_policy_info
20struct ip6t_policy_spec
21{
22 u_int8_t saddr:1,
23 daddr:1,
24 proto:1,
25 mode:1,
26 spi:1,
27 reqid:1;
28};
29
30union ip6t_policy_addr
31{
32 struct in_addr a4;
33 struct in6_addr a6;
34};
35
36struct ip6t_policy_elem
37{
38 union ip6t_policy_addr saddr;
39 union ip6t_policy_addr smask;
40 union ip6t_policy_addr daddr;
41 union ip6t_policy_addr dmask;
42 u_int32_t spi;
43 u_int32_t reqid;
44 u_int8_t proto;
45 u_int8_t mode;
46
47 struct ip6t_policy_spec match;
48 struct ip6t_policy_spec invert;
49};
50
51struct ip6t_policy_info
52{
53 struct ip6t_policy_elem pol[IP6T_POLICY_MAX_ELEM];
54 u_int16_t flags;
55 u_int16_t len;
56};
57 20
58#endif /* _IP6T_POLICY_H */ 21#endif /* _IP6T_POLICY_H */
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index c256ebe2a7b4..f8f3d1c927f8 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -151,6 +151,7 @@ struct netlink_skb_parms
151 151
152extern struct sock *netlink_kernel_create(int unit, unsigned int groups, void (*input)(struct sock *sk, int len), struct module *module); 152extern struct sock *netlink_kernel_create(int unit, unsigned int groups, void (*input)(struct sock *sk, int len), struct module *module);
153extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err); 153extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
154extern int netlink_has_listeners(struct sock *sk, unsigned int group);
154extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock); 155extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock);
155extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid, 156extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid,
156 __u32 group, gfp_t allocation); 157 __u32 group, gfp_t allocation);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 751eea58bde8..b9810ddf435a 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1857,16 +1857,22 @@
1857#define PCI_DEVICE_ID_TIGON3_5705M 0x165d 1857#define PCI_DEVICE_ID_TIGON3_5705M 0x165d
1858#define PCI_DEVICE_ID_TIGON3_5705M_2 0x165e 1858#define PCI_DEVICE_ID_TIGON3_5705M_2 0x165e
1859#define PCI_DEVICE_ID_TIGON3_5714 0x1668 1859#define PCI_DEVICE_ID_TIGON3_5714 0x1668
1860#define PCI_DEVICE_ID_TIGON3_5714S 0x1669
1860#define PCI_DEVICE_ID_TIGON3_5780 0x166a 1861#define PCI_DEVICE_ID_TIGON3_5780 0x166a
1861#define PCI_DEVICE_ID_TIGON3_5780S 0x166b 1862#define PCI_DEVICE_ID_TIGON3_5780S 0x166b
1862#define PCI_DEVICE_ID_TIGON3_5705F 0x166e 1863#define PCI_DEVICE_ID_TIGON3_5705F 0x166e
1864#define PCI_DEVICE_ID_TIGON3_5754M 0x1672
1863#define PCI_DEVICE_ID_TIGON3_5750 0x1676 1865#define PCI_DEVICE_ID_TIGON3_5750 0x1676
1864#define PCI_DEVICE_ID_TIGON3_5751 0x1677 1866#define PCI_DEVICE_ID_TIGON3_5751 0x1677
1865#define PCI_DEVICE_ID_TIGON3_5715 0x1678 1867#define PCI_DEVICE_ID_TIGON3_5715 0x1678
1868#define PCI_DEVICE_ID_TIGON3_5715S 0x1679
1869#define PCI_DEVICE_ID_TIGON3_5754 0x167a
1866#define PCI_DEVICE_ID_TIGON3_5750M 0x167c 1870#define PCI_DEVICE_ID_TIGON3_5750M 0x167c
1867#define PCI_DEVICE_ID_TIGON3_5751M 0x167d 1871#define PCI_DEVICE_ID_TIGON3_5751M 0x167d
1868#define PCI_DEVICE_ID_TIGON3_5751F 0x167e 1872#define PCI_DEVICE_ID_TIGON3_5751F 0x167e
1873#define PCI_DEVICE_ID_TIGON3_5787M 0x1693
1869#define PCI_DEVICE_ID_TIGON3_5782 0x1696 1874#define PCI_DEVICE_ID_TIGON3_5782 0x1696
1875#define PCI_DEVICE_ID_TIGON3_5787 0x169b
1870#define PCI_DEVICE_ID_TIGON3_5788 0x169c 1876#define PCI_DEVICE_ID_TIGON3_5788 0x169c
1871#define PCI_DEVICE_ID_TIGON3_5789 0x169d 1877#define PCI_DEVICE_ID_TIGON3_5789 0x169d
1872#define PCI_DEVICE_ID_TIGON3_5702X 0x16a6 1878#define PCI_DEVICE_ID_TIGON3_5702X 0x16a6
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index d50482ba27fe..d572d5376319 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -199,6 +199,7 @@ enum
199#define RTPROT_BIRD 12 /* BIRD */ 199#define RTPROT_BIRD 12 /* BIRD */
200#define RTPROT_DNROUTED 13 /* DECnet routing daemon */ 200#define RTPROT_DNROUTED 13 /* DECnet routing daemon */
201#define RTPROT_XORP 14 /* XORP */ 201#define RTPROT_XORP 14 /* XORP */
202#define RTPROT_NTK 15 /* Netsukuku */
202 203
203/* rtm_scope 204/* rtm_scope
204 205
@@ -733,6 +734,8 @@ enum
733#define IFLA_MAP IFLA_MAP 734#define IFLA_MAP IFLA_MAP
734 IFLA_WEIGHT, 735 IFLA_WEIGHT,
735#define IFLA_WEIGHT IFLA_WEIGHT 736#define IFLA_WEIGHT IFLA_WEIGHT
737 IFLA_OPERSTATE,
738 IFLA_LINKMODE,
736 __IFLA_MAX 739 __IFLA_MAX
737}; 740};
738 741
@@ -905,6 +908,7 @@ struct tcamsg
905#ifdef __KERNEL__ 908#ifdef __KERNEL__
906 909
907#include <linux/config.h> 910#include <linux/config.h>
911#include <linux/mutex.h>
908 912
909extern size_t rtattr_strlcpy(char *dest, const struct rtattr *rta, size_t size); 913extern size_t rtattr_strlcpy(char *dest, const struct rtattr *rta, size_t size);
910static __inline__ int rtattr_strcmp(const struct rtattr *rta, const char *str) 914static __inline__ int rtattr_strcmp(const struct rtattr *rta, const char *str)
@@ -1036,24 +1040,17 @@ __rta_reserve(struct sk_buff *skb, int attrtype, int attrlen)
1036 1040
1037extern void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change); 1041extern void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change);
1038 1042
1039extern struct semaphore rtnl_sem; 1043/* RTNL is used as a global lock for all changes to network configuration */
1040
1041#define rtnl_shlock() down(&rtnl_sem)
1042#define rtnl_shlock_nowait() down_trylock(&rtnl_sem)
1043
1044#define rtnl_shunlock() do { up(&rtnl_sem); \
1045 if (rtnl && rtnl->sk_receive_queue.qlen) \
1046 rtnl->sk_data_ready(rtnl, 0); \
1047 } while(0)
1048
1049extern void rtnl_lock(void); 1044extern void rtnl_lock(void);
1050extern int rtnl_lock_interruptible(void);
1051extern void rtnl_unlock(void); 1045extern void rtnl_unlock(void);
1046extern int rtnl_trylock(void);
1047
1052extern void rtnetlink_init(void); 1048extern void rtnetlink_init(void);
1049extern void __rtnl_unlock(void);
1053 1050
1054#define ASSERT_RTNL() do { \ 1051#define ASSERT_RTNL() do { \
1055 if (unlikely(down_trylock(&rtnl_sem) == 0)) { \ 1052 if (unlikely(rtnl_trylock())) { \
1056 up(&rtnl_sem); \ 1053 rtnl_unlock(); \
1057 printk(KERN_ERR "RTNL: assertion failed at %s (%d)\n", \ 1054 printk(KERN_ERR "RTNL: assertion failed at %s (%d)\n", \
1058 __FILE__, __LINE__); \ 1055 __FILE__, __LINE__); \
1059 dump_stack(); \ 1056 dump_stack(); \
diff --git a/include/linux/security.h b/include/linux/security.h
index 7cbef482e13a..b18eb8cfa639 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1286,7 +1286,8 @@ struct security_operations {
1286 int (*socket_setsockopt) (struct socket * sock, int level, int optname); 1286 int (*socket_setsockopt) (struct socket * sock, int level, int optname);
1287 int (*socket_shutdown) (struct socket * sock, int how); 1287 int (*socket_shutdown) (struct socket * sock, int how);
1288 int (*socket_sock_rcv_skb) (struct sock * sk, struct sk_buff * skb); 1288 int (*socket_sock_rcv_skb) (struct sock * sk, struct sk_buff * skb);
1289 int (*socket_getpeersec) (struct socket *sock, char __user *optval, int __user *optlen, unsigned len); 1289 int (*socket_getpeersec_stream) (struct socket *sock, char __user *optval, int __user *optlen, unsigned len);
1290 int (*socket_getpeersec_dgram) (struct sk_buff *skb, char **secdata, u32 *seclen);
1290 int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority); 1291 int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority);
1291 void (*sk_free_security) (struct sock *sk); 1292 void (*sk_free_security) (struct sock *sk);
1292 unsigned int (*sk_getsid) (struct sock *sk, struct flowi *fl, u8 dir); 1293 unsigned int (*sk_getsid) (struct sock *sk, struct flowi *fl, u8 dir);
@@ -2741,10 +2742,16 @@ static inline int security_sock_rcv_skb (struct sock * sk,
2741 return security_ops->socket_sock_rcv_skb (sk, skb); 2742 return security_ops->socket_sock_rcv_skb (sk, skb);
2742} 2743}
2743 2744
2744static inline int security_socket_getpeersec(struct socket *sock, char __user *optval, 2745static inline int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
2745 int __user *optlen, unsigned len) 2746 int __user *optlen, unsigned len)
2746{ 2747{
2747 return security_ops->socket_getpeersec(sock, optval, optlen, len); 2748 return security_ops->socket_getpeersec_stream(sock, optval, optlen, len);
2749}
2750
2751static inline int security_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata,
2752 u32 *seclen)
2753{
2754 return security_ops->socket_getpeersec_dgram(skb, secdata, seclen);
2748} 2755}
2749 2756
2750static inline int security_sk_alloc(struct sock *sk, int family, gfp_t priority) 2757static inline int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
@@ -2863,8 +2870,14 @@ static inline int security_sock_rcv_skb (struct sock * sk,
2863 return 0; 2870 return 0;
2864} 2871}
2865 2872
2866static inline int security_socket_getpeersec(struct socket *sock, char __user *optval, 2873static inline int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
2867 int __user *optlen, unsigned len) 2874 int __user *optlen, unsigned len)
2875{
2876 return -ENOPROTOOPT;
2877}
2878
2879static inline int security_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata,
2880 u32 *seclen)
2868{ 2881{
2869 return -ENOPROTOOPT; 2882 return -ENOPROTOOPT;
2870} 2883}
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index ad7cc22bd424..613b9513f8b9 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -270,7 +270,6 @@ struct sk_buff {
270 270
271 void (*destructor)(struct sk_buff *skb); 271 void (*destructor)(struct sk_buff *skb);
272#ifdef CONFIG_NETFILTER 272#ifdef CONFIG_NETFILTER
273 __u32 nfmark;
274 struct nf_conntrack *nfct; 273 struct nf_conntrack *nfct;
275#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) 274#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
276 struct sk_buff *nfct_reasm; 275 struct sk_buff *nfct_reasm;
@@ -278,6 +277,7 @@ struct sk_buff {
278#ifdef CONFIG_BRIDGE_NETFILTER 277#ifdef CONFIG_BRIDGE_NETFILTER
279 struct nf_bridge_info *nf_bridge; 278 struct nf_bridge_info *nf_bridge;
280#endif 279#endif
280 __u32 nfmark;
281#endif /* CONFIG_NETFILTER */ 281#endif /* CONFIG_NETFILTER */
282#ifdef CONFIG_NET_SCHED 282#ifdef CONFIG_NET_SCHED
283 __u16 tc_index; /* traffic control index */ 283 __u16 tc_index; /* traffic control index */
@@ -304,6 +304,7 @@ struct sk_buff {
304 304
305#include <asm/system.h> 305#include <asm/system.h>
306 306
307extern void kfree_skb(struct sk_buff *skb);
307extern void __kfree_skb(struct sk_buff *skb); 308extern void __kfree_skb(struct sk_buff *skb);
308extern struct sk_buff *__alloc_skb(unsigned int size, 309extern struct sk_buff *__alloc_skb(unsigned int size,
309 gfp_t priority, int fclone); 310 gfp_t priority, int fclone);
@@ -404,22 +405,6 @@ static inline struct sk_buff *skb_get(struct sk_buff *skb)
404 */ 405 */
405 406
406/** 407/**
407 * kfree_skb - free an sk_buff
408 * @skb: buffer to free
409 *
410 * Drop a reference to the buffer and free it if the usage count has
411 * hit zero.
412 */
413static inline void kfree_skb(struct sk_buff *skb)
414{
415 if (likely(atomic_read(&skb->users) == 1))
416 smp_rmb();
417 else if (likely(!atomic_dec_and_test(&skb->users)))
418 return;
419 __kfree_skb(skb);
420}
421
422/**
423 * skb_cloned - is the buffer a clone 408 * skb_cloned - is the buffer a clone
424 * @skb: buffer to check 409 * @skb: buffer to check
425 * 410 *
@@ -1174,12 +1159,14 @@ static inline int skb_linearize(struct sk_buff *skb, gfp_t gfp)
1174 */ 1159 */
1175 1160
1176static inline void skb_postpull_rcsum(struct sk_buff *skb, 1161static inline void skb_postpull_rcsum(struct sk_buff *skb,
1177 const void *start, int len) 1162 const void *start, unsigned int len)
1178{ 1163{
1179 if (skb->ip_summed == CHECKSUM_HW) 1164 if (skb->ip_summed == CHECKSUM_HW)
1180 skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0)); 1165 skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0));
1181} 1166}
1182 1167
1168unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len);
1169
1183/** 1170/**
1184 * pskb_trim_rcsum - trim received skb and update checksum 1171 * pskb_trim_rcsum - trim received skb and update checksum
1185 * @skb: buffer to trim 1172 * @skb: buffer to trim
@@ -1351,16 +1338,6 @@ static inline void nf_conntrack_put_reasm(struct sk_buff *skb)
1351 kfree_skb(skb); 1338 kfree_skb(skb);
1352} 1339}
1353#endif 1340#endif
1354static inline void nf_reset(struct sk_buff *skb)
1355{
1356 nf_conntrack_put(skb->nfct);
1357 skb->nfct = NULL;
1358#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
1359 nf_conntrack_put_reasm(skb->nfct_reasm);
1360 skb->nfct_reasm = NULL;
1361#endif
1362}
1363
1364#ifdef CONFIG_BRIDGE_NETFILTER 1341#ifdef CONFIG_BRIDGE_NETFILTER
1365static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge) 1342static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
1366{ 1343{
@@ -1373,6 +1350,20 @@ static inline void nf_bridge_get(struct nf_bridge_info *nf_bridge)
1373 atomic_inc(&nf_bridge->use); 1350 atomic_inc(&nf_bridge->use);
1374} 1351}
1375#endif /* CONFIG_BRIDGE_NETFILTER */ 1352#endif /* CONFIG_BRIDGE_NETFILTER */
1353static inline void nf_reset(struct sk_buff *skb)
1354{
1355 nf_conntrack_put(skb->nfct);
1356 skb->nfct = NULL;
1357#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
1358 nf_conntrack_put_reasm(skb->nfct_reasm);
1359 skb->nfct_reasm = NULL;
1360#endif
1361#ifdef CONFIG_BRIDGE_NETFILTER
1362 nf_bridge_put(skb->nf_bridge);
1363 skb->nf_bridge = NULL;
1364#endif
1365}
1366
1376#else /* CONFIG_NETFILTER */ 1367#else /* CONFIG_NETFILTER */
1377static inline void nf_reset(struct sk_buff *skb) {} 1368static inline void nf_reset(struct sk_buff *skb) {}
1378#endif /* CONFIG_NETFILTER */ 1369#endif /* CONFIG_NETFILTER */
diff --git a/include/linux/socket.h b/include/linux/socket.h
index b02dda4ee83d..9ab2ddd80221 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -150,6 +150,7 @@ __KINLINE struct cmsghdr * cmsg_nxthdr (struct msghdr *__msg, struct cmsghdr *__
150 150
151#define SCM_RIGHTS 0x01 /* rw: access rights (array of int) */ 151#define SCM_RIGHTS 0x01 /* rw: access rights (array of int) */
152#define SCM_CREDENTIALS 0x02 /* rw: struct ucred */ 152#define SCM_CREDENTIALS 0x02 /* rw: struct ucred */
153#define SCM_SECURITY 0x03 /* rw: security label */
153 154
154struct ucred { 155struct ucred {
155 __u32 pid; 156 __u32 pid;
diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
index d33c6face032..b4acb3d37c3f 100644
--- a/include/linux/sunrpc/svcsock.h
+++ b/include/linux/sunrpc/svcsock.h
@@ -36,7 +36,7 @@ struct svc_sock {
36 36
37 struct list_head sk_deferred; /* deferred requests that need to 37 struct list_head sk_deferred; /* deferred requests that need to
38 * be revisted */ 38 * be revisted */
39 struct semaphore sk_sem; /* to serialize sending data */ 39 struct mutex sk_mutex; /* to serialize sending data */
40 40
41 int (*sk_recvfrom)(struct svc_rqst *rqstp); 41 int (*sk_recvfrom)(struct svc_rqst *rqstp);
42 int (*sk_sendto)(struct svc_rqst *rqstp); 42 int (*sk_sendto)(struct svc_rqst *rqstp);
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index bac61db26456..76eaeff76f82 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -211,6 +211,7 @@ enum
211 NET_SCTP=17, 211 NET_SCTP=17,
212 NET_LLC=18, 212 NET_LLC=18,
213 NET_NETFILTER=19, 213 NET_NETFILTER=19,
214 NET_DCCP=20,
214}; 215};
215 216
216/* /proc/sys/kernel/random */ 217/* /proc/sys/kernel/random */
@@ -261,6 +262,8 @@ enum
261 NET_CORE_DEV_WEIGHT=17, 262 NET_CORE_DEV_WEIGHT=17,
262 NET_CORE_SOMAXCONN=18, 263 NET_CORE_SOMAXCONN=18,
263 NET_CORE_BUDGET=19, 264 NET_CORE_BUDGET=19,
265 NET_CORE_AEVENT_ETIME=20,
266 NET_CORE_AEVENT_RSEQTH=21,
264}; 267};
265 268
266/* /proc/sys/net/ethernet */ 269/* /proc/sys/net/ethernet */
@@ -397,6 +400,9 @@ enum
397 NET_TCP_CONG_CONTROL=110, 400 NET_TCP_CONG_CONTROL=110,
398 NET_TCP_ABC=111, 401 NET_TCP_ABC=111,
399 NET_IPV4_IPFRAG_MAX_DIST=112, 402 NET_IPV4_IPFRAG_MAX_DIST=112,
403 NET_TCP_MTU_PROBING=113,
404 NET_TCP_BASE_MSS=114,
405 NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS=115,
400}; 406};
401 407
402enum { 408enum {
@@ -451,6 +457,7 @@ enum
451 NET_IPV4_CONF_ARP_ANNOUNCE=18, 457 NET_IPV4_CONF_ARP_ANNOUNCE=18,
452 NET_IPV4_CONF_ARP_IGNORE=19, 458 NET_IPV4_CONF_ARP_IGNORE=19,
453 NET_IPV4_CONF_PROMOTE_SECONDARIES=20, 459 NET_IPV4_CONF_PROMOTE_SECONDARIES=20,
460 NET_IPV4_CONF_ARP_ACCEPT=21,
454 __NET_IPV4_CONF_MAX 461 __NET_IPV4_CONF_MAX
455}; 462};
456 463
@@ -531,6 +538,11 @@ enum {
531 NET_IPV6_MAX_DESYNC_FACTOR=15, 538 NET_IPV6_MAX_DESYNC_FACTOR=15,
532 NET_IPV6_MAX_ADDRESSES=16, 539 NET_IPV6_MAX_ADDRESSES=16,
533 NET_IPV6_FORCE_MLD_VERSION=17, 540 NET_IPV6_FORCE_MLD_VERSION=17,
541 NET_IPV6_ACCEPT_RA_DEFRTR=18,
542 NET_IPV6_ACCEPT_RA_PINFO=19,
543 NET_IPV6_ACCEPT_RA_RTR_PREF=20,
544 NET_IPV6_RTR_PROBE_INTERVAL=21,
545 NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN=22,
534 __NET_IPV6_MAX 546 __NET_IPV6_MAX
535}; 547};
536 548
@@ -562,6 +574,21 @@ enum {
562 __NET_NEIGH_MAX 574 __NET_NEIGH_MAX
563}; 575};
564 576
577/* /proc/sys/net/dccp */
578enum {
579 NET_DCCP_DEFAULT=1,
580};
581
582/* /proc/sys/net/dccp/default */
583enum {
584 NET_DCCP_DEFAULT_SEQ_WINDOW = 1,
585 NET_DCCP_DEFAULT_RX_CCID = 2,
586 NET_DCCP_DEFAULT_TX_CCID = 3,
587 NET_DCCP_DEFAULT_ACK_RATIO = 4,
588 NET_DCCP_DEFAULT_SEND_ACKVEC = 5,
589 NET_DCCP_DEFAULT_SEND_NDP = 6,
590};
591
565/* /proc/sys/net/ipx */ 592/* /proc/sys/net/ipx */
566enum { 593enum {
567 NET_IPX_PPROP_BROADCASTING=1, 594 NET_IPX_PPROP_BROADCASTING=1,
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index f2bb2396853f..542d39596bd8 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -343,6 +343,12 @@ struct tcp_sock {
343 __u32 seq; 343 __u32 seq;
344 __u32 time; 344 __u32 time;
345 } rcvq_space; 345 } rcvq_space;
346
347/* TCP-specific MTU probe information. */
348 struct {
349 __u32 probe_seq_start;
350 __u32 probe_seq_end;
351 } mtu_probe;
346}; 352};
347 353
348static inline struct tcp_sock *tcp_sk(const struct sock *sk) 354static inline struct tcp_sock *tcp_sk(const struct sock *sk)
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index 82fbb758e28f..6b42cc474c01 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -156,6 +156,10 @@ enum {
156 XFRM_MSG_FLUSHPOLICY, 156 XFRM_MSG_FLUSHPOLICY,
157#define XFRM_MSG_FLUSHPOLICY XFRM_MSG_FLUSHPOLICY 157#define XFRM_MSG_FLUSHPOLICY XFRM_MSG_FLUSHPOLICY
158 158
159 XFRM_MSG_NEWAE,
160#define XFRM_MSG_NEWAE XFRM_MSG_NEWAE
161 XFRM_MSG_GETAE,
162#define XFRM_MSG_GETAE XFRM_MSG_GETAE
159 __XFRM_MSG_MAX 163 __XFRM_MSG_MAX
160}; 164};
161#define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1) 165#define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
@@ -194,6 +198,21 @@ struct xfrm_encap_tmpl {
194 xfrm_address_t encap_oa; 198 xfrm_address_t encap_oa;
195}; 199};
196 200
201/* AEVENT flags */
202enum xfrm_ae_ftype_t {
203 XFRM_AE_UNSPEC,
204 XFRM_AE_RTHR=1, /* replay threshold*/
205 XFRM_AE_RVAL=2, /* replay value */
206 XFRM_AE_LVAL=4, /* lifetime value */
207 XFRM_AE_ETHR=8, /* expiry timer threshold */
208 XFRM_AE_CR=16, /* Event cause is replay update */
209 XFRM_AE_CE=32, /* Event cause is timer expiry */
210 XFRM_AE_CU=64, /* Event cause is policy update */
211 __XFRM_AE_MAX
212
213#define XFRM_AE_MAX (__XFRM_AE_MAX - 1)
214};
215
197/* Netlink message attributes. */ 216/* Netlink message attributes. */
198enum xfrm_attr_type_t { 217enum xfrm_attr_type_t {
199 XFRMA_UNSPEC, 218 XFRMA_UNSPEC,
@@ -205,6 +224,10 @@ enum xfrm_attr_type_t {
205 XFRMA_SA, 224 XFRMA_SA,
206 XFRMA_POLICY, 225 XFRMA_POLICY,
207 XFRMA_SEC_CTX, /* struct xfrm_sec_ctx */ 226 XFRMA_SEC_CTX, /* struct xfrm_sec_ctx */
227 XFRMA_LTIME_VAL,
228 XFRMA_REPLAY_VAL,
229 XFRMA_REPLAY_THRESH,
230 XFRMA_ETIMER_THRESH,
208 __XFRMA_MAX 231 __XFRMA_MAX
209 232
210#define XFRMA_MAX (__XFRMA_MAX - 1) 233#define XFRMA_MAX (__XFRMA_MAX - 1)
@@ -235,6 +258,11 @@ struct xfrm_usersa_id {
235 __u8 proto; 258 __u8 proto;
236}; 259};
237 260
261struct xfrm_aevent_id {
262 struct xfrm_usersa_id sa_id;
263 __u32 flags;
264};
265
238struct xfrm_userspi_info { 266struct xfrm_userspi_info {
239 struct xfrm_usersa_info info; 267 struct xfrm_usersa_info info;
240 __u32 min; 268 __u32 min;
@@ -306,6 +334,8 @@ enum xfrm_nlgroups {
306#define XFRMNLGRP_SA XFRMNLGRP_SA 334#define XFRMNLGRP_SA XFRMNLGRP_SA
307 XFRMNLGRP_POLICY, 335 XFRMNLGRP_POLICY,
308#define XFRMNLGRP_POLICY XFRMNLGRP_POLICY 336#define XFRMNLGRP_POLICY XFRMNLGRP_POLICY
337 XFRMNLGRP_AEVENTS,
338#define XFRMNLGRP_AEVENTS XFRMNLGRP_AEVENTS
309 __XFRMNLGRP_MAX 339 __XFRMNLGRP_MAX
310}; 340};
311#define XFRMNLGRP_MAX (__XFRMNLGRP_MAX - 1) 341#define XFRMNLGRP_MAX (__XFRMNLGRP_MAX - 1)
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index bfc1779fc753..427dac94bc7e 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -4,6 +4,7 @@
4#include <linux/config.h> 4#include <linux/config.h>
5#include <linux/socket.h> 5#include <linux/socket.h>
6#include <linux/un.h> 6#include <linux/un.h>
7#include <linux/mutex.h>
7#include <net/sock.h> 8#include <net/sock.h>
8 9
9extern void unix_inflight(struct file *fp); 10extern void unix_inflight(struct file *fp);
@@ -71,7 +72,7 @@ struct unix_sock {
71 struct unix_address *addr; 72 struct unix_address *addr;
72 struct dentry *dentry; 73 struct dentry *dentry;
73 struct vfsmount *mnt; 74 struct vfsmount *mnt;
74 struct semaphore readsem; 75 struct mutex readlock;
75 struct sock *peer; 76 struct sock *peer;
76 struct sock *other; 77 struct sock *other;
77 struct sock *gc_tree; 78 struct sock *gc_tree;
diff --git a/include/net/dn.h b/include/net/dn.h
index a4b6168e1e25..465b78302782 100644
--- a/include/net/dn.h
+++ b/include/net/dn.h
@@ -6,10 +6,8 @@
6#include <net/tcp.h> 6#include <net/tcp.h>
7#include <asm/byteorder.h> 7#include <asm/byteorder.h>
8 8
9typedef unsigned short dn_address; 9#define dn_ntohs(x) le16_to_cpu(x)
10 10#define dn_htons(x) cpu_to_le16(x)
11#define dn_ntohs(x) le16_to_cpu((unsigned short)(x))
12#define dn_htons(x) cpu_to_le16((unsigned short)(x))
13 11
14struct dn_scp /* Session Control Port */ 12struct dn_scp /* Session Control Port */
15{ 13{
@@ -31,36 +29,36 @@ struct dn_scp /* Session Control Port */
31#define DN_CL 15 /* Closed */ 29#define DN_CL 15 /* Closed */
32#define DN_CN 16 /* Closed Notification */ 30#define DN_CN 16 /* Closed Notification */
33 31
34 unsigned short addrloc; 32 __le16 addrloc;
35 unsigned short addrrem; 33 __le16 addrrem;
36 unsigned short numdat; 34 __u16 numdat;
37 unsigned short numoth; 35 __u16 numoth;
38 unsigned short numoth_rcv; 36 __u16 numoth_rcv;
39 unsigned short numdat_rcv; 37 __u16 numdat_rcv;
40 unsigned short ackxmt_dat; 38 __u16 ackxmt_dat;
41 unsigned short ackxmt_oth; 39 __u16 ackxmt_oth;
42 unsigned short ackrcv_dat; 40 __u16 ackrcv_dat;
43 unsigned short ackrcv_oth; 41 __u16 ackrcv_oth;
44 unsigned char flowrem_sw; 42 __u8 flowrem_sw;
45 unsigned char flowloc_sw; 43 __u8 flowloc_sw;
46#define DN_SEND 2 44#define DN_SEND 2
47#define DN_DONTSEND 1 45#define DN_DONTSEND 1
48#define DN_NOCHANGE 0 46#define DN_NOCHANGE 0
49 unsigned short flowrem_dat; 47 __u16 flowrem_dat;
50 unsigned short flowrem_oth; 48 __u16 flowrem_oth;
51 unsigned short flowloc_dat; 49 __u16 flowloc_dat;
52 unsigned short flowloc_oth; 50 __u16 flowloc_oth;
53 unsigned char services_rem; 51 __u8 services_rem;
54 unsigned char services_loc; 52 __u8 services_loc;
55 unsigned char info_rem; 53 __u8 info_rem;
56 unsigned char info_loc; 54 __u8 info_loc;
57 55
58 unsigned short segsize_rem; 56 __u16 segsize_rem;
59 unsigned short segsize_loc; 57 __u16 segsize_loc;
60 58
61 unsigned char nonagle; 59 __u8 nonagle;
62 unsigned char multi_ireq; 60 __u8 multi_ireq;
63 unsigned char accept_mode; 61 __u8 accept_mode;
64 unsigned long seg_total; /* Running total of current segment */ 62 unsigned long seg_total; /* Running total of current segment */
65 63
66 struct optdata_dn conndata_in; 64 struct optdata_dn conndata_in;
@@ -160,40 +158,41 @@ static inline struct dn_scp *DN_SK(struct sock *sk)
160 */ 158 */
161#define DN_SKB_CB(skb) ((struct dn_skb_cb *)(skb)->cb) 159#define DN_SKB_CB(skb) ((struct dn_skb_cb *)(skb)->cb)
162struct dn_skb_cb { 160struct dn_skb_cb {
163 unsigned short dst; 161 __le16 dst;
164 unsigned short src; 162 __le16 src;
165 unsigned short hops; 163 __u16 hops;
166 unsigned short dst_port; 164 __le16 dst_port;
167 unsigned short src_port; 165 __le16 src_port;
168 unsigned char services; 166 __u8 services;
169 unsigned char info; 167 __u8 info;
170 unsigned char rt_flags; 168 __u8 rt_flags;
171 unsigned char nsp_flags; 169 __u8 nsp_flags;
172 unsigned short segsize; 170 __u16 segsize;
173 unsigned short segnum; 171 __u16 segnum;
174 unsigned short xmit_count; 172 __u16 xmit_count;
175 unsigned long stamp; 173 unsigned long stamp;
176 int iif; 174 int iif;
177}; 175};
178 176
179static inline dn_address dn_eth2dn(unsigned char *ethaddr) 177static inline __le16 dn_eth2dn(unsigned char *ethaddr)
180{ 178{
181 return ethaddr[4] | (ethaddr[5] << 8); 179 return dn_htons(ethaddr[4] | (ethaddr[5] << 8));
182} 180}
183 181
184static inline dn_address dn_saddr2dn(struct sockaddr_dn *saddr) 182static inline __le16 dn_saddr2dn(struct sockaddr_dn *saddr)
185{ 183{
186 return *(dn_address *)saddr->sdn_nodeaddr; 184 return *(__le16 *)saddr->sdn_nodeaddr;
187} 185}
188 186
189static inline void dn_dn2eth(unsigned char *ethaddr, dn_address addr) 187static inline void dn_dn2eth(unsigned char *ethaddr, __le16 addr)
190{ 188{
189 __u16 a = dn_ntohs(addr);
191 ethaddr[0] = 0xAA; 190 ethaddr[0] = 0xAA;
192 ethaddr[1] = 0x00; 191 ethaddr[1] = 0x00;
193 ethaddr[2] = 0x04; 192 ethaddr[2] = 0x04;
194 ethaddr[3] = 0x00; 193 ethaddr[3] = 0x00;
195 ethaddr[4] = (unsigned char)(addr & 0xff); 194 ethaddr[4] = (__u8)(a & 0xff);
196 ethaddr[5] = (unsigned char)(addr >> 8); 195 ethaddr[5] = (__u8)(a >> 8);
197} 196}
198 197
199static inline void dn_sk_ports_copy(struct flowi *fl, struct dn_scp *scp) 198static inline void dn_sk_ports_copy(struct flowi *fl, struct dn_scp *scp)
@@ -202,7 +201,7 @@ static inline void dn_sk_ports_copy(struct flowi *fl, struct dn_scp *scp)
202 fl->uli_u.dnports.dport = scp->addrrem; 201 fl->uli_u.dnports.dport = scp->addrrem;
203 fl->uli_u.dnports.objnum = scp->addr.sdn_objnum; 202 fl->uli_u.dnports.objnum = scp->addr.sdn_objnum;
204 if (fl->uli_u.dnports.objnum == 0) { 203 if (fl->uli_u.dnports.objnum == 0) {
205 fl->uli_u.dnports.objnamel = scp->addr.sdn_objnamel; 204 fl->uli_u.dnports.objnamel = (__u8)dn_ntohs(scp->addr.sdn_objnamel);
206 memcpy(fl->uli_u.dnports.objname, scp->addr.sdn_objname, 16); 205 memcpy(fl->uli_u.dnports.objname, scp->addr.sdn_objname, 16);
207 } 206 }
208} 207}
@@ -217,7 +216,7 @@ extern unsigned dn_mss_from_pmtu(struct net_device *dev, int mtu);
217extern struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr); 216extern struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr);
218extern struct sock *dn_find_by_skb(struct sk_buff *skb); 217extern struct sock *dn_find_by_skb(struct sk_buff *skb);
219#define DN_ASCBUF_LEN 9 218#define DN_ASCBUF_LEN 9
220extern char *dn_addr2asc(dn_address, char *); 219extern char *dn_addr2asc(__u16, char *);
221extern int dn_destroy_timer(struct sock *sk); 220extern int dn_destroy_timer(struct sock *sk);
222 221
223extern int dn_sockaddr2username(struct sockaddr_dn *addr, unsigned char *buf, unsigned char type); 222extern int dn_sockaddr2username(struct sockaddr_dn *addr, unsigned char *buf, unsigned char type);
@@ -226,7 +225,7 @@ extern int dn_username2sockaddr(unsigned char *data, int len, struct sockaddr_dn
226extern void dn_start_slow_timer(struct sock *sk); 225extern void dn_start_slow_timer(struct sock *sk);
227extern void dn_stop_slow_timer(struct sock *sk); 226extern void dn_stop_slow_timer(struct sock *sk);
228 227
229extern dn_address decnet_address; 228extern __le16 decnet_address;
230extern int decnet_debug_level; 229extern int decnet_debug_level;
231extern int decnet_time_wait; 230extern int decnet_time_wait;
232extern int decnet_dn_count; 231extern int decnet_dn_count;
diff --git a/include/net/dn_dev.h b/include/net/dn_dev.h
index 5a86e78081bf..cee46821dc53 100644
--- a/include/net/dn_dev.h
+++ b/include/net/dn_dev.h
@@ -7,11 +7,11 @@ struct dn_dev;
7struct dn_ifaddr { 7struct dn_ifaddr {
8 struct dn_ifaddr *ifa_next; 8 struct dn_ifaddr *ifa_next;
9 struct dn_dev *ifa_dev; 9 struct dn_dev *ifa_dev;
10 dn_address ifa_local; 10 __le16 ifa_local;
11 dn_address ifa_address; 11 __le16 ifa_address;
12 unsigned char ifa_flags; 12 __u8 ifa_flags;
13 unsigned char ifa_scope; 13 __u8 ifa_scope;
14 char ifa_label[IFNAMSIZ]; 14 char ifa_label[IFNAMSIZ];
15}; 15};
16 16
17#define DN_DEV_S_RU 0 /* Run - working normally */ 17#define DN_DEV_S_RU 0 /* Run - working normally */
@@ -91,7 +91,7 @@ struct dn_dev {
91 struct timer_list timer; 91 struct timer_list timer;
92 unsigned long t3; 92 unsigned long t3;
93 struct neigh_parms *neigh_parms; 93 struct neigh_parms *neigh_parms;
94 unsigned char addr[ETH_ALEN]; 94 __u8 addr[ETH_ALEN];
95 struct neighbour *router; /* Default router on circuit */ 95 struct neighbour *router; /* Default router on circuit */
96 struct neighbour *peer; /* Peer on pointopoint links */ 96 struct neighbour *peer; /* Peer on pointopoint links */
97 unsigned long uptime; /* Time device went up in jiffies */ 97 unsigned long uptime; /* Time device went up in jiffies */
@@ -99,56 +99,56 @@ struct dn_dev {
99 99
100struct dn_short_packet 100struct dn_short_packet
101{ 101{
102 unsigned char msgflg; 102 __u8 msgflg;
103 unsigned short dstnode; 103 __le16 dstnode;
104 unsigned short srcnode; 104 __le16 srcnode;
105 unsigned char forward; 105 __u8 forward;
106} __attribute__((packed)); 106} __attribute__((packed));
107 107
108struct dn_long_packet 108struct dn_long_packet
109{ 109{
110 unsigned char msgflg; 110 __u8 msgflg;
111 unsigned char d_area; 111 __u8 d_area;
112 unsigned char d_subarea; 112 __u8 d_subarea;
113 unsigned char d_id[6]; 113 __u8 d_id[6];
114 unsigned char s_area; 114 __u8 s_area;
115 unsigned char s_subarea; 115 __u8 s_subarea;
116 unsigned char s_id[6]; 116 __u8 s_id[6];
117 unsigned char nl2; 117 __u8 nl2;
118 unsigned char visit_ct; 118 __u8 visit_ct;
119 unsigned char s_class; 119 __u8 s_class;
120 unsigned char pt; 120 __u8 pt;
121} __attribute__((packed)); 121} __attribute__((packed));
122 122
123/*------------------------- DRP - Routing messages ---------------------*/ 123/*------------------------- DRP - Routing messages ---------------------*/
124 124
125struct endnode_hello_message 125struct endnode_hello_message
126{ 126{
127 unsigned char msgflg; 127 __u8 msgflg;
128 unsigned char tiver[3]; 128 __u8 tiver[3];
129 unsigned char id[6]; 129 __u8 id[6];
130 unsigned char iinfo; 130 __u8 iinfo;
131 unsigned short blksize; 131 __le16 blksize;
132 unsigned char area; 132 __u8 area;
133 unsigned char seed[8]; 133 __u8 seed[8];
134 unsigned char neighbor[6]; 134 __u8 neighbor[6];
135 unsigned short timer; 135 __le16 timer;
136 unsigned char mpd; 136 __u8 mpd;
137 unsigned char datalen; 137 __u8 datalen;
138 unsigned char data[2]; 138 __u8 data[2];
139} __attribute__((packed)); 139} __attribute__((packed));
140 140
141struct rtnode_hello_message 141struct rtnode_hello_message
142{ 142{
143 unsigned char msgflg; 143 __u8 msgflg;
144 unsigned char tiver[3]; 144 __u8 tiver[3];
145 unsigned char id[6]; 145 __u8 id[6];
146 unsigned char iinfo; 146 __u8 iinfo;
147 unsigned short blksize; 147 __le16 blksize;
148 unsigned char priority; 148 __u8 priority;
149 unsigned char area; 149 __u8 area;
150 unsigned short timer; 150 __le16 timer;
151 unsigned char mpd; 151 __u8 mpd;
152} __attribute__((packed)); 152} __attribute__((packed));
153 153
154 154
@@ -169,12 +169,12 @@ extern void dn_dev_down(struct net_device *);
169 169
170extern int dn_dev_set_default(struct net_device *dev, int force); 170extern int dn_dev_set_default(struct net_device *dev, int force);
171extern struct net_device *dn_dev_get_default(void); 171extern struct net_device *dn_dev_get_default(void);
172extern int dn_dev_bind_default(dn_address *addr); 172extern int dn_dev_bind_default(__le16 *addr);
173 173
174extern int register_dnaddr_notifier(struct notifier_block *nb); 174extern int register_dnaddr_notifier(struct notifier_block *nb);
175extern int unregister_dnaddr_notifier(struct notifier_block *nb); 175extern int unregister_dnaddr_notifier(struct notifier_block *nb);
176 176
177static inline int dn_dev_islocal(struct net_device *dev, dn_address addr) 177static inline int dn_dev_islocal(struct net_device *dev, __le16 addr)
178{ 178{
179 struct dn_dev *dn_db = dev->dn_ptr; 179 struct dn_dev *dn_db = dev->dn_ptr;
180 struct dn_ifaddr *ifa; 180 struct dn_ifaddr *ifa;
diff --git a/include/net/dn_fib.h b/include/net/dn_fib.h
index cd3c96d9601b..a15dcf0d5c1e 100644
--- a/include/net/dn_fib.h
+++ b/include/net/dn_fib.h
@@ -37,7 +37,7 @@ struct dn_fib_nh {
37 int nh_weight; 37 int nh_weight;
38 int nh_power; 38 int nh_power;
39 int nh_oif; 39 int nh_oif;
40 u32 nh_gw; 40 __le16 nh_gw;
41}; 41};
42 42
43struct dn_fib_info { 43struct dn_fib_info {
@@ -48,7 +48,7 @@ struct dn_fib_info {
48 int fib_dead; 48 int fib_dead;
49 unsigned fib_flags; 49 unsigned fib_flags;
50 int fib_protocol; 50 int fib_protocol;
51 dn_address fib_prefsrc; 51 __le16 fib_prefsrc;
52 __u32 fib_priority; 52 __u32 fib_priority;
53 __u32 fib_metrics[RTAX_MAX]; 53 __u32 fib_metrics[RTAX_MAX];
54#define dn_fib_mtu fib_metrics[RTAX_MTU-1] 54#define dn_fib_mtu fib_metrics[RTAX_MTU-1]
@@ -71,15 +71,15 @@ struct dn_fib_info {
71#define DN_FIB_RES_OIF(res) (DN_FIB_RES_NH(res).nh_oif) 71#define DN_FIB_RES_OIF(res) (DN_FIB_RES_NH(res).nh_oif)
72 72
73typedef struct { 73typedef struct {
74 u16 datum; 74 __le16 datum;
75} dn_fib_key_t; 75} dn_fib_key_t;
76 76
77typedef struct { 77typedef struct {
78 u16 datum; 78 __le16 datum;
79} dn_fib_hash_t; 79} dn_fib_hash_t;
80 80
81typedef struct { 81typedef struct {
82 u16 datum; 82 __u16 datum;
83} dn_fib_idx_t; 83} dn_fib_idx_t;
84 84
85struct dn_fib_node { 85struct dn_fib_node {
@@ -126,11 +126,11 @@ extern int dn_fib_semantic_match(int type, struct dn_fib_info *fi,
126 const struct flowi *fl, 126 const struct flowi *fl,
127 struct dn_fib_res *res); 127 struct dn_fib_res *res);
128extern void dn_fib_release_info(struct dn_fib_info *fi); 128extern void dn_fib_release_info(struct dn_fib_info *fi);
129extern u16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type); 129extern __le16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type);
130extern void dn_fib_flush(void); 130extern void dn_fib_flush(void);
131extern void dn_fib_select_multipath(const struct flowi *fl, 131extern void dn_fib_select_multipath(const struct flowi *fl,
132 struct dn_fib_res *res); 132 struct dn_fib_res *res);
133extern int dn_fib_sync_down(dn_address local, struct net_device *dev, 133extern int dn_fib_sync_down(__le16 local, struct net_device *dev,
134 int force); 134 int force);
135extern int dn_fib_sync_up(struct net_device *dev); 135extern int dn_fib_sync_up(struct net_device *dev);
136 136
@@ -148,8 +148,8 @@ extern void dn_fib_table_cleanup(void);
148extern void dn_fib_rules_init(void); 148extern void dn_fib_rules_init(void);
149extern void dn_fib_rules_cleanup(void); 149extern void dn_fib_rules_cleanup(void);
150extern void dn_fib_rule_put(struct dn_fib_rule *); 150extern void dn_fib_rule_put(struct dn_fib_rule *);
151extern __u16 dn_fib_rules_policy(__u16 saddr, struct dn_fib_res *res, unsigned *flags); 151extern __le16 dn_fib_rules_policy(__le16 saddr, struct dn_fib_res *res, unsigned *flags);
152extern unsigned dnet_addr_type(__u16 addr); 152extern unsigned dnet_addr_type(__le16 addr);
153extern int dn_fib_lookup(const struct flowi *fl, struct dn_fib_res *res); 153extern int dn_fib_lookup(const struct flowi *fl, struct dn_fib_res *res);
154 154
155/* 155/*
@@ -194,10 +194,10 @@ extern struct dn_fib_table *dn_fib_tables[];
194 194
195#endif /* CONFIG_DECNET_ROUTER */ 195#endif /* CONFIG_DECNET_ROUTER */
196 196
197static inline u16 dnet_make_mask(int n) 197static inline __le16 dnet_make_mask(int n)
198{ 198{
199 if (n) 199 if (n)
200 return htons(~((1<<(16-n))-1)); 200 return dn_htons(~((1<<(16-n))-1));
201 return 0; 201 return 0;
202} 202}
203 203
diff --git a/include/net/dn_neigh.h b/include/net/dn_neigh.h
index 4b1eb038d637..4cb4ae7fb81f 100644
--- a/include/net/dn_neigh.h
+++ b/include/net/dn_neigh.h
@@ -7,13 +7,13 @@
7 */ 7 */
8struct dn_neigh { 8struct dn_neigh {
9 struct neighbour n; 9 struct neighbour n;
10 dn_address addr; 10 __le16 addr;
11 unsigned long flags; 11 unsigned long flags;
12#define DN_NDFLAG_R1 0x0001 /* Router L1 */ 12#define DN_NDFLAG_R1 0x0001 /* Router L1 */
13#define DN_NDFLAG_R2 0x0002 /* Router L2 */ 13#define DN_NDFLAG_R2 0x0002 /* Router L2 */
14#define DN_NDFLAG_P3 0x0004 /* Phase III Node */ 14#define DN_NDFLAG_P3 0x0004 /* Phase III Node */
15 unsigned long blksize; 15 unsigned long blksize;
16 unsigned char priority; 16 __u8 priority;
17}; 17};
18 18
19extern void dn_neigh_init(void); 19extern void dn_neigh_init(void);
diff --git a/include/net/dn_nsp.h b/include/net/dn_nsp.h
index e6182b86262b..96e816b6974d 100644
--- a/include/net/dn_nsp.h
+++ b/include/net/dn_nsp.h
@@ -72,77 +72,77 @@ extern struct sk_buff *dn_alloc_send_skb(struct sock *sk, size_t *size, int nobl
72 72
73struct nsp_data_seg_msg 73struct nsp_data_seg_msg
74{ 74{
75 unsigned char msgflg; 75 __u8 msgflg;
76 unsigned short dstaddr; 76 __le16 dstaddr;
77 unsigned short srcaddr; 77 __le16 srcaddr;
78} __attribute__((packed)); 78} __attribute__((packed));
79 79
80struct nsp_data_opt_msg 80struct nsp_data_opt_msg
81{ 81{
82 unsigned short acknum; 82 __le16 acknum;
83 unsigned short segnum; 83 __le16 segnum;
84 unsigned short lsflgs; 84 __le16 lsflgs;
85} __attribute__((packed)); 85} __attribute__((packed));
86 86
87struct nsp_data_opt_msg1 87struct nsp_data_opt_msg1
88{ 88{
89 unsigned short acknum; 89 __le16 acknum;
90 unsigned short segnum; 90 __le16 segnum;
91} __attribute__((packed)); 91} __attribute__((packed));
92 92
93 93
94/* Acknowledgment Message (data/other data) */ 94/* Acknowledgment Message (data/other data) */
95struct nsp_data_ack_msg 95struct nsp_data_ack_msg
96{ 96{
97 unsigned char msgflg; 97 __u8 msgflg;
98 unsigned short dstaddr; 98 __le16 dstaddr;
99 unsigned short srcaddr; 99 __le16 srcaddr;
100 unsigned short acknum; 100 __le16 acknum;
101} __attribute__((packed)); 101} __attribute__((packed));
102 102
103/* Connect Acknowledgment Message */ 103/* Connect Acknowledgment Message */
104struct nsp_conn_ack_msg 104struct nsp_conn_ack_msg
105{ 105{
106 unsigned char msgflg; 106 __u8 msgflg;
107 unsigned short dstaddr; 107 __le16 dstaddr;
108} __attribute__((packed)); 108} __attribute__((packed));
109 109
110 110
111/* Connect Initiate/Retransmit Initiate/Connect Confirm */ 111/* Connect Initiate/Retransmit Initiate/Connect Confirm */
112struct nsp_conn_init_msg 112struct nsp_conn_init_msg
113{ 113{
114 unsigned char msgflg; 114 __u8 msgflg;
115#define NSP_CI 0x18 /* Connect Initiate */ 115#define NSP_CI 0x18 /* Connect Initiate */
116#define NSP_RCI 0x68 /* Retrans. Conn Init */ 116#define NSP_RCI 0x68 /* Retrans. Conn Init */
117 unsigned short dstaddr; 117 __le16 dstaddr;
118 unsigned short srcaddr; 118 __le16 srcaddr;
119 unsigned char services; 119 __u8 services;
120#define NSP_FC_NONE 0x00 /* Flow Control None */ 120#define NSP_FC_NONE 0x00 /* Flow Control None */
121#define NSP_FC_SRC 0x04 /* Seg Req. Count */ 121#define NSP_FC_SRC 0x04 /* Seg Req. Count */
122#define NSP_FC_SCMC 0x08 /* Sess. Control Mess */ 122#define NSP_FC_SCMC 0x08 /* Sess. Control Mess */
123#define NSP_FC_MASK 0x0c /* FC type mask */ 123#define NSP_FC_MASK 0x0c /* FC type mask */
124 unsigned char info; 124 __u8 info;
125 unsigned short segsize; 125 __le16 segsize;
126} __attribute__((packed)); 126} __attribute__((packed));
127 127
128/* Disconnect Initiate/Disconnect Confirm */ 128/* Disconnect Initiate/Disconnect Confirm */
129struct nsp_disconn_init_msg 129struct nsp_disconn_init_msg
130{ 130{
131 unsigned char msgflg; 131 __u8 msgflg;
132 unsigned short dstaddr; 132 __le16 dstaddr;
133 unsigned short srcaddr; 133 __le16 srcaddr;
134 unsigned short reason; 134 __le16 reason;
135} __attribute__((packed)); 135} __attribute__((packed));
136 136
137 137
138 138
139struct srcobj_fmt 139struct srcobj_fmt
140{ 140{
141 char format; 141 __u8 format;
142 unsigned char task; 142 __u8 task;
143 unsigned short grpcode; 143 __le16 grpcode;
144 unsigned short usrcode; 144 __le16 usrcode;
145 char dlen; 145 __u8 dlen;
146} __attribute__((packed)); 146} __attribute__((packed));
147 147
148/* 148/*
@@ -150,7 +150,7 @@ struct srcobj_fmt
150 * numbers used in NSP. Similar in operation to the functions 150 * numbers used in NSP. Similar in operation to the functions
151 * of the same name in TCP. 151 * of the same name in TCP.
152 */ 152 */
153static __inline__ int dn_before(unsigned short seq1, unsigned short seq2) 153static __inline__ int dn_before(__u16 seq1, __u16 seq2)
154{ 154{
155 seq1 &= 0x0fff; 155 seq1 &= 0x0fff;
156 seq2 &= 0x0fff; 156 seq2 &= 0x0fff;
@@ -159,7 +159,7 @@ static __inline__ int dn_before(unsigned short seq1, unsigned short seq2)
159} 159}
160 160
161 161
162static __inline__ int dn_after(unsigned short seq1, unsigned short seq2) 162static __inline__ int dn_after(__u16 seq1, __u16 seq2)
163{ 163{
164 seq1 &= 0x0fff; 164 seq1 &= 0x0fff;
165 seq2 &= 0x0fff; 165 seq2 &= 0x0fff;
@@ -167,23 +167,23 @@ static __inline__ int dn_after(unsigned short seq1, unsigned short seq2)
167 return (int)((seq2 - seq1) & 0x0fff) > 2048; 167 return (int)((seq2 - seq1) & 0x0fff) > 2048;
168} 168}
169 169
170static __inline__ int dn_equal(unsigned short seq1, unsigned short seq2) 170static __inline__ int dn_equal(__u16 seq1, __u16 seq2)
171{ 171{
172 return ((seq1 ^ seq2) & 0x0fff) == 0; 172 return ((seq1 ^ seq2) & 0x0fff) == 0;
173} 173}
174 174
175static __inline__ int dn_before_or_equal(unsigned short seq1, unsigned short seq2) 175static __inline__ int dn_before_or_equal(__u16 seq1, __u16 seq2)
176{ 176{
177 return (dn_before(seq1, seq2) || dn_equal(seq1, seq2)); 177 return (dn_before(seq1, seq2) || dn_equal(seq1, seq2));
178} 178}
179 179
180static __inline__ void seq_add(unsigned short *seq, unsigned short off) 180static __inline__ void seq_add(__u16 *seq, __u16 off)
181{ 181{
182 (*seq) += off; 182 (*seq) += off;
183 (*seq) &= 0x0fff; 183 (*seq) &= 0x0fff;
184} 184}
185 185
186static __inline__ int seq_next(unsigned short seq1, unsigned short seq2) 186static __inline__ int seq_next(__u16 seq1, __u16 seq2)
187{ 187{
188 return dn_equal(seq1 + 1, seq2); 188 return dn_equal(seq1 + 1, seq2);
189} 189}
@@ -191,7 +191,7 @@ static __inline__ int seq_next(unsigned short seq1, unsigned short seq2)
191/* 191/*
192 * Can we delay the ack ? 192 * Can we delay the ack ?
193 */ 193 */
194static __inline__ int sendack(unsigned short seq) 194static __inline__ int sendack(__u16 seq)
195{ 195{
196 return (int)((seq & 0x1000) ? 0 : 1); 196 return (int)((seq & 0x1000) ? 0 : 1);
197} 197}
diff --git a/include/net/dn_route.h b/include/net/dn_route.h
index 5122da3f2eb3..76f957e258b0 100644
--- a/include/net/dn_route.h
+++ b/include/net/dn_route.h
@@ -71,12 +71,12 @@ struct dn_route {
71 struct dn_route *rt_next; 71 struct dn_route *rt_next;
72 } u; 72 } u;
73 73
74 __u16 rt_saddr; 74 __le16 rt_saddr;
75 __u16 rt_daddr; 75 __le16 rt_daddr;
76 __u16 rt_gateway; 76 __le16 rt_gateway;
77 __u16 rt_local_src; /* Source used for forwarding packets */ 77 __le16 rt_local_src; /* Source used for forwarding packets */
78 __u16 rt_src_map; 78 __le16 rt_src_map;
79 __u16 rt_dst_map; 79 __le16 rt_dst_map;
80 80
81 unsigned rt_flags; 81 unsigned rt_flags;
82 unsigned rt_type; 82 unsigned rt_type;
diff --git a/include/net/flow.h b/include/net/flow.h
index ec7eb86eb203..04d89f763451 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -30,8 +30,8 @@ struct flowi {
30 } ip6_u; 30 } ip6_u;
31 31
32 struct { 32 struct {
33 __u16 daddr; 33 __le16 daddr;
34 __u16 saddr; 34 __le16 saddr;
35 __u32 fwmark; 35 __u32 fwmark;
36 __u8 scope; 36 __u8 scope;
37 } dn_u; 37 } dn_u;
@@ -64,8 +64,8 @@ struct flowi {
64 } icmpt; 64 } icmpt;
65 65
66 struct { 66 struct {
67 __u16 sport; 67 __le16 sport;
68 __u16 dport; 68 __le16 dport;
69 __u8 objnum; 69 __u8 objnum;
70 __u8 objnamel; /* Not 16 bits since max val is 16 */ 70 __u8 objnamel; /* Not 16 bits since max val is 16 */
71 __u8 objname[16]; /* Not zero terminated */ 71 __u8 objname[16]; /* Not zero terminated */
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index eb8afe3499a9..e459e1a0ae4a 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -180,11 +180,8 @@ struct inet6_dev
180 180
181#ifdef CONFIG_IPV6_PRIVACY 181#ifdef CONFIG_IPV6_PRIVACY
182 u8 rndid[8]; 182 u8 rndid[8];
183 u8 entropy[8];
184 struct timer_list regen_timer; 183 struct timer_list regen_timer;
185 struct inet6_ifaddr *tempaddr_list; 184 struct inet6_ifaddr *tempaddr_list;
186 __u8 work_eui64[8];
187 __u8 work_digest[16];
188#endif 185#endif
189 186
190 struct neigh_parms *nd_parms; 187 struct neigh_parms *nd_parms;
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index fa587c94e9d0..9bf73fe50948 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -50,6 +50,12 @@ struct inet_connection_sock_af_ops {
50 char __user *optval, int optlen); 50 char __user *optval, int optlen);
51 int (*getsockopt)(struct sock *sk, int level, int optname, 51 int (*getsockopt)(struct sock *sk, int level, int optname,
52 char __user *optval, int __user *optlen); 52 char __user *optval, int __user *optlen);
53 int (*compat_setsockopt)(struct sock *sk,
54 int level, int optname,
55 char __user *optval, int optlen);
56 int (*compat_getsockopt)(struct sock *sk,
57 int level, int optname,
58 char __user *optval, int __user *optlen);
53 void (*addr2sockaddr)(struct sock *sk, struct sockaddr *); 59 void (*addr2sockaddr)(struct sock *sk, struct sockaddr *);
54 int sockaddr_len; 60 int sockaddr_len;
55}; 61};
@@ -72,6 +78,7 @@ struct inet_connection_sock_af_ops {
72 * @icsk_probes_out: unanswered 0 window probes 78 * @icsk_probes_out: unanswered 0 window probes
73 * @icsk_ext_hdr_len: Network protocol overhead (IP/IPv6 options) 79 * @icsk_ext_hdr_len: Network protocol overhead (IP/IPv6 options)
74 * @icsk_ack: Delayed ACK control data 80 * @icsk_ack: Delayed ACK control data
81 * @icsk_mtup; MTU probing control data
75 */ 82 */
76struct inet_connection_sock { 83struct inet_connection_sock {
77 /* inet_sock has to be the first member! */ 84 /* inet_sock has to be the first member! */
@@ -104,6 +111,16 @@ struct inet_connection_sock {
104 __u16 last_seg_size; /* Size of last incoming segment */ 111 __u16 last_seg_size; /* Size of last incoming segment */
105 __u16 rcv_mss; /* MSS used for delayed ACK decisions */ 112 __u16 rcv_mss; /* MSS used for delayed ACK decisions */
106 } icsk_ack; 113 } icsk_ack;
114 struct {
115 int enabled;
116
117 /* Range of MTUs to search */
118 int search_high;
119 int search_low;
120
121 /* Information on the current probe. */
122 int probe_size;
123 } icsk_mtup;
107 u32 icsk_ca_priv[16]; 124 u32 icsk_ca_priv[16];
108#define ICSK_CA_PRIV_SIZE (16 * sizeof(u32)) 125#define ICSK_CA_PRIV_SIZE (16 * sizeof(u32))
109}; 126};
@@ -310,4 +327,13 @@ extern void inet_csk_listen_stop(struct sock *sk);
310 327
311extern void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr); 328extern void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
312 329
330extern int inet_csk_ctl_sock_create(struct socket **sock,
331 unsigned short family,
332 unsigned short type,
333 unsigned char protocol);
334
335extern int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname,
336 char __user *optval, int __user *optlen);
337extern int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname,
338 char __user *optval, int optlen);
313#endif /* _INET_CONNECTION_SOCK_H */ 339#endif /* _INET_CONNECTION_SOCK_H */
diff --git a/include/net/ip.h b/include/net/ip.h
index fab3d5b3ab1c..8fe6156ca9b0 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -356,6 +356,10 @@ extern void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb);
356extern int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc); 356extern int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc);
357extern int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen); 357extern int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen);
358extern int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen); 358extern int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen);
359extern int compat_ip_setsockopt(struct sock *sk, int level,
360 int optname, char __user *optval, int optlen);
361extern int compat_ip_getsockopt(struct sock *sk, int level,
362 int optname, char __user *optval, int __user *optlen);
359extern int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *)); 363extern int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *));
360 364
361extern int ip_recv_error(struct sock *sk, struct msghdr *msg, int len); 365extern int ip_recv_error(struct sock *sk, struct msghdr *msg, int len);
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 1f2e428ca364..a398ae5e30f9 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -7,6 +7,23 @@
7#define IP6_RT_PRIO_KERN 512 7#define IP6_RT_PRIO_KERN 512
8#define IP6_RT_FLOW_MASK 0x00ff 8#define IP6_RT_FLOW_MASK 0x00ff
9 9
10struct route_info {
11 __u8 type;
12 __u8 length;
13 __u8 prefix_len;
14#if defined(__BIG_ENDIAN_BITFIELD)
15 __u8 reserved_h:3,
16 route_pref:2,
17 reserved_l:3;
18#elif defined(__LITTLE_ENDIAN_BITFIELD)
19 __u8 reserved_l:3,
20 route_pref:2,
21 reserved_h:3;
22#endif
23 __u32 lifetime;
24 __u8 prefix[0]; /* 0,8 or 16 */
25};
26
10#ifdef __KERNEL__ 27#ifdef __KERNEL__
11 28
12#include <net/flow.h> 29#include <net/flow.h>
@@ -87,11 +104,14 @@ extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
87extern struct rt6_info * rt6_get_dflt_router(struct in6_addr *addr, 104extern struct rt6_info * rt6_get_dflt_router(struct in6_addr *addr,
88 struct net_device *dev); 105 struct net_device *dev);
89extern struct rt6_info * rt6_add_dflt_router(struct in6_addr *gwaddr, 106extern struct rt6_info * rt6_add_dflt_router(struct in6_addr *gwaddr,
90 struct net_device *dev); 107 struct net_device *dev,
108 unsigned int pref);
91 109
92extern void rt6_purge_dflt_routers(void); 110extern void rt6_purge_dflt_routers(void);
93 111
94extern void rt6_reset_dflt_pointer(struct rt6_info *rt); 112extern int rt6_route_rcv(struct net_device *dev,
113 u8 *opt, int len,
114 struct in6_addr *gwaddr);
95 115
96extern void rt6_redirect(struct in6_addr *dest, 116extern void rt6_redirect(struct in6_addr *dest,
97 struct in6_addr *saddr, 117 struct in6_addr *saddr,
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 3b1d963d396c..6d6f0634ae41 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -282,6 +282,18 @@ static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr
282 return memcmp((const void *) a1, (const void *) a2, sizeof(struct in6_addr)); 282 return memcmp((const void *) a1, (const void *) a2, sizeof(struct in6_addr));
283} 283}
284 284
285static inline int
286ipv6_masked_addr_cmp(const struct in6_addr *a1, const struct in6_addr *m,
287 const struct in6_addr *a2)
288{
289 unsigned int i;
290
291 for (i = 0; i < 4; i++)
292 if ((a1->s6_addr32[i] ^ a2->s6_addr32[i]) & m->s6_addr32[i])
293 return 1;
294 return 0;
295}
296
285static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2) 297static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2)
286{ 298{
287 memcpy((void *) a1, (const void *) a2, sizeof(struct in6_addr)); 299 memcpy((void *) a1, (const void *) a2, sizeof(struct in6_addr));
@@ -508,6 +520,16 @@ extern int ipv6_getsockopt(struct sock *sk, int level,
508 int optname, 520 int optname,
509 char __user *optval, 521 char __user *optval,
510 int __user *optlen); 522 int __user *optlen);
523extern int compat_ipv6_setsockopt(struct sock *sk,
524 int level,
525 int optname,
526 char __user *optval,
527 int optlen);
528extern int compat_ipv6_getsockopt(struct sock *sk,
529 int level,
530 int optname,
531 char __user *optval,
532 int __user *optlen);
511 533
512extern void ipv6_packet_init(void); 534extern void ipv6_packet_init(void);
513 535
diff --git a/include/net/llc.h b/include/net/llc.h
index 1adb2ef3f6f7..f5024583fc8b 100644
--- a/include/net/llc.h
+++ b/include/net/llc.h
@@ -71,7 +71,7 @@ extern int llc_rcv(struct sk_buff *skb, struct net_device *dev,
71 struct packet_type *pt, struct net_device *orig_dev); 71 struct packet_type *pt, struct net_device *orig_dev);
72 72
73extern int llc_mac_hdr_init(struct sk_buff *skb, 73extern int llc_mac_hdr_init(struct sk_buff *skb,
74 unsigned char *sa, unsigned char *da); 74 const unsigned char *sa, const unsigned char *da);
75 75
76extern void llc_add_pack(int type, void (*handler)(struct llc_sap *sap, 76extern void llc_add_pack(int type, void (*handler)(struct llc_sap *sap,
77 struct sk_buff *skb)); 77 struct sk_buff *skb));
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index bbac87eeb422..91fa271a0064 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -22,6 +22,8 @@ enum {
22 ND_OPT_PREFIX_INFO = 3, /* RFC2461 */ 22 ND_OPT_PREFIX_INFO = 3, /* RFC2461 */
23 ND_OPT_REDIRECT_HDR = 4, /* RFC2461 */ 23 ND_OPT_REDIRECT_HDR = 4, /* RFC2461 */
24 ND_OPT_MTU = 5, /* RFC2461 */ 24 ND_OPT_MTU = 5, /* RFC2461 */
25 __ND_OPT_ARRAY_MAX,
26 ND_OPT_ROUTE_INFO = 24, /* RFC4191 */
25 __ND_OPT_MAX 27 __ND_OPT_MAX
26}; 28};
27 29
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 6fa9ae190741..b0666d66293f 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -68,6 +68,7 @@ struct neigh_parms
68 struct net_device *dev; 68 struct net_device *dev;
69 struct neigh_parms *next; 69 struct neigh_parms *next;
70 int (*neigh_setup)(struct neighbour *); 70 int (*neigh_setup)(struct neighbour *);
71 void (*neigh_destructor)(struct neighbour *);
71 struct neigh_table *tbl; 72 struct neigh_table *tbl;
72 73
73 void *sysctl_table; 74 void *sysctl_table;
@@ -145,7 +146,6 @@ struct neighbour
145struct neigh_ops 146struct neigh_ops
146{ 147{
147 int family; 148 int family;
148 void (*destructor)(struct neighbour *);
149 void (*solicit)(struct neighbour *, struct sk_buff*); 149 void (*solicit)(struct neighbour *, struct sk_buff*);
150 void (*error_report)(struct neighbour *, struct sk_buff*); 150 void (*error_report)(struct neighbour *, struct sk_buff*);
151 int (*output)(struct sk_buff*); 151 int (*output)(struct sk_buff*);
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 6d075ca16e6e..2743c156caa0 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -67,6 +67,18 @@ do { \
67 67
68struct nf_conntrack_helper; 68struct nf_conntrack_helper;
69 69
70/* nf_conn feature for connections that have a helper */
71struct nf_conn_help {
72 /* Helper. if any */
73 struct nf_conntrack_helper *helper;
74
75 union nf_conntrack_help help;
76
77 /* Current number of expected connections */
78 unsigned int expecting;
79};
80
81
70#include <net/netfilter/ipv4/nf_conntrack_ipv4.h> 82#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
71struct nf_conn 83struct nf_conn
72{ 84{
@@ -81,6 +93,9 @@ struct nf_conn
81 /* Have we seen traffic both ways yet? (bitset) */ 93 /* Have we seen traffic both ways yet? (bitset) */
82 unsigned long status; 94 unsigned long status;
83 95
96 /* If we were expected by an expectation, this will be it */
97 struct nf_conn *master;
98
84 /* Timer function; drops refcnt when it goes off. */ 99 /* Timer function; drops refcnt when it goes off. */
85 struct timer_list timeout; 100 struct timer_list timeout;
86 101
@@ -88,38 +103,22 @@ struct nf_conn
88 /* Accounting Information (same cache line as other written members) */ 103 /* Accounting Information (same cache line as other written members) */
89 struct ip_conntrack_counter counters[IP_CT_DIR_MAX]; 104 struct ip_conntrack_counter counters[IP_CT_DIR_MAX];
90#endif 105#endif
91 /* If we were expected by an expectation, this will be it */
92 struct nf_conn *master;
93
94 /* Current number of expected connections */
95 unsigned int expecting;
96 106
97 /* Unique ID that identifies this conntrack*/ 107 /* Unique ID that identifies this conntrack*/
98 unsigned int id; 108 unsigned int id;
99 109
100 /* Helper. if any */
101 struct nf_conntrack_helper *helper;
102
103 /* features - nat, helper, ... used by allocating system */ 110 /* features - nat, helper, ... used by allocating system */
104 u_int32_t features; 111 u_int32_t features;
105 112
106 /* Storage reserved for other modules: */
107
108 union nf_conntrack_proto proto;
109
110#if defined(CONFIG_NF_CONNTRACK_MARK) 113#if defined(CONFIG_NF_CONNTRACK_MARK)
111 u_int32_t mark; 114 u_int32_t mark;
112#endif 115#endif
113 116
114 /* These members are dynamically allocated. */ 117 /* Storage reserved for other modules: */
115 118 union nf_conntrack_proto proto;
116 union nf_conntrack_help *help;
117 119
118 /* Layer 3 dependent members. (ex: NAT) */ 120 /* features dynamically at the end: helper, nat (both optional) */
119 union { 121 char data[0];
120 struct nf_conntrack_ipv4 *ipv4;
121 } l3proto;
122 void *data[0];
123}; 122};
124 123
125struct nf_conntrack_expect 124struct nf_conntrack_expect
@@ -373,10 +372,23 @@ nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
373#define NF_CT_F_NUM 4 372#define NF_CT_F_NUM 4
374 373
375extern int 374extern int
376nf_conntrack_register_cache(u_int32_t features, const char *name, size_t size, 375nf_conntrack_register_cache(u_int32_t features, const char *name, size_t size);
377 int (*init_conntrack)(struct nf_conn *, u_int32_t));
378extern void 376extern void
379nf_conntrack_unregister_cache(u_int32_t features); 377nf_conntrack_unregister_cache(u_int32_t features);
380 378
379/* valid combinations:
380 * basic: nf_conn, nf_conn .. nf_conn_help
381 * nat: nf_conn .. nf_conn_nat, nf_conn .. nf_conn_nat, nf_conn help
382 */
383static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
384{
385 unsigned int offset = sizeof(struct nf_conn);
386
387 if (!(ct->features & NF_CT_F_HELP))
388 return NULL;
389
390 return (struct nf_conn_help *) ((void *)ct + offset);
391}
392
381#endif /* __KERNEL__ */ 393#endif /* __KERNEL__ */
382#endif /* _NF_CONNTRACK_H */ 394#endif /* _NF_CONNTRACK_H */
diff --git a/include/net/scm.h b/include/net/scm.h
index c3fa3d5ab606..540619cb7160 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -37,10 +37,12 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
37static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, 37static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
38 struct scm_cookie *scm) 38 struct scm_cookie *scm)
39{ 39{
40 memset(scm, 0, sizeof(*scm)); 40 struct task_struct *p = current;
41 scm->creds.uid = current->uid; 41 scm->creds.uid = p->uid;
42 scm->creds.gid = current->gid; 42 scm->creds.gid = p->gid;
43 scm->creds.pid = current->tgid; 43 scm->creds.pid = p->tgid;
44 scm->fp = NULL;
45 scm->seq = 0;
44 if (msg->msg_controllen <= 0) 46 if (msg->msg_controllen <= 0)
45 return 0; 47 return 0;
46 return __scm_send(sock, msg, scm); 48 return __scm_send(sock, msg, scm);
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 072f407848a6..eba99f375517 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -514,6 +514,16 @@ struct sctp_af {
514 int optname, 514 int optname,
515 char __user *optval, 515 char __user *optval,
516 int __user *optlen); 516 int __user *optlen);
517 int (*compat_setsockopt) (struct sock *sk,
518 int level,
519 int optname,
520 char __user *optval,
521 int optlen);
522 int (*compat_getsockopt) (struct sock *sk,
523 int level,
524 int optname,
525 char __user *optval,
526 int __user *optlen);
517 struct dst_entry *(*get_dst) (struct sctp_association *asoc, 527 struct dst_entry *(*get_dst) (struct sctp_association *asoc,
518 union sctp_addr *daddr, 528 union sctp_addr *daddr,
519 union sctp_addr *saddr); 529 union sctp_addr *saddr);
diff --git a/include/net/sock.h b/include/net/sock.h
index f63d0d56712c..ec226f31dc2a 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -520,6 +520,14 @@ struct proto {
520 int (*getsockopt)(struct sock *sk, int level, 520 int (*getsockopt)(struct sock *sk, int level,
521 int optname, char __user *optval, 521 int optname, char __user *optval,
522 int __user *option); 522 int __user *option);
523 int (*compat_setsockopt)(struct sock *sk,
524 int level,
525 int optname, char __user *optval,
526 int optlen);
527 int (*compat_getsockopt)(struct sock *sk,
528 int level,
529 int optname, char __user *optval,
530 int __user *option);
523 int (*sendmsg)(struct kiocb *iocb, struct sock *sk, 531 int (*sendmsg)(struct kiocb *iocb, struct sock *sk,
524 struct msghdr *msg, size_t len); 532 struct msghdr *msg, size_t len);
525 int (*recvmsg)(struct kiocb *iocb, struct sock *sk, 533 int (*recvmsg)(struct kiocb *iocb, struct sock *sk,
@@ -816,6 +824,10 @@ extern int sock_common_recvmsg(struct kiocb *iocb, struct socket *sock,
816 struct msghdr *msg, size_t size, int flags); 824 struct msghdr *msg, size_t size, int flags);
817extern int sock_common_setsockopt(struct socket *sock, int level, int optname, 825extern int sock_common_setsockopt(struct socket *sock, int level, int optname,
818 char __user *optval, int optlen); 826 char __user *optval, int optlen);
827extern int compat_sock_common_getsockopt(struct socket *sock, int level,
828 int optname, char __user *optval, int __user *optlen);
829extern int compat_sock_common_setsockopt(struct socket *sock, int level,
830 int optname, char __user *optval, int optlen);
819 831
820extern void sk_common_release(struct sock *sk); 832extern void sk_common_release(struct sock *sk);
821 833
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 77f21c65bbca..9418f4d1afbb 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -60,6 +60,9 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
60/* Minimal RCV_MSS. */ 60/* Minimal RCV_MSS. */
61#define TCP_MIN_RCVMSS 536U 61#define TCP_MIN_RCVMSS 536U
62 62
63/* The least MTU to use for probing */
64#define TCP_BASE_MSS 512
65
63/* After receiving this amount of duplicate ACKs fast retransmit starts. */ 66/* After receiving this amount of duplicate ACKs fast retransmit starts. */
64#define TCP_FASTRETRANS_THRESH 3 67#define TCP_FASTRETRANS_THRESH 3
65 68
@@ -219,6 +222,9 @@ extern int sysctl_tcp_nometrics_save;
219extern int sysctl_tcp_moderate_rcvbuf; 222extern int sysctl_tcp_moderate_rcvbuf;
220extern int sysctl_tcp_tso_win_divisor; 223extern int sysctl_tcp_tso_win_divisor;
221extern int sysctl_tcp_abc; 224extern int sysctl_tcp_abc;
225extern int sysctl_tcp_mtu_probing;
226extern int sysctl_tcp_base_mss;
227extern int sysctl_tcp_workaround_signed_windows;
222 228
223extern atomic_t tcp_memory_allocated; 229extern atomic_t tcp_memory_allocated;
224extern atomic_t tcp_sockets_allocated; 230extern atomic_t tcp_sockets_allocated;
@@ -347,6 +353,12 @@ extern int tcp_getsockopt(struct sock *sk, int level,
347extern int tcp_setsockopt(struct sock *sk, int level, 353extern int tcp_setsockopt(struct sock *sk, int level,
348 int optname, char __user *optval, 354 int optname, char __user *optval,
349 int optlen); 355 int optlen);
356extern int compat_tcp_getsockopt(struct sock *sk,
357 int level, int optname,
358 char __user *optval, int __user *optlen);
359extern int compat_tcp_setsockopt(struct sock *sk,
360 int level, int optname,
361 char __user *optval, int optlen);
350extern void tcp_set_keepalive(struct sock *sk, int val); 362extern void tcp_set_keepalive(struct sock *sk, int val);
351extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, 363extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk,
352 struct msghdr *msg, 364 struct msghdr *msg,
@@ -447,6 +459,10 @@ extern int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
447 459
448extern void tcp_initialize_rcv_mss(struct sock *sk); 460extern void tcp_initialize_rcv_mss(struct sock *sk);
449 461
462extern int tcp_mtu_to_mss(struct sock *sk, int pmtu);
463extern int tcp_mss_to_mtu(struct sock *sk, int mss);
464extern void tcp_mtup_init(struct sock *sk);
465
450static inline void __tcp_fast_path_on(struct tcp_sock *tp, u32 snd_wnd) 466static inline void __tcp_fast_path_on(struct tcp_sock *tp, u32 snd_wnd)
451{ 467{
452 tp->pred_flags = htonl((tp->tcp_header_len << 26) | 468 tp->pred_flags = htonl((tp->tcp_header_len << 26) |
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 8d362c49b8a9..61b7504fc2ba 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -11,6 +11,7 @@
11#include <linux/crypto.h> 11#include <linux/crypto.h>
12#include <linux/pfkeyv2.h> 12#include <linux/pfkeyv2.h>
13#include <linux/in6.h> 13#include <linux/in6.h>
14#include <linux/mutex.h>
14 15
15#include <net/sock.h> 16#include <net/sock.h>
16#include <net/dst.h> 17#include <net/dst.h>
@@ -20,7 +21,11 @@
20 21
21#define XFRM_ALIGN8(len) (((len) + 7) & ~7) 22#define XFRM_ALIGN8(len) (((len) + 7) & ~7)
22 23
23extern struct semaphore xfrm_cfg_sem; 24extern struct sock *xfrm_nl;
25extern u32 sysctl_xfrm_aevent_etime;
26extern u32 sysctl_xfrm_aevent_rseqth;
27
28extern struct mutex xfrm_cfg_mutex;
24 29
25/* Organization of SPD aka "XFRM rules" 30/* Organization of SPD aka "XFRM rules"
26 ------------------------------------ 31 ------------------------------------
@@ -135,6 +140,16 @@ struct xfrm_state
135 /* State for replay detection */ 140 /* State for replay detection */
136 struct xfrm_replay_state replay; 141 struct xfrm_replay_state replay;
137 142
143 /* Replay detection state at the time we sent the last notification */
144 struct xfrm_replay_state preplay;
145
146 /* Replay detection notification settings */
147 u32 replay_maxage;
148 u32 replay_maxdiff;
149
150 /* Replay detection notification timer */
151 struct timer_list rtimer;
152
138 /* Statistics */ 153 /* Statistics */
139 struct xfrm_stats stats; 154 struct xfrm_stats stats;
140 155
@@ -169,6 +184,7 @@ struct km_event
169 u32 hard; 184 u32 hard;
170 u32 proto; 185 u32 proto;
171 u32 byid; 186 u32 byid;
187 u32 aevent;
172 } data; 188 } data;
173 189
174 u32 seq; 190 u32 seq;
@@ -199,10 +215,13 @@ extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
199extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo); 215extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
200extern void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c); 216extern void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c);
201extern void km_state_notify(struct xfrm_state *x, struct km_event *c); 217extern void km_state_notify(struct xfrm_state *x, struct km_event *c);
202
203#define XFRM_ACQ_EXPIRES 30 218#define XFRM_ACQ_EXPIRES 30
204 219
205struct xfrm_tmpl; 220struct xfrm_tmpl;
221extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
222extern void km_state_expired(struct xfrm_state *x, int hard, u32 pid);
223extern int __xfrm_state_delete(struct xfrm_state *x);
224
206struct xfrm_state_afinfo { 225struct xfrm_state_afinfo {
207 unsigned short family; 226 unsigned short family;
208 rwlock_t lock; 227 rwlock_t lock;
@@ -305,7 +324,21 @@ struct xfrm_policy
305 struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH]; 324 struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH];
306}; 325};
307 326
308#define XFRM_KM_TIMEOUT 30 327#define XFRM_KM_TIMEOUT 30
328/* which seqno */
329#define XFRM_REPLAY_SEQ 1
330#define XFRM_REPLAY_OSEQ 2
331#define XFRM_REPLAY_SEQ_MASK 3
332/* what happened */
333#define XFRM_REPLAY_UPDATE XFRM_AE_CR
334#define XFRM_REPLAY_TIMEOUT XFRM_AE_CE
335
336/* default aevent timeout in units of 100ms */
337#define XFRM_AE_ETIME 10
338/* Async Event timer multiplier */
339#define XFRM_AE_ETH_M 10
340/* default seq threshold size */
341#define XFRM_AE_SEQT_SIZE 2
309 342
310struct xfrm_mgr 343struct xfrm_mgr
311{ 344{
@@ -865,6 +898,7 @@ extern int xfrm_state_delete(struct xfrm_state *x);
865extern void xfrm_state_flush(u8 proto); 898extern void xfrm_state_flush(u8 proto);
866extern int xfrm_replay_check(struct xfrm_state *x, u32 seq); 899extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
867extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq); 900extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
901extern void xfrm_replay_notify(struct xfrm_state *x, int event);
868extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb); 902extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb);
869extern int xfrm_state_mtu(struct xfrm_state *x, int mtu); 903extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
870extern int xfrm_init_state(struct xfrm_state *x); 904extern int xfrm_init_state(struct xfrm_state *x);
@@ -924,7 +958,7 @@ extern void xfrm_init_pmtu(struct dst_entry *dst);
924 958
925extern wait_queue_head_t km_waitq; 959extern wait_queue_head_t km_waitq;
926extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport); 960extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
927extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard); 961extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid);
928 962
929extern void xfrm_input_init(void); 963extern void xfrm_input_init(void);
930extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq); 964extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq);
@@ -965,4 +999,24 @@ static inline int xfrm_policy_id2dir(u32 index)
965 return index & 7; 999 return index & 7;
966} 1000}
967 1001
1002static inline int xfrm_aevent_is_on(void)
1003{
1004 struct sock *nlsk;
1005 int ret = 0;
1006
1007 rcu_read_lock();
1008 nlsk = rcu_dereference(xfrm_nl);
1009 if (nlsk)
1010 ret = netlink_has_listeners(nlsk, XFRMNLGRP_AEVENTS);
1011 rcu_read_unlock();
1012 return ret;
1013}
1014
1015static inline void xfrm_aevent_doreplay(struct xfrm_state *x)
1016{
1017 if (xfrm_aevent_is_on())
1018 xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
1019}
1020
1021
968#endif /* _NET_XFRM_H */ 1022#endif /* _NET_XFRM_H */
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/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..13177a1a4b39 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,42 @@ 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);
513} 544}
514 545
546asmlinkage long compat_sys_getsockopt(int fd, int level, int optname,
547 char __user *optval, int __user *optlen)
548{
549 int err;
550 struct socket *sock;
551
552 if ((sock = sockfd_lookup(fd, &err))!=NULL)
553 {
554 err = security_socket_getsockopt(sock, level,
555 optname);
556 if (err) {
557 sockfd_put(sock);
558 return err;
559 }
560
561 if (level == SOL_SOCKET)
562 err = compat_sock_getsockopt(sock, level,
563 optname, optval, optlen);
564 else if (sock->ops->compat_getsockopt)
565 err = sock->ops->compat_getsockopt(sock, level,
566 optname, optval, optlen);
567 else
568 err = sock->ops->getsockopt(sock, level,
569 optname, optval, optlen);
570 sockfd_put(sock);
571 }
572 return err;
573}
515/* Argument list sizes for compat_sys_socketcall */ 574/* Argument list sizes for compat_sys_socketcall */
516#define AL(x) ((x) * sizeof(u32)) 575#define AL(x) ((x) * sizeof(u32))
517static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), 576static 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..8eedaedba743 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -113,6 +113,7 @@
113#include <linux/moduleparam.h> 113#include <linux/moduleparam.h>
114#include <linux/kernel.h> 114#include <linux/kernel.h>
115#include <linux/smp_lock.h> 115#include <linux/smp_lock.h>
116#include <linux/mutex.h>
116#include <linux/sched.h> 117#include <linux/sched.h>
117#include <linux/slab.h> 118#include <linux/slab.h>
118#include <linux/vmalloc.h> 119#include <linux/vmalloc.h>
@@ -125,6 +126,7 @@
125#include <linux/capability.h> 126#include <linux/capability.h>
126#include <linux/delay.h> 127#include <linux/delay.h>
127#include <linux/timer.h> 128#include <linux/timer.h>
129#include <linux/list.h>
128#include <linux/init.h> 130#include <linux/init.h>
129#include <linux/skbuff.h> 131#include <linux/skbuff.h>
130#include <linux/netdevice.h> 132#include <linux/netdevice.h>
@@ -149,38 +151,34 @@
149#include <asm/io.h> 151#include <asm/io.h>
150#include <asm/dma.h> 152#include <asm/dma.h>
151#include <asm/uaccess.h> 153#include <asm/uaccess.h>
152#include <asm/div64.h> /* do_div */ 154#include <asm/div64.h> /* do_div */
153#include <asm/timex.h> 155#include <asm/timex.h>
154 156
155 157#define VERSION "pktgen v2.66: Packet Generator for packet performance testing.\n"
156#define VERSION "pktgen v2.63: Packet Generator for packet performance testing.\n"
157 158
158/* #define PG_DEBUG(a) a */ 159/* #define PG_DEBUG(a) a */
159#define PG_DEBUG(a) 160#define PG_DEBUG(a)
160 161
161/* The buckets are exponential in 'width' */ 162/* The buckets are exponential in 'width' */
162#define LAT_BUCKETS_MAX 32 163#define LAT_BUCKETS_MAX 32
163#define IP_NAME_SZ 32 164#define IP_NAME_SZ 32
164 165
165/* Device flag bits */ 166/* Device flag bits */
166#define F_IPSRC_RND (1<<0) /* IP-Src Random */ 167#define F_IPSRC_RND (1<<0) /* IP-Src Random */
167#define F_IPDST_RND (1<<1) /* IP-Dst Random */ 168#define F_IPDST_RND (1<<1) /* IP-Dst Random */
168#define F_UDPSRC_RND (1<<2) /* UDP-Src Random */ 169#define F_UDPSRC_RND (1<<2) /* UDP-Src Random */
169#define F_UDPDST_RND (1<<3) /* UDP-Dst Random */ 170#define F_UDPDST_RND (1<<3) /* UDP-Dst Random */
170#define F_MACSRC_RND (1<<4) /* MAC-Src Random */ 171#define F_MACSRC_RND (1<<4) /* MAC-Src Random */
171#define F_MACDST_RND (1<<5) /* MAC-Dst Random */ 172#define F_MACDST_RND (1<<5) /* MAC-Dst Random */
172#define F_TXSIZE_RND (1<<6) /* Transmit size is random */ 173#define F_TXSIZE_RND (1<<6) /* Transmit size is random */
173#define F_IPV6 (1<<7) /* Interface in IPV6 Mode */ 174#define F_IPV6 (1<<7) /* Interface in IPV6 Mode */
174 175
175/* Thread control flag bits */ 176/* Thread control flag bits */
176#define T_TERMINATE (1<<0) 177#define T_TERMINATE (1<<0)
177#define T_STOP (1<<1) /* Stop run */ 178#define T_STOP (1<<1) /* Stop run */
178#define T_RUN (1<<2) /* Start run */ 179#define T_RUN (1<<2) /* Start run */
179#define T_REMDEV (1<<3) /* Remove all devs */ 180#define T_REMDEVALL (1<<3) /* Remove all devs */
180 181#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 182
185/* If lock -- can be removed after some work */ 183/* If lock -- can be removed after some work */
186#define if_lock(t) spin_lock(&(t->if_lock)); 184#define if_lock(t) spin_lock(&(t->if_lock));
@@ -194,10 +192,9 @@ static struct proc_dir_entry *pg_proc_dir = NULL;
194 192
195#define MAX_CFLOWS 65536 193#define MAX_CFLOWS 65536
196 194
197struct flow_state 195struct flow_state {
198{ 196 __u32 cur_daddr;
199 __u32 cur_daddr; 197 int count;
200 int count;
201}; 198};
202 199
203struct pktgen_dev { 200struct pktgen_dev {
@@ -206,141 +203,144 @@ struct pktgen_dev {
206 * Try to keep frequent/infrequent used vars. separated. 203 * Try to keep frequent/infrequent used vars. separated.
207 */ 204 */
208 205
209 char ifname[IFNAMSIZ]; 206 char ifname[IFNAMSIZ];
210 char result[512]; 207 char result[512];
211 208
212 struct pktgen_thread* pg_thread; /* the owner */ 209 struct pktgen_thread *pg_thread; /* the owner */
213 struct pktgen_dev *next; /* Used for chaining in the thread's run-queue */ 210 struct list_head list; /* Used for chaining in the thread's run-queue */
214 211
215 int running; /* if this changes to false, the test will stop */ 212 int running; /* if this changes to false, the test will stop */
216 213
217 /* If min != max, then we will either do a linear iteration, or 214 /* If min != max, then we will either do a linear iteration, or
218 * we will do a random selection from within the range. 215 * we will do a random selection from within the range.
219 */ 216 */
220 __u32 flags; 217 __u32 flags;
221 218 int removal_mark; /* non-zero => the device is marked for
222 int min_pkt_size; /* = ETH_ZLEN; */ 219 * removal by worker thread */
223 int max_pkt_size; /* = ETH_ZLEN; */ 220
224 int nfrags; 221 int min_pkt_size; /* = ETH_ZLEN; */
225 __u32 delay_us; /* Default delay */ 222 int max_pkt_size; /* = ETH_ZLEN; */
226 __u32 delay_ns; 223 int nfrags;
227 __u64 count; /* Default No packets to send */ 224 __u32 delay_us; /* Default delay */
228 __u64 sofar; /* How many pkts we've sent so far */ 225 __u32 delay_ns;
229 __u64 tx_bytes; /* How many bytes we've transmitted */ 226 __u64 count; /* Default No packets to send */
230 __u64 errors; /* Errors when trying to transmit, pkts will be re-sent */ 227 __u64 sofar; /* How many pkts we've sent so far */
231 228 __u64 tx_bytes; /* How many bytes we've transmitted */
232 /* runtime counters relating to clone_skb */ 229 __u64 errors; /* Errors when trying to transmit, pkts will be re-sent */
233 __u64 next_tx_us; /* timestamp of when to tx next */ 230
234 __u32 next_tx_ns; 231 /* runtime counters relating to clone_skb */
235 232 __u64 next_tx_us; /* timestamp of when to tx next */
236 __u64 allocated_skbs; 233 __u32 next_tx_ns;
237 __u32 clone_count; 234
238 int last_ok; /* Was last skb sent? 235 __u64 allocated_skbs;
239 * Or a failed transmit of some sort? This will keep 236 __u32 clone_count;
240 * sequence numbers in order, for example. 237 int last_ok; /* Was last skb sent?
241 */ 238 * Or a failed transmit of some sort? This will keep
242 __u64 started_at; /* micro-seconds */ 239 * sequence numbers in order, for example.
243 __u64 stopped_at; /* micro-seconds */ 240 */
244 __u64 idle_acc; /* micro-seconds */ 241 __u64 started_at; /* micro-seconds */
245 __u32 seq_num; 242 __u64 stopped_at; /* micro-seconds */
246 243 __u64 idle_acc; /* micro-seconds */
247 int clone_skb; /* Use multiple SKBs during packet gen. If this number 244 __u32 seq_num;
248 * is greater than 1, then that many copies of the same 245
249 * packet will be sent before a new packet is allocated. 246 int clone_skb; /* Use multiple SKBs during packet gen. If this number
250 * For instance, if you want to send 1024 identical packets 247 * is greater than 1, then that many copies of the same
251 * before creating a new packet, set clone_skb to 1024. 248 * packet will be sent before a new packet is allocated.
252 */ 249 * For instance, if you want to send 1024 identical packets
253 250 * before creating a new packet, set clone_skb to 1024.
254 char dst_min[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */ 251 */
255 char dst_max[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */ 252
256 char src_min[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */ 253 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 */ 254 char dst_max[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */
258 255 char src_min[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */
259 struct in6_addr in6_saddr; 256 char src_max[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */
260 struct in6_addr in6_daddr; 257
261 struct in6_addr cur_in6_daddr; 258 struct in6_addr in6_saddr;
262 struct in6_addr cur_in6_saddr; 259 struct in6_addr in6_daddr;
260 struct in6_addr cur_in6_daddr;
261 struct in6_addr cur_in6_saddr;
263 /* For ranges */ 262 /* For ranges */
264 struct in6_addr min_in6_daddr; 263 struct in6_addr min_in6_daddr;
265 struct in6_addr max_in6_daddr; 264 struct in6_addr max_in6_daddr;
266 struct in6_addr min_in6_saddr; 265 struct in6_addr min_in6_saddr;
267 struct in6_addr max_in6_saddr; 266 struct in6_addr max_in6_saddr;
268 267
269 /* If we're doing ranges, random or incremental, then this 268 /* If we're doing ranges, random or incremental, then this
270 * defines the min/max for those ranges. 269 * defines the min/max for those ranges.
271 */ 270 */
272 __u32 saddr_min; /* inclusive, source IP address */ 271 __u32 saddr_min; /* inclusive, source IP address */
273 __u32 saddr_max; /* exclusive, source IP address */ 272 __u32 saddr_max; /* exclusive, source IP address */
274 __u32 daddr_min; /* inclusive, dest IP address */ 273 __u32 daddr_min; /* inclusive, dest IP address */
275 __u32 daddr_max; /* exclusive, dest IP address */ 274 __u32 daddr_max; /* exclusive, dest IP address */
276 275
277 __u16 udp_src_min; /* inclusive, source UDP port */ 276 __u16 udp_src_min; /* inclusive, source UDP port */
278 __u16 udp_src_max; /* exclusive, source UDP port */ 277 __u16 udp_src_max; /* exclusive, source UDP port */
279 __u16 udp_dst_min; /* inclusive, dest UDP port */ 278 __u16 udp_dst_min; /* inclusive, dest UDP port */
280 __u16 udp_dst_max; /* exclusive, dest UDP port */ 279 __u16 udp_dst_max; /* exclusive, dest UDP port */
281 280
282 __u32 src_mac_count; /* How many MACs to iterate through */ 281 __u32 src_mac_count; /* How many MACs to iterate through */
283 __u32 dst_mac_count; /* How many MACs to iterate through */ 282 __u32 dst_mac_count; /* How many MACs to iterate through */
284 283
285 unsigned char dst_mac[ETH_ALEN]; 284 unsigned char dst_mac[ETH_ALEN];
286 unsigned char src_mac[ETH_ALEN]; 285 unsigned char src_mac[ETH_ALEN];
287 286
288 __u32 cur_dst_mac_offset; 287 __u32 cur_dst_mac_offset;
289 __u32 cur_src_mac_offset; 288 __u32 cur_src_mac_offset;
290 __u32 cur_saddr; 289 __u32 cur_saddr;
291 __u32 cur_daddr; 290 __u32 cur_daddr;
292 __u16 cur_udp_dst; 291 __u16 cur_udp_dst;
293 __u16 cur_udp_src; 292 __u16 cur_udp_src;
294 __u32 cur_pkt_size; 293 __u32 cur_pkt_size;
295 294
296 __u8 hh[14]; 295 __u8 hh[14];
297 /* = { 296 /* = {
298 0x00, 0x80, 0xC8, 0x79, 0xB3, 0xCB, 297 0x00, 0x80, 0xC8, 0x79, 0xB3, 0xCB,
299 298
300 We fill in SRC address later 299 We fill in SRC address later
301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 300 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
302 0x08, 0x00 301 0x08, 0x00
303 }; 302 };
304 */ 303 */
305 __u16 pad; /* pad out the hh struct to an even 16 bytes */ 304 __u16 pad; /* pad out the hh struct to an even 16 bytes */
306 305
307 struct sk_buff* skb; /* skb we are to transmit next, mainly used for when we 306 struct sk_buff *skb; /* skb we are to transmit next, mainly used for when we
308 * are transmitting the same one multiple times 307 * are transmitting the same one multiple times
309 */ 308 */
310 struct net_device* odev; /* The out-going device. Note that the device should 309 struct net_device *odev; /* The out-going device. Note that the device should
311 * have it's pg_info pointer pointing back to this 310 * have it's pg_info pointer pointing back to this
312 * device. This will be set when the user specifies 311 * device. This will be set when the user specifies
313 * the out-going device name (not when the inject is 312 * the out-going device name (not when the inject is
314 * started as it used to do.) 313 * started as it used to do.)
315 */ 314 */
316 struct flow_state *flows; 315 struct flow_state *flows;
317 unsigned cflows; /* Concurrent flows (config) */ 316 unsigned cflows; /* Concurrent flows (config) */
318 unsigned lflow; /* Flow length (config) */ 317 unsigned lflow; /* Flow length (config) */
319 unsigned nflows; /* accumulated flows (stats) */ 318 unsigned nflows; /* accumulated flows (stats) */
320}; 319};
321 320
322struct pktgen_hdr { 321struct pktgen_hdr {
323 __u32 pgh_magic; 322 __u32 pgh_magic;
324 __u32 seq_num; 323 __u32 seq_num;
325 __u32 tv_sec; 324 __u32 tv_sec;
326 __u32 tv_usec; 325 __u32 tv_usec;
327}; 326};
328 327
329struct pktgen_thread { 328struct pktgen_thread {
330 spinlock_t if_lock; 329 spinlock_t if_lock;
331 struct pktgen_dev *if_list; /* All device here */ 330 struct list_head if_list; /* All device here */
332 struct pktgen_thread* next; 331 struct list_head th_list;
333 char name[32]; 332 int removed;
334 char result[512]; 333 char name[32];
335 u32 max_before_softirq; /* We'll call do_softirq to prevent starvation. */ 334 char result[512];
336 335 u32 max_before_softirq; /* We'll call do_softirq to prevent starvation. */
337 /* Field for thread to receive "posted" events terminate, stop ifs etc.*/ 336
338 337 /* Field for thread to receive "posted" events terminate, stop ifs etc. */
339 u32 control; 338
339 u32 control;
340 int pid; 340 int pid;
341 int cpu; 341 int cpu;
342 342
343 wait_queue_head_t queue; 343 wait_queue_head_t queue;
344}; 344};
345 345
346#define REMOVE 1 346#define REMOVE 1
@@ -364,77 +364,76 @@ struct pktgen_thread {
364 */ 364 */
365static inline s64 divremdi3(s64 x, s64 y, int type) 365static inline s64 divremdi3(s64 x, s64 y, int type)
366{ 366{
367 u64 a = (x < 0) ? -x : x; 367 u64 a = (x < 0) ? -x : x;
368 u64 b = (y < 0) ? -y : y; 368 u64 b = (y < 0) ? -y : y;
369 u64 res = 0, d = 1; 369 u64 res = 0, d = 1;
370 370
371 if (b > 0) { 371 if (b > 0) {
372 while (b < a) { 372 while (b < a) {
373 b <<= 1; 373 b <<= 1;
374 d <<= 1; 374 d <<= 1;
375 } 375 }
376 } 376 }
377 377
378 do { 378 do {
379 if ( a >= b ) { 379 if (a >= b) {
380 a -= b; 380 a -= b;
381 res += d; 381 res += d;
382 } 382 }
383 b >>= 1; 383 b >>= 1;
384 d >>= 1; 384 d >>= 1;
385 } 385 }
386 while (d); 386 while (d);
387 387
388 if (PG_DIV == type) { 388 if (PG_DIV == type) {
389 return (((x ^ y) & (1ll<<63)) == 0) ? res : -(s64)res; 389 return (((x ^ y) & (1ll << 63)) == 0) ? res : -(s64) res;
390 } 390 } else {
391 else { 391 return ((x & (1ll << 63)) == 0) ? a : -(s64) a;
392 return ((x & (1ll<<63)) == 0) ? a : -(s64)a; 392 }
393 }
394} 393}
395 394
396/* End of hacks to deal with 64-bit math on x86 */ 395/* End of hacks to deal with 64-bit math on x86 */
397 396
398/** Convert to milliseconds */ 397/** Convert to milliseconds */
399static inline __u64 tv_to_ms(const struct timeval* tv) 398static inline __u64 tv_to_ms(const struct timeval *tv)
400{ 399{
401 __u64 ms = tv->tv_usec / 1000; 400 __u64 ms = tv->tv_usec / 1000;
402 ms += (__u64)tv->tv_sec * (__u64)1000; 401 ms += (__u64) tv->tv_sec * (__u64) 1000;
403 return ms; 402 return ms;
404} 403}
405 404
406
407/** Convert to micro-seconds */ 405/** Convert to micro-seconds */
408static inline __u64 tv_to_us(const struct timeval* tv) 406static inline __u64 tv_to_us(const struct timeval *tv)
409{ 407{
410 __u64 us = tv->tv_usec; 408 __u64 us = tv->tv_usec;
411 us += (__u64)tv->tv_sec * (__u64)1000000; 409 us += (__u64) tv->tv_sec * (__u64) 1000000;
412 return us; 410 return us;
413} 411}
414 412
415static inline __u64 pg_div(__u64 n, __u32 base) { 413static inline __u64 pg_div(__u64 n, __u32 base)
416 __u64 tmp = n; 414{
417 do_div(tmp, base); 415 __u64 tmp = n;
418 /* printk("pktgen: pg_div, n: %llu base: %d rv: %llu\n", 416 do_div(tmp, base);
419 n, base, tmp); */ 417 /* printk("pktgen: pg_div, n: %llu base: %d rv: %llu\n",
420 return tmp; 418 n, base, tmp); */
419 return tmp;
421} 420}
422 421
423static inline __u64 pg_div64(__u64 n, __u64 base) 422static inline __u64 pg_div64(__u64 n, __u64 base)
424{ 423{
425 __u64 tmp = n; 424 __u64 tmp = n;
426/* 425/*
427 * How do we know if the architecture we are running on 426 * How do we know if the architecture we are running on
428 * supports division with 64 bit base? 427 * supports division with 64 bit base?
429 * 428 *
430 */ 429 */
431#if defined(__sparc_v9__) || defined(__powerpc64__) || defined(__alpha__) || defined(__x86_64__) || defined(__ia64__) 430#if defined(__sparc_v9__) || defined(__powerpc64__) || defined(__alpha__) || defined(__x86_64__) || defined(__ia64__)
432 431
433 do_div(tmp, base); 432 do_div(tmp, base);
434#else 433#else
435 tmp = divremdi3(n, base, PG_DIV); 434 tmp = divremdi3(n, base, PG_DIV);
436#endif 435#endif
437 return tmp; 436 return tmp;
438} 437}
439 438
440static inline u32 pktgen_random(void) 439static inline u32 pktgen_random(void)
@@ -448,51 +447,51 @@ static inline u32 pktgen_random(void)
448#endif 447#endif
449} 448}
450 449
451static inline __u64 getCurMs(void) 450static inline __u64 getCurMs(void)
452{ 451{
453 struct timeval tv; 452 struct timeval tv;
454 do_gettimeofday(&tv); 453 do_gettimeofday(&tv);
455 return tv_to_ms(&tv); 454 return tv_to_ms(&tv);
456} 455}
457 456
458static inline __u64 getCurUs(void) 457static inline __u64 getCurUs(void)
459{ 458{
460 struct timeval tv; 459 struct timeval tv;
461 do_gettimeofday(&tv); 460 do_gettimeofday(&tv);
462 return tv_to_us(&tv); 461 return tv_to_us(&tv);
463} 462}
464 463
465static inline __u64 tv_diff(const struct timeval* a, const struct timeval* b) 464static inline __u64 tv_diff(const struct timeval *a, const struct timeval *b)
466{ 465{
467 return tv_to_us(a) - tv_to_us(b); 466 return tv_to_us(a) - tv_to_us(b);
468} 467}
469 468
470
471/* old include end */ 469/* old include end */
472 470
473static char version[] __initdata = VERSION; 471static char version[] __initdata = VERSION;
474 472
475static int pktgen_remove_device(struct pktgen_thread* t, struct pktgen_dev *i); 473static int pktgen_remove_device(struct pktgen_thread *t, struct pktgen_dev *i);
476static int pktgen_add_device(struct pktgen_thread* t, const char* ifname); 474static 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); 475static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t,
476 const char *ifname);
478static int pktgen_device_event(struct notifier_block *, unsigned long, void *); 477static int pktgen_device_event(struct notifier_block *, unsigned long, void *);
479static void pktgen_run_all_threads(void); 478static void pktgen_run_all_threads(void);
480static void pktgen_stop_all_threads_ifs(void); 479static void pktgen_stop_all_threads_ifs(void);
481static int pktgen_stop_device(struct pktgen_dev *pkt_dev); 480static int pktgen_stop_device(struct pktgen_dev *pkt_dev);
482static void pktgen_stop(struct pktgen_thread* t); 481static void pktgen_stop(struct pktgen_thread *t);
483static void pktgen_clear_counters(struct pktgen_dev *pkt_dev); 482static void pktgen_clear_counters(struct pktgen_dev *pkt_dev);
484static struct pktgen_dev *pktgen_NN_threads(const char* dev_name, int remove); 483static int pktgen_mark_device(const char *ifname);
485static unsigned int scan_ip6(const char *s,char ip[16]); 484static unsigned int scan_ip6(const char *s, char ip[16]);
486static unsigned int fmt_ip6(char *s,const char ip[16]); 485static unsigned int fmt_ip6(char *s, const char ip[16]);
487 486
488/* Module parameters, defaults. */ 487/* Module parameters, defaults. */
489static int pg_count_d = 1000; /* 1000 pkts by default */ 488static int pg_count_d = 1000; /* 1000 pkts by default */
490static int pg_delay_d; 489static int pg_delay_d;
491static int pg_clone_skb_d; 490static int pg_clone_skb_d;
492static int debug; 491static int debug;
493 492
494static DECLARE_MUTEX(pktgen_sem); 493static DEFINE_MUTEX(pktgen_thread_lock);
495static struct pktgen_thread *pktgen_threads = NULL; 494static LIST_HEAD(pktgen_threads);
496 495
497static struct notifier_block pktgen_notifier_block = { 496static struct notifier_block pktgen_notifier_block = {
498 .notifier_call = pktgen_device_event, 497 .notifier_call = pktgen_device_event,
@@ -504,21 +503,21 @@ static struct notifier_block pktgen_notifier_block = {
504 */ 503 */
505 504
506static int pgctrl_show(struct seq_file *seq, void *v) 505static int pgctrl_show(struct seq_file *seq, void *v)
507{ 506{
508 seq_puts(seq, VERSION); 507 seq_puts(seq, VERSION);
509 return 0; 508 return 0;
510} 509}
511 510
512static ssize_t pgctrl_write(struct file* file,const char __user * buf, 511static ssize_t pgctrl_write(struct file *file, const char __user * buf,
513 size_t count, loff_t *ppos) 512 size_t count, loff_t * ppos)
514{ 513{
515 int err = 0; 514 int err = 0;
516 char data[128]; 515 char data[128];
517 516
518 if (!capable(CAP_NET_ADMIN)){ 517 if (!capable(CAP_NET_ADMIN)) {
519 err = -EPERM; 518 err = -EPERM;
520 goto out; 519 goto out;
521 } 520 }
522 521
523 if (count > sizeof(data)) 522 if (count > sizeof(data))
524 count = sizeof(data); 523 count = sizeof(data);
@@ -526,22 +525,22 @@ static ssize_t pgctrl_write(struct file* file,const char __user * buf,
526 if (copy_from_user(data, buf, count)) { 525 if (copy_from_user(data, buf, count)) {
527 err = -EFAULT; 526 err = -EFAULT;
528 goto out; 527 goto out;
529 } 528 }
530 data[count-1] = 0; /* Make string */ 529 data[count - 1] = 0; /* Make string */
531 530
532 if (!strcmp(data, "stop")) 531 if (!strcmp(data, "stop"))
533 pktgen_stop_all_threads_ifs(); 532 pktgen_stop_all_threads_ifs();
534 533
535 else if (!strcmp(data, "start")) 534 else if (!strcmp(data, "start"))
536 pktgen_run_all_threads(); 535 pktgen_run_all_threads();
537 536
538 else 537 else
539 printk("pktgen: Unknown command: %s\n", data); 538 printk("pktgen: Unknown command: %s\n", data);
540 539
541 err = count; 540 err = count;
542 541
543 out: 542out:
544 return err; 543 return err;
545} 544}
546 545
547static int pgctrl_open(struct inode *inode, struct file *file) 546static int pgctrl_open(struct inode *inode, struct file *file)
@@ -550,147 +549,158 @@ static int pgctrl_open(struct inode *inode, struct file *file)
550} 549}
551 550
552static struct file_operations pktgen_fops = { 551static struct file_operations pktgen_fops = {
553 .owner = THIS_MODULE, 552 .owner = THIS_MODULE,
554 .open = pgctrl_open, 553 .open = pgctrl_open,
555 .read = seq_read, 554 .read = seq_read,
556 .llseek = seq_lseek, 555 .llseek = seq_lseek,
557 .write = pgctrl_write, 556 .write = pgctrl_write,
558 .release = single_release, 557 .release = single_release,
559}; 558};
560 559
561static int pktgen_if_show(struct seq_file *seq, void *v) 560static int pktgen_if_show(struct seq_file *seq, void *v)
562{ 561{
563 int i; 562 int i;
564 struct pktgen_dev *pkt_dev = seq->private; 563 struct pktgen_dev *pkt_dev = seq->private;
565 __u64 sa; 564 __u64 sa;
566 __u64 stopped; 565 __u64 stopped;
567 __u64 now = getCurUs(); 566 __u64 now = getCurUs();
568 567
569 seq_printf(seq, "Params: count %llu min_pkt_size: %u max_pkt_size: %u\n", 568 seq_printf(seq,
570 (unsigned long long) pkt_dev->count, 569 "Params: count %llu min_pkt_size: %u max_pkt_size: %u\n",
571 pkt_dev->min_pkt_size, pkt_dev->max_pkt_size); 570 (unsigned long long)pkt_dev->count, pkt_dev->min_pkt_size,
571 pkt_dev->max_pkt_size);
572
573 seq_printf(seq,
574 " frags: %d delay: %u clone_skb: %d ifname: %s\n",
575 pkt_dev->nfrags,
576 1000 * pkt_dev->delay_us + pkt_dev->delay_ns,
577 pkt_dev->clone_skb, pkt_dev->ifname);
578
579 seq_printf(seq, " flows: %u flowlen: %u\n", pkt_dev->cflows,
580 pkt_dev->lflow);
581
582 if (pkt_dev->flags & F_IPV6) {
583 char b1[128], b2[128], b3[128];
584 fmt_ip6(b1, pkt_dev->in6_saddr.s6_addr);
585 fmt_ip6(b2, pkt_dev->min_in6_saddr.s6_addr);
586 fmt_ip6(b3, pkt_dev->max_in6_saddr.s6_addr);
587 seq_printf(seq,
588 " saddr: %s min_saddr: %s max_saddr: %s\n", b1,
589 b2, b3);
590
591 fmt_ip6(b1, pkt_dev->in6_daddr.s6_addr);
592 fmt_ip6(b2, pkt_dev->min_in6_daddr.s6_addr);
593 fmt_ip6(b3, pkt_dev->max_in6_daddr.s6_addr);
594 seq_printf(seq,
595 " daddr: %s min_daddr: %s max_daddr: %s\n", b1,
596 b2, b3);
597
598 } else
599 seq_printf(seq,
600 " dst_min: %s dst_max: %s\n src_min: %s src_max: %s\n",
601 pkt_dev->dst_min, pkt_dev->dst_max, pkt_dev->src_min,
602 pkt_dev->src_max);
572 603
573 seq_printf(seq, " frags: %d delay: %u clone_skb: %d ifname: %s\n", 604 seq_puts(seq, " src_mac: ");
574 pkt_dev->nfrags, 1000*pkt_dev->delay_us+pkt_dev->delay_ns, pkt_dev->clone_skb, pkt_dev->ifname);
575 605
576 seq_printf(seq, " flows: %u flowlen: %u\n", pkt_dev->cflows, pkt_dev->lflow); 606 if (is_zero_ether_addr(pkt_dev->src_mac))
607 for (i = 0; i < 6; i++)
608 seq_printf(seq, "%02X%s", pkt_dev->odev->dev_addr[i],
609 i == 5 ? " " : ":");
610 else
611 for (i = 0; i < 6; i++)
612 seq_printf(seq, "%02X%s", pkt_dev->src_mac[i],
613 i == 5 ? " " : ":");
614
615 seq_printf(seq, "dst_mac: ");
616 for (i = 0; i < 6; i++)
617 seq_printf(seq, "%02X%s", pkt_dev->dst_mac[i],
618 i == 5 ? "\n" : ":");
619
620 seq_printf(seq,
621 " udp_src_min: %d udp_src_max: %d udp_dst_min: %d udp_dst_max: %d\n",
622 pkt_dev->udp_src_min, pkt_dev->udp_src_max,
623 pkt_dev->udp_dst_min, pkt_dev->udp_dst_max);
624
625 seq_printf(seq,
626 " src_mac_count: %d dst_mac_count: %d \n Flags: ",
627 pkt_dev->src_mac_count, pkt_dev->dst_mac_count);
577 628
629 if (pkt_dev->flags & F_IPV6)
630 seq_printf(seq, "IPV6 ");
578 631
579 if(pkt_dev->flags & F_IPV6) { 632 if (pkt_dev->flags & F_IPSRC_RND)
580 char b1[128], b2[128], b3[128]; 633 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 634
586 fmt_ip6(b1, pkt_dev->in6_daddr.s6_addr); 635 if (pkt_dev->flags & F_IPDST_RND)
587 fmt_ip6(b2, pkt_dev->min_in6_daddr.s6_addr); 636 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 637
591 } 638 if (pkt_dev->flags & F_TXSIZE_RND)
592 else 639 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 640
596 seq_puts(seq, " src_mac: "); 641 if (pkt_dev->flags & F_UDPSRC_RND)
642 seq_printf(seq, "UDPSRC_RND ");
597 643
598 if (is_zero_ether_addr(pkt_dev->src_mac)) 644 if (pkt_dev->flags & F_UDPDST_RND)
599 for (i = 0; i < 6; i++) 645 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 646
605 seq_printf(seq, "dst_mac: "); 647 if (pkt_dev->flags & F_MACSRC_RND)
606 for (i = 0; i < 6; i++) 648 seq_printf(seq, "MACSRC_RND ");
607 seq_printf(seq, "%02X%s", pkt_dev->dst_mac[i], i == 5 ? "\n" : ":");
608 649
609 seq_printf(seq, " udp_src_min: %d udp_src_max: %d udp_dst_min: %d udp_dst_max: %d\n", 650 if (pkt_dev->flags & F_MACDST_RND)
610 pkt_dev->udp_src_min, pkt_dev->udp_src_max, pkt_dev->udp_dst_min, 651 seq_printf(seq, "MACDST_RND ");
611 pkt_dev->udp_dst_max);
612 652
613 seq_printf(seq, " src_mac_count: %d dst_mac_count: %d \n Flags: ", 653 seq_puts(seq, "\n");
614 pkt_dev->src_mac_count, pkt_dev->dst_mac_count); 654
655 sa = pkt_dev->started_at;
656 stopped = pkt_dev->stopped_at;
657 if (pkt_dev->running)
658 stopped = now; /* not really stopped, more like last-running-at */
615 659
660 seq_printf(seq,
661 "Current:\n pkts-sofar: %llu errors: %llu\n started: %lluus stopped: %lluus idle: %lluus\n",
662 (unsigned long long)pkt_dev->sofar,
663 (unsigned long long)pkt_dev->errors, (unsigned long long)sa,
664 (unsigned long long)stopped,
665 (unsigned long long)pkt_dev->idle_acc);
616 666
617 if (pkt_dev->flags & F_IPV6) 667 seq_printf(seq,
618 seq_printf(seq, "IPV6 "); 668 " seq_num: %d cur_dst_mac_offset: %d cur_src_mac_offset: %d\n",
619
620 if (pkt_dev->flags & F_IPSRC_RND)
621 seq_printf(seq, "IPSRC_RND ");
622
623 if (pkt_dev->flags & F_IPDST_RND)
624 seq_printf(seq, "IPDST_RND ");
625
626 if (pkt_dev->flags & F_TXSIZE_RND)
627 seq_printf(seq, "TXSIZE_RND ");
628
629 if (pkt_dev->flags & F_UDPSRC_RND)
630 seq_printf(seq, "UDPSRC_RND ");
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, 669 pkt_dev->seq_num, pkt_dev->cur_dst_mac_offset,
658 pkt_dev->cur_src_mac_offset); 670 pkt_dev->cur_src_mac_offset);
659 671
660 if(pkt_dev->flags & F_IPV6) { 672 if (pkt_dev->flags & F_IPV6) {
661 char b1[128], b2[128]; 673 char b1[128], b2[128];
662 fmt_ip6(b1, pkt_dev->cur_in6_daddr.s6_addr); 674 fmt_ip6(b1, pkt_dev->cur_in6_daddr.s6_addr);
663 fmt_ip6(b2, pkt_dev->cur_in6_saddr.s6_addr); 675 fmt_ip6(b2, pkt_dev->cur_in6_saddr.s6_addr);
664 seq_printf(seq, " cur_saddr: %s cur_daddr: %s\n", b2, b1); 676 seq_printf(seq, " cur_saddr: %s cur_daddr: %s\n", b2, b1);
665 } 677 } else
666 else 678 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); 679 pkt_dev->cur_saddr, pkt_dev->cur_daddr);
669 680
670 681 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); 682 pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src);
673 683
674 seq_printf(seq, " flows: %u\n", pkt_dev->nflows); 684 seq_printf(seq, " flows: %u\n", pkt_dev->nflows);
675 685
676 if (pkt_dev->result[0]) 686 if (pkt_dev->result[0])
677 seq_printf(seq, "Result: %s\n", pkt_dev->result); 687 seq_printf(seq, "Result: %s\n", pkt_dev->result);
678 else 688 else
679 seq_printf(seq, "Result: Idle\n"); 689 seq_printf(seq, "Result: Idle\n");
680 690
681 return 0; 691 return 0;
682} 692}
683 693
684 694static int count_trail_chars(const char __user * user_buffer,
685static int count_trail_chars(const char __user *user_buffer, unsigned int maxlen) 695 unsigned int maxlen)
686{ 696{
687 int i; 697 int i;
688 698
689 for (i = 0; i < maxlen; i++) { 699 for (i = 0; i < maxlen; i++) {
690 char c; 700 char c;
691 if (get_user(c, &user_buffer[i])) 701 if (get_user(c, &user_buffer[i]))
692 return -EFAULT; 702 return -EFAULT;
693 switch (c) { 703 switch (c) {
694 case '\"': 704 case '\"':
695 case '\n': 705 case '\n':
696 case '\r': 706 case '\r':
@@ -706,34 +716,34 @@ done:
706 return i; 716 return i;
707} 717}
708 718
709static unsigned long num_arg(const char __user *user_buffer, unsigned long maxlen, 719static unsigned long num_arg(const char __user * user_buffer,
710 unsigned long *num) 720 unsigned long maxlen, unsigned long *num)
711{ 721{
712 int i = 0; 722 int i = 0;
713 *num = 0; 723 *num = 0;
714 724
715 for(; i < maxlen; i++) { 725 for (; i < maxlen; i++) {
716 char c; 726 char c;
717 if (get_user(c, &user_buffer[i])) 727 if (get_user(c, &user_buffer[i]))
718 return -EFAULT; 728 return -EFAULT;
719 if ((c >= '0') && (c <= '9')) { 729 if ((c >= '0') && (c <= '9')) {
720 *num *= 10; 730 *num *= 10;
721 *num += c -'0'; 731 *num += c - '0';
722 } else 732 } else
723 break; 733 break;
724 } 734 }
725 return i; 735 return i;
726} 736}
727 737
728static int strn_len(const char __user *user_buffer, unsigned int maxlen) 738static int strn_len(const char __user * user_buffer, unsigned int maxlen)
729{ 739{
730 int i = 0; 740 int i = 0;
731 741
732 for(; i < maxlen; i++) { 742 for (; i < maxlen; i++) {
733 char c; 743 char c;
734 if (get_user(c, &user_buffer[i])) 744 if (get_user(c, &user_buffer[i]))
735 return -EFAULT; 745 return -EFAULT;
736 switch (c) { 746 switch (c) {
737 case '\"': 747 case '\"':
738 case '\n': 748 case '\n':
739 case '\r': 749 case '\r':
@@ -746,119 +756,133 @@ static int strn_len(const char __user *user_buffer, unsigned int maxlen)
746 }; 756 };
747 } 757 }
748done_str: 758done_str:
749
750 return i; 759 return i;
751} 760}
752 761
753static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer, 762static ssize_t pktgen_if_write(struct file *file,
754 size_t count, loff_t *offset) 763 const char __user * user_buffer, size_t count,
764 loff_t * offset)
755{ 765{
756 struct seq_file *seq = (struct seq_file *) file->private_data; 766 struct seq_file *seq = (struct seq_file *)file->private_data;
757 struct pktgen_dev *pkt_dev = seq->private; 767 struct pktgen_dev *pkt_dev = seq->private;
758 int i = 0, max, len; 768 int i = 0, max, len;
759 char name[16], valstr[32]; 769 char name[16], valstr[32];
760 unsigned long value = 0; 770 unsigned long value = 0;
761 char* pg_result = NULL; 771 char *pg_result = NULL;
762 int tmp = 0; 772 int tmp = 0;
763 char buf[128]; 773 char buf[128];
764 774
765 pg_result = &(pkt_dev->result[0]); 775 pg_result = &(pkt_dev->result[0]);
766 776
767 if (count < 1) { 777 if (count < 1) {
768 printk("pktgen: wrong command format\n"); 778 printk("pktgen: wrong command format\n");
769 return -EINVAL; 779 return -EINVAL;
770 } 780 }
771 781
772 max = count - i; 782 max = count - i;
773 tmp = count_trail_chars(&user_buffer[i], max); 783 tmp = count_trail_chars(&user_buffer[i], max);
774 if (tmp < 0) { 784 if (tmp < 0) {
775 printk("pktgen: illegal format\n"); 785 printk("pktgen: illegal format\n");
776 return tmp; 786 return tmp;
777 } 787 }
778 i += tmp; 788 i += tmp;
779 789
780 /* Read variable name */ 790 /* Read variable name */
781 791
782 len = strn_len(&user_buffer[i], sizeof(name) - 1); 792 len = strn_len(&user_buffer[i], sizeof(name) - 1);
783 if (len < 0) { return len; } 793 if (len < 0) {
794 return len;
795 }
784 memset(name, 0, sizeof(name)); 796 memset(name, 0, sizeof(name));
785 if (copy_from_user(name, &user_buffer[i], len) ) 797 if (copy_from_user(name, &user_buffer[i], len))
786 return -EFAULT; 798 return -EFAULT;
787 i += len; 799 i += len;
788 800
789 max = count -i; 801 max = count - i;
790 len = count_trail_chars(&user_buffer[i], max); 802 len = count_trail_chars(&user_buffer[i], max);
791 if (len < 0) 803 if (len < 0)
792 return len; 804 return len;
793 805
794 i += len; 806 i += len;
795 807
796 if (debug) { 808 if (debug) {
797 char tb[count + 1]; 809 char tb[count + 1];
798 if (copy_from_user(tb, user_buffer, count)) 810 if (copy_from_user(tb, user_buffer, count))
799 return -EFAULT; 811 return -EFAULT;
800 tb[count] = 0; 812 tb[count] = 0;
801 printk("pktgen: %s,%lu buffer -:%s:-\n", name, 813 printk("pktgen: %s,%lu buffer -:%s:-\n", name,
802 (unsigned long) count, tb); 814 (unsigned long)count, tb);
803 } 815 }
804 816
805 if (!strcmp(name, "min_pkt_size")) { 817 if (!strcmp(name, "min_pkt_size")) {
806 len = num_arg(&user_buffer[i], 10, &value); 818 len = num_arg(&user_buffer[i], 10, &value);
807 if (len < 0) { return len; } 819 if (len < 0) {
820 return len;
821 }
808 i += len; 822 i += len;
809 if (value < 14+20+8) 823 if (value < 14 + 20 + 8)
810 value = 14+20+8; 824 value = 14 + 20 + 8;
811 if (value != pkt_dev->min_pkt_size) { 825 if (value != pkt_dev->min_pkt_size) {
812 pkt_dev->min_pkt_size = value; 826 pkt_dev->min_pkt_size = value;
813 pkt_dev->cur_pkt_size = value; 827 pkt_dev->cur_pkt_size = value;
814 } 828 }
815 sprintf(pg_result, "OK: min_pkt_size=%u", pkt_dev->min_pkt_size); 829 sprintf(pg_result, "OK: min_pkt_size=%u",
830 pkt_dev->min_pkt_size);
816 return count; 831 return count;
817 } 832 }
818 833
819 if (!strcmp(name, "max_pkt_size")) { 834 if (!strcmp(name, "max_pkt_size")) {
820 len = num_arg(&user_buffer[i], 10, &value); 835 len = num_arg(&user_buffer[i], 10, &value);
821 if (len < 0) { return len; } 836 if (len < 0) {
837 return len;
838 }
822 i += len; 839 i += len;
823 if (value < 14+20+8) 840 if (value < 14 + 20 + 8)
824 value = 14+20+8; 841 value = 14 + 20 + 8;
825 if (value != pkt_dev->max_pkt_size) { 842 if (value != pkt_dev->max_pkt_size) {
826 pkt_dev->max_pkt_size = value; 843 pkt_dev->max_pkt_size = value;
827 pkt_dev->cur_pkt_size = value; 844 pkt_dev->cur_pkt_size = value;
828 } 845 }
829 sprintf(pg_result, "OK: max_pkt_size=%u", pkt_dev->max_pkt_size); 846 sprintf(pg_result, "OK: max_pkt_size=%u",
847 pkt_dev->max_pkt_size);
830 return count; 848 return count;
831 } 849 }
832 850
833 /* Shortcut for min = max */ 851 /* Shortcut for min = max */
834 852
835 if (!strcmp(name, "pkt_size")) { 853 if (!strcmp(name, "pkt_size")) {
836 len = num_arg(&user_buffer[i], 10, &value); 854 len = num_arg(&user_buffer[i], 10, &value);
837 if (len < 0) { return len; } 855 if (len < 0) {
856 return len;
857 }
838 i += len; 858 i += len;
839 if (value < 14+20+8) 859 if (value < 14 + 20 + 8)
840 value = 14+20+8; 860 value = 14 + 20 + 8;
841 if (value != pkt_dev->min_pkt_size) { 861 if (value != pkt_dev->min_pkt_size) {
842 pkt_dev->min_pkt_size = value; 862 pkt_dev->min_pkt_size = value;
843 pkt_dev->max_pkt_size = value; 863 pkt_dev->max_pkt_size = value;
844 pkt_dev->cur_pkt_size = value; 864 pkt_dev->cur_pkt_size = value;
845 } 865 }
846 sprintf(pg_result, "OK: pkt_size=%u", pkt_dev->min_pkt_size); 866 sprintf(pg_result, "OK: pkt_size=%u", pkt_dev->min_pkt_size);
847 return count; 867 return count;
848 } 868 }
849 869
850 if (!strcmp(name, "debug")) { 870 if (!strcmp(name, "debug")) {
851 len = num_arg(&user_buffer[i], 10, &value); 871 len = num_arg(&user_buffer[i], 10, &value);
852 if (len < 0) { return len; } 872 if (len < 0) {
873 return len;
874 }
853 i += len; 875 i += len;
854 debug = value; 876 debug = value;
855 sprintf(pg_result, "OK: debug=%u", debug); 877 sprintf(pg_result, "OK: debug=%u", debug);
856 return count; 878 return count;
857 } 879 }
858 880
859 if (!strcmp(name, "frags")) { 881 if (!strcmp(name, "frags")) {
860 len = num_arg(&user_buffer[i], 10, &value); 882 len = num_arg(&user_buffer[i], 10, &value);
861 if (len < 0) { return len; } 883 if (len < 0) {
884 return len;
885 }
862 i += len; 886 i += len;
863 pkt_dev->nfrags = value; 887 pkt_dev->nfrags = value;
864 sprintf(pg_result, "OK: frags=%u", pkt_dev->nfrags); 888 sprintf(pg_result, "OK: frags=%u", pkt_dev->nfrags);
@@ -866,7 +890,9 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer
866 } 890 }
867 if (!strcmp(name, "delay")) { 891 if (!strcmp(name, "delay")) {
868 len = num_arg(&user_buffer[i], 10, &value); 892 len = num_arg(&user_buffer[i], 10, &value);
869 if (len < 0) { return len; } 893 if (len < 0) {
894 return len;
895 }
870 i += len; 896 i += len;
871 if (value == 0x7FFFFFFF) { 897 if (value == 0x7FFFFFFF) {
872 pkt_dev->delay_us = 0x7FFFFFFF; 898 pkt_dev->delay_us = 0x7FFFFFFF;
@@ -875,308 +901,347 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer
875 pkt_dev->delay_us = value / 1000; 901 pkt_dev->delay_us = value / 1000;
876 pkt_dev->delay_ns = value % 1000; 902 pkt_dev->delay_ns = value % 1000;
877 } 903 }
878 sprintf(pg_result, "OK: delay=%u", 1000*pkt_dev->delay_us+pkt_dev->delay_ns); 904 sprintf(pg_result, "OK: delay=%u",
905 1000 * pkt_dev->delay_us + pkt_dev->delay_ns);
879 return count; 906 return count;
880 } 907 }
881 if (!strcmp(name, "udp_src_min")) { 908 if (!strcmp(name, "udp_src_min")) {
882 len = num_arg(&user_buffer[i], 10, &value); 909 len = num_arg(&user_buffer[i], 10, &value);
883 if (len < 0) { return len; } 910 if (len < 0) {
911 return len;
912 }
884 i += len; 913 i += len;
885 if (value != pkt_dev->udp_src_min) { 914 if (value != pkt_dev->udp_src_min) {
886 pkt_dev->udp_src_min = value; 915 pkt_dev->udp_src_min = value;
887 pkt_dev->cur_udp_src = value; 916 pkt_dev->cur_udp_src = value;
888 } 917 }
889 sprintf(pg_result, "OK: udp_src_min=%u", pkt_dev->udp_src_min); 918 sprintf(pg_result, "OK: udp_src_min=%u", pkt_dev->udp_src_min);
890 return count; 919 return count;
891 } 920 }
892 if (!strcmp(name, "udp_dst_min")) { 921 if (!strcmp(name, "udp_dst_min")) {
893 len = num_arg(&user_buffer[i], 10, &value); 922 len = num_arg(&user_buffer[i], 10, &value);
894 if (len < 0) { return len; } 923 if (len < 0) {
924 return len;
925 }
895 i += len; 926 i += len;
896 if (value != pkt_dev->udp_dst_min) { 927 if (value != pkt_dev->udp_dst_min) {
897 pkt_dev->udp_dst_min = value; 928 pkt_dev->udp_dst_min = value;
898 pkt_dev->cur_udp_dst = value; 929 pkt_dev->cur_udp_dst = value;
899 } 930 }
900 sprintf(pg_result, "OK: udp_dst_min=%u", pkt_dev->udp_dst_min); 931 sprintf(pg_result, "OK: udp_dst_min=%u", pkt_dev->udp_dst_min);
901 return count; 932 return count;
902 } 933 }
903 if (!strcmp(name, "udp_src_max")) { 934 if (!strcmp(name, "udp_src_max")) {
904 len = num_arg(&user_buffer[i], 10, &value); 935 len = num_arg(&user_buffer[i], 10, &value);
905 if (len < 0) { return len; } 936 if (len < 0) {
937 return len;
938 }
906 i += len; 939 i += len;
907 if (value != pkt_dev->udp_src_max) { 940 if (value != pkt_dev->udp_src_max) {
908 pkt_dev->udp_src_max = value; 941 pkt_dev->udp_src_max = value;
909 pkt_dev->cur_udp_src = value; 942 pkt_dev->cur_udp_src = value;
910 } 943 }
911 sprintf(pg_result, "OK: udp_src_max=%u", pkt_dev->udp_src_max); 944 sprintf(pg_result, "OK: udp_src_max=%u", pkt_dev->udp_src_max);
912 return count; 945 return count;
913 } 946 }
914 if (!strcmp(name, "udp_dst_max")) { 947 if (!strcmp(name, "udp_dst_max")) {
915 len = num_arg(&user_buffer[i], 10, &value); 948 len = num_arg(&user_buffer[i], 10, &value);
916 if (len < 0) { return len; } 949 if (len < 0) {
950 return len;
951 }
917 i += len; 952 i += len;
918 if (value != pkt_dev->udp_dst_max) { 953 if (value != pkt_dev->udp_dst_max) {
919 pkt_dev->udp_dst_max = value; 954 pkt_dev->udp_dst_max = value;
920 pkt_dev->cur_udp_dst = value; 955 pkt_dev->cur_udp_dst = value;
921 } 956 }
922 sprintf(pg_result, "OK: udp_dst_max=%u", pkt_dev->udp_dst_max); 957 sprintf(pg_result, "OK: udp_dst_max=%u", pkt_dev->udp_dst_max);
923 return count; 958 return count;
924 } 959 }
925 if (!strcmp(name, "clone_skb")) { 960 if (!strcmp(name, "clone_skb")) {
926 len = num_arg(&user_buffer[i], 10, &value); 961 len = num_arg(&user_buffer[i], 10, &value);
927 if (len < 0) { return len; } 962 if (len < 0) {
963 return len;
964 }
928 i += len; 965 i += len;
929 pkt_dev->clone_skb = value; 966 pkt_dev->clone_skb = value;
930 967
931 sprintf(pg_result, "OK: clone_skb=%d", pkt_dev->clone_skb); 968 sprintf(pg_result, "OK: clone_skb=%d", pkt_dev->clone_skb);
932 return count; 969 return count;
933 } 970 }
934 if (!strcmp(name, "count")) { 971 if (!strcmp(name, "count")) {
935 len = num_arg(&user_buffer[i], 10, &value); 972 len = num_arg(&user_buffer[i], 10, &value);
936 if (len < 0) { return len; } 973 if (len < 0) {
974 return len;
975 }
937 i += len; 976 i += len;
938 pkt_dev->count = value; 977 pkt_dev->count = value;
939 sprintf(pg_result, "OK: count=%llu", 978 sprintf(pg_result, "OK: count=%llu",
940 (unsigned long long) pkt_dev->count); 979 (unsigned long long)pkt_dev->count);
941 return count; 980 return count;
942 } 981 }
943 if (!strcmp(name, "src_mac_count")) { 982 if (!strcmp(name, "src_mac_count")) {
944 len = num_arg(&user_buffer[i], 10, &value); 983 len = num_arg(&user_buffer[i], 10, &value);
945 if (len < 0) { return len; } 984 if (len < 0) {
985 return len;
986 }
946 i += len; 987 i += len;
947 if (pkt_dev->src_mac_count != value) { 988 if (pkt_dev->src_mac_count != value) {
948 pkt_dev->src_mac_count = value; 989 pkt_dev->src_mac_count = value;
949 pkt_dev->cur_src_mac_offset = 0; 990 pkt_dev->cur_src_mac_offset = 0;
950 } 991 }
951 sprintf(pg_result, "OK: src_mac_count=%d", pkt_dev->src_mac_count); 992 sprintf(pg_result, "OK: src_mac_count=%d",
993 pkt_dev->src_mac_count);
952 return count; 994 return count;
953 } 995 }
954 if (!strcmp(name, "dst_mac_count")) { 996 if (!strcmp(name, "dst_mac_count")) {
955 len = num_arg(&user_buffer[i], 10, &value); 997 len = num_arg(&user_buffer[i], 10, &value);
956 if (len < 0) { return len; } 998 if (len < 0) {
999 return len;
1000 }
957 i += len; 1001 i += len;
958 if (pkt_dev->dst_mac_count != value) { 1002 if (pkt_dev->dst_mac_count != value) {
959 pkt_dev->dst_mac_count = value; 1003 pkt_dev->dst_mac_count = value;
960 pkt_dev->cur_dst_mac_offset = 0; 1004 pkt_dev->cur_dst_mac_offset = 0;
961 } 1005 }
962 sprintf(pg_result, "OK: dst_mac_count=%d", pkt_dev->dst_mac_count); 1006 sprintf(pg_result, "OK: dst_mac_count=%d",
1007 pkt_dev->dst_mac_count);
963 return count; 1008 return count;
964 } 1009 }
965 if (!strcmp(name, "flag")) { 1010 if (!strcmp(name, "flag")) {
966 char f[32]; 1011 char f[32];
967 memset(f, 0, 32); 1012 memset(f, 0, 32);
968 len = strn_len(&user_buffer[i], sizeof(f) - 1); 1013 len = strn_len(&user_buffer[i], sizeof(f) - 1);
969 if (len < 0) { return len; } 1014 if (len < 0) {
1015 return len;
1016 }
970 if (copy_from_user(f, &user_buffer[i], len)) 1017 if (copy_from_user(f, &user_buffer[i], len))
971 return -EFAULT; 1018 return -EFAULT;
972 i += len; 1019 i += len;
973 if (strcmp(f, "IPSRC_RND") == 0) 1020 if (strcmp(f, "IPSRC_RND") == 0)
974 pkt_dev->flags |= F_IPSRC_RND; 1021 pkt_dev->flags |= F_IPSRC_RND;
975 1022
976 else if (strcmp(f, "!IPSRC_RND") == 0) 1023 else if (strcmp(f, "!IPSRC_RND") == 0)
977 pkt_dev->flags &= ~F_IPSRC_RND; 1024 pkt_dev->flags &= ~F_IPSRC_RND;
978 1025
979 else if (strcmp(f, "TXSIZE_RND") == 0) 1026 else if (strcmp(f, "TXSIZE_RND") == 0)
980 pkt_dev->flags |= F_TXSIZE_RND; 1027 pkt_dev->flags |= F_TXSIZE_RND;
981 1028
982 else if (strcmp(f, "!TXSIZE_RND") == 0) 1029 else if (strcmp(f, "!TXSIZE_RND") == 0)
983 pkt_dev->flags &= ~F_TXSIZE_RND; 1030 pkt_dev->flags &= ~F_TXSIZE_RND;
984 1031
985 else if (strcmp(f, "IPDST_RND") == 0) 1032 else if (strcmp(f, "IPDST_RND") == 0)
986 pkt_dev->flags |= F_IPDST_RND; 1033 pkt_dev->flags |= F_IPDST_RND;
987 1034
988 else if (strcmp(f, "!IPDST_RND") == 0) 1035 else if (strcmp(f, "!IPDST_RND") == 0)
989 pkt_dev->flags &= ~F_IPDST_RND; 1036 pkt_dev->flags &= ~F_IPDST_RND;
990 1037
991 else if (strcmp(f, "UDPSRC_RND") == 0) 1038 else if (strcmp(f, "UDPSRC_RND") == 0)
992 pkt_dev->flags |= F_UDPSRC_RND; 1039 pkt_dev->flags |= F_UDPSRC_RND;
993 1040
994 else if (strcmp(f, "!UDPSRC_RND") == 0) 1041 else if (strcmp(f, "!UDPSRC_RND") == 0)
995 pkt_dev->flags &= ~F_UDPSRC_RND; 1042 pkt_dev->flags &= ~F_UDPSRC_RND;
996 1043
997 else if (strcmp(f, "UDPDST_RND") == 0) 1044 else if (strcmp(f, "UDPDST_RND") == 0)
998 pkt_dev->flags |= F_UDPDST_RND; 1045 pkt_dev->flags |= F_UDPDST_RND;
999 1046
1000 else if (strcmp(f, "!UDPDST_RND") == 0) 1047 else if (strcmp(f, "!UDPDST_RND") == 0)
1001 pkt_dev->flags &= ~F_UDPDST_RND; 1048 pkt_dev->flags &= ~F_UDPDST_RND;
1002 1049
1003 else if (strcmp(f, "MACSRC_RND") == 0) 1050 else if (strcmp(f, "MACSRC_RND") == 0)
1004 pkt_dev->flags |= F_MACSRC_RND; 1051 pkt_dev->flags |= F_MACSRC_RND;
1005 1052
1006 else if (strcmp(f, "!MACSRC_RND") == 0) 1053 else if (strcmp(f, "!MACSRC_RND") == 0)
1007 pkt_dev->flags &= ~F_MACSRC_RND; 1054 pkt_dev->flags &= ~F_MACSRC_RND;
1008 1055
1009 else if (strcmp(f, "MACDST_RND") == 0) 1056 else if (strcmp(f, "MACDST_RND") == 0)
1010 pkt_dev->flags |= F_MACDST_RND; 1057 pkt_dev->flags |= F_MACDST_RND;
1011 1058
1012 else if (strcmp(f, "!MACDST_RND") == 0) 1059 else if (strcmp(f, "!MACDST_RND") == 0)
1013 pkt_dev->flags &= ~F_MACDST_RND; 1060 pkt_dev->flags &= ~F_MACDST_RND;
1014 1061
1015 else { 1062 else {
1016 sprintf(pg_result, "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s", 1063 sprintf(pg_result,
1017 f, 1064 "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
1018 "IPSRC_RND, IPDST_RND, TXSIZE_RND, UDPSRC_RND, UDPDST_RND, MACSRC_RND, MACDST_RND\n"); 1065 f,
1019 return count; 1066 "IPSRC_RND, IPDST_RND, TXSIZE_RND, UDPSRC_RND, UDPDST_RND, MACSRC_RND, MACDST_RND\n");
1020 } 1067 return count;
1068 }
1021 sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags); 1069 sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags);
1022 return count; 1070 return count;
1023 } 1071 }
1024 if (!strcmp(name, "dst_min") || !strcmp(name, "dst")) { 1072 if (!strcmp(name, "dst_min") || !strcmp(name, "dst")) {
1025 len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_min) - 1); 1073 len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_min) - 1);
1026 if (len < 0) { return len; } 1074 if (len < 0) {
1075 return len;
1076 }
1027 1077
1028 if (copy_from_user(buf, &user_buffer[i], len)) 1078 if (copy_from_user(buf, &user_buffer[i], len))
1029 return -EFAULT; 1079 return -EFAULT;
1030 buf[len] = 0; 1080 buf[len] = 0;
1031 if (strcmp(buf, pkt_dev->dst_min) != 0) { 1081 if (strcmp(buf, pkt_dev->dst_min) != 0) {
1032 memset(pkt_dev->dst_min, 0, sizeof(pkt_dev->dst_min)); 1082 memset(pkt_dev->dst_min, 0, sizeof(pkt_dev->dst_min));
1033 strncpy(pkt_dev->dst_min, buf, len); 1083 strncpy(pkt_dev->dst_min, buf, len);
1034 pkt_dev->daddr_min = in_aton(pkt_dev->dst_min); 1084 pkt_dev->daddr_min = in_aton(pkt_dev->dst_min);
1035 pkt_dev->cur_daddr = pkt_dev->daddr_min; 1085 pkt_dev->cur_daddr = pkt_dev->daddr_min;
1036 } 1086 }
1037 if(debug) 1087 if (debug)
1038 printk("pktgen: dst_min set to: %s\n", pkt_dev->dst_min); 1088 printk("pktgen: dst_min set to: %s\n",
1039 i += len; 1089 pkt_dev->dst_min);
1090 i += len;
1040 sprintf(pg_result, "OK: dst_min=%s", pkt_dev->dst_min); 1091 sprintf(pg_result, "OK: dst_min=%s", pkt_dev->dst_min);
1041 return count; 1092 return count;
1042 } 1093 }
1043 if (!strcmp(name, "dst_max")) { 1094 if (!strcmp(name, "dst_max")) {
1044 len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_max) - 1); 1095 len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_max) - 1);
1045 if (len < 0) { return len; } 1096 if (len < 0) {
1097 return len;
1098 }
1046 1099
1047 if (copy_from_user(buf, &user_buffer[i], len)) 1100 if (copy_from_user(buf, &user_buffer[i], len))
1048 return -EFAULT; 1101 return -EFAULT;
1049 1102
1050 buf[len] = 0; 1103 buf[len] = 0;
1051 if (strcmp(buf, pkt_dev->dst_max) != 0) { 1104 if (strcmp(buf, pkt_dev->dst_max) != 0) {
1052 memset(pkt_dev->dst_max, 0, sizeof(pkt_dev->dst_max)); 1105 memset(pkt_dev->dst_max, 0, sizeof(pkt_dev->dst_max));
1053 strncpy(pkt_dev->dst_max, buf, len); 1106 strncpy(pkt_dev->dst_max, buf, len);
1054 pkt_dev->daddr_max = in_aton(pkt_dev->dst_max); 1107 pkt_dev->daddr_max = in_aton(pkt_dev->dst_max);
1055 pkt_dev->cur_daddr = pkt_dev->daddr_max; 1108 pkt_dev->cur_daddr = pkt_dev->daddr_max;
1056 } 1109 }
1057 if(debug) 1110 if (debug)
1058 printk("pktgen: dst_max set to: %s\n", pkt_dev->dst_max); 1111 printk("pktgen: dst_max set to: %s\n",
1112 pkt_dev->dst_max);
1059 i += len; 1113 i += len;
1060 sprintf(pg_result, "OK: dst_max=%s", pkt_dev->dst_max); 1114 sprintf(pg_result, "OK: dst_max=%s", pkt_dev->dst_max);
1061 return count; 1115 return count;
1062 } 1116 }
1063 if (!strcmp(name, "dst6")) { 1117 if (!strcmp(name, "dst6")) {
1064 len = strn_len(&user_buffer[i], sizeof(buf) - 1); 1118 len = strn_len(&user_buffer[i], sizeof(buf) - 1);
1065 if (len < 0) return len; 1119 if (len < 0)
1120 return len;
1066 1121
1067 pkt_dev->flags |= F_IPV6; 1122 pkt_dev->flags |= F_IPV6;
1068 1123
1069 if (copy_from_user(buf, &user_buffer[i], len)) 1124 if (copy_from_user(buf, &user_buffer[i], len))
1070 return -EFAULT; 1125 return -EFAULT;
1071 buf[len] = 0; 1126 buf[len] = 0;
1072 1127
1073 scan_ip6(buf, pkt_dev->in6_daddr.s6_addr); 1128 scan_ip6(buf, pkt_dev->in6_daddr.s6_addr);
1074 fmt_ip6(buf, pkt_dev->in6_daddr.s6_addr); 1129 fmt_ip6(buf, pkt_dev->in6_daddr.s6_addr);
1075 1130
1076 ipv6_addr_copy(&pkt_dev->cur_in6_daddr, &pkt_dev->in6_daddr); 1131 ipv6_addr_copy(&pkt_dev->cur_in6_daddr, &pkt_dev->in6_daddr);
1077 1132
1078 if(debug) 1133 if (debug)
1079 printk("pktgen: dst6 set to: %s\n", buf); 1134 printk("pktgen: dst6 set to: %s\n", buf);
1080 1135
1081 i += len; 1136 i += len;
1082 sprintf(pg_result, "OK: dst6=%s", buf); 1137 sprintf(pg_result, "OK: dst6=%s", buf);
1083 return count; 1138 return count;
1084 } 1139 }
1085 if (!strcmp(name, "dst6_min")) { 1140 if (!strcmp(name, "dst6_min")) {
1086 len = strn_len(&user_buffer[i], sizeof(buf) - 1); 1141 len = strn_len(&user_buffer[i], sizeof(buf) - 1);
1087 if (len < 0) return len; 1142 if (len < 0)
1143 return len;
1088 1144
1089 pkt_dev->flags |= F_IPV6; 1145 pkt_dev->flags |= F_IPV6;
1090 1146
1091 if (copy_from_user(buf, &user_buffer[i], len)) 1147 if (copy_from_user(buf, &user_buffer[i], len))
1092 return -EFAULT; 1148 return -EFAULT;
1093 buf[len] = 0; 1149 buf[len] = 0;
1094 1150
1095 scan_ip6(buf, pkt_dev->min_in6_daddr.s6_addr); 1151 scan_ip6(buf, pkt_dev->min_in6_daddr.s6_addr);
1096 fmt_ip6(buf, pkt_dev->min_in6_daddr.s6_addr); 1152 fmt_ip6(buf, pkt_dev->min_in6_daddr.s6_addr);
1097 1153
1098 ipv6_addr_copy(&pkt_dev->cur_in6_daddr, &pkt_dev->min_in6_daddr); 1154 ipv6_addr_copy(&pkt_dev->cur_in6_daddr,
1099 if(debug) 1155 &pkt_dev->min_in6_daddr);
1156 if (debug)
1100 printk("pktgen: dst6_min set to: %s\n", buf); 1157 printk("pktgen: dst6_min set to: %s\n", buf);
1101 1158
1102 i += len; 1159 i += len;
1103 sprintf(pg_result, "OK: dst6_min=%s", buf); 1160 sprintf(pg_result, "OK: dst6_min=%s", buf);
1104 return count; 1161 return count;
1105 } 1162 }
1106 if (!strcmp(name, "dst6_max")) { 1163 if (!strcmp(name, "dst6_max")) {
1107 len = strn_len(&user_buffer[i], sizeof(buf) - 1); 1164 len = strn_len(&user_buffer[i], sizeof(buf) - 1);
1108 if (len < 0) return len; 1165 if (len < 0)
1166 return len;
1109 1167
1110 pkt_dev->flags |= F_IPV6; 1168 pkt_dev->flags |= F_IPV6;
1111 1169
1112 if (copy_from_user(buf, &user_buffer[i], len)) 1170 if (copy_from_user(buf, &user_buffer[i], len))
1113 return -EFAULT; 1171 return -EFAULT;
1114 buf[len] = 0; 1172 buf[len] = 0;
1115 1173
1116 scan_ip6(buf, pkt_dev->max_in6_daddr.s6_addr); 1174 scan_ip6(buf, pkt_dev->max_in6_daddr.s6_addr);
1117 fmt_ip6(buf, pkt_dev->max_in6_daddr.s6_addr); 1175 fmt_ip6(buf, pkt_dev->max_in6_daddr.s6_addr);
1118 1176
1119 if(debug) 1177 if (debug)
1120 printk("pktgen: dst6_max set to: %s\n", buf); 1178 printk("pktgen: dst6_max set to: %s\n", buf);
1121 1179
1122 i += len; 1180 i += len;
1123 sprintf(pg_result, "OK: dst6_max=%s", buf); 1181 sprintf(pg_result, "OK: dst6_max=%s", buf);
1124 return count; 1182 return count;
1125 } 1183 }
1126 if (!strcmp(name, "src6")) { 1184 if (!strcmp(name, "src6")) {
1127 len = strn_len(&user_buffer[i], sizeof(buf) - 1); 1185 len = strn_len(&user_buffer[i], sizeof(buf) - 1);
1128 if (len < 0) return len; 1186 if (len < 0)
1187 return len;
1129 1188
1130 pkt_dev->flags |= F_IPV6; 1189 pkt_dev->flags |= F_IPV6;
1131 1190
1132 if (copy_from_user(buf, &user_buffer[i], len)) 1191 if (copy_from_user(buf, &user_buffer[i], len))
1133 return -EFAULT; 1192 return -EFAULT;
1134 buf[len] = 0; 1193 buf[len] = 0;
1135 1194
1136 scan_ip6(buf, pkt_dev->in6_saddr.s6_addr); 1195 scan_ip6(buf, pkt_dev->in6_saddr.s6_addr);
1137 fmt_ip6(buf, pkt_dev->in6_saddr.s6_addr); 1196 fmt_ip6(buf, pkt_dev->in6_saddr.s6_addr);
1138 1197
1139 ipv6_addr_copy(&pkt_dev->cur_in6_saddr, &pkt_dev->in6_saddr); 1198 ipv6_addr_copy(&pkt_dev->cur_in6_saddr, &pkt_dev->in6_saddr);
1140 1199
1141 if(debug) 1200 if (debug)
1142 printk("pktgen: src6 set to: %s\n", buf); 1201 printk("pktgen: src6 set to: %s\n", buf);
1143 1202
1144 i += len; 1203 i += len;
1145 sprintf(pg_result, "OK: src6=%s", buf); 1204 sprintf(pg_result, "OK: src6=%s", buf);
1146 return count; 1205 return count;
1147 } 1206 }
1148 if (!strcmp(name, "src_min")) { 1207 if (!strcmp(name, "src_min")) {
1149 len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_min) - 1); 1208 len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_min) - 1);
1150 if (len < 0) { return len; } 1209 if (len < 0) {
1151 if (copy_from_user(buf, &user_buffer[i], len)) 1210 return len;
1211 }
1212 if (copy_from_user(buf, &user_buffer[i], len))
1152 return -EFAULT; 1213 return -EFAULT;
1153 buf[len] = 0; 1214 buf[len] = 0;
1154 if (strcmp(buf, pkt_dev->src_min) != 0) { 1215 if (strcmp(buf, pkt_dev->src_min) != 0) {
1155 memset(pkt_dev->src_min, 0, sizeof(pkt_dev->src_min)); 1216 memset(pkt_dev->src_min, 0, sizeof(pkt_dev->src_min));
1156 strncpy(pkt_dev->src_min, buf, len); 1217 strncpy(pkt_dev->src_min, buf, len);
1157 pkt_dev->saddr_min = in_aton(pkt_dev->src_min); 1218 pkt_dev->saddr_min = in_aton(pkt_dev->src_min);
1158 pkt_dev->cur_saddr = pkt_dev->saddr_min; 1219 pkt_dev->cur_saddr = pkt_dev->saddr_min;
1159 } 1220 }
1160 if(debug) 1221 if (debug)
1161 printk("pktgen: src_min set to: %s\n", pkt_dev->src_min); 1222 printk("pktgen: src_min set to: %s\n",
1223 pkt_dev->src_min);
1162 i += len; 1224 i += len;
1163 sprintf(pg_result, "OK: src_min=%s", pkt_dev->src_min); 1225 sprintf(pg_result, "OK: src_min=%s", pkt_dev->src_min);
1164 return count; 1226 return count;
1165 } 1227 }
1166 if (!strcmp(name, "src_max")) { 1228 if (!strcmp(name, "src_max")) {
1167 len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_max) - 1); 1229 len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_max) - 1);
1168 if (len < 0) { return len; } 1230 if (len < 0) {
1169 if (copy_from_user(buf, &user_buffer[i], len)) 1231 return len;
1232 }
1233 if (copy_from_user(buf, &user_buffer[i], len))
1170 return -EFAULT; 1234 return -EFAULT;
1171 buf[len] = 0; 1235 buf[len] = 0;
1172 if (strcmp(buf, pkt_dev->src_max) != 0) { 1236 if (strcmp(buf, pkt_dev->src_max) != 0) {
1173 memset(pkt_dev->src_max, 0, sizeof(pkt_dev->src_max)); 1237 memset(pkt_dev->src_max, 0, sizeof(pkt_dev->src_max));
1174 strncpy(pkt_dev->src_max, buf, len); 1238 strncpy(pkt_dev->src_max, buf, len);
1175 pkt_dev->saddr_max = in_aton(pkt_dev->src_max); 1239 pkt_dev->saddr_max = in_aton(pkt_dev->src_max);
1176 pkt_dev->cur_saddr = pkt_dev->saddr_max; 1240 pkt_dev->cur_saddr = pkt_dev->saddr_max;
1177 } 1241 }
1178 if(debug) 1242 if (debug)
1179 printk("pktgen: src_max set to: %s\n", pkt_dev->src_max); 1243 printk("pktgen: src_max set to: %s\n",
1244 pkt_dev->src_max);
1180 i += len; 1245 i += len;
1181 sprintf(pg_result, "OK: src_max=%s", pkt_dev->src_max); 1246 sprintf(pg_result, "OK: src_max=%s", pkt_dev->src_max);
1182 return count; 1247 return count;
@@ -1186,15 +1251,17 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer
1186 unsigned char old_dmac[ETH_ALEN]; 1251 unsigned char old_dmac[ETH_ALEN];
1187 unsigned char *m = pkt_dev->dst_mac; 1252 unsigned char *m = pkt_dev->dst_mac;
1188 memcpy(old_dmac, pkt_dev->dst_mac, ETH_ALEN); 1253 memcpy(old_dmac, pkt_dev->dst_mac, ETH_ALEN);
1189 1254
1190 len = strn_len(&user_buffer[i], sizeof(valstr) - 1); 1255 len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
1191 if (len < 0) { return len; } 1256 if (len < 0) {
1257 return len;
1258 }
1192 memset(valstr, 0, sizeof(valstr)); 1259 memset(valstr, 0, sizeof(valstr));
1193 if( copy_from_user(valstr, &user_buffer[i], len)) 1260 if (copy_from_user(valstr, &user_buffer[i], len))
1194 return -EFAULT; 1261 return -EFAULT;
1195 i += len; 1262 i += len;
1196 1263
1197 for(*m = 0;*v && m < pkt_dev->dst_mac + 6; v++) { 1264 for (*m = 0; *v && m < pkt_dev->dst_mac + 6; v++) {
1198 if (*v >= '0' && *v <= '9') { 1265 if (*v >= '0' && *v <= '9') {
1199 *m *= 16; 1266 *m *= 16;
1200 *m += *v - '0'; 1267 *m += *v - '0';
@@ -1216,7 +1283,7 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer
1216 /* Set up Dest MAC */ 1283 /* Set up Dest MAC */
1217 if (compare_ether_addr(old_dmac, pkt_dev->dst_mac)) 1284 if (compare_ether_addr(old_dmac, pkt_dev->dst_mac))
1218 memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN); 1285 memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN);
1219 1286
1220 sprintf(pg_result, "OK: dstmac"); 1287 sprintf(pg_result, "OK: dstmac");
1221 return count; 1288 return count;
1222 } 1289 }
@@ -1225,13 +1292,15 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer
1225 unsigned char *m = pkt_dev->src_mac; 1292 unsigned char *m = pkt_dev->src_mac;
1226 1293
1227 len = strn_len(&user_buffer[i], sizeof(valstr) - 1); 1294 len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
1228 if (len < 0) { return len; } 1295 if (len < 0) {
1296 return len;
1297 }
1229 memset(valstr, 0, sizeof(valstr)); 1298 memset(valstr, 0, sizeof(valstr));
1230 if( copy_from_user(valstr, &user_buffer[i], len)) 1299 if (copy_from_user(valstr, &user_buffer[i], len))
1231 return -EFAULT; 1300 return -EFAULT;
1232 i += len; 1301 i += len;
1233 1302
1234 for(*m = 0;*v && m < pkt_dev->src_mac + 6; v++) { 1303 for (*m = 0; *v && m < pkt_dev->src_mac + 6; v++) {
1235 if (*v >= '0' && *v <= '9') { 1304 if (*v >= '0' && *v <= '9') {
1236 *m *= 16; 1305 *m *= 16;
1237 *m += *v - '0'; 1306 *m += *v - '0';
@@ -1248,21 +1317,23 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer
1248 m++; 1317 m++;
1249 *m = 0; 1318 *m = 0;
1250 } 1319 }
1251 } 1320 }
1252 1321
1253 sprintf(pg_result, "OK: srcmac"); 1322 sprintf(pg_result, "OK: srcmac");
1254 return count; 1323 return count;
1255 } 1324 }
1256 1325
1257 if (!strcmp(name, "clear_counters")) { 1326 if (!strcmp(name, "clear_counters")) {
1258 pktgen_clear_counters(pkt_dev); 1327 pktgen_clear_counters(pkt_dev);
1259 sprintf(pg_result, "OK: Clearing counters.\n"); 1328 sprintf(pg_result, "OK: Clearing counters.\n");
1260 return count; 1329 return count;
1261 } 1330 }
1262 1331
1263 if (!strcmp(name, "flows")) { 1332 if (!strcmp(name, "flows")) {
1264 len = num_arg(&user_buffer[i], 10, &value); 1333 len = num_arg(&user_buffer[i], 10, &value);
1265 if (len < 0) { return len; } 1334 if (len < 0) {
1335 return len;
1336 }
1266 i += len; 1337 i += len;
1267 if (value > MAX_CFLOWS) 1338 if (value > MAX_CFLOWS)
1268 value = MAX_CFLOWS; 1339 value = MAX_CFLOWS;
@@ -1274,13 +1345,15 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer
1274 1345
1275 if (!strcmp(name, "flowlen")) { 1346 if (!strcmp(name, "flowlen")) {
1276 len = num_arg(&user_buffer[i], 10, &value); 1347 len = num_arg(&user_buffer[i], 10, &value);
1277 if (len < 0) { return len; } 1348 if (len < 0) {
1349 return len;
1350 }
1278 i += len; 1351 i += len;
1279 pkt_dev->lflow = value; 1352 pkt_dev->lflow = value;
1280 sprintf(pg_result, "OK: flowlen=%u", pkt_dev->lflow); 1353 sprintf(pg_result, "OK: flowlen=%u", pkt_dev->lflow);
1281 return count; 1354 return count;
1282 } 1355 }
1283 1356
1284 sprintf(pkt_dev->result, "No such parameter \"%s\"", name); 1357 sprintf(pkt_dev->result, "No such parameter \"%s\"", name);
1285 return -EINVAL; 1358 return -EINVAL;
1286} 1359}
@@ -1291,35 +1364,35 @@ static int pktgen_if_open(struct inode *inode, struct file *file)
1291} 1364}
1292 1365
1293static struct file_operations pktgen_if_fops = { 1366static struct file_operations pktgen_if_fops = {
1294 .owner = THIS_MODULE, 1367 .owner = THIS_MODULE,
1295 .open = pktgen_if_open, 1368 .open = pktgen_if_open,
1296 .read = seq_read, 1369 .read = seq_read,
1297 .llseek = seq_lseek, 1370 .llseek = seq_lseek,
1298 .write = pktgen_if_write, 1371 .write = pktgen_if_write,
1299 .release = single_release, 1372 .release = single_release,
1300}; 1373};
1301 1374
1302static int pktgen_thread_show(struct seq_file *seq, void *v) 1375static int pktgen_thread_show(struct seq_file *seq, void *v)
1303{ 1376{
1304 struct pktgen_thread *t = seq->private; 1377 struct pktgen_thread *t = seq->private;
1305 struct pktgen_dev *pkt_dev = NULL; 1378 struct pktgen_dev *pkt_dev;
1306 1379
1307 BUG_ON(!t); 1380 BUG_ON(!t);
1308 1381
1309 seq_printf(seq, "Name: %s max_before_softirq: %d\n", 1382 seq_printf(seq, "Name: %s max_before_softirq: %d\n",
1310 t->name, t->max_before_softirq); 1383 t->name, t->max_before_softirq);
1384
1385 seq_printf(seq, "Running: ");
1311 1386
1312 seq_printf(seq, "Running: "); 1387 if_lock(t);
1313 1388 list_for_each_entry(pkt_dev, &t->if_list, list)
1314 if_lock(t); 1389 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); 1390 seq_printf(seq, "%s ", pkt_dev->ifname);
1318
1319 seq_printf(seq, "\nStopped: ");
1320 1391
1321 for(pkt_dev = t->if_list;pkt_dev; pkt_dev = pkt_dev->next) 1392 seq_printf(seq, "\nStopped: ");
1322 if(!pkt_dev->running) 1393
1394 list_for_each_entry(pkt_dev, &t->if_list, list)
1395 if (!pkt_dev->running)
1323 seq_printf(seq, "%s ", pkt_dev->ifname); 1396 seq_printf(seq, "%s ", pkt_dev->ifname);
1324 1397
1325 if (t->result[0]) 1398 if (t->result[0])
@@ -1327,30 +1400,30 @@ static int pktgen_thread_show(struct seq_file *seq, void *v)
1327 else 1400 else
1328 seq_printf(seq, "\nResult: NA\n"); 1401 seq_printf(seq, "\nResult: NA\n");
1329 1402
1330 if_unlock(t); 1403 if_unlock(t);
1331 1404
1332 return 0; 1405 return 0;
1333} 1406}
1334 1407
1335static ssize_t pktgen_thread_write(struct file *file, 1408static ssize_t pktgen_thread_write(struct file *file,
1336 const char __user *user_buffer, 1409 const char __user * user_buffer,
1337 size_t count, loff_t *offset) 1410 size_t count, loff_t * offset)
1338{ 1411{
1339 struct seq_file *seq = (struct seq_file *) file->private_data; 1412 struct seq_file *seq = (struct seq_file *)file->private_data;
1340 struct pktgen_thread *t = seq->private; 1413 struct pktgen_thread *t = seq->private;
1341 int i = 0, max, len, ret; 1414 int i = 0, max, len, ret;
1342 char name[40]; 1415 char name[40];
1343 char *pg_result; 1416 char *pg_result;
1344 unsigned long value = 0; 1417 unsigned long value = 0;
1345 1418
1346 if (count < 1) { 1419 if (count < 1) {
1347 // sprintf(pg_result, "Wrong command format"); 1420 // sprintf(pg_result, "Wrong command format");
1348 return -EINVAL; 1421 return -EINVAL;
1349 } 1422 }
1350 1423
1351 max = count - i; 1424 max = count - i;
1352 len = count_trail_chars(&user_buffer[i], max); 1425 len = count_trail_chars(&user_buffer[i], max);
1353 if (len < 0) 1426 if (len < 0)
1354 return len; 1427 return len;
1355 1428
1356 i += len; 1429 i += len;
@@ -1358,26 +1431,25 @@ static ssize_t pktgen_thread_write(struct file *file,
1358 /* Read variable name */ 1431 /* Read variable name */
1359 1432
1360 len = strn_len(&user_buffer[i], sizeof(name) - 1); 1433 len = strn_len(&user_buffer[i], sizeof(name) - 1);
1361 if (len < 0) 1434 if (len < 0)
1362 return len; 1435 return len;
1363 1436
1364 memset(name, 0, sizeof(name)); 1437 memset(name, 0, sizeof(name));
1365 if (copy_from_user(name, &user_buffer[i], len)) 1438 if (copy_from_user(name, &user_buffer[i], len))
1366 return -EFAULT; 1439 return -EFAULT;
1367 i += len; 1440 i += len;
1368 1441
1369 max = count -i; 1442 max = count - i;
1370 len = count_trail_chars(&user_buffer[i], max); 1443 len = count_trail_chars(&user_buffer[i], max);
1371 if (len < 0) 1444 if (len < 0)
1372 return len; 1445 return len;
1373 1446
1374 i += len; 1447 i += len;
1375 1448
1376 if (debug) 1449 if (debug)
1377 printk("pktgen: t=%s, count=%lu\n", name, 1450 printk("pktgen: t=%s, count=%lu\n", name, (unsigned long)count);
1378 (unsigned long) count);
1379 1451
1380 if(!t) { 1452 if (!t) {
1381 printk("pktgen: ERROR: No thread\n"); 1453 printk("pktgen: ERROR: No thread\n");
1382 ret = -EINVAL; 1454 ret = -EINVAL;
1383 goto out; 1455 goto out;
@@ -1385,48 +1457,47 @@ static ssize_t pktgen_thread_write(struct file *file,
1385 1457
1386 pg_result = &(t->result[0]); 1458 pg_result = &(t->result[0]);
1387 1459
1388 if (!strcmp(name, "add_device")) { 1460 if (!strcmp(name, "add_device")) {
1389 char f[32]; 1461 char f[32];
1390 memset(f, 0, 32); 1462 memset(f, 0, 32);
1391 len = strn_len(&user_buffer[i], sizeof(f) - 1); 1463 len = strn_len(&user_buffer[i], sizeof(f) - 1);
1392 if (len < 0) { 1464 if (len < 0) {
1393 ret = len; 1465 ret = len;
1394 goto out; 1466 goto out;
1395 } 1467 }
1396 if( copy_from_user(f, &user_buffer[i], len) ) 1468 if (copy_from_user(f, &user_buffer[i], len))
1397 return -EFAULT; 1469 return -EFAULT;
1398 i += len; 1470 i += len;
1399 thread_lock(); 1471 mutex_lock(&pktgen_thread_lock);
1400 pktgen_add_device(t, f); 1472 pktgen_add_device(t, f);
1401 thread_unlock(); 1473 mutex_unlock(&pktgen_thread_lock);
1402 ret = count; 1474 ret = count;
1403 sprintf(pg_result, "OK: add_device=%s", f); 1475 sprintf(pg_result, "OK: add_device=%s", f);
1404 goto out; 1476 goto out;
1405 } 1477 }
1406 1478
1407 if (!strcmp(name, "rem_device_all")) { 1479 if (!strcmp(name, "rem_device_all")) {
1408 thread_lock(); 1480 mutex_lock(&pktgen_thread_lock);
1409 t->control |= T_REMDEV; 1481 t->control |= T_REMDEVALL;
1410 thread_unlock(); 1482 mutex_unlock(&pktgen_thread_lock);
1411 schedule_timeout_interruptible(msecs_to_jiffies(125)); /* Propagate thread->control */ 1483 schedule_timeout_interruptible(msecs_to_jiffies(125)); /* Propagate thread->control */
1412 ret = count; 1484 ret = count;
1413 sprintf(pg_result, "OK: rem_device_all"); 1485 sprintf(pg_result, "OK: rem_device_all");
1414 goto out; 1486 goto out;
1415 } 1487 }
1416 1488
1417 if (!strcmp(name, "max_before_softirq")) { 1489 if (!strcmp(name, "max_before_softirq")) {
1418 len = num_arg(&user_buffer[i], 10, &value); 1490 len = num_arg(&user_buffer[i], 10, &value);
1419 thread_lock(); 1491 mutex_lock(&pktgen_thread_lock);
1420 t->max_before_softirq = value; 1492 t->max_before_softirq = value;
1421 thread_unlock(); 1493 mutex_unlock(&pktgen_thread_lock);
1422 ret = count; 1494 ret = count;
1423 sprintf(pg_result, "OK: max_before_softirq=%lu", value); 1495 sprintf(pg_result, "OK: max_before_softirq=%lu", value);
1424 goto out; 1496 goto out;
1425 } 1497 }
1426 1498
1427 ret = -EINVAL; 1499 ret = -EINVAL;
1428 out: 1500out:
1429
1430 return ret; 1501 return ret;
1431} 1502}
1432 1503
@@ -1436,47 +1507,78 @@ static int pktgen_thread_open(struct inode *inode, struct file *file)
1436} 1507}
1437 1508
1438static struct file_operations pktgen_thread_fops = { 1509static struct file_operations pktgen_thread_fops = {
1439 .owner = THIS_MODULE, 1510 .owner = THIS_MODULE,
1440 .open = pktgen_thread_open, 1511 .open = pktgen_thread_open,
1441 .read = seq_read, 1512 .read = seq_read,
1442 .llseek = seq_lseek, 1513 .llseek = seq_lseek,
1443 .write = pktgen_thread_write, 1514 .write = pktgen_thread_write,
1444 .release = single_release, 1515 .release = single_release,
1445}; 1516};
1446 1517
1447/* Think find or remove for NN */ 1518/* Think find or remove for NN */
1448static struct pktgen_dev *__pktgen_NN_threads(const char* ifname, int remove) 1519static struct pktgen_dev *__pktgen_NN_threads(const char *ifname, int remove)
1449{ 1520{
1450 struct pktgen_thread *t; 1521 struct pktgen_thread *t;
1451 struct pktgen_dev *pkt_dev = NULL; 1522 struct pktgen_dev *pkt_dev = NULL;
1452 1523
1453 t = pktgen_threads; 1524 list_for_each_entry(t, &pktgen_threads, th_list) {
1454
1455 while (t) {
1456 pkt_dev = pktgen_find_dev(t, ifname); 1525 pkt_dev = pktgen_find_dev(t, ifname);
1457 if (pkt_dev) { 1526 if (pkt_dev) {
1458 if(remove) { 1527 if (remove) {
1459 if_lock(t); 1528 if_lock(t);
1460 pktgen_remove_device(t, pkt_dev); 1529 pkt_dev->removal_mark = 1;
1461 if_unlock(t); 1530 t->control |= T_REMDEV;
1462 } 1531 if_unlock(t);
1532 }
1463 break; 1533 break;
1464 } 1534 }
1465 t = t->next;
1466 } 1535 }
1467 return pkt_dev; 1536 return pkt_dev;
1468} 1537}
1469 1538
1470static struct pktgen_dev *pktgen_NN_threads(const char* ifname, int remove) 1539/*
1540 * mark a device for removal
1541 */
1542static int pktgen_mark_device(const char *ifname)
1471{ 1543{
1472 struct pktgen_dev *pkt_dev = NULL; 1544 struct pktgen_dev *pkt_dev = NULL;
1473 thread_lock(); 1545 const int max_tries = 10, msec_per_try = 125;
1474 pkt_dev = __pktgen_NN_threads(ifname, remove); 1546 int i = 0;
1475 thread_unlock(); 1547 int ret = 0;
1476 return pkt_dev; 1548
1549 mutex_lock(&pktgen_thread_lock);
1550 PG_DEBUG(printk("pktgen: pktgen_mark_device marking %s for removal\n",
1551 ifname));
1552
1553 while (1) {
1554
1555 pkt_dev = __pktgen_NN_threads(ifname, REMOVE);
1556 if (pkt_dev == NULL)
1557 break; /* success */
1558
1559 mutex_unlock(&pktgen_thread_lock);
1560 PG_DEBUG(printk("pktgen: pktgen_mark_device waiting for %s "
1561 "to disappear....\n", ifname));
1562 schedule_timeout_interruptible(msecs_to_jiffies(msec_per_try));
1563 mutex_lock(&pktgen_thread_lock);
1564
1565 if (++i >= max_tries) {
1566 printk("pktgen_mark_device: timed out after waiting "
1567 "%d msec for device %s to be removed\n",
1568 msec_per_try * i, ifname);
1569 ret = 1;
1570 break;
1571 }
1572
1573 }
1574
1575 mutex_unlock(&pktgen_thread_lock);
1576
1577 return ret;
1477} 1578}
1478 1579
1479static int pktgen_device_event(struct notifier_block *unused, unsigned long event, void *ptr) 1580static int pktgen_device_event(struct notifier_block *unused,
1581 unsigned long event, void *ptr)
1480{ 1582{
1481 struct net_device *dev = (struct net_device *)(ptr); 1583 struct net_device *dev = (struct net_device *)(ptr);
1482 1584
@@ -1491,9 +1593,9 @@ static int pktgen_device_event(struct notifier_block *unused, unsigned long even
1491 case NETDEV_UP: 1593 case NETDEV_UP:
1492 /* Ignore for now */ 1594 /* Ignore for now */
1493 break; 1595 break;
1494 1596
1495 case NETDEV_UNREGISTER: 1597 case NETDEV_UNREGISTER:
1496 pktgen_NN_threads(dev->name, REMOVE); 1598 pktgen_mark_device(dev->name);
1497 break; 1599 break;
1498 }; 1600 };
1499 1601
@@ -1502,15 +1604,16 @@ static int pktgen_device_event(struct notifier_block *unused, unsigned long even
1502 1604
1503/* Associate pktgen_dev with a device. */ 1605/* Associate pktgen_dev with a device. */
1504 1606
1505static struct net_device* pktgen_setup_dev(struct pktgen_dev *pkt_dev) { 1607static struct net_device *pktgen_setup_dev(struct pktgen_dev *pkt_dev)
1608{
1506 struct net_device *odev; 1609 struct net_device *odev;
1507 1610
1508 /* Clean old setups */ 1611 /* Clean old setups */
1509 1612
1510 if (pkt_dev->odev) { 1613 if (pkt_dev->odev) {
1511 dev_put(pkt_dev->odev); 1614 dev_put(pkt_dev->odev);
1512 pkt_dev->odev = NULL; 1615 pkt_dev->odev = NULL;
1513 } 1616 }
1514 1617
1515 odev = dev_get_by_name(pkt_dev->ifname); 1618 odev = dev_get_by_name(pkt_dev->ifname);
1516 1619
@@ -1519,7 +1622,8 @@ static struct net_device* pktgen_setup_dev(struct pktgen_dev *pkt_dev) {
1519 goto out; 1622 goto out;
1520 } 1623 }
1521 if (odev->type != ARPHRD_ETHER) { 1624 if (odev->type != ARPHRD_ETHER) {
1522 printk("pktgen: not an ethernet device: \"%s\"\n", pkt_dev->ifname); 1625 printk("pktgen: not an ethernet device: \"%s\"\n",
1626 pkt_dev->ifname);
1523 goto out_put; 1627 goto out_put;
1524 } 1628 }
1525 if (!netif_running(odev)) { 1629 if (!netif_running(odev)) {
@@ -1527,13 +1631,13 @@ static struct net_device* pktgen_setup_dev(struct pktgen_dev *pkt_dev) {
1527 goto out_put; 1631 goto out_put;
1528 } 1632 }
1529 pkt_dev->odev = odev; 1633 pkt_dev->odev = odev;
1530 1634
1531 return pkt_dev->odev; 1635 return pkt_dev->odev;
1532 1636
1533out_put: 1637out_put:
1534 dev_put(odev); 1638 dev_put(odev);
1535out: 1639out:
1536 return NULL; 1640 return NULL;
1537 1641
1538} 1642}
1539 1643
@@ -1543,59 +1647,64 @@ out:
1543static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) 1647static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
1544{ 1648{
1545 /* Try once more, just in case it works now. */ 1649 /* Try once more, just in case it works now. */
1546 if (!pkt_dev->odev) 1650 if (!pkt_dev->odev)
1547 pktgen_setup_dev(pkt_dev); 1651 pktgen_setup_dev(pkt_dev);
1548 1652
1549 if (!pkt_dev->odev) { 1653 if (!pkt_dev->odev) {
1550 printk("pktgen: ERROR: pkt_dev->odev == NULL in setup_inject.\n"); 1654 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"); 1655 sprintf(pkt_dev->result,
1552 return; 1656 "ERROR: pkt_dev->odev == NULL in setup_inject.\n");
1553 } 1657 return;
1554 1658 }
1555 /* Default to the interface's mac if not explicitly set. */ 1659
1660 /* Default to the interface's mac if not explicitly set. */
1556 1661
1557 if (is_zero_ether_addr(pkt_dev->src_mac)) 1662 if (is_zero_ether_addr(pkt_dev->src_mac))
1558 memcpy(&(pkt_dev->hh[6]), pkt_dev->odev->dev_addr, ETH_ALEN); 1663 memcpy(&(pkt_dev->hh[6]), pkt_dev->odev->dev_addr, ETH_ALEN);
1559 1664
1560 /* Set up Dest MAC */ 1665 /* Set up Dest MAC */
1561 memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN); 1666 memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN);
1562 1667
1563 /* Set up pkt size */ 1668 /* Set up pkt size */
1564 pkt_dev->cur_pkt_size = pkt_dev->min_pkt_size; 1669 pkt_dev->cur_pkt_size = pkt_dev->min_pkt_size;
1565 1670
1566 if(pkt_dev->flags & F_IPV6) { 1671 if (pkt_dev->flags & F_IPV6) {
1567 /* 1672 /*
1568 * Skip this automatic address setting until locks or functions 1673 * Skip this automatic address setting until locks or functions
1569 * gets exported 1674 * gets exported
1570 */ 1675 */
1571 1676
1572#ifdef NOTNOW 1677#ifdef NOTNOW
1573 int i, set = 0, err=1; 1678 int i, set = 0, err = 1;
1574 struct inet6_dev *idev; 1679 struct inet6_dev *idev;
1575 1680
1576 for(i=0; i< IN6_ADDR_HSIZE; i++) 1681 for (i = 0; i < IN6_ADDR_HSIZE; i++)
1577 if(pkt_dev->cur_in6_saddr.s6_addr[i]) { 1682 if (pkt_dev->cur_in6_saddr.s6_addr[i]) {
1578 set = 1; 1683 set = 1;
1579 break; 1684 break;
1580 } 1685 }
1581 1686
1582 if(!set) { 1687 if (!set) {
1583 1688
1584 /* 1689 /*
1585 * Use linklevel address if unconfigured. 1690 * Use linklevel address if unconfigured.
1586 * 1691 *
1587 * use ipv6_get_lladdr if/when it's get exported 1692 * use ipv6_get_lladdr if/when it's get exported
1588 */ 1693 */
1589 1694
1590
1591 read_lock(&addrconf_lock); 1695 read_lock(&addrconf_lock);
1592 if ((idev = __in6_dev_get(pkt_dev->odev)) != NULL) { 1696 if ((idev = __in6_dev_get(pkt_dev->odev)) != NULL) {
1593 struct inet6_ifaddr *ifp; 1697 struct inet6_ifaddr *ifp;
1594 1698
1595 read_lock_bh(&idev->lock); 1699 read_lock_bh(&idev->lock);
1596 for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { 1700 for (ifp = idev->addr_list; ifp;
1597 if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) { 1701 ifp = ifp->if_next) {
1598 ipv6_addr_copy(&pkt_dev->cur_in6_saddr, &ifp->addr); 1702 if (ifp->scope == IFA_LINK
1703 && !(ifp->
1704 flags & IFA_F_TENTATIVE)) {
1705 ipv6_addr_copy(&pkt_dev->
1706 cur_in6_saddr,
1707 &ifp->addr);
1599 err = 0; 1708 err = 0;
1600 break; 1709 break;
1601 } 1710 }
@@ -1603,28 +1712,28 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
1603 read_unlock_bh(&idev->lock); 1712 read_unlock_bh(&idev->lock);
1604 } 1713 }
1605 read_unlock(&addrconf_lock); 1714 read_unlock(&addrconf_lock);
1606 if(err) printk("pktgen: ERROR: IPv6 link address not availble.\n"); 1715 if (err)
1716 printk("pktgen: ERROR: IPv6 link address not availble.\n");
1607 } 1717 }
1608#endif 1718#endif
1609 } 1719 } else {
1610 else {
1611 pkt_dev->saddr_min = 0; 1720 pkt_dev->saddr_min = 0;
1612 pkt_dev->saddr_max = 0; 1721 pkt_dev->saddr_max = 0;
1613 if (strlen(pkt_dev->src_min) == 0) { 1722 if (strlen(pkt_dev->src_min) == 0) {
1614 1723
1615 struct in_device *in_dev; 1724 struct in_device *in_dev;
1616 1725
1617 rcu_read_lock(); 1726 rcu_read_lock();
1618 in_dev = __in_dev_get_rcu(pkt_dev->odev); 1727 in_dev = __in_dev_get_rcu(pkt_dev->odev);
1619 if (in_dev) { 1728 if (in_dev) {
1620 if (in_dev->ifa_list) { 1729 if (in_dev->ifa_list) {
1621 pkt_dev->saddr_min = in_dev->ifa_list->ifa_address; 1730 pkt_dev->saddr_min =
1731 in_dev->ifa_list->ifa_address;
1622 pkt_dev->saddr_max = pkt_dev->saddr_min; 1732 pkt_dev->saddr_max = pkt_dev->saddr_min;
1623 } 1733 }
1624 } 1734 }
1625 rcu_read_unlock(); 1735 rcu_read_unlock();
1626 } 1736 } else {
1627 else {
1628 pkt_dev->saddr_min = in_aton(pkt_dev->src_min); 1737 pkt_dev->saddr_min = in_aton(pkt_dev->src_min);
1629 pkt_dev->saddr_max = in_aton(pkt_dev->src_max); 1738 pkt_dev->saddr_max = in_aton(pkt_dev->src_max);
1630 } 1739 }
@@ -1632,13 +1741,13 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
1632 pkt_dev->daddr_min = in_aton(pkt_dev->dst_min); 1741 pkt_dev->daddr_min = in_aton(pkt_dev->dst_min);
1633 pkt_dev->daddr_max = in_aton(pkt_dev->dst_max); 1742 pkt_dev->daddr_max = in_aton(pkt_dev->dst_max);
1634 } 1743 }
1635 /* Initialize current values. */ 1744 /* Initialize current values. */
1636 pkt_dev->cur_dst_mac_offset = 0; 1745 pkt_dev->cur_dst_mac_offset = 0;
1637 pkt_dev->cur_src_mac_offset = 0; 1746 pkt_dev->cur_src_mac_offset = 0;
1638 pkt_dev->cur_saddr = pkt_dev->saddr_min; 1747 pkt_dev->cur_saddr = pkt_dev->saddr_min;
1639 pkt_dev->cur_daddr = pkt_dev->daddr_min; 1748 pkt_dev->cur_daddr = pkt_dev->daddr_min;
1640 pkt_dev->cur_udp_dst = pkt_dev->udp_dst_min; 1749 pkt_dev->cur_udp_dst = pkt_dev->udp_dst_min;
1641 pkt_dev->cur_udp_src = pkt_dev->udp_src_min; 1750 pkt_dev->cur_udp_src = pkt_dev->udp_src_min;
1642 pkt_dev->nflows = 0; 1751 pkt_dev->nflows = 0;
1643} 1752}
1644 1753
@@ -1651,7 +1760,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)); 1760 printk(KERN_INFO "sleeping for %d\n", (int)(spin_until_us - now));
1652 while (now < spin_until_us) { 1761 while (now < spin_until_us) {
1653 /* TODO: optimize sleeping behavior */ 1762 /* TODO: optimize sleeping behavior */
1654 if (spin_until_us - now > jiffies_to_usecs(1)+1) 1763 if (spin_until_us - now > jiffies_to_usecs(1) + 1)
1655 schedule_timeout_interruptible(1); 1764 schedule_timeout_interruptible(1);
1656 else if (spin_until_us - now > 100) { 1765 else if (spin_until_us - now > 100) {
1657 do_softirq(); 1766 do_softirq();
@@ -1667,102 +1776,110 @@ static void spin(struct pktgen_dev *pkt_dev, __u64 spin_until_us)
1667 pkt_dev->idle_acc += now - start; 1776 pkt_dev->idle_acc += now - start;
1668} 1777}
1669 1778
1670
1671/* Increment/randomize headers according to flags and current values 1779/* Increment/randomize headers according to flags and current values
1672 * for IP src/dest, UDP src/dst port, MAC-Addr src/dst 1780 * for IP src/dest, UDP src/dst port, MAC-Addr src/dst
1673 */ 1781 */
1674static void mod_cur_headers(struct pktgen_dev *pkt_dev) { 1782static void mod_cur_headers(struct pktgen_dev *pkt_dev)
1675 __u32 imn; 1783{
1676 __u32 imx; 1784 __u32 imn;
1677 int flow = 0; 1785 __u32 imx;
1786 int flow = 0;
1678 1787
1679 if(pkt_dev->cflows) { 1788 if (pkt_dev->cflows) {
1680 flow = pktgen_random() % pkt_dev->cflows; 1789 flow = pktgen_random() % pkt_dev->cflows;
1681 1790
1682 if (pkt_dev->flows[flow].count > pkt_dev->lflow) 1791 if (pkt_dev->flows[flow].count > pkt_dev->lflow)
1683 pkt_dev->flows[flow].count = 0; 1792 pkt_dev->flows[flow].count = 0;
1684 } 1793 }
1685
1686 1794
1687 /* Deal with source MAC */ 1795 /* Deal with source MAC */
1688 if (pkt_dev->src_mac_count > 1) { 1796 if (pkt_dev->src_mac_count > 1) {
1689 __u32 mc; 1797 __u32 mc;
1690 __u32 tmp; 1798 __u32 tmp;
1691 1799
1692 if (pkt_dev->flags & F_MACSRC_RND) 1800 if (pkt_dev->flags & F_MACSRC_RND)
1693 mc = pktgen_random() % (pkt_dev->src_mac_count); 1801 mc = pktgen_random() % (pkt_dev->src_mac_count);
1694 else { 1802 else {
1695 mc = pkt_dev->cur_src_mac_offset++; 1803 mc = pkt_dev->cur_src_mac_offset++;
1696 if (pkt_dev->cur_src_mac_offset > pkt_dev->src_mac_count) 1804 if (pkt_dev->cur_src_mac_offset >
1697 pkt_dev->cur_src_mac_offset = 0; 1805 pkt_dev->src_mac_count)
1698 } 1806 pkt_dev->cur_src_mac_offset = 0;
1699 1807 }
1700 tmp = pkt_dev->src_mac[5] + (mc & 0xFF); 1808
1701 pkt_dev->hh[11] = tmp; 1809 tmp = pkt_dev->src_mac[5] + (mc & 0xFF);
1702 tmp = (pkt_dev->src_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8)); 1810 pkt_dev->hh[11] = tmp;
1703 pkt_dev->hh[10] = tmp; 1811 tmp = (pkt_dev->src_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8));
1704 tmp = (pkt_dev->src_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8)); 1812 pkt_dev->hh[10] = tmp;
1705 pkt_dev->hh[9] = tmp; 1813 tmp = (pkt_dev->src_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8));
1706 tmp = (pkt_dev->src_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8)); 1814 pkt_dev->hh[9] = tmp;
1707 pkt_dev->hh[8] = tmp; 1815 tmp = (pkt_dev->src_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8));
1708 tmp = (pkt_dev->src_mac[1] + (tmp >> 8)); 1816 pkt_dev->hh[8] = tmp;
1709 pkt_dev->hh[7] = tmp; 1817 tmp = (pkt_dev->src_mac[1] + (tmp >> 8));
1710 } 1818 pkt_dev->hh[7] = tmp;
1711 1819 }
1712 /* Deal with Destination MAC */ 1820
1713 if (pkt_dev->dst_mac_count > 1) { 1821 /* Deal with Destination MAC */
1714 __u32 mc; 1822 if (pkt_dev->dst_mac_count > 1) {
1715 __u32 tmp; 1823 __u32 mc;
1716 1824 __u32 tmp;
1717 if (pkt_dev->flags & F_MACDST_RND) 1825
1718 mc = pktgen_random() % (pkt_dev->dst_mac_count); 1826 if (pkt_dev->flags & F_MACDST_RND)
1719 1827 mc = pktgen_random() % (pkt_dev->dst_mac_count);
1720 else { 1828
1721 mc = pkt_dev->cur_dst_mac_offset++; 1829 else {
1722 if (pkt_dev->cur_dst_mac_offset > pkt_dev->dst_mac_count) { 1830 mc = pkt_dev->cur_dst_mac_offset++;
1723 pkt_dev->cur_dst_mac_offset = 0; 1831 if (pkt_dev->cur_dst_mac_offset >
1724 } 1832 pkt_dev->dst_mac_count) {
1725 } 1833 pkt_dev->cur_dst_mac_offset = 0;
1726 1834 }
1727 tmp = pkt_dev->dst_mac[5] + (mc & 0xFF); 1835 }
1728 pkt_dev->hh[5] = tmp; 1836
1729 tmp = (pkt_dev->dst_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8)); 1837 tmp = pkt_dev->dst_mac[5] + (mc & 0xFF);
1730 pkt_dev->hh[4] = tmp; 1838 pkt_dev->hh[5] = tmp;
1731 tmp = (pkt_dev->dst_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8)); 1839 tmp = (pkt_dev->dst_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8));
1732 pkt_dev->hh[3] = tmp; 1840 pkt_dev->hh[4] = tmp;
1733 tmp = (pkt_dev->dst_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8)); 1841 tmp = (pkt_dev->dst_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8));
1734 pkt_dev->hh[2] = tmp; 1842 pkt_dev->hh[3] = tmp;
1735 tmp = (pkt_dev->dst_mac[1] + (tmp >> 8)); 1843 tmp = (pkt_dev->dst_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8));
1736 pkt_dev->hh[1] = tmp; 1844 pkt_dev->hh[2] = tmp;
1737 } 1845 tmp = (pkt_dev->dst_mac[1] + (tmp >> 8));
1738 1846 pkt_dev->hh[1] = tmp;
1739 if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) { 1847 }
1740 if (pkt_dev->flags & F_UDPSRC_RND) 1848
1741 pkt_dev->cur_udp_src = ((pktgen_random() % (pkt_dev->udp_src_max - pkt_dev->udp_src_min)) + pkt_dev->udp_src_min); 1849 if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) {
1742 1850 if (pkt_dev->flags & F_UDPSRC_RND)
1743 else { 1851 pkt_dev->cur_udp_src =
1852 ((pktgen_random() %
1853 (pkt_dev->udp_src_max - pkt_dev->udp_src_min)) +
1854 pkt_dev->udp_src_min);
1855
1856 else {
1744 pkt_dev->cur_udp_src++; 1857 pkt_dev->cur_udp_src++;
1745 if (pkt_dev->cur_udp_src >= pkt_dev->udp_src_max) 1858 if (pkt_dev->cur_udp_src >= pkt_dev->udp_src_max)
1746 pkt_dev->cur_udp_src = pkt_dev->udp_src_min; 1859 pkt_dev->cur_udp_src = pkt_dev->udp_src_min;
1747 } 1860 }
1748 } 1861 }
1749 1862
1750 if (pkt_dev->udp_dst_min < pkt_dev->udp_dst_max) { 1863 if (pkt_dev->udp_dst_min < pkt_dev->udp_dst_max) {
1751 if (pkt_dev->flags & F_UDPDST_RND) { 1864 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); 1865 pkt_dev->cur_udp_dst =
1753 } 1866 ((pktgen_random() %
1754 else { 1867 (pkt_dev->udp_dst_max - pkt_dev->udp_dst_min)) +
1868 pkt_dev->udp_dst_min);
1869 } else {
1755 pkt_dev->cur_udp_dst++; 1870 pkt_dev->cur_udp_dst++;
1756 if (pkt_dev->cur_udp_dst >= pkt_dev->udp_dst_max) 1871 if (pkt_dev->cur_udp_dst >= pkt_dev->udp_dst_max)
1757 pkt_dev->cur_udp_dst = pkt_dev->udp_dst_min; 1872 pkt_dev->cur_udp_dst = pkt_dev->udp_dst_min;
1758 } 1873 }
1759 } 1874 }
1760 1875
1761 if (!(pkt_dev->flags & F_IPV6)) { 1876 if (!(pkt_dev->flags & F_IPV6)) {
1762 1877
1763 if ((imn = ntohl(pkt_dev->saddr_min)) < (imx = ntohl(pkt_dev->saddr_max))) { 1878 if ((imn = ntohl(pkt_dev->saddr_min)) < (imx =
1879 ntohl(pkt_dev->
1880 saddr_max))) {
1764 __u32 t; 1881 __u32 t;
1765 if (pkt_dev->flags & F_IPSRC_RND) 1882 if (pkt_dev->flags & F_IPSRC_RND)
1766 t = ((pktgen_random() % (imx - imn)) + imn); 1883 t = ((pktgen_random() % (imx - imn)) + imn);
1767 else { 1884 else {
1768 t = ntohl(pkt_dev->cur_saddr); 1885 t = ntohl(pkt_dev->cur_saddr);
@@ -1773,25 +1890,32 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) {
1773 } 1890 }
1774 pkt_dev->cur_saddr = htonl(t); 1891 pkt_dev->cur_saddr = htonl(t);
1775 } 1892 }
1776 1893
1777 if (pkt_dev->cflows && pkt_dev->flows[flow].count != 0) { 1894 if (pkt_dev->cflows && pkt_dev->flows[flow].count != 0) {
1778 pkt_dev->cur_daddr = pkt_dev->flows[flow].cur_daddr; 1895 pkt_dev->cur_daddr = pkt_dev->flows[flow].cur_daddr;
1779 } else { 1896 } else {
1780 1897
1781 if ((imn = ntohl(pkt_dev->daddr_min)) < (imx = ntohl(pkt_dev->daddr_max))) { 1898 if ((imn = ntohl(pkt_dev->daddr_min)) < (imx =
1899 ntohl(pkt_dev->
1900 daddr_max)))
1901 {
1782 __u32 t; 1902 __u32 t;
1783 if (pkt_dev->flags & F_IPDST_RND) { 1903 if (pkt_dev->flags & F_IPDST_RND) {
1784 1904
1785 t = ((pktgen_random() % (imx - imn)) + imn); 1905 t = ((pktgen_random() % (imx - imn)) +
1906 imn);
1786 t = htonl(t); 1907 t = htonl(t);
1787 1908
1788 while( LOOPBACK(t) || MULTICAST(t) || BADCLASS(t) || ZERONET(t) || LOCAL_MCAST(t) ) { 1909 while (LOOPBACK(t) || MULTICAST(t)
1789 t = ((pktgen_random() % (imx - imn)) + imn); 1910 || BADCLASS(t) || ZERONET(t)
1911 || LOCAL_MCAST(t)) {
1912 t = ((pktgen_random() %
1913 (imx - imn)) + imn);
1790 t = htonl(t); 1914 t = htonl(t);
1791 } 1915 }
1792 pkt_dev->cur_daddr = t; 1916 pkt_dev->cur_daddr = t;
1793 } 1917 }
1794 1918
1795 else { 1919 else {
1796 t = ntohl(pkt_dev->cur_daddr); 1920 t = ntohl(pkt_dev->cur_daddr);
1797 t++; 1921 t++;
@@ -1801,60 +1925,59 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) {
1801 pkt_dev->cur_daddr = htonl(t); 1925 pkt_dev->cur_daddr = htonl(t);
1802 } 1926 }
1803 } 1927 }
1804 if(pkt_dev->cflows) { 1928 if (pkt_dev->cflows) {
1805 pkt_dev->flows[flow].cur_daddr = pkt_dev->cur_daddr; 1929 pkt_dev->flows[flow].cur_daddr =
1930 pkt_dev->cur_daddr;
1806 pkt_dev->nflows++; 1931 pkt_dev->nflows++;
1807 } 1932 }
1808 } 1933 }
1809 } 1934 } else { /* IPV6 * */
1810 else /* IPV6 * */ 1935
1811 { 1936 if (pkt_dev->min_in6_daddr.s6_addr32[0] == 0 &&
1812 if(pkt_dev->min_in6_daddr.s6_addr32[0] == 0 && 1937 pkt_dev->min_in6_daddr.s6_addr32[1] == 0 &&
1813 pkt_dev->min_in6_daddr.s6_addr32[1] == 0 && 1938 pkt_dev->min_in6_daddr.s6_addr32[2] == 0 &&
1814 pkt_dev->min_in6_daddr.s6_addr32[2] == 0 && 1939 pkt_dev->min_in6_daddr.s6_addr32[3] == 0) ;
1815 pkt_dev->min_in6_daddr.s6_addr32[3] == 0);
1816 else { 1940 else {
1817 int i; 1941 int i;
1818 1942
1819 /* Only random destinations yet */ 1943 /* Only random destinations yet */
1820 1944
1821 for(i=0; i < 4; i++) { 1945 for (i = 0; i < 4; i++) {
1822 pkt_dev->cur_in6_daddr.s6_addr32[i] = 1946 pkt_dev->cur_in6_daddr.s6_addr32[i] =
1823 ((pktgen_random() | 1947 ((pktgen_random() |
1824 pkt_dev->min_in6_daddr.s6_addr32[i]) & 1948 pkt_dev->min_in6_daddr.s6_addr32[i]) &
1825 pkt_dev->max_in6_daddr.s6_addr32[i]); 1949 pkt_dev->max_in6_daddr.s6_addr32[i]);
1826 } 1950 }
1827 } 1951 }
1828 } 1952 }
1829 1953
1830 if (pkt_dev->min_pkt_size < pkt_dev->max_pkt_size) { 1954 if (pkt_dev->min_pkt_size < pkt_dev->max_pkt_size) {
1831 __u32 t; 1955 __u32 t;
1832 if (pkt_dev->flags & F_TXSIZE_RND) { 1956 if (pkt_dev->flags & F_TXSIZE_RND) {
1833 t = ((pktgen_random() % (pkt_dev->max_pkt_size - pkt_dev->min_pkt_size)) 1957 t = ((pktgen_random() %
1834 + pkt_dev->min_pkt_size); 1958 (pkt_dev->max_pkt_size - pkt_dev->min_pkt_size))
1835 } 1959 + pkt_dev->min_pkt_size);
1836 else { 1960 } else {
1837 t = pkt_dev->cur_pkt_size + 1; 1961 t = pkt_dev->cur_pkt_size + 1;
1838 if (t > pkt_dev->max_pkt_size) 1962 if (t > pkt_dev->max_pkt_size)
1839 t = pkt_dev->min_pkt_size; 1963 t = pkt_dev->min_pkt_size;
1840 } 1964 }
1841 pkt_dev->cur_pkt_size = t; 1965 pkt_dev->cur_pkt_size = t;
1842 } 1966 }
1843 1967
1844 pkt_dev->flows[flow].count++; 1968 pkt_dev->flows[flow].count++;
1845} 1969}
1846 1970
1847 1971static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
1848static struct sk_buff *fill_packet_ipv4(struct net_device *odev, 1972 struct pktgen_dev *pkt_dev)
1849 struct pktgen_dev *pkt_dev)
1850{ 1973{
1851 struct sk_buff *skb = NULL; 1974 struct sk_buff *skb = NULL;
1852 __u8 *eth; 1975 __u8 *eth;
1853 struct udphdr *udph; 1976 struct udphdr *udph;
1854 int datalen, iplen; 1977 int datalen, iplen;
1855 struct iphdr *iph; 1978 struct iphdr *iph;
1856 struct pktgen_hdr *pgh = NULL; 1979 struct pktgen_hdr *pgh = NULL;
1857 1980
1858 /* Update any of the values, used when we're incrementing various 1981 /* Update any of the values, used when we're incrementing various
1859 * fields. 1982 * fields.
1860 */ 1983 */
@@ -1875,47 +1998,47 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
1875 udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr)); 1998 udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
1876 1999
1877 memcpy(eth, pkt_dev->hh, 12); 2000 memcpy(eth, pkt_dev->hh, 12);
1878 *(u16*)&eth[12] = __constant_htons(ETH_P_IP); 2001 *(u16 *) & eth[12] = __constant_htons(ETH_P_IP);
1879 2002
1880 datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8; /* Eth + IPh + UDPh */ 2003 datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8; /* Eth + IPh + UDPh */
1881 if (datalen < sizeof(struct pktgen_hdr)) 2004 if (datalen < sizeof(struct pktgen_hdr))
1882 datalen = sizeof(struct pktgen_hdr); 2005 datalen = sizeof(struct pktgen_hdr);
1883 2006
1884 udph->source = htons(pkt_dev->cur_udp_src); 2007 udph->source = htons(pkt_dev->cur_udp_src);
1885 udph->dest = htons(pkt_dev->cur_udp_dst); 2008 udph->dest = htons(pkt_dev->cur_udp_dst);
1886 udph->len = htons(datalen + 8); /* DATA + udphdr */ 2009 udph->len = htons(datalen + 8); /* DATA + udphdr */
1887 udph->check = 0; /* No checksum */ 2010 udph->check = 0; /* No checksum */
1888 2011
1889 iph->ihl = 5; 2012 iph->ihl = 5;
1890 iph->version = 4; 2013 iph->version = 4;
1891 iph->ttl = 32; 2014 iph->ttl = 32;
1892 iph->tos = 0; 2015 iph->tos = 0;
1893 iph->protocol = IPPROTO_UDP; /* UDP */ 2016 iph->protocol = IPPROTO_UDP; /* UDP */
1894 iph->saddr = pkt_dev->cur_saddr; 2017 iph->saddr = pkt_dev->cur_saddr;
1895 iph->daddr = pkt_dev->cur_daddr; 2018 iph->daddr = pkt_dev->cur_daddr;
1896 iph->frag_off = 0; 2019 iph->frag_off = 0;
1897 iplen = 20 + 8 + datalen; 2020 iplen = 20 + 8 + datalen;
1898 iph->tot_len = htons(iplen); 2021 iph->tot_len = htons(iplen);
1899 iph->check = 0; 2022 iph->check = 0;
1900 iph->check = ip_fast_csum((void *) iph, iph->ihl); 2023 iph->check = ip_fast_csum((void *)iph, iph->ihl);
1901 skb->protocol = __constant_htons(ETH_P_IP); 2024 skb->protocol = __constant_htons(ETH_P_IP);
1902 skb->mac.raw = ((u8 *)iph) - 14; 2025 skb->mac.raw = ((u8 *) iph) - 14;
1903 skb->dev = odev; 2026 skb->dev = odev;
1904 skb->pkt_type = PACKET_HOST; 2027 skb->pkt_type = PACKET_HOST;
1905 2028
1906 if (pkt_dev->nfrags <= 0) 2029 if (pkt_dev->nfrags <= 0)
1907 pgh = (struct pktgen_hdr *)skb_put(skb, datalen); 2030 pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
1908 else { 2031 else {
1909 int frags = pkt_dev->nfrags; 2032 int frags = pkt_dev->nfrags;
1910 int i; 2033 int i;
1911 2034
1912 pgh = (struct pktgen_hdr*)(((char*)(udph)) + 8); 2035 pgh = (struct pktgen_hdr *)(((char *)(udph)) + 8);
1913 2036
1914 if (frags > MAX_SKB_FRAGS) 2037 if (frags > MAX_SKB_FRAGS)
1915 frags = MAX_SKB_FRAGS; 2038 frags = MAX_SKB_FRAGS;
1916 if (datalen > frags*PAGE_SIZE) { 2039 if (datalen > frags * PAGE_SIZE) {
1917 skb_put(skb, datalen-frags*PAGE_SIZE); 2040 skb_put(skb, datalen - frags * PAGE_SIZE);
1918 datalen = frags*PAGE_SIZE; 2041 datalen = frags * PAGE_SIZE;
1919 } 2042 }
1920 2043
1921 i = 0; 2044 i = 0;
@@ -1924,7 +2047,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
1924 skb_shinfo(skb)->frags[i].page = page; 2047 skb_shinfo(skb)->frags[i].page = page;
1925 skb_shinfo(skb)->frags[i].page_offset = 0; 2048 skb_shinfo(skb)->frags[i].page_offset = 0;
1926 skb_shinfo(skb)->frags[i].size = 2049 skb_shinfo(skb)->frags[i].size =
1927 (datalen < PAGE_SIZE ? datalen : PAGE_SIZE); 2050 (datalen < PAGE_SIZE ? datalen : PAGE_SIZE);
1928 datalen -= skb_shinfo(skb)->frags[i].size; 2051 datalen -= skb_shinfo(skb)->frags[i].size;
1929 skb->len += skb_shinfo(skb)->frags[i].size; 2052 skb->len += skb_shinfo(skb)->frags[i].size;
1930 skb->data_len += skb_shinfo(skb)->frags[i].size; 2053 skb->data_len += skb_shinfo(skb)->frags[i].size;
@@ -1944,30 +2067,33 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
1944 2067
1945 skb_shinfo(skb)->frags[i - 1].size -= rem; 2068 skb_shinfo(skb)->frags[i - 1].size -= rem;
1946 2069
1947 skb_shinfo(skb)->frags[i] = skb_shinfo(skb)->frags[i - 1]; 2070 skb_shinfo(skb)->frags[i] =
2071 skb_shinfo(skb)->frags[i - 1];
1948 get_page(skb_shinfo(skb)->frags[i].page); 2072 get_page(skb_shinfo(skb)->frags[i].page);
1949 skb_shinfo(skb)->frags[i].page = skb_shinfo(skb)->frags[i - 1].page; 2073 skb_shinfo(skb)->frags[i].page =
1950 skb_shinfo(skb)->frags[i].page_offset += skb_shinfo(skb)->frags[i - 1].size; 2074 skb_shinfo(skb)->frags[i - 1].page;
2075 skb_shinfo(skb)->frags[i].page_offset +=
2076 skb_shinfo(skb)->frags[i - 1].size;
1951 skb_shinfo(skb)->frags[i].size = rem; 2077 skb_shinfo(skb)->frags[i].size = rem;
1952 i++; 2078 i++;
1953 skb_shinfo(skb)->nr_frags = i; 2079 skb_shinfo(skb)->nr_frags = i;
1954 } 2080 }
1955 } 2081 }
1956 2082
1957 /* Stamp the time, and sequence number, convert them to network byte order */ 2083 /* Stamp the time, and sequence number, convert them to network byte order */
2084
2085 if (pgh) {
2086 struct timeval timestamp;
2087
2088 pgh->pgh_magic = htonl(PKTGEN_MAGIC);
2089 pgh->seq_num = htonl(pkt_dev->seq_num);
2090
2091 do_gettimeofday(&timestamp);
2092 pgh->tv_sec = htonl(timestamp.tv_sec);
2093 pgh->tv_usec = htonl(timestamp.tv_usec);
2094 }
2095 pkt_dev->seq_num++;
1958 2096
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; 2097 return skb;
1972} 2098}
1973 2099
@@ -1980,23 +2106,24 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
1980 * --ro 2106 * --ro
1981 */ 2107 */
1982 2108
1983static unsigned int scan_ip6(const char *s,char ip[16]) 2109static unsigned int scan_ip6(const char *s, char ip[16])
1984{ 2110{
1985 unsigned int i; 2111 unsigned int i;
1986 unsigned int len=0; 2112 unsigned int len = 0;
1987 unsigned long u; 2113 unsigned long u;
1988 char suffix[16]; 2114 char suffix[16];
1989 unsigned int prefixlen=0; 2115 unsigned int prefixlen = 0;
1990 unsigned int suffixlen=0; 2116 unsigned int suffixlen = 0;
1991 __u32 tmp; 2117 __u32 tmp;
1992 2118
1993 for (i=0; i<16; i++) ip[i]=0; 2119 for (i = 0; i < 16; i++)
2120 ip[i] = 0;
1994 2121
1995 for (;;) { 2122 for (;;) {
1996 if (*s == ':') { 2123 if (*s == ':') {
1997 len++; 2124 len++;
1998 if (s[1] == ':') { /* Found "::", skip to part 2 */ 2125 if (s[1] == ':') { /* Found "::", skip to part 2 */
1999 s+=2; 2126 s += 2;
2000 len++; 2127 len++;
2001 break; 2128 break;
2002 } 2129 }
@@ -2004,129 +2131,149 @@ static unsigned int scan_ip6(const char *s,char ip[16])
2004 } 2131 }
2005 { 2132 {
2006 char *tmp; 2133 char *tmp;
2007 u=simple_strtoul(s,&tmp,16); 2134 u = simple_strtoul(s, &tmp, 16);
2008 i=tmp-s; 2135 i = tmp - s;
2009 } 2136 }
2010 2137
2011 if (!i) return 0; 2138 if (!i)
2012 if (prefixlen==12 && s[i]=='.') { 2139 return 0;
2140 if (prefixlen == 12 && s[i] == '.') {
2013 2141
2014 /* the last 4 bytes may be written as IPv4 address */ 2142 /* the last 4 bytes may be written as IPv4 address */
2015 2143
2016 tmp = in_aton(s); 2144 tmp = in_aton(s);
2017 memcpy((struct in_addr*)(ip+12), &tmp, sizeof(tmp)); 2145 memcpy((struct in_addr *)(ip + 12), &tmp, sizeof(tmp));
2018 return i+len; 2146 return i + len;
2019 } 2147 }
2020 ip[prefixlen++] = (u >> 8); 2148 ip[prefixlen++] = (u >> 8);
2021 ip[prefixlen++] = (u & 255); 2149 ip[prefixlen++] = (u & 255);
2022 s += i; len += i; 2150 s += i;
2023 if (prefixlen==16) 2151 len += i;
2152 if (prefixlen == 16)
2024 return len; 2153 return len;
2025 } 2154 }
2026 2155
2027/* part 2, after "::" */ 2156/* part 2, after "::" */
2028 for (;;) { 2157 for (;;) {
2029 if (*s == ':') { 2158 if (*s == ':') {
2030 if (suffixlen==0) 2159 if (suffixlen == 0)
2031 break; 2160 break;
2032 s++; 2161 s++;
2033 len++; 2162 len++;
2034 } else if (suffixlen!=0) 2163 } else if (suffixlen != 0)
2035 break; 2164 break;
2036 { 2165 {
2037 char *tmp; 2166 char *tmp;
2038 u=simple_strtol(s,&tmp,16); 2167 u = simple_strtol(s, &tmp, 16);
2039 i=tmp-s; 2168 i = tmp - s;
2040 } 2169 }
2041 if (!i) { 2170 if (!i) {
2042 if (*s) len--; 2171 if (*s)
2172 len--;
2043 break; 2173 break;
2044 } 2174 }
2045 if (suffixlen+prefixlen<=12 && s[i]=='.') { 2175 if (suffixlen + prefixlen <= 12 && s[i] == '.') {
2046 tmp = in_aton(s); 2176 tmp = in_aton(s);
2047 memcpy((struct in_addr*)(suffix+suffixlen), &tmp, sizeof(tmp)); 2177 memcpy((struct in_addr *)(suffix + suffixlen), &tmp,
2048 suffixlen+=4; 2178 sizeof(tmp));
2049 len+=strlen(s); 2179 suffixlen += 4;
2180 len += strlen(s);
2050 break; 2181 break;
2051 } 2182 }
2052 suffix[suffixlen++] = (u >> 8); 2183 suffix[suffixlen++] = (u >> 8);
2053 suffix[suffixlen++] = (u & 255); 2184 suffix[suffixlen++] = (u & 255);
2054 s += i; len += i; 2185 s += i;
2055 if (prefixlen+suffixlen==16) 2186 len += i;
2187 if (prefixlen + suffixlen == 16)
2056 break; 2188 break;
2057 } 2189 }
2058 for (i=0; i<suffixlen; i++) 2190 for (i = 0; i < suffixlen; i++)
2059 ip[16-suffixlen+i] = suffix[i]; 2191 ip[16 - suffixlen + i] = suffix[i];
2060 return len; 2192 return len;
2061} 2193}
2062 2194
2063static char tohex(char hexdigit) { 2195static char tohex(char hexdigit)
2064 return hexdigit>9?hexdigit+'a'-10:hexdigit+'0'; 2196{
2197 return hexdigit > 9 ? hexdigit + 'a' - 10 : hexdigit + '0';
2065} 2198}
2066 2199
2067static int fmt_xlong(char* s,unsigned int i) { 2200static int fmt_xlong(char *s, unsigned int i)
2068 char* bak=s; 2201{
2069 *s=tohex((i>>12)&0xf); if (s!=bak || *s!='0') ++s; 2202 char *bak = s;
2070 *s=tohex((i>>8)&0xf); if (s!=bak || *s!='0') ++s; 2203 *s = tohex((i >> 12) & 0xf);
2071 *s=tohex((i>>4)&0xf); if (s!=bak || *s!='0') ++s; 2204 if (s != bak || *s != '0')
2072 *s=tohex(i&0xf); 2205 ++s;
2073 return s-bak+1; 2206 *s = tohex((i >> 8) & 0xf);
2207 if (s != bak || *s != '0')
2208 ++s;
2209 *s = tohex((i >> 4) & 0xf);
2210 if (s != bak || *s != '0')
2211 ++s;
2212 *s = tohex(i & 0xf);
2213 return s - bak + 1;
2074} 2214}
2075 2215
2076static unsigned int fmt_ip6(char *s,const char ip[16]) { 2216static unsigned int fmt_ip6(char *s, const char ip[16])
2217{
2077 unsigned int len; 2218 unsigned int len;
2078 unsigned int i; 2219 unsigned int i;
2079 unsigned int temp; 2220 unsigned int temp;
2080 unsigned int compressing; 2221 unsigned int compressing;
2081 int j; 2222 int j;
2082 2223
2083 len = 0; compressing = 0; 2224 len = 0;
2084 for (j=0; j<16; j+=2) { 2225 compressing = 0;
2226 for (j = 0; j < 16; j += 2) {
2085 2227
2086#ifdef V4MAPPEDPREFIX 2228#ifdef V4MAPPEDPREFIX
2087 if (j==12 && !memcmp(ip,V4mappedprefix,12)) { 2229 if (j == 12 && !memcmp(ip, V4mappedprefix, 12)) {
2088 inet_ntoa_r(*(struct in_addr*)(ip+12),s); 2230 inet_ntoa_r(*(struct in_addr *)(ip + 12), s);
2089 temp=strlen(s); 2231 temp = strlen(s);
2090 return len+temp; 2232 return len + temp;
2091 } 2233 }
2092#endif 2234#endif
2093 temp = ((unsigned long) (unsigned char) ip[j] << 8) + 2235 temp = ((unsigned long)(unsigned char)ip[j] << 8) +
2094 (unsigned long) (unsigned char) ip[j+1]; 2236 (unsigned long)(unsigned char)ip[j + 1];
2095 if (temp == 0) { 2237 if (temp == 0) {
2096 if (!compressing) { 2238 if (!compressing) {
2097 compressing=1; 2239 compressing = 1;
2098 if (j==0) { 2240 if (j == 0) {
2099 *s++=':'; ++len; 2241 *s++ = ':';
2242 ++len;
2100 } 2243 }
2101 } 2244 }
2102 } else { 2245 } else {
2103 if (compressing) { 2246 if (compressing) {
2104 compressing=0; 2247 compressing = 0;
2105 *s++=':'; ++len; 2248 *s++ = ':';
2249 ++len;
2106 } 2250 }
2107 i = fmt_xlong(s,temp); len += i; s += i; 2251 i = fmt_xlong(s, temp);
2108 if (j<14) { 2252 len += i;
2253 s += i;
2254 if (j < 14) {
2109 *s++ = ':'; 2255 *s++ = ':';
2110 ++len; 2256 ++len;
2111 } 2257 }
2112 } 2258 }
2113 } 2259 }
2114 if (compressing) { 2260 if (compressing) {
2115 *s++=':'; ++len; 2261 *s++ = ':';
2262 ++len;
2116 } 2263 }
2117 *s=0; 2264 *s = 0;
2118 return len; 2265 return len;
2119} 2266}
2120 2267
2121static struct sk_buff *fill_packet_ipv6(struct net_device *odev, 2268static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2122 struct pktgen_dev *pkt_dev) 2269 struct pktgen_dev *pkt_dev)
2123{ 2270{
2124 struct sk_buff *skb = NULL; 2271 struct sk_buff *skb = NULL;
2125 __u8 *eth; 2272 __u8 *eth;
2126 struct udphdr *udph; 2273 struct udphdr *udph;
2127 int datalen; 2274 int datalen;
2128 struct ipv6hdr *iph; 2275 struct ipv6hdr *iph;
2129 struct pktgen_hdr *pgh = NULL; 2276 struct pktgen_hdr *pgh = NULL;
2130 2277
2131 /* Update any of the values, used when we're incrementing various 2278 /* Update any of the values, used when we're incrementing various
2132 * fields. 2279 * fields.
@@ -2147,23 +2294,23 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2147 udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr)); 2294 udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
2148 2295
2149 memcpy(eth, pkt_dev->hh, 12); 2296 memcpy(eth, pkt_dev->hh, 12);
2150 *(u16*)&eth[12] = __constant_htons(ETH_P_IPV6); 2297 *(u16 *) & eth[12] = __constant_htons(ETH_P_IPV6);
2151 2298
2152 datalen = pkt_dev->cur_pkt_size-14- 2299 datalen = pkt_dev->cur_pkt_size - 14 - sizeof(struct ipv6hdr) - sizeof(struct udphdr); /* Eth + IPh + UDPh */
2153 sizeof(struct ipv6hdr)-sizeof(struct udphdr); /* Eth + IPh + UDPh */
2154 2300
2155 if (datalen < sizeof(struct pktgen_hdr)) { 2301 if (datalen < sizeof(struct pktgen_hdr)) {
2156 datalen = sizeof(struct pktgen_hdr); 2302 datalen = sizeof(struct pktgen_hdr);
2157 if (net_ratelimit()) 2303 if (net_ratelimit())
2158 printk(KERN_INFO "pktgen: increased datalen to %d\n", datalen); 2304 printk(KERN_INFO "pktgen: increased datalen to %d\n",
2305 datalen);
2159 } 2306 }
2160 2307
2161 udph->source = htons(pkt_dev->cur_udp_src); 2308 udph->source = htons(pkt_dev->cur_udp_src);
2162 udph->dest = htons(pkt_dev->cur_udp_dst); 2309 udph->dest = htons(pkt_dev->cur_udp_dst);
2163 udph->len = htons(datalen + sizeof(struct udphdr)); 2310 udph->len = htons(datalen + sizeof(struct udphdr));
2164 udph->check = 0; /* No checksum */ 2311 udph->check = 0; /* No checksum */
2165 2312
2166 *(u32*)iph = __constant_htonl(0x60000000); /* Version + flow */ 2313 *(u32 *) iph = __constant_htonl(0x60000000); /* Version + flow */
2167 2314
2168 iph->hop_limit = 32; 2315 iph->hop_limit = 32;
2169 2316
@@ -2173,24 +2320,24 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2173 ipv6_addr_copy(&iph->daddr, &pkt_dev->cur_in6_daddr); 2320 ipv6_addr_copy(&iph->daddr, &pkt_dev->cur_in6_daddr);
2174 ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr); 2321 ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr);
2175 2322
2176 skb->mac.raw = ((u8 *)iph) - 14; 2323 skb->mac.raw = ((u8 *) iph) - 14;
2177 skb->protocol = __constant_htons(ETH_P_IPV6); 2324 skb->protocol = __constant_htons(ETH_P_IPV6);
2178 skb->dev = odev; 2325 skb->dev = odev;
2179 skb->pkt_type = PACKET_HOST; 2326 skb->pkt_type = PACKET_HOST;
2180 2327
2181 if (pkt_dev->nfrags <= 0) 2328 if (pkt_dev->nfrags <= 0)
2182 pgh = (struct pktgen_hdr *)skb_put(skb, datalen); 2329 pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
2183 else { 2330 else {
2184 int frags = pkt_dev->nfrags; 2331 int frags = pkt_dev->nfrags;
2185 int i; 2332 int i;
2186 2333
2187 pgh = (struct pktgen_hdr*)(((char*)(udph)) + 8); 2334 pgh = (struct pktgen_hdr *)(((char *)(udph)) + 8);
2188 2335
2189 if (frags > MAX_SKB_FRAGS) 2336 if (frags > MAX_SKB_FRAGS)
2190 frags = MAX_SKB_FRAGS; 2337 frags = MAX_SKB_FRAGS;
2191 if (datalen > frags*PAGE_SIZE) { 2338 if (datalen > frags * PAGE_SIZE) {
2192 skb_put(skb, datalen-frags*PAGE_SIZE); 2339 skb_put(skb, datalen - frags * PAGE_SIZE);
2193 datalen = frags*PAGE_SIZE; 2340 datalen = frags * PAGE_SIZE;
2194 } 2341 }
2195 2342
2196 i = 0; 2343 i = 0;
@@ -2199,7 +2346,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2199 skb_shinfo(skb)->frags[i].page = page; 2346 skb_shinfo(skb)->frags[i].page = page;
2200 skb_shinfo(skb)->frags[i].page_offset = 0; 2347 skb_shinfo(skb)->frags[i].page_offset = 0;
2201 skb_shinfo(skb)->frags[i].size = 2348 skb_shinfo(skb)->frags[i].size =
2202 (datalen < PAGE_SIZE ? datalen : PAGE_SIZE); 2349 (datalen < PAGE_SIZE ? datalen : PAGE_SIZE);
2203 datalen -= skb_shinfo(skb)->frags[i].size; 2350 datalen -= skb_shinfo(skb)->frags[i].size;
2204 skb->len += skb_shinfo(skb)->frags[i].size; 2351 skb->len += skb_shinfo(skb)->frags[i].size;
2205 skb->data_len += skb_shinfo(skb)->frags[i].size; 2352 skb->data_len += skb_shinfo(skb)->frags[i].size;
@@ -2219,305 +2366,333 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2219 2366
2220 skb_shinfo(skb)->frags[i - 1].size -= rem; 2367 skb_shinfo(skb)->frags[i - 1].size -= rem;
2221 2368
2222 skb_shinfo(skb)->frags[i] = skb_shinfo(skb)->frags[i - 1]; 2369 skb_shinfo(skb)->frags[i] =
2370 skb_shinfo(skb)->frags[i - 1];
2223 get_page(skb_shinfo(skb)->frags[i].page); 2371 get_page(skb_shinfo(skb)->frags[i].page);
2224 skb_shinfo(skb)->frags[i].page = skb_shinfo(skb)->frags[i - 1].page; 2372 skb_shinfo(skb)->frags[i].page =
2225 skb_shinfo(skb)->frags[i].page_offset += skb_shinfo(skb)->frags[i - 1].size; 2373 skb_shinfo(skb)->frags[i - 1].page;
2374 skb_shinfo(skb)->frags[i].page_offset +=
2375 skb_shinfo(skb)->frags[i - 1].size;
2226 skb_shinfo(skb)->frags[i].size = rem; 2376 skb_shinfo(skb)->frags[i].size = rem;
2227 i++; 2377 i++;
2228 skb_shinfo(skb)->nr_frags = i; 2378 skb_shinfo(skb)->nr_frags = i;
2229 } 2379 }
2230 } 2380 }
2231 2381
2232 /* Stamp the time, and sequence number, convert them to network byte order */ 2382 /* Stamp the time, and sequence number, convert them to network byte order */
2233 /* should we update cloned packets too ? */ 2383 /* should we update cloned packets too ? */
2234 if (pgh) { 2384 if (pgh) {
2235 struct timeval timestamp; 2385 struct timeval timestamp;
2236 2386
2237 pgh->pgh_magic = htonl(PKTGEN_MAGIC); 2387 pgh->pgh_magic = htonl(PKTGEN_MAGIC);
2238 pgh->seq_num = htonl(pkt_dev->seq_num); 2388 pgh->seq_num = htonl(pkt_dev->seq_num);
2239 2389
2240 do_gettimeofday(&timestamp); 2390 do_gettimeofday(&timestamp);
2241 pgh->tv_sec = htonl(timestamp.tv_sec); 2391 pgh->tv_sec = htonl(timestamp.tv_sec);
2242 pgh->tv_usec = htonl(timestamp.tv_usec); 2392 pgh->tv_usec = htonl(timestamp.tv_usec);
2243 } 2393 }
2244 pkt_dev->seq_num++; 2394 pkt_dev->seq_num++;
2245 2395
2246 return skb; 2396 return skb;
2247} 2397}
2248 2398
2249static inline struct sk_buff *fill_packet(struct net_device *odev, 2399static inline struct sk_buff *fill_packet(struct net_device *odev,
2250 struct pktgen_dev *pkt_dev) 2400 struct pktgen_dev *pkt_dev)
2251{ 2401{
2252 if(pkt_dev->flags & F_IPV6) 2402 if (pkt_dev->flags & F_IPV6)
2253 return fill_packet_ipv6(odev, pkt_dev); 2403 return fill_packet_ipv6(odev, pkt_dev);
2254 else 2404 else
2255 return fill_packet_ipv4(odev, pkt_dev); 2405 return fill_packet_ipv4(odev, pkt_dev);
2256} 2406}
2257 2407
2258static void pktgen_clear_counters(struct pktgen_dev *pkt_dev) 2408static void pktgen_clear_counters(struct pktgen_dev *pkt_dev)
2259{ 2409{
2260 pkt_dev->seq_num = 1; 2410 pkt_dev->seq_num = 1;
2261 pkt_dev->idle_acc = 0; 2411 pkt_dev->idle_acc = 0;
2262 pkt_dev->sofar = 0; 2412 pkt_dev->sofar = 0;
2263 pkt_dev->tx_bytes = 0; 2413 pkt_dev->tx_bytes = 0;
2264 pkt_dev->errors = 0; 2414 pkt_dev->errors = 0;
2265} 2415}
2266 2416
2267/* Set up structure for sending pkts, clear counters */ 2417/* Set up structure for sending pkts, clear counters */
2268 2418
2269static void pktgen_run(struct pktgen_thread *t) 2419static void pktgen_run(struct pktgen_thread *t)
2270{ 2420{
2271 struct pktgen_dev *pkt_dev = NULL; 2421 struct pktgen_dev *pkt_dev;
2272 int started = 0; 2422 int started = 0;
2273 2423
2274 PG_DEBUG(printk("pktgen: entering pktgen_run. %p\n", t)); 2424 PG_DEBUG(printk("pktgen: entering pktgen_run. %p\n", t));
2275 2425
2276 if_lock(t); 2426 if_lock(t);
2277 for (pkt_dev = t->if_list; pkt_dev; pkt_dev = pkt_dev->next ) { 2427 list_for_each_entry(pkt_dev, &t->if_list, list) {
2278 2428
2279 /* 2429 /*
2280 * setup odev and create initial packet. 2430 * setup odev and create initial packet.
2281 */ 2431 */
2282 pktgen_setup_inject(pkt_dev); 2432 pktgen_setup_inject(pkt_dev);
2283 2433
2284 if(pkt_dev->odev) { 2434 if (pkt_dev->odev) {
2285 pktgen_clear_counters(pkt_dev); 2435 pktgen_clear_counters(pkt_dev);
2286 pkt_dev->running = 1; /* Cranke yeself! */ 2436 pkt_dev->running = 1; /* Cranke yeself! */
2287 pkt_dev->skb = NULL; 2437 pkt_dev->skb = NULL;
2288 pkt_dev->started_at = getCurUs(); 2438 pkt_dev->started_at = getCurUs();
2289 pkt_dev->next_tx_us = getCurUs(); /* Transmit immediately */ 2439 pkt_dev->next_tx_us = getCurUs(); /* Transmit immediately */
2290 pkt_dev->next_tx_ns = 0; 2440 pkt_dev->next_tx_ns = 0;
2291 2441
2292 strcpy(pkt_dev->result, "Starting"); 2442 strcpy(pkt_dev->result, "Starting");
2293 started++; 2443 started++;
2294 } 2444 } else
2295 else
2296 strcpy(pkt_dev->result, "Error starting"); 2445 strcpy(pkt_dev->result, "Error starting");
2297 } 2446 }
2298 if_unlock(t); 2447 if_unlock(t);
2299 if(started) t->control &= ~(T_STOP); 2448 if (started)
2449 t->control &= ~(T_STOP);
2300} 2450}
2301 2451
2302static void pktgen_stop_all_threads_ifs(void) 2452static void pktgen_stop_all_threads_ifs(void)
2303{ 2453{
2304 struct pktgen_thread *t = pktgen_threads; 2454 struct pktgen_thread *t;
2305 2455
2306 PG_DEBUG(printk("pktgen: entering pktgen_stop_all_threads.\n")); 2456 PG_DEBUG(printk("pktgen: entering pktgen_stop_all_threads_ifs.\n"));
2307 2457
2308 thread_lock(); 2458 mutex_lock(&pktgen_thread_lock);
2309 while(t) { 2459
2310 pktgen_stop(t); 2460 list_for_each_entry(t, &pktgen_threads, th_list)
2311 t = t->next; 2461 t->control |= T_STOP;
2312 } 2462
2313 thread_unlock(); 2463 mutex_unlock(&pktgen_thread_lock);
2314} 2464}
2315 2465
2316static int thread_is_running(struct pktgen_thread *t ) 2466static int thread_is_running(struct pktgen_thread *t)
2317{ 2467{
2318 struct pktgen_dev *next; 2468 struct pktgen_dev *pkt_dev;
2319 int res = 0; 2469 int res = 0;
2320 2470
2321 for(next=t->if_list; next; next=next->next) { 2471 list_for_each_entry(pkt_dev, &t->if_list, list)
2322 if(next->running) { 2472 if (pkt_dev->running) {
2323 res = 1; 2473 res = 1;
2324 break; 2474 break;
2325 } 2475 }
2326 } 2476 return res;
2327 return res;
2328} 2477}
2329 2478
2330static int pktgen_wait_thread_run(struct pktgen_thread *t ) 2479static int pktgen_wait_thread_run(struct pktgen_thread *t)
2331{ 2480{
2332 if_lock(t); 2481 if_lock(t);
2333 2482
2334 while(thread_is_running(t)) { 2483 while (thread_is_running(t)) {
2335 2484
2336 if_unlock(t); 2485 if_unlock(t);
2337 2486
2338 msleep_interruptible(100); 2487 msleep_interruptible(100);
2339 2488
2340 if (signal_pending(current)) 2489 if (signal_pending(current))
2341 goto signal; 2490 goto signal;
2342 if_lock(t); 2491 if_lock(t);
2343 } 2492 }
2344 if_unlock(t); 2493 if_unlock(t);
2345 return 1; 2494 return 1;
2346 signal: 2495signal:
2347 return 0; 2496 return 0;
2348} 2497}
2349 2498
2350static int pktgen_wait_all_threads_run(void) 2499static int pktgen_wait_all_threads_run(void)
2351{ 2500{
2352 struct pktgen_thread *t = pktgen_threads; 2501 struct pktgen_thread *t;
2353 int sig = 1; 2502 int sig = 1;
2354 2503
2355 while (t) { 2504 mutex_lock(&pktgen_thread_lock);
2505
2506 list_for_each_entry(t, &pktgen_threads, th_list) {
2356 sig = pktgen_wait_thread_run(t); 2507 sig = pktgen_wait_thread_run(t);
2357 if( sig == 0 ) break; 2508 if (sig == 0)
2358 thread_lock(); 2509 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 } 2510 }
2511
2512 if (sig == 0)
2513 list_for_each_entry(t, &pktgen_threads, th_list)
2514 t->control |= (T_STOP);
2515
2516 mutex_unlock(&pktgen_thread_lock);
2370 return sig; 2517 return sig;
2371} 2518}
2372 2519
2373static void pktgen_run_all_threads(void) 2520static void pktgen_run_all_threads(void)
2374{ 2521{
2375 struct pktgen_thread *t = pktgen_threads; 2522 struct pktgen_thread *t;
2376 2523
2377 PG_DEBUG(printk("pktgen: entering pktgen_run_all_threads.\n")); 2524 PG_DEBUG(printk("pktgen: entering pktgen_run_all_threads.\n"));
2378 2525
2379 thread_lock(); 2526 mutex_lock(&pktgen_thread_lock);
2380 2527
2381 while(t) { 2528 list_for_each_entry(t, &pktgen_threads, th_list)
2382 t->control |= (T_RUN); 2529 t->control |= (T_RUN);
2383 t = t->next;
2384 }
2385 thread_unlock();
2386 2530
2387 schedule_timeout_interruptible(msecs_to_jiffies(125)); /* Propagate thread->control */ 2531 mutex_unlock(&pktgen_thread_lock);
2388 2532
2533 schedule_timeout_interruptible(msecs_to_jiffies(125)); /* Propagate thread->control */
2534
2389 pktgen_wait_all_threads_run(); 2535 pktgen_wait_all_threads_run();
2390} 2536}
2391 2537
2392
2393static void show_results(struct pktgen_dev *pkt_dev, int nr_frags) 2538static void show_results(struct pktgen_dev *pkt_dev, int nr_frags)
2394{ 2539{
2395 __u64 total_us, bps, mbps, pps, idle; 2540 __u64 total_us, bps, mbps, pps, idle;
2396 char *p = pkt_dev->result; 2541 char *p = pkt_dev->result;
2397 2542
2398 total_us = pkt_dev->stopped_at - pkt_dev->started_at; 2543 total_us = pkt_dev->stopped_at - pkt_dev->started_at;
2399 2544
2400 idle = pkt_dev->idle_acc; 2545 idle = pkt_dev->idle_acc;
2401 2546
2402 p += sprintf(p, "OK: %llu(c%llu+d%llu) usec, %llu (%dbyte,%dfrags)\n", 2547 p += sprintf(p, "OK: %llu(c%llu+d%llu) usec, %llu (%dbyte,%dfrags)\n",
2403 (unsigned long long) total_us, 2548 (unsigned long long)total_us,
2404 (unsigned long long)(total_us - idle), 2549 (unsigned long long)(total_us - idle),
2405 (unsigned long long) idle, 2550 (unsigned long long)idle,
2406 (unsigned long long) pkt_dev->sofar, 2551 (unsigned long long)pkt_dev->sofar,
2407 pkt_dev->cur_pkt_size, nr_frags); 2552 pkt_dev->cur_pkt_size, nr_frags);
2408 2553
2409 pps = pkt_dev->sofar * USEC_PER_SEC; 2554 pps = pkt_dev->sofar * USEC_PER_SEC;
2410 2555
2411 while ((total_us >> 32) != 0) { 2556 while ((total_us >> 32) != 0) {
2412 pps >>= 1; 2557 pps >>= 1;
2413 total_us >>= 1; 2558 total_us >>= 1;
2414 } 2559 }
2415 2560
2416 do_div(pps, total_us); 2561 do_div(pps, total_us);
2417 2562
2418 bps = pps * 8 * pkt_dev->cur_pkt_size; 2563 bps = pps * 8 * pkt_dev->cur_pkt_size;
2419 2564
2420 mbps = bps; 2565 mbps = bps;
2421 do_div(mbps, 1000000); 2566 do_div(mbps, 1000000);
2422 p += sprintf(p, " %llupps %lluMb/sec (%llubps) errors: %llu", 2567 p += sprintf(p, " %llupps %lluMb/sec (%llubps) errors: %llu",
2423 (unsigned long long) pps, 2568 (unsigned long long)pps,
2424 (unsigned long long) mbps, 2569 (unsigned long long)mbps,
2425 (unsigned long long) bps, 2570 (unsigned long long)bps,
2426 (unsigned long long) pkt_dev->errors); 2571 (unsigned long long)pkt_dev->errors);
2427} 2572}
2428
2429 2573
2430/* Set stopped-at timer, remove from running list, do counters & statistics */ 2574/* Set stopped-at timer, remove from running list, do counters & statistics */
2431 2575
2432static int pktgen_stop_device(struct pktgen_dev *pkt_dev) 2576static int pktgen_stop_device(struct pktgen_dev *pkt_dev)
2433{ 2577{
2434 2578 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 2579
2440 pkt_dev->stopped_at = getCurUs(); 2580 if (!pkt_dev->running) {
2441 pkt_dev->running = 0; 2581 printk("pktgen: interface: %s is already stopped\n",
2582 pkt_dev->ifname);
2583 return -EINVAL;
2584 }
2442 2585
2443 show_results(pkt_dev, skb_shinfo(pkt_dev->skb)->nr_frags); 2586 pkt_dev->stopped_at = getCurUs();
2587 pkt_dev->running = 0;
2444 2588
2445 if (pkt_dev->skb) 2589 show_results(pkt_dev, nr_frags);
2446 kfree_skb(pkt_dev->skb);
2447 2590
2448 pkt_dev->skb = NULL; 2591 return 0;
2449
2450 return 0;
2451} 2592}
2452 2593
2453static struct pktgen_dev *next_to_run(struct pktgen_thread *t ) 2594static struct pktgen_dev *next_to_run(struct pktgen_thread *t)
2454{ 2595{
2455 struct pktgen_dev *next, *best = NULL; 2596 struct pktgen_dev *pkt_dev, *best = NULL;
2456 2597
2457 if_lock(t); 2598 if_lock(t);
2458 2599
2459 for(next=t->if_list; next ; next=next->next) { 2600 list_for_each_entry(pkt_dev, &t->if_list, list) {
2460 if(!next->running) continue; 2601 if (!pkt_dev->running)
2461 if(best == NULL) best=next; 2602 continue;
2462 else if ( next->next_tx_us < best->next_tx_us) 2603 if (best == NULL)
2463 best = next; 2604 best = pkt_dev;
2605 else if (pkt_dev->next_tx_us < best->next_tx_us)
2606 best = pkt_dev;
2464 } 2607 }
2465 if_unlock(t); 2608 if_unlock(t);
2466 return best; 2609 return best;
2467} 2610}
2468 2611
2469static void pktgen_stop(struct pktgen_thread *t) { 2612static void pktgen_stop(struct pktgen_thread *t)
2470 struct pktgen_dev *next = NULL; 2613{
2614 struct pktgen_dev *pkt_dev;
2471 2615
2472 PG_DEBUG(printk("pktgen: entering pktgen_stop.\n")); 2616 PG_DEBUG(printk("pktgen: entering pktgen_stop\n"));
2473 2617
2474 if_lock(t); 2618 if_lock(t);
2475 2619
2476 for(next=t->if_list; next; next=next->next) 2620 list_for_each_entry(pkt_dev, &t->if_list, list) {
2477 pktgen_stop_device(next); 2621 pktgen_stop_device(pkt_dev);
2622 if (pkt_dev->skb)
2623 kfree_skb(pkt_dev->skb);
2478 2624
2479 if_unlock(t); 2625 pkt_dev->skb = NULL;
2626 }
2627
2628 if_unlock(t);
2480} 2629}
2481 2630
2482static void pktgen_rem_all_ifs(struct pktgen_thread *t) 2631/*
2632 * one of our devices needs to be removed - find it
2633 * and remove it
2634 */
2635static void pktgen_rem_one_if(struct pktgen_thread *t)
2483{ 2636{
2484 struct pktgen_dev *cur, *next = NULL; 2637 struct list_head *q, *n;
2485 2638 struct pktgen_dev *cur;
2486 /* Remove all devices, free mem */ 2639
2487 2640 PG_DEBUG(printk("pktgen: entering pktgen_rem_one_if\n"));
2488 if_lock(t); 2641
2489 2642 if_lock(t);
2490 for(cur=t->if_list; cur; cur=next) { 2643
2491 next = cur->next; 2644 list_for_each_safe(q, n, &t->if_list) {
2645 cur = list_entry(q, struct pktgen_dev, list);
2646
2647 if (!cur->removal_mark)
2648 continue;
2649
2650 if (cur->skb)
2651 kfree_skb(cur->skb);
2652 cur->skb = NULL;
2653
2492 pktgen_remove_device(t, cur); 2654 pktgen_remove_device(t, cur);
2655
2656 break;
2493 } 2657 }
2494 2658
2495 if_unlock(t); 2659 if_unlock(t);
2496} 2660}
2497 2661
2498static void pktgen_rem_thread(struct pktgen_thread *t) 2662static void pktgen_rem_all_ifs(struct pktgen_thread *t)
2499{ 2663{
2500 /* Remove from the thread list */ 2664 struct list_head *q, *n;
2665 struct pktgen_dev *cur;
2501 2666
2502 struct pktgen_thread *tmp = pktgen_threads; 2667 /* Remove all devices, free mem */
2503 2668
2504 remove_proc_entry(t->name, pg_proc_dir); 2669 PG_DEBUG(printk("pktgen: entering pktgen_rem_all_ifs\n"));
2670 if_lock(t);
2505 2671
2506 thread_lock(); 2672 list_for_each_safe(q, n, &t->if_list) {
2673 cur = list_entry(q, struct pktgen_dev, list);
2507 2674
2508 if (tmp == t) 2675 if (cur->skb)
2509 pktgen_threads = tmp->next; 2676 kfree_skb(cur->skb);
2510 else { 2677 cur->skb = NULL;
2511 while (tmp) { 2678
2512 if (tmp->next == t) { 2679 pktgen_remove_device(t, cur);
2513 tmp->next = t->next;
2514 t->next = NULL;
2515 break;
2516 }
2517 tmp = tmp->next;
2518 }
2519 } 2680 }
2520 thread_unlock(); 2681
2682 if_unlock(t);
2683}
2684
2685static void pktgen_rem_thread(struct pktgen_thread *t)
2686{
2687 /* Remove from the thread list */
2688
2689 remove_proc_entry(t->name, pg_proc_dir);
2690
2691 mutex_lock(&pktgen_thread_lock);
2692
2693 list_del(&t->th_list);
2694
2695 mutex_unlock(&pktgen_thread_lock);
2521} 2696}
2522 2697
2523static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev) 2698static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
@@ -2527,7 +2702,7 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
2527 int ret; 2702 int ret;
2528 2703
2529 odev = pkt_dev->odev; 2704 odev = pkt_dev->odev;
2530 2705
2531 if (pkt_dev->delay_us || pkt_dev->delay_ns) { 2706 if (pkt_dev->delay_us || pkt_dev->delay_ns) {
2532 u64 now; 2707 u64 now;
2533 2708
@@ -2544,67 +2719,71 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
2544 goto out; 2719 goto out;
2545 } 2720 }
2546 } 2721 }
2547 2722
2548 if (netif_queue_stopped(odev) || need_resched()) { 2723 if (netif_queue_stopped(odev) || need_resched()) {
2549 idle_start = getCurUs(); 2724 idle_start = getCurUs();
2550 2725
2551 if (!netif_running(odev)) { 2726 if (!netif_running(odev)) {
2552 pktgen_stop_device(pkt_dev); 2727 pktgen_stop_device(pkt_dev);
2728 if (pkt_dev->skb)
2729 kfree_skb(pkt_dev->skb);
2730 pkt_dev->skb = NULL;
2553 goto out; 2731 goto out;
2554 } 2732 }
2555 if (need_resched()) 2733 if (need_resched())
2556 schedule(); 2734 schedule();
2557 2735
2558 pkt_dev->idle_acc += getCurUs() - idle_start; 2736 pkt_dev->idle_acc += getCurUs() - idle_start;
2559 2737
2560 if (netif_queue_stopped(odev)) { 2738 if (netif_queue_stopped(odev)) {
2561 pkt_dev->next_tx_us = getCurUs(); /* TODO */ 2739 pkt_dev->next_tx_us = getCurUs(); /* TODO */
2562 pkt_dev->next_tx_ns = 0; 2740 pkt_dev->next_tx_ns = 0;
2563 goto out; /* Try the next interface */ 2741 goto out; /* Try the next interface */
2564 } 2742 }
2565 } 2743 }
2566 2744
2567 if (pkt_dev->last_ok || !pkt_dev->skb) { 2745 if (pkt_dev->last_ok || !pkt_dev->skb) {
2568 if ((++pkt_dev->clone_count >= pkt_dev->clone_skb ) || (!pkt_dev->skb)) { 2746 if ((++pkt_dev->clone_count >= pkt_dev->clone_skb)
2747 || (!pkt_dev->skb)) {
2569 /* build a new pkt */ 2748 /* build a new pkt */
2570 if (pkt_dev->skb) 2749 if (pkt_dev->skb)
2571 kfree_skb(pkt_dev->skb); 2750 kfree_skb(pkt_dev->skb);
2572 2751
2573 pkt_dev->skb = fill_packet(odev, pkt_dev); 2752 pkt_dev->skb = fill_packet(odev, pkt_dev);
2574 if (pkt_dev->skb == NULL) { 2753 if (pkt_dev->skb == NULL) {
2575 printk("pktgen: ERROR: couldn't allocate skb in fill_packet.\n"); 2754 printk("pktgen: ERROR: couldn't allocate skb in fill_packet.\n");
2576 schedule(); 2755 schedule();
2577 pkt_dev->clone_count--; /* back out increment, OOM */ 2756 pkt_dev->clone_count--; /* back out increment, OOM */
2578 goto out; 2757 goto out;
2579 } 2758 }
2580 pkt_dev->allocated_skbs++; 2759 pkt_dev->allocated_skbs++;
2581 pkt_dev->clone_count = 0; /* reset counter */ 2760 pkt_dev->clone_count = 0; /* reset counter */
2582 } 2761 }
2583 } 2762 }
2584 2763
2585 spin_lock_bh(&odev->xmit_lock); 2764 spin_lock_bh(&odev->xmit_lock);
2586 if (!netif_queue_stopped(odev)) { 2765 if (!netif_queue_stopped(odev)) {
2587 2766
2588 atomic_inc(&(pkt_dev->skb->users)); 2767 atomic_inc(&(pkt_dev->skb->users));
2589retry_now: 2768 retry_now:
2590 ret = odev->hard_start_xmit(pkt_dev->skb, odev); 2769 ret = odev->hard_start_xmit(pkt_dev->skb, odev);
2591 if (likely(ret == NETDEV_TX_OK)) { 2770 if (likely(ret == NETDEV_TX_OK)) {
2592 pkt_dev->last_ok = 1; 2771 pkt_dev->last_ok = 1;
2593 pkt_dev->sofar++; 2772 pkt_dev->sofar++;
2594 pkt_dev->seq_num++; 2773 pkt_dev->seq_num++;
2595 pkt_dev->tx_bytes += pkt_dev->cur_pkt_size; 2774 pkt_dev->tx_bytes += pkt_dev->cur_pkt_size;
2596 2775
2597 } else if (ret == NETDEV_TX_LOCKED 2776 } else if (ret == NETDEV_TX_LOCKED
2598 && (odev->features & NETIF_F_LLTX)) { 2777 && (odev->features & NETIF_F_LLTX)) {
2599 cpu_relax(); 2778 cpu_relax();
2600 goto retry_now; 2779 goto retry_now;
2601 } else { /* Retry it next time */ 2780 } else { /* Retry it next time */
2602 2781
2603 atomic_dec(&(pkt_dev->skb->users)); 2782 atomic_dec(&(pkt_dev->skb->users));
2604 2783
2605 if (debug && net_ratelimit()) 2784 if (debug && net_ratelimit())
2606 printk(KERN_INFO "pktgen: Hard xmit error\n"); 2785 printk(KERN_INFO "pktgen: Hard xmit error\n");
2607 2786
2608 pkt_dev->errors++; 2787 pkt_dev->errors++;
2609 pkt_dev->last_ok = 0; 2788 pkt_dev->last_ok = 0;
2610 } 2789 }
@@ -2619,16 +2798,16 @@ retry_now:
2619 pkt_dev->next_tx_us++; 2798 pkt_dev->next_tx_us++;
2620 pkt_dev->next_tx_ns -= 1000; 2799 pkt_dev->next_tx_ns -= 1000;
2621 } 2800 }
2622 } 2801 }
2623 2802
2624 else { /* Retry it next time */ 2803 else { /* Retry it next time */
2625 pkt_dev->last_ok = 0; 2804 pkt_dev->last_ok = 0;
2626 pkt_dev->next_tx_us = getCurUs(); /* TODO */ 2805 pkt_dev->next_tx_us = getCurUs(); /* TODO */
2627 pkt_dev->next_tx_ns = 0; 2806 pkt_dev->next_tx_ns = 0;
2628 } 2807 }
2629 2808
2630 spin_unlock_bh(&odev->xmit_lock); 2809 spin_unlock_bh(&odev->xmit_lock);
2631 2810
2632 /* If pkt_dev->count is zero, then run forever */ 2811 /* If pkt_dev->count is zero, then run forever */
2633 if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) { 2812 if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) {
2634 if (atomic_read(&(pkt_dev->skb->users)) != 1) { 2813 if (atomic_read(&(pkt_dev->skb->users)) != 1) {
@@ -2641,72 +2820,74 @@ retry_now:
2641 } 2820 }
2642 pkt_dev->idle_acc += getCurUs() - idle_start; 2821 pkt_dev->idle_acc += getCurUs() - idle_start;
2643 } 2822 }
2644 2823
2645 /* Done with this */ 2824 /* Done with this */
2646 pktgen_stop_device(pkt_dev); 2825 pktgen_stop_device(pkt_dev);
2647 } 2826 if (pkt_dev->skb)
2648 out:; 2827 kfree_skb(pkt_dev->skb);
2649 } 2828 pkt_dev->skb = NULL;
2829 }
2830out:;
2831}
2650 2832
2651/* 2833/*
2652 * Main loop of the thread goes here 2834 * Main loop of the thread goes here
2653 */ 2835 */
2654 2836
2655static void pktgen_thread_worker(struct pktgen_thread *t) 2837static void pktgen_thread_worker(struct pktgen_thread *t)
2656{ 2838{
2657 DEFINE_WAIT(wait); 2839 DEFINE_WAIT(wait);
2658 struct pktgen_dev *pkt_dev = NULL; 2840 struct pktgen_dev *pkt_dev = NULL;
2659 int cpu = t->cpu; 2841 int cpu = t->cpu;
2660 sigset_t tmpsig; 2842 sigset_t tmpsig;
2661 u32 max_before_softirq; 2843 u32 max_before_softirq;
2662 u32 tx_since_softirq = 0; 2844 u32 tx_since_softirq = 0;
2663 2845
2664 daemonize("pktgen/%d", cpu); 2846 daemonize("pktgen/%d", cpu);
2665 2847
2666 /* Block all signals except SIGKILL, SIGSTOP and SIGTERM */ 2848 /* Block all signals except SIGKILL, SIGSTOP and SIGTERM */
2667 2849
2668 spin_lock_irq(&current->sighand->siglock); 2850 spin_lock_irq(&current->sighand->siglock);
2669 tmpsig = current->blocked; 2851 tmpsig = current->blocked;
2670 siginitsetinv(&current->blocked, 2852 siginitsetinv(&current->blocked,
2671 sigmask(SIGKILL) | 2853 sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGTERM));
2672 sigmask(SIGSTOP)|
2673 sigmask(SIGTERM));
2674 2854
2675 recalc_sigpending(); 2855 recalc_sigpending();
2676 spin_unlock_irq(&current->sighand->siglock); 2856 spin_unlock_irq(&current->sighand->siglock);
2677 2857
2678 /* Migrate to the right CPU */ 2858 /* Migrate to the right CPU */
2679 set_cpus_allowed(current, cpumask_of_cpu(cpu)); 2859 set_cpus_allowed(current, cpumask_of_cpu(cpu));
2680 if (smp_processor_id() != cpu) 2860 if (smp_processor_id() != cpu)
2681 BUG(); 2861 BUG();
2682 2862
2683 init_waitqueue_head(&t->queue); 2863 init_waitqueue_head(&t->queue);
2684 2864
2685 t->control &= ~(T_TERMINATE); 2865 t->control &= ~(T_TERMINATE);
2686 t->control &= ~(T_RUN); 2866 t->control &= ~(T_RUN);
2687 t->control &= ~(T_STOP); 2867 t->control &= ~(T_STOP);
2868 t->control &= ~(T_REMDEVALL);
2688 t->control &= ~(T_REMDEV); 2869 t->control &= ~(T_REMDEV);
2689 2870
2690 t->pid = current->pid; 2871 t->pid = current->pid;
2691 2872
2692 PG_DEBUG(printk("pktgen: starting pktgen/%d: pid=%d\n", cpu, current->pid)); 2873 PG_DEBUG(printk("pktgen: starting pktgen/%d: pid=%d\n", cpu, current->pid));
2693 2874
2694 max_before_softirq = t->max_before_softirq; 2875 max_before_softirq = t->max_before_softirq;
2695
2696 __set_current_state(TASK_INTERRUPTIBLE);
2697 mb();
2698 2876
2699 while (1) { 2877 __set_current_state(TASK_INTERRUPTIBLE);
2700 2878 mb();
2879
2880 while (1) {
2881
2701 __set_current_state(TASK_RUNNING); 2882 __set_current_state(TASK_RUNNING);
2702 2883
2703 /* 2884 /*
2704 * Get next dev to xmit -- if any. 2885 * Get next dev to xmit -- if any.
2705 */ 2886 */
2706 2887
2707 pkt_dev = next_to_run(t); 2888 pkt_dev = next_to_run(t);
2708 2889
2709 if (pkt_dev) { 2890 if (pkt_dev) {
2710 2891
2711 pktgen_xmit(pkt_dev); 2892 pktgen_xmit(pkt_dev);
2712 2893
@@ -2724,115 +2905,125 @@ static void pktgen_thread_worker(struct pktgen_thread *t)
2724 } 2905 }
2725 } else { 2906 } else {
2726 prepare_to_wait(&(t->queue), &wait, TASK_INTERRUPTIBLE); 2907 prepare_to_wait(&(t->queue), &wait, TASK_INTERRUPTIBLE);
2727 schedule_timeout(HZ/10); 2908 schedule_timeout(HZ / 10);
2728 finish_wait(&(t->queue), &wait); 2909 finish_wait(&(t->queue), &wait);
2729 } 2910 }
2730 2911
2731 /* 2912 /*
2732 * Back from sleep, either due to the timeout or signal. 2913 * Back from sleep, either due to the timeout or signal.
2733 * We check if we have any "posted" work for us. 2914 * We check if we have any "posted" work for us.
2734 */ 2915 */
2735 2916
2736 if (t->control & T_TERMINATE || signal_pending(current)) 2917 if (t->control & T_TERMINATE || signal_pending(current))
2737 /* we received a request to terminate ourself */ 2918 /* we received a request to terminate ourself */
2738 break; 2919 break;
2739
2740 2920
2741 if(t->control & T_STOP) { 2921 if (t->control & T_STOP) {
2742 pktgen_stop(t); 2922 pktgen_stop(t);
2743 t->control &= ~(T_STOP); 2923 t->control &= ~(T_STOP);
2744 } 2924 }
2745 2925
2746 if(t->control & T_RUN) { 2926 if (t->control & T_RUN) {
2747 pktgen_run(t); 2927 pktgen_run(t);
2748 t->control &= ~(T_RUN); 2928 t->control &= ~(T_RUN);
2749 } 2929 }
2750 2930
2751 if(t->control & T_REMDEV) { 2931 if (t->control & T_REMDEVALL) {
2752 pktgen_rem_all_ifs(t); 2932 pktgen_rem_all_ifs(t);
2933 t->control &= ~(T_REMDEVALL);
2934 }
2935
2936 if (t->control & T_REMDEV) {
2937 pktgen_rem_one_if(t);
2753 t->control &= ~(T_REMDEV); 2938 t->control &= ~(T_REMDEV);
2754 } 2939 }
2755 2940
2756 if (need_resched()) 2941 if (need_resched())
2757 schedule(); 2942 schedule();
2758 } 2943 }
2944
2945 PG_DEBUG(printk("pktgen: %s stopping all device\n", t->name));
2946 pktgen_stop(t);
2759 2947
2760 PG_DEBUG(printk("pktgen: %s stopping all device\n", t->name)); 2948 PG_DEBUG(printk("pktgen: %s removing all device\n", t->name));
2761 pktgen_stop(t); 2949 pktgen_rem_all_ifs(t);
2762 2950
2763 PG_DEBUG(printk("pktgen: %s removing all device\n", t->name)); 2951 PG_DEBUG(printk("pktgen: %s removing thread.\n", t->name));
2764 pktgen_rem_all_ifs(t); 2952 pktgen_rem_thread(t);
2765 2953
2766 PG_DEBUG(printk("pktgen: %s removing thread.\n", t->name)); 2954 t->removed = 1;
2767 pktgen_rem_thread(t);
2768} 2955}
2769 2956
2770static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t, const char* ifname) 2957static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t,
2958 const char *ifname)
2771{ 2959{
2772 struct pktgen_dev *pkt_dev = NULL; 2960 struct pktgen_dev *p, *pkt_dev = NULL;
2773 if_lock(t); 2961 if_lock(t);
2774 2962
2775 for(pkt_dev=t->if_list; pkt_dev; pkt_dev = pkt_dev->next ) { 2963 list_for_each_entry(p, &t->if_list, list)
2776 if (strncmp(pkt_dev->ifname, ifname, IFNAMSIZ) == 0) { 2964 if (strncmp(p->ifname, ifname, IFNAMSIZ) == 0) {
2777 break; 2965 pkt_dev = p;
2778 } 2966 break;
2779 } 2967 }
2780 2968
2781 if_unlock(t); 2969 if_unlock(t);
2782 PG_DEBUG(printk("pktgen: find_dev(%s) returning %p\n", ifname,pkt_dev)); 2970 PG_DEBUG(printk("pktgen: find_dev(%s) returning %p\n", ifname, pkt_dev));
2783 return pkt_dev; 2971 return pkt_dev;
2784} 2972}
2785 2973
2786/* 2974/*
2787 * Adds a dev at front of if_list. 2975 * Adds a dev at front of if_list.
2788 */ 2976 */
2789 2977
2790static int add_dev_to_thread(struct pktgen_thread *t, struct pktgen_dev *pkt_dev) 2978static int add_dev_to_thread(struct pktgen_thread *t,
2979 struct pktgen_dev *pkt_dev)
2791{ 2980{
2792 int rv = 0; 2981 int rv = 0;
2793 2982
2794 if_lock(t); 2983 if_lock(t);
2795 2984
2796 if (pkt_dev->pg_thread) { 2985 if (pkt_dev->pg_thread) {
2797 printk("pktgen: ERROR: already assigned to a thread.\n"); 2986 printk("pktgen: ERROR: already assigned to a thread.\n");
2798 rv = -EBUSY; 2987 rv = -EBUSY;
2799 goto out; 2988 goto out;
2800 } 2989 }
2801 pkt_dev->next =t->if_list; t->if_list=pkt_dev; 2990
2802 pkt_dev->pg_thread = t; 2991 list_add(&pkt_dev->list, &t->if_list);
2992 pkt_dev->pg_thread = t;
2803 pkt_dev->running = 0; 2993 pkt_dev->running = 0;
2804 2994
2805 out: 2995out:
2806 if_unlock(t); 2996 if_unlock(t);
2807 return rv; 2997 return rv;
2808} 2998}
2809 2999
2810/* Called under thread lock */ 3000/* Called under thread lock */
2811 3001
2812static int pktgen_add_device(struct pktgen_thread *t, const char* ifname) 3002static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
2813{ 3003{
2814 struct pktgen_dev *pkt_dev; 3004 struct pktgen_dev *pkt_dev;
2815 struct proc_dir_entry *pe; 3005 struct proc_dir_entry *pe;
2816 3006
2817 /* We don't allow a device to be on several threads */ 3007 /* We don't allow a device to be on several threads */
2818 3008
2819 pkt_dev = __pktgen_NN_threads(ifname, FIND); 3009 pkt_dev = __pktgen_NN_threads(ifname, FIND);
2820 if (pkt_dev) { 3010 if (pkt_dev) {
2821 printk("pktgen: ERROR: interface already used.\n"); 3011 printk("pktgen: ERROR: interface already used.\n");
2822 return -EBUSY; 3012 return -EBUSY;
2823 } 3013 }
2824 3014
2825 pkt_dev = kzalloc(sizeof(struct pktgen_dev), GFP_KERNEL); 3015 pkt_dev = kzalloc(sizeof(struct pktgen_dev), GFP_KERNEL);
2826 if (!pkt_dev) 3016 if (!pkt_dev)
2827 return -ENOMEM; 3017 return -ENOMEM;
2828 3018
2829 pkt_dev->flows = vmalloc(MAX_CFLOWS*sizeof(struct flow_state)); 3019 pkt_dev->flows = vmalloc(MAX_CFLOWS * sizeof(struct flow_state));
2830 if (pkt_dev->flows == NULL) { 3020 if (pkt_dev->flows == NULL) {
2831 kfree(pkt_dev); 3021 kfree(pkt_dev);
2832 return -ENOMEM; 3022 return -ENOMEM;
2833 } 3023 }
2834 memset(pkt_dev->flows, 0, MAX_CFLOWS*sizeof(struct flow_state)); 3024 memset(pkt_dev->flows, 0, MAX_CFLOWS * sizeof(struct flow_state));
2835 3025
3026 pkt_dev->removal_mark = 0;
2836 pkt_dev->min_pkt_size = ETH_ZLEN; 3027 pkt_dev->min_pkt_size = ETH_ZLEN;
2837 pkt_dev->max_pkt_size = ETH_ZLEN; 3028 pkt_dev->max_pkt_size = ETH_ZLEN;
2838 pkt_dev->nfrags = 0; 3029 pkt_dev->nfrags = 0;
@@ -2841,14 +3032,14 @@ static int pktgen_add_device(struct pktgen_thread *t, const char* ifname)
2841 pkt_dev->delay_ns = pg_delay_d % 1000; 3032 pkt_dev->delay_ns = pg_delay_d % 1000;
2842 pkt_dev->count = pg_count_d; 3033 pkt_dev->count = pg_count_d;
2843 pkt_dev->sofar = 0; 3034 pkt_dev->sofar = 0;
2844 pkt_dev->udp_src_min = 9; /* sink port */ 3035 pkt_dev->udp_src_min = 9; /* sink port */
2845 pkt_dev->udp_src_max = 9; 3036 pkt_dev->udp_src_max = 9;
2846 pkt_dev->udp_dst_min = 9; 3037 pkt_dev->udp_dst_min = 9;
2847 pkt_dev->udp_dst_max = 9; 3038 pkt_dev->udp_dst_max = 9;
2848 3039
2849 strncpy(pkt_dev->ifname, ifname, IFNAMSIZ); 3040 strncpy(pkt_dev->ifname, ifname, IFNAMSIZ);
2850 3041
2851 if (! pktgen_setup_dev(pkt_dev)) { 3042 if (!pktgen_setup_dev(pkt_dev)) {
2852 printk("pktgen: ERROR: pktgen_setup_dev failed.\n"); 3043 printk("pktgen: ERROR: pktgen_setup_dev failed.\n");
2853 if (pkt_dev->flows) 3044 if (pkt_dev->flows)
2854 vfree(pkt_dev->flows); 3045 vfree(pkt_dev->flows);
@@ -2871,65 +3062,74 @@ static int pktgen_add_device(struct pktgen_thread *t, const char* ifname)
2871 return add_dev_to_thread(t, pkt_dev); 3062 return add_dev_to_thread(t, pkt_dev);
2872} 3063}
2873 3064
2874static struct pktgen_thread * __init pktgen_find_thread(const char* name) 3065static struct pktgen_thread *__init pktgen_find_thread(const char *name)
2875{ 3066{
2876 struct pktgen_thread *t = NULL; 3067 struct pktgen_thread *t;
2877 3068
2878 thread_lock(); 3069 mutex_lock(&pktgen_thread_lock);
2879 3070
2880 t = pktgen_threads; 3071 list_for_each_entry(t, &pktgen_threads, th_list)
2881 while (t) { 3072 if (strcmp(t->name, name) == 0) {
2882 if (strcmp(t->name, name) == 0) 3073 mutex_unlock(&pktgen_thread_lock);
2883 break; 3074 return t;
3075 }
2884 3076
2885 t = t->next; 3077 mutex_unlock(&pktgen_thread_lock);
2886 } 3078 return NULL;
2887 thread_unlock();
2888 return t;
2889} 3079}
2890 3080
2891static int __init pktgen_create_thread(const char* name, int cpu) 3081static int __init pktgen_create_thread(const char *name, int cpu)
2892{ 3082{
2893 struct pktgen_thread *t = NULL; 3083 int err;
3084 struct pktgen_thread *t = NULL;
2894 struct proc_dir_entry *pe; 3085 struct proc_dir_entry *pe;
2895 3086
2896 if (strlen(name) > 31) { 3087 if (strlen(name) > 31) {
2897 printk("pktgen: ERROR: Thread name cannot be more than 31 characters.\n"); 3088 printk("pktgen: ERROR: Thread name cannot be more than 31 characters.\n");
2898 return -EINVAL; 3089 return -EINVAL;
2899 } 3090 }
2900 3091
2901 if (pktgen_find_thread(name)) { 3092 if (pktgen_find_thread(name)) {
2902 printk("pktgen: ERROR: thread: %s already exists\n", name); 3093 printk("pktgen: ERROR: thread: %s already exists\n", name);
2903 return -EINVAL; 3094 return -EINVAL;
2904 } 3095 }
2905 3096
2906 t = kzalloc(sizeof(struct pktgen_thread), GFP_KERNEL); 3097 t = kzalloc(sizeof(struct pktgen_thread), GFP_KERNEL);
2907 if (!t) { 3098 if (!t) {
2908 printk("pktgen: ERROR: out of memory, can't create new thread.\n"); 3099 printk("pktgen: ERROR: out of memory, can't create new thread.\n");
2909 return -ENOMEM; 3100 return -ENOMEM;
2910 } 3101 }
2911 3102
2912 strcpy(t->name, name); 3103 strcpy(t->name, name);
2913 spin_lock_init(&t->if_lock); 3104 spin_lock_init(&t->if_lock);
2914 t->cpu = cpu; 3105 t->cpu = cpu;
2915 3106
2916 pe = create_proc_entry(t->name, 0600, pg_proc_dir); 3107 pe = create_proc_entry(t->name, 0600, pg_proc_dir);
2917 if (!pe) { 3108 if (!pe) {
2918 printk("pktgen: cannot create %s/%s procfs entry.\n", 3109 printk("pktgen: cannot create %s/%s procfs entry.\n",
2919 PG_PROC_DIR, t->name); 3110 PG_PROC_DIR, t->name);
2920 kfree(t); 3111 kfree(t);
2921 return -EINVAL; 3112 return -EINVAL;
2922 } 3113 }
2923 3114
2924 pe->proc_fops = &pktgen_thread_fops; 3115 pe->proc_fops = &pktgen_thread_fops;
2925 pe->data = t; 3116 pe->data = t;
2926 3117
2927 t->next = pktgen_threads; 3118 INIT_LIST_HEAD(&t->if_list);
2928 pktgen_threads = t;
2929 3119
2930 if (kernel_thread((void *) pktgen_thread_worker, (void *) t, 3120 list_add_tail(&t->th_list, &pktgen_threads);
2931 CLONE_FS | CLONE_FILES | CLONE_SIGHAND) < 0) 3121
3122 t->removed = 0;
3123
3124 err = kernel_thread((void *)pktgen_thread_worker, (void *)t,
3125 CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
3126 if (err < 0) {
2932 printk("pktgen: kernel_thread() failed for cpu %d\n", t->cpu); 3127 printk("pktgen: kernel_thread() failed for cpu %d\n", t->cpu);
3128 remove_proc_entry(t->name, pg_proc_dir);
3129 list_del(&t->th_list);
3130 kfree(t);
3131 return err;
3132 }
2933 3133
2934 return 0; 3134 return 0;
2935} 3135}
@@ -2937,55 +3137,52 @@ static int __init pktgen_create_thread(const char* name, int cpu)
2937/* 3137/*
2938 * Removes a device from the thread if_list. 3138 * Removes a device from the thread if_list.
2939 */ 3139 */
2940static void _rem_dev_from_if_list(struct pktgen_thread *t, struct pktgen_dev *pkt_dev) 3140static void _rem_dev_from_if_list(struct pktgen_thread *t,
3141 struct pktgen_dev *pkt_dev)
2941{ 3142{
2942 struct pktgen_dev *i, *prev = NULL; 3143 struct list_head *q, *n;
2943 3144 struct pktgen_dev *p;
2944 i = t->if_list;
2945 3145
2946 while(i) { 3146 list_for_each_safe(q, n, &t->if_list) {
2947 if(i == pkt_dev) { 3147 p = list_entry(q, struct pktgen_dev, list);
2948 if(prev) prev->next = i->next; 3148 if (p == pkt_dev)
2949 else t->if_list = NULL; 3149 list_del(&p->list);
2950 break;
2951 }
2952 prev = i;
2953 i=i->next;
2954 } 3150 }
2955} 3151}
2956 3152
2957static int pktgen_remove_device(struct pktgen_thread *t, struct pktgen_dev *pkt_dev) 3153static int pktgen_remove_device(struct pktgen_thread *t,
3154 struct pktgen_dev *pkt_dev)
2958{ 3155{
2959 3156
2960 PG_DEBUG(printk("pktgen: remove_device pkt_dev=%p\n", pkt_dev)); 3157 PG_DEBUG(printk("pktgen: remove_device pkt_dev=%p\n", pkt_dev));
2961 3158
2962 if (pkt_dev->running) { 3159 if (pkt_dev->running) {
2963 printk("pktgen:WARNING: trying to remove a running interface, stopping it now.\n"); 3160 printk("pktgen:WARNING: trying to remove a running interface, stopping it now.\n");
2964 pktgen_stop_device(pkt_dev); 3161 pktgen_stop_device(pkt_dev);
2965 } 3162 }
2966 3163
2967 /* Dis-associate from the interface */ 3164 /* Dis-associate from the interface */
2968 3165
2969 if (pkt_dev->odev) { 3166 if (pkt_dev->odev) {
2970 dev_put(pkt_dev->odev); 3167 dev_put(pkt_dev->odev);
2971 pkt_dev->odev = NULL; 3168 pkt_dev->odev = NULL;
2972 } 3169 }
2973 3170
2974 /* And update the thread if_list */ 3171 /* And update the thread if_list */
2975 3172
2976 _rem_dev_from_if_list(t, pkt_dev); 3173 _rem_dev_from_if_list(t, pkt_dev);
2977 3174
2978 /* Clean up proc file system */ 3175 /* Clean up proc file system */
2979 3176
2980 remove_proc_entry(pkt_dev->ifname, pg_proc_dir); 3177 remove_proc_entry(pkt_dev->ifname, pg_proc_dir);
2981 3178
2982 if (pkt_dev->flows) 3179 if (pkt_dev->flows)
2983 vfree(pkt_dev->flows); 3180 vfree(pkt_dev->flows);
2984 kfree(pkt_dev); 3181 kfree(pkt_dev);
2985 return 0; 3182 return 0;
2986} 3183}
2987 3184
2988static int __init pg_init(void) 3185static int __init pg_init(void)
2989{ 3186{
2990 int cpu; 3187 int cpu;
2991 struct proc_dir_entry *pe; 3188 struct proc_dir_entry *pe;
@@ -2998,50 +3195,65 @@ static int __init pg_init(void)
2998 pg_proc_dir->owner = THIS_MODULE; 3195 pg_proc_dir->owner = THIS_MODULE;
2999 3196
3000 pe = create_proc_entry(PGCTRL, 0600, pg_proc_dir); 3197 pe = create_proc_entry(PGCTRL, 0600, pg_proc_dir);
3001 if (pe == NULL) { 3198 if (pe == NULL) {
3002 printk("pktgen: ERROR: cannot create %s procfs entry.\n", PGCTRL); 3199 printk("pktgen: ERROR: cannot create %s procfs entry.\n",
3200 PGCTRL);
3003 proc_net_remove(PG_PROC_DIR); 3201 proc_net_remove(PG_PROC_DIR);
3004 return -EINVAL; 3202 return -EINVAL;
3005 } 3203 }
3006 3204
3007 pe->proc_fops = &pktgen_fops; 3205 pe->proc_fops = &pktgen_fops;
3008 pe->data = NULL; 3206 pe->data = NULL;
3009 3207
3010 /* Register us to receive netdevice events */ 3208 /* Register us to receive netdevice events */
3011 register_netdevice_notifier(&pktgen_notifier_block); 3209 register_netdevice_notifier(&pktgen_notifier_block);
3012 3210
3013 for_each_online_cpu(cpu) { 3211 for_each_online_cpu(cpu) {
3212 int err;
3014 char buf[30]; 3213 char buf[30];
3015 3214
3016 sprintf(buf, "kpktgend_%i", cpu); 3215 sprintf(buf, "kpktgend_%i", cpu);
3017 pktgen_create_thread(buf, cpu); 3216 err = pktgen_create_thread(buf, cpu);
3018 } 3217 if (err)
3019 return 0; 3218 printk("pktgen: WARNING: Cannot create thread for cpu %d (%d)\n",
3219 cpu, err);
3220 }
3221
3222 if (list_empty(&pktgen_threads)) {
3223 printk("pktgen: ERROR: Initialization failed for all threads\n");
3224 unregister_netdevice_notifier(&pktgen_notifier_block);
3225 remove_proc_entry(PGCTRL, pg_proc_dir);
3226 proc_net_remove(PG_PROC_DIR);
3227 return -ENODEV;
3228 }
3229
3230 return 0;
3020} 3231}
3021 3232
3022static void __exit pg_cleanup(void) 3233static void __exit pg_cleanup(void)
3023{ 3234{
3235 struct pktgen_thread *t;
3236 struct list_head *q, *n;
3024 wait_queue_head_t queue; 3237 wait_queue_head_t queue;
3025 init_waitqueue_head(&queue); 3238 init_waitqueue_head(&queue);
3026 3239
3027 /* Stop all interfaces & threads */ 3240 /* Stop all interfaces & threads */
3028 3241
3029 while (pktgen_threads) { 3242 list_for_each_safe(q, n, &pktgen_threads) {
3030 struct pktgen_thread *t = pktgen_threads; 3243 t = list_entry(q, struct pktgen_thread, th_list);
3031 pktgen_threads->control |= (T_TERMINATE); 3244 t->control |= (T_TERMINATE);
3032 3245
3033 wait_event_interruptible_timeout(queue, (t != pktgen_threads), HZ); 3246 wait_event_interruptible_timeout(queue, (t->removed == 1), HZ);
3034 } 3247 }
3035 3248
3036 /* Un-register us from receiving netdevice events */ 3249 /* Un-register us from receiving netdevice events */
3037 unregister_netdevice_notifier(&pktgen_notifier_block); 3250 unregister_netdevice_notifier(&pktgen_notifier_block);
3038 3251
3039 /* Clean up proc file system */ 3252 /* Clean up proc file system */
3040 remove_proc_entry(PGCTRL, pg_proc_dir); 3253 remove_proc_entry(PGCTRL, pg_proc_dir);
3041 proc_net_remove(PG_PROC_DIR); 3254 proc_net_remove(PG_PROC_DIR);
3042} 3255}
3043 3256
3044
3045module_init(pg_init); 3257module_init(pg_init);
3046module_exit(pg_cleanup); 3258module_exit(pg_cleanup);
3047 3259
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index eca2976abb25..ae10d3740faa 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>
@@ -51,25 +52,31 @@
51#include <net/pkt_sched.h> 52#include <net/pkt_sched.h>
52#include <net/netlink.h> 53#include <net/netlink.h>
53 54
54DECLARE_MUTEX(rtnl_sem); 55static DEFINE_MUTEX(rtnl_mutex);
55 56
56void rtnl_lock(void) 57void rtnl_lock(void)
57{ 58{
58 rtnl_shlock(); 59 mutex_lock(&rtnl_mutex);
59} 60}
60 61
61int rtnl_lock_interruptible(void) 62void __rtnl_unlock(void)
62{ 63{
63 return down_interruptible(&rtnl_sem); 64 mutex_unlock(&rtnl_mutex);
64} 65}
65 66
66void rtnl_unlock(void) 67void rtnl_unlock(void)
67{ 68{
68 rtnl_shunlock(); 69 mutex_unlock(&rtnl_mutex);
69 70 if (rtnl && rtnl->sk_receive_queue.qlen)
71 rtnl->sk_data_ready(rtnl, 0);
70 netdev_run_todo(); 72 netdev_run_todo();
71} 73}
72 74
75int rtnl_trylock(void)
76{
77 return mutex_trylock(&rtnl_mutex);
78}
79
73int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len) 80int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len)
74{ 81{
75 memset(tb, 0, sizeof(struct rtattr*)*maxattr); 82 memset(tb, 0, sizeof(struct rtattr*)*maxattr);
@@ -179,6 +186,33 @@ rtattr_failure:
179} 186}
180 187
181 188
189static void set_operstate(struct net_device *dev, unsigned char transition)
190{
191 unsigned char operstate = dev->operstate;
192
193 switch(transition) {
194 case IF_OPER_UP:
195 if ((operstate == IF_OPER_DORMANT ||
196 operstate == IF_OPER_UNKNOWN) &&
197 !netif_dormant(dev))
198 operstate = IF_OPER_UP;
199 break;
200
201 case IF_OPER_DORMANT:
202 if (operstate == IF_OPER_UP ||
203 operstate == IF_OPER_UNKNOWN)
204 operstate = IF_OPER_DORMANT;
205 break;
206 };
207
208 if (dev->operstate != operstate) {
209 write_lock_bh(&dev_base_lock);
210 dev->operstate = operstate;
211 write_unlock_bh(&dev_base_lock);
212 netdev_state_change(dev);
213 }
214}
215
182static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, 216static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
183 int type, u32 pid, u32 seq, u32 change, 217 int type, u32 pid, u32 seq, u32 change,
184 unsigned int flags) 218 unsigned int flags)
@@ -209,6 +243,13 @@ static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
209 } 243 }
210 244
211 if (1) { 245 if (1) {
246 u8 operstate = netif_running(dev)?dev->operstate:IF_OPER_DOWN;
247 u8 link_mode = dev->link_mode;
248 RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate);
249 RTA_PUT(skb, IFLA_LINKMODE, sizeof(link_mode), &link_mode);
250 }
251
252 if (1) {
212 struct rtnl_link_ifmap map = { 253 struct rtnl_link_ifmap map = {
213 .mem_start = dev->mem_start, 254 .mem_start = dev->mem_start,
214 .mem_end = dev->mem_end, 255 .mem_end = dev->mem_end,
@@ -399,6 +440,22 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
399 dev->weight = *((u32 *) RTA_DATA(ida[IFLA_WEIGHT - 1])); 440 dev->weight = *((u32 *) RTA_DATA(ida[IFLA_WEIGHT - 1]));
400 } 441 }
401 442
443 if (ida[IFLA_OPERSTATE - 1]) {
444 if (ida[IFLA_OPERSTATE - 1]->rta_len != RTA_LENGTH(sizeof(u8)))
445 goto out;
446
447 set_operstate(dev, *((u8 *) RTA_DATA(ida[IFLA_OPERSTATE - 1])));
448 }
449
450 if (ida[IFLA_LINKMODE - 1]) {
451 if (ida[IFLA_LINKMODE - 1]->rta_len != RTA_LENGTH(sizeof(u8)))
452 goto out;
453
454 write_lock_bh(&dev_base_lock);
455 dev->link_mode = *((u8 *) RTA_DATA(ida[IFLA_LINKMODE - 1]));
456 write_unlock_bh(&dev_base_lock);
457 }
458
402 if (ifm->ifi_index >= 0 && ida[IFLA_IFNAME - 1]) { 459 if (ifm->ifi_index >= 0 && ida[IFLA_IFNAME - 1]) {
403 char ifname[IFNAMSIZ]; 460 char ifname[IFNAMSIZ];
404 461
@@ -575,9 +632,9 @@ static void rtnetlink_rcv(struct sock *sk, int len)
575 unsigned int qlen = 0; 632 unsigned int qlen = 0;
576 633
577 do { 634 do {
578 rtnl_lock(); 635 mutex_lock(&rtnl_mutex);
579 netlink_run_queue(sk, &qlen, &rtnetlink_rcv_msg); 636 netlink_run_queue(sk, &qlen, &rtnetlink_rcv_msg);
580 up(&rtnl_sem); 637 mutex_unlock(&rtnl_mutex);
581 638
582 netdev_run_todo(); 639 netdev_run_todo();
583 } while (qlen); 640 } while (qlen);
@@ -654,6 +711,5 @@ EXPORT_SYMBOL(rtnetlink_links);
654EXPORT_SYMBOL(rtnetlink_put_metrics); 711EXPORT_SYMBOL(rtnetlink_put_metrics);
655EXPORT_SYMBOL(rtnl); 712EXPORT_SYMBOL(rtnl);
656EXPORT_SYMBOL(rtnl_lock); 713EXPORT_SYMBOL(rtnl_lock);
657EXPORT_SYMBOL(rtnl_lock_interruptible); 714EXPORT_SYMBOL(rtnl_trylock);
658EXPORT_SYMBOL(rtnl_sem);
659EXPORT_SYMBOL(rtnl_unlock); 715EXPORT_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/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/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..768e8f5d7daa 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,24 @@ 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*/
104 106
105int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) 107int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
106{ 108{
107 struct rtattr **rta = arg; 109 struct rtattr **rta = arg;
108 struct rtmsg *rtm = NLMSG_DATA(nlh); 110 struct rtmsg *rtm = NLMSG_DATA(nlh);
109 struct fib_rule *r, **rp; 111 struct fib_rule *r;
112 struct hlist_node *node;
110 int err = -ESRCH; 113 int err = -ESRCH;
111 114
112 for (rp=&fib_rules; (r=*rp) != NULL; rp=&r->r_next) { 115 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) && 116 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 && 117 rtm->rtm_src_len == r->r_src_len &&
115 rtm->rtm_dst_len == r->r_dst_len && 118 rtm->rtm_dst_len == r->r_dst_len &&
@@ -126,10 +129,8 @@ int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
126 if (r == &local_rule) 129 if (r == &local_rule)
127 break; 130 break;
128 131
129 write_lock_bh(&fib_rules_lock); 132 hlist_del_rcu(&r->hlist);
130 *rp = r->r_next;
131 r->r_dead = 1; 133 r->r_dead = 1;
132 write_unlock_bh(&fib_rules_lock);
133 fib_rule_put(r); 134 fib_rule_put(r);
134 err = 0; 135 err = 0;
135 break; 136 break;
@@ -150,21 +151,30 @@ static struct fib_table *fib_empty_table(void)
150 return NULL; 151 return NULL;
151} 152}
152 153
154static inline void fib_rule_put_rcu(struct rcu_head *head)
155{
156 struct fib_rule *r = container_of(head, struct fib_rule, rcu);
157 kfree(r);
158}
159
153void fib_rule_put(struct fib_rule *r) 160void fib_rule_put(struct fib_rule *r)
154{ 161{
155 if (atomic_dec_and_test(&r->r_clntref)) { 162 if (atomic_dec_and_test(&r->r_clntref)) {
156 if (r->r_dead) 163 if (r->r_dead)
157 kfree(r); 164 call_rcu(&r->rcu, fib_rule_put_rcu);
158 else 165 else
159 printk("Freeing alive rule %p\n", r); 166 printk("Freeing alive rule %p\n", r);
160 } 167 }
161} 168}
162 169
170/* writer func called from netlink -- rtnl_sem hold*/
171
163int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) 172int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
164{ 173{
165 struct rtattr **rta = arg; 174 struct rtattr **rta = arg;
166 struct rtmsg *rtm = NLMSG_DATA(nlh); 175 struct rtmsg *rtm = NLMSG_DATA(nlh);
167 struct fib_rule *r, *new_r, **rp; 176 struct fib_rule *r, *new_r, *last = NULL;
177 struct hlist_node *node = NULL;
168 unsigned char table_id; 178 unsigned char table_id;
169 179
170 if (rtm->rtm_src_len > 32 || rtm->rtm_dst_len > 32 || 180 if (rtm->rtm_src_len > 32 || rtm->rtm_dst_len > 32 ||
@@ -188,6 +198,7 @@ int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
188 if (!new_r) 198 if (!new_r)
189 return -ENOMEM; 199 return -ENOMEM;
190 memset(new_r, 0, sizeof(*new_r)); 200 memset(new_r, 0, sizeof(*new_r));
201
191 if (rta[RTA_SRC-1]) 202 if (rta[RTA_SRC-1])
192 memcpy(&new_r->r_src, RTA_DATA(rta[RTA_SRC-1]), 4); 203 memcpy(&new_r->r_src, RTA_DATA(rta[RTA_SRC-1]), 4);
193 if (rta[RTA_DST-1]) 204 if (rta[RTA_DST-1])
@@ -220,28 +231,28 @@ int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
220 if (rta[RTA_FLOW-1]) 231 if (rta[RTA_FLOW-1])
221 memcpy(&new_r->r_tclassid, RTA_DATA(rta[RTA_FLOW-1]), 4); 232 memcpy(&new_r->r_tclassid, RTA_DATA(rta[RTA_FLOW-1]), 4);
222#endif 233#endif
234 r = container_of(fib_rules.first, struct fib_rule, hlist);
223 235
224 rp = &fib_rules;
225 if (!new_r->r_preference) { 236 if (!new_r->r_preference) {
226 r = fib_rules; 237 if (r && r->hlist.next != NULL) {
227 if (r && (r = r->r_next) != NULL) { 238 r = container_of(r->hlist.next, struct fib_rule, hlist);
228 rp = &fib_rules->r_next;
229 if (r->r_preference) 239 if (r->r_preference)
230 new_r->r_preference = r->r_preference - 1; 240 new_r->r_preference = r->r_preference - 1;
231 } 241 }
232 } 242 }
233 243
234 while ( (r = *rp) != NULL ) { 244 hlist_for_each_entry(r, node, &fib_rules, hlist) {
235 if (r->r_preference > new_r->r_preference) 245 if (r->r_preference > new_r->r_preference)
236 break; 246 break;
237 rp = &r->r_next; 247 last = r;
238 } 248 }
239
240 new_r->r_next = r;
241 atomic_inc(&new_r->r_clntref); 249 atomic_inc(&new_r->r_clntref);
242 write_lock_bh(&fib_rules_lock); 250
243 *rp = new_r; 251 if (last)
244 write_unlock_bh(&fib_rules_lock); 252 hlist_add_after_rcu(&last->hlist, &new_r->hlist);
253 else
254 hlist_add_before_rcu(&new_r->hlist, &r->hlist);
255
245 return 0; 256 return 0;
246} 257}
247 258
@@ -254,30 +265,30 @@ u32 fib_rules_tclass(struct fib_result *res)
254} 265}
255#endif 266#endif
256 267
268/* callers should hold rtnl semaphore */
257 269
258static void fib_rules_detach(struct net_device *dev) 270static void fib_rules_detach(struct net_device *dev)
259{ 271{
272 struct hlist_node *node;
260 struct fib_rule *r; 273 struct fib_rule *r;
261 274
262 for (r=fib_rules; r; r=r->r_next) { 275 hlist_for_each_entry(r, node, &fib_rules, hlist) {
263 if (r->r_ifindex == dev->ifindex) { 276 if (r->r_ifindex == dev->ifindex)
264 write_lock_bh(&fib_rules_lock);
265 r->r_ifindex = -1; 277 r->r_ifindex = -1;
266 write_unlock_bh(&fib_rules_lock); 278
267 }
268 } 279 }
269} 280}
270 281
282/* callers should hold rtnl semaphore */
283
271static void fib_rules_attach(struct net_device *dev) 284static void fib_rules_attach(struct net_device *dev)
272{ 285{
286 struct hlist_node *node;
273 struct fib_rule *r; 287 struct fib_rule *r;
274 288
275 for (r=fib_rules; r; r=r->r_next) { 289 hlist_for_each_entry(r, node, &fib_rules, hlist) {
276 if (r->r_ifindex == -1 && strcmp(dev->name, r->r_ifname) == 0) { 290 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; 291 r->r_ifindex = dev->ifindex;
279 write_unlock_bh(&fib_rules_lock);
280 }
281 } 292 }
282} 293}
283 294
@@ -286,14 +297,17 @@ int fib_lookup(const struct flowi *flp, struct fib_result *res)
286 int err; 297 int err;
287 struct fib_rule *r, *policy; 298 struct fib_rule *r, *policy;
288 struct fib_table *tb; 299 struct fib_table *tb;
300 struct hlist_node *node;
289 301
290 u32 daddr = flp->fl4_dst; 302 u32 daddr = flp->fl4_dst;
291 u32 saddr = flp->fl4_src; 303 u32 saddr = flp->fl4_src;
292 304
293FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ", 305FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ",
294 NIPQUAD(flp->fl4_dst), NIPQUAD(flp->fl4_src)); 306 NIPQUAD(flp->fl4_dst), NIPQUAD(flp->fl4_src));
295 read_lock(&fib_rules_lock); 307
296 for (r = fib_rules; r; r=r->r_next) { 308 rcu_read_lock();
309
310 hlist_for_each_entry_rcu(r, node, &fib_rules, hlist) {
297 if (((saddr^r->r_src) & r->r_srcmask) || 311 if (((saddr^r->r_src) & r->r_srcmask) ||
298 ((daddr^r->r_dst) & r->r_dstmask) || 312 ((daddr^r->r_dst) & r->r_dstmask) ||
299 (r->r_tos && r->r_tos != flp->fl4_tos) || 313 (r->r_tos && r->r_tos != flp->fl4_tos) ||
@@ -309,14 +323,14 @@ FRprintk("tb %d r %d ", r->r_table, r->r_action);
309 policy = r; 323 policy = r;
310 break; 324 break;
311 case RTN_UNREACHABLE: 325 case RTN_UNREACHABLE:
312 read_unlock(&fib_rules_lock); 326 rcu_read_unlock();
313 return -ENETUNREACH; 327 return -ENETUNREACH;
314 default: 328 default:
315 case RTN_BLACKHOLE: 329 case RTN_BLACKHOLE:
316 read_unlock(&fib_rules_lock); 330 rcu_read_unlock();
317 return -EINVAL; 331 return -EINVAL;
318 case RTN_PROHIBIT: 332 case RTN_PROHIBIT:
319 read_unlock(&fib_rules_lock); 333 rcu_read_unlock();
320 return -EACCES; 334 return -EACCES;
321 } 335 }
322 336
@@ -327,16 +341,16 @@ FRprintk("tb %d r %d ", r->r_table, r->r_action);
327 res->r = policy; 341 res->r = policy;
328 if (policy) 342 if (policy)
329 atomic_inc(&policy->r_clntref); 343 atomic_inc(&policy->r_clntref);
330 read_unlock(&fib_rules_lock); 344 rcu_read_unlock();
331 return 0; 345 return 0;
332 } 346 }
333 if (err < 0 && err != -EAGAIN) { 347 if (err < 0 && err != -EAGAIN) {
334 read_unlock(&fib_rules_lock); 348 rcu_read_unlock();
335 return err; 349 return err;
336 } 350 }
337 } 351 }
338FRprintk("FAILURE\n"); 352FRprintk("FAILURE\n");
339 read_unlock(&fib_rules_lock); 353 rcu_read_unlock();
340 return -ENETUNREACH; 354 return -ENETUNREACH;
341} 355}
342 356
@@ -414,20 +428,25 @@ rtattr_failure:
414 return -1; 428 return -1;
415} 429}
416 430
431/* callers should hold rtnl semaphore */
432
417int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) 433int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
418{ 434{
419 int idx; 435 int idx = 0;
420 int s_idx = cb->args[0]; 436 int s_idx = cb->args[0];
421 struct fib_rule *r; 437 struct fib_rule *r;
438 struct hlist_node *node;
439
440 rcu_read_lock();
441 hlist_for_each_entry(r, node, &fib_rules, hlist) {
422 442
423 read_lock(&fib_rules_lock);
424 for (r=fib_rules, idx=0; r; r = r->r_next, idx++) {
425 if (idx < s_idx) 443 if (idx < s_idx)
426 continue; 444 continue;
427 if (inet_fill_rule(skb, r, cb, NLM_F_MULTI) < 0) 445 if (inet_fill_rule(skb, r, cb, NLM_F_MULTI) < 0)
428 break; 446 break;
447 idx++;
429 } 448 }
430 read_unlock(&fib_rules_lock); 449 rcu_read_unlock();
431 cb->args[0] = idx; 450 cb->args[0] = idx;
432 451
433 return skb->len; 452 return skb->len;
@@ -435,5 +454,9 @@ int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
435 454
436void __init fib_rules_init(void) 455void __init fib_rules_init(void)
437{ 456{
457 INIT_HLIST_HEAD(&fib_rules);
458 hlist_add_head(&local_rule.hlist, &fib_rules);
459 hlist_add_after(&local_rule.hlist, &main_rule.hlist);
460 hlist_add_after(&main_rule.hlist, &default_rule.hlist);
438 register_netdevice_notifier(&fib_rules_notifier); 461 register_netdevice_notifier(&fib_rules_notifier);
439} 462}
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_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..f7efb3f27bf5 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,13 @@ 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),
1141}; 1149};
1142 1150
1143static struct arpt_target arpt_error_target = { 1151static struct arpt_target arpt_error_target = {
1144 .name = ARPT_ERROR_TARGET, 1152 .name = ARPT_ERROR_TARGET,
1145 .target = arpt_error, 1153 .target = arpt_error,
1154 .targetsize = ARPT_FUNCTION_MAXNAMELEN,
1146}; 1155};
1147 1156
1148static struct nf_sockopt_ops arpt_sockopts = { 1157static struct nf_sockopt_ops 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_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
new file mode 100644
index 000000000000..20da6730b860
--- /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/****************************************************************************/
642static int 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..5ce2e3fc2c7f 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -327,9 +327,10 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
327 group = NFNLGRP_CONNTRACK_UPDATE; 327 group = NFNLGRP_CONNTRACK_UPDATE;
328 } else 328 } else
329 return NOTIFY_DONE; 329 return NOTIFY_DONE;
330 330
331 /* FIXME: Check if there are any listeners before, don't hurt performance */ 331 if (!nfnetlink_has_listeners(group))
332 332 return NOTIFY_DONE;
333
333 skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); 334 skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
334 if (!skb) 335 if (!skb)
335 return NOTIFY_DONE; 336 return NOTIFY_DONE;
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..39705f9bc154 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,27 @@ 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),
1330}; 1338};
1331 1339
1332static struct ipt_target ipt_error_target = { 1340static struct ipt_target ipt_error_target = {
1333 .name = IPT_ERROR_TARGET, 1341 .name = IPT_ERROR_TARGET,
1334 .target = ipt_error, 1342 .target = ipt_error,
1343 .targetsize = IPT_FUNCTION_MAXNAMELEN,
1335}; 1344};
1336 1345
1337static struct nf_sockopt_ops ipt_sockopts = { 1346static struct nf_sockopt_ops ipt_sockopts = {
@@ -1346,8 +1355,10 @@ static struct nf_sockopt_ops ipt_sockopts = {
1346 1355
1347static struct ipt_match icmp_matchstruct = { 1356static struct ipt_match icmp_matchstruct = {
1348 .name = "icmp", 1357 .name = "icmp",
1349 .match = &icmp_match, 1358 .match = icmp_match,
1350 .checkentry = &icmp_checkentry, 1359 .matchsize = sizeof(struct ipt_icmp),
1360 .proto = IPPROTO_ICMP,
1361 .checkentry = icmp_checkentry,
1351}; 1362};
1352 1363
1353static int __init init(void) 1364static int __init init(void)
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..cb9c661f3f33 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,
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..4fbc40b13f19 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -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..602feec47738 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 == -ENOPROTOOPT && 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 == -ENOPROTOOPT && 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..5a2063bda676 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,27 @@ 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),
1385}; 1380};
1386 1381
1387static struct ip6t_target ip6t_error_target = { 1382static struct ip6t_target ip6t_error_target = {
1388 .name = IP6T_ERROR_TARGET, 1383 .name = IP6T_ERROR_TARGET,
1389 .target = ip6t_error, 1384 .target = ip6t_error,
1385 .targetsize = IP6T_FUNCTION_MAXNAMELEN,
1390}; 1386};
1391 1387
1392static struct nf_sockopt_ops ip6t_sockopts = { 1388static struct nf_sockopt_ops ip6t_sockopts = {
@@ -1402,7 +1398,9 @@ static struct nf_sockopt_ops ip6t_sockopts = {
1402static struct ip6t_match icmp6_matchstruct = { 1398static struct ip6t_match icmp6_matchstruct = {
1403 .name = "icmp6", 1399 .name = "icmp6",
1404 .match = &icmp6_match, 1400 .match = &icmp6_match,
1405 .checkentry = &icmp6_checkentry, 1401 .matchsize = sizeof(struct ip6t_icmp),
1402 .checkentry = icmp6_checkentry,
1403 .proto = IPPROTO_ICMPV6,
1406}; 1404};
1407 1405
1408static int __init init(void) 1406static int __init init(void)
@@ -1515,7 +1513,6 @@ EXPORT_SYMBOL(ip6t_unregister_table);
1515EXPORT_SYMBOL(ip6t_do_table); 1513EXPORT_SYMBOL(ip6t_do_table);
1516EXPORT_SYMBOL(ip6t_ext_hdr); 1514EXPORT_SYMBOL(ip6t_ext_hdr);
1517EXPORT_SYMBOL(ipv6_find_hdr); 1515EXPORT_SYMBOL(ipv6_find_hdr);
1518EXPORT_SYMBOL(ip6_masked_addrcmp);
1519 1516
1520module_init(init); 1517module_init(init);
1521module_exit(fini); 1518module_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..ac35f9526368 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
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..174027809148 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -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..f6498234e264 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,9 @@
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
23 * 26 *
24 * Derived from net/ipv4/netfilter/ip_conntrack_core.c 27 * Derived from net/ipv4/netfilter/ip_conntrack_core.c
25 */ 28 */
@@ -55,7 +58,7 @@
55#include <net/netfilter/nf_conntrack_core.h> 58#include <net/netfilter/nf_conntrack_core.h>
56#include <linux/netfilter_ipv4/listhelp.h> 59#include <linux/netfilter_ipv4/listhelp.h>
57 60
58#define NF_CONNTRACK_VERSION "0.4.1" 61#define NF_CONNTRACK_VERSION "0.5.0"
59 62
60#if 0 63#if 0
61#define DEBUGP printk 64#define DEBUGP printk
@@ -182,7 +185,7 @@ static struct {
182DEFINE_RWLOCK(nf_ct_cache_lock); 185DEFINE_RWLOCK(nf_ct_cache_lock);
183 186
184/* This avoids calling kmem_cache_create() with same name simultaneously */ 187/* This avoids calling kmem_cache_create() with same name simultaneously */
185DECLARE_MUTEX(nf_ct_cache_mutex); 188static DEFINE_MUTEX(nf_ct_cache_mutex);
186 189
187extern struct nf_conntrack_protocol nf_conntrack_generic_protocol; 190extern struct nf_conntrack_protocol nf_conntrack_generic_protocol;
188struct nf_conntrack_protocol * 191struct nf_conntrack_protocol *
@@ -259,21 +262,8 @@ static inline u_int32_t hash_conntrack(const struct nf_conntrack_tuple *tuple)
259 nf_conntrack_hash_rnd); 262 nf_conntrack_hash_rnd);
260} 263}
261 264
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, 265int nf_conntrack_register_cache(u_int32_t features, const char *name,
275 size_t size, 266 size_t size)
276 int (*init)(struct nf_conn *, u_int32_t))
277{ 267{
278 int ret = 0; 268 int ret = 0;
279 char *cache_name; 269 char *cache_name;
@@ -288,7 +278,7 @@ int nf_conntrack_register_cache(u_int32_t features, const char *name,
288 return -EINVAL; 278 return -EINVAL;
289 } 279 }
290 280
291 down(&nf_ct_cache_mutex); 281 mutex_lock(&nf_ct_cache_mutex);
292 282
293 write_lock_bh(&nf_ct_cache_lock); 283 write_lock_bh(&nf_ct_cache_lock);
294 /* e.g: multiple helpers are loaded */ 284 /* e.g: multiple helpers are loaded */
@@ -296,8 +286,7 @@ int nf_conntrack_register_cache(u_int32_t features, const char *name,
296 DEBUGP("nf_conntrack_register_cache: already resisterd.\n"); 286 DEBUGP("nf_conntrack_register_cache: already resisterd.\n");
297 if ((!strncmp(nf_ct_cache[features].name, name, 287 if ((!strncmp(nf_ct_cache[features].name, name,
298 NF_CT_FEATURES_NAMELEN)) 288 NF_CT_FEATURES_NAMELEN))
299 && nf_ct_cache[features].size == size 289 && nf_ct_cache[features].size == size) {
300 && nf_ct_cache[features].init_conntrack == init) {
301 DEBUGP("nf_conntrack_register_cache: reusing.\n"); 290 DEBUGP("nf_conntrack_register_cache: reusing.\n");
302 nf_ct_cache[features].use++; 291 nf_ct_cache[features].use++;
303 ret = 0; 292 ret = 0;
@@ -305,7 +294,7 @@ int nf_conntrack_register_cache(u_int32_t features, const char *name,
305 ret = -EBUSY; 294 ret = -EBUSY;
306 295
307 write_unlock_bh(&nf_ct_cache_lock); 296 write_unlock_bh(&nf_ct_cache_lock);
308 up(&nf_ct_cache_mutex); 297 mutex_unlock(&nf_ct_cache_mutex);
309 return ret; 298 return ret;
310 } 299 }
311 write_unlock_bh(&nf_ct_cache_lock); 300 write_unlock_bh(&nf_ct_cache_lock);
@@ -340,7 +329,6 @@ int nf_conntrack_register_cache(u_int32_t features, const char *name,
340 write_lock_bh(&nf_ct_cache_lock); 329 write_lock_bh(&nf_ct_cache_lock);
341 nf_ct_cache[features].use = 1; 330 nf_ct_cache[features].use = 1;
342 nf_ct_cache[features].size = size; 331 nf_ct_cache[features].size = size;
343 nf_ct_cache[features].init_conntrack = init;
344 nf_ct_cache[features].cachep = cachep; 332 nf_ct_cache[features].cachep = cachep;
345 nf_ct_cache[features].name = cache_name; 333 nf_ct_cache[features].name = cache_name;
346 write_unlock_bh(&nf_ct_cache_lock); 334 write_unlock_bh(&nf_ct_cache_lock);
@@ -350,7 +338,7 @@ int nf_conntrack_register_cache(u_int32_t features, const char *name,
350out_free_name: 338out_free_name:
351 kfree(cache_name); 339 kfree(cache_name);
352out_up_mutex: 340out_up_mutex:
353 up(&nf_ct_cache_mutex); 341 mutex_unlock(&nf_ct_cache_mutex);
354 return ret; 342 return ret;
355} 343}
356 344
@@ -365,19 +353,18 @@ void nf_conntrack_unregister_cache(u_int32_t features)
365 * slab cache. 353 * slab cache.
366 */ 354 */
367 DEBUGP("nf_conntrack_unregister_cache: 0x%04x\n", features); 355 DEBUGP("nf_conntrack_unregister_cache: 0x%04x\n", features);
368 down(&nf_ct_cache_mutex); 356 mutex_lock(&nf_ct_cache_mutex);
369 357
370 write_lock_bh(&nf_ct_cache_lock); 358 write_lock_bh(&nf_ct_cache_lock);
371 if (--nf_ct_cache[features].use > 0) { 359 if (--nf_ct_cache[features].use > 0) {
372 write_unlock_bh(&nf_ct_cache_lock); 360 write_unlock_bh(&nf_ct_cache_lock);
373 up(&nf_ct_cache_mutex); 361 mutex_unlock(&nf_ct_cache_mutex);
374 return; 362 return;
375 } 363 }
376 cachep = nf_ct_cache[features].cachep; 364 cachep = nf_ct_cache[features].cachep;
377 name = nf_ct_cache[features].name; 365 name = nf_ct_cache[features].name;
378 nf_ct_cache[features].cachep = NULL; 366 nf_ct_cache[features].cachep = NULL;
379 nf_ct_cache[features].name = NULL; 367 nf_ct_cache[features].name = NULL;
380 nf_ct_cache[features].init_conntrack = NULL;
381 nf_ct_cache[features].size = 0; 368 nf_ct_cache[features].size = 0;
382 write_unlock_bh(&nf_ct_cache_lock); 369 write_unlock_bh(&nf_ct_cache_lock);
383 370
@@ -386,7 +373,7 @@ void nf_conntrack_unregister_cache(u_int32_t features)
386 kmem_cache_destroy(cachep); 373 kmem_cache_destroy(cachep);
387 kfree(name); 374 kfree(name);
388 375
389 up(&nf_ct_cache_mutex); 376 mutex_unlock(&nf_ct_cache_mutex);
390} 377}
391 378
392int 379int
@@ -432,11 +419,15 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
432/* nf_conntrack_expect helper functions */ 419/* nf_conntrack_expect helper functions */
433void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) 420void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
434{ 421{
422 struct nf_conn_help *master_help = nfct_help(exp->master);
423
424 NF_CT_ASSERT(master_help);
435 ASSERT_WRITE_LOCK(&nf_conntrack_lock); 425 ASSERT_WRITE_LOCK(&nf_conntrack_lock);
436 NF_CT_ASSERT(!timer_pending(&exp->timeout)); 426 NF_CT_ASSERT(!timer_pending(&exp->timeout));
427
437 list_del(&exp->list); 428 list_del(&exp->list);
438 NF_CT_STAT_INC(expect_delete); 429 NF_CT_STAT_INC(expect_delete);
439 exp->master->expecting--; 430 master_help->expecting--;
440 nf_conntrack_expect_put(exp); 431 nf_conntrack_expect_put(exp);
441} 432}
442 433
@@ -508,9 +499,10 @@ find_expectation(const struct nf_conntrack_tuple *tuple)
508void nf_ct_remove_expectations(struct nf_conn *ct) 499void nf_ct_remove_expectations(struct nf_conn *ct)
509{ 500{
510 struct nf_conntrack_expect *i, *tmp; 501 struct nf_conntrack_expect *i, *tmp;
502 struct nf_conn_help *help = nfct_help(ct);
511 503
512 /* Optimization: most connection never expect any others. */ 504 /* Optimization: most connection never expect any others. */
513 if (ct->expecting == 0) 505 if (!help || help->expecting == 0)
514 return; 506 return;
515 507
516 list_for_each_entry_safe(i, tmp, &nf_conntrack_expect_list, list) { 508 list_for_each_entry_safe(i, tmp, &nf_conntrack_expect_list, list) {
@@ -713,6 +705,7 @@ __nf_conntrack_confirm(struct sk_buff **pskb)
713 conntrack_tuple_cmp, 705 conntrack_tuple_cmp,
714 struct nf_conntrack_tuple_hash *, 706 struct nf_conntrack_tuple_hash *,
715 &ct->tuplehash[IP_CT_DIR_REPLY].tuple, NULL)) { 707 &ct->tuplehash[IP_CT_DIR_REPLY].tuple, NULL)) {
708 struct nf_conn_help *help;
716 /* Remove from unconfirmed list */ 709 /* Remove from unconfirmed list */
717 list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); 710 list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
718 711
@@ -726,7 +719,8 @@ __nf_conntrack_confirm(struct sk_buff **pskb)
726 set_bit(IPS_CONFIRMED_BIT, &ct->status); 719 set_bit(IPS_CONFIRMED_BIT, &ct->status);
727 NF_CT_STAT_INC(insert); 720 NF_CT_STAT_INC(insert);
728 write_unlock_bh(&nf_conntrack_lock); 721 write_unlock_bh(&nf_conntrack_lock);
729 if (ct->helper) 722 help = nfct_help(ct);
723 if (help && help->helper)
730 nf_conntrack_event_cache(IPCT_HELPER, *pskb); 724 nf_conntrack_event_cache(IPCT_HELPER, *pskb);
731#ifdef CONFIG_NF_NAT_NEEDED 725#ifdef CONFIG_NF_NAT_NEEDED
732 if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) || 726 if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) ||
@@ -842,8 +836,9 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
842{ 836{
843 struct nf_conn *conntrack = NULL; 837 struct nf_conn *conntrack = NULL;
844 u_int32_t features = 0; 838 u_int32_t features = 0;
839 struct nf_conntrack_helper *helper;
845 840
846 if (!nf_conntrack_hash_rnd_initted) { 841 if (unlikely(!nf_conntrack_hash_rnd_initted)) {
847 get_random_bytes(&nf_conntrack_hash_rnd, 4); 842 get_random_bytes(&nf_conntrack_hash_rnd, 4);
848 nf_conntrack_hash_rnd_initted = 1; 843 nf_conntrack_hash_rnd_initted = 1;
849 } 844 }
@@ -863,8 +858,11 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
863 858
864 /* find features needed by this conntrack. */ 859 /* find features needed by this conntrack. */
865 features = l3proto->get_features(orig); 860 features = l3proto->get_features(orig);
861
862 /* FIXME: protect helper list per RCU */
866 read_lock_bh(&nf_conntrack_lock); 863 read_lock_bh(&nf_conntrack_lock);
867 if (__nf_ct_helper_find(repl) != NULL) 864 helper = __nf_ct_helper_find(repl);
865 if (helper)
868 features |= NF_CT_F_HELP; 866 features |= NF_CT_F_HELP;
869 read_unlock_bh(&nf_conntrack_lock); 867 read_unlock_bh(&nf_conntrack_lock);
870 868
@@ -872,7 +870,7 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
872 870
873 read_lock_bh(&nf_ct_cache_lock); 871 read_lock_bh(&nf_ct_cache_lock);
874 872
875 if (!nf_ct_cache[features].use) { 873 if (unlikely(!nf_ct_cache[features].use)) {
876 DEBUGP("nf_conntrack_alloc: not supported features = 0x%x\n", 874 DEBUGP("nf_conntrack_alloc: not supported features = 0x%x\n",
877 features); 875 features);
878 goto out; 876 goto out;
@@ -886,12 +884,10 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
886 884
887 memset(conntrack, 0, nf_ct_cache[features].size); 885 memset(conntrack, 0, nf_ct_cache[features].size);
888 conntrack->features = features; 886 conntrack->features = features;
889 if (nf_ct_cache[features].init_conntrack && 887 if (helper) {
890 nf_ct_cache[features].init_conntrack(conntrack, features) < 0) { 888 struct nf_conn_help *help = nfct_help(conntrack);
891 DEBUGP("nf_conntrack_alloc: failed to init\n"); 889 NF_CT_ASSERT(help);
892 kmem_cache_free(nf_ct_cache[features].cachep, conntrack); 890 help->helper = helper;
893 conntrack = NULL;
894 goto out;
895 } 891 }
896 892
897 atomic_set(&conntrack->ct_general.use, 1); 893 atomic_set(&conntrack->ct_general.use, 1);
@@ -972,11 +968,8 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
972#endif 968#endif
973 nf_conntrack_get(&conntrack->master->ct_general); 969 nf_conntrack_get(&conntrack->master->ct_general);
974 NF_CT_STAT_INC(expect_new); 970 NF_CT_STAT_INC(expect_new);
975 } else { 971 } else
976 conntrack->helper = __nf_ct_helper_find(&repl_tuple);
977
978 NF_CT_STAT_INC(new); 972 NF_CT_STAT_INC(new);
979 }
980 973
981 /* Overload tuple linked list to put us in unconfirmed list. */ 974 /* Overload tuple linked list to put us in unconfirmed list. */
982 list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed); 975 list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed);
@@ -1206,14 +1199,16 @@ void nf_conntrack_expect_put(struct nf_conntrack_expect *exp)
1206 1199
1207static void nf_conntrack_expect_insert(struct nf_conntrack_expect *exp) 1200static void nf_conntrack_expect_insert(struct nf_conntrack_expect *exp)
1208{ 1201{
1202 struct nf_conn_help *master_help = nfct_help(exp->master);
1203
1209 atomic_inc(&exp->use); 1204 atomic_inc(&exp->use);
1210 exp->master->expecting++; 1205 master_help->expecting++;
1211 list_add(&exp->list, &nf_conntrack_expect_list); 1206 list_add(&exp->list, &nf_conntrack_expect_list);
1212 1207
1213 init_timer(&exp->timeout); 1208 init_timer(&exp->timeout);
1214 exp->timeout.data = (unsigned long)exp; 1209 exp->timeout.data = (unsigned long)exp;
1215 exp->timeout.function = expectation_timed_out; 1210 exp->timeout.function = expectation_timed_out;
1216 exp->timeout.expires = jiffies + exp->master->helper->timeout * HZ; 1211 exp->timeout.expires = jiffies + master_help->helper->timeout * HZ;
1217 add_timer(&exp->timeout); 1212 add_timer(&exp->timeout);
1218 1213
1219 exp->id = ++nf_conntrack_expect_next_id; 1214 exp->id = ++nf_conntrack_expect_next_id;
@@ -1239,10 +1234,12 @@ static void evict_oldest_expect(struct nf_conn *master)
1239 1234
1240static inline int refresh_timer(struct nf_conntrack_expect *i) 1235static inline int refresh_timer(struct nf_conntrack_expect *i)
1241{ 1236{
1237 struct nf_conn_help *master_help = nfct_help(i->master);
1238
1242 if (!del_timer(&i->timeout)) 1239 if (!del_timer(&i->timeout))
1243 return 0; 1240 return 0;
1244 1241
1245 i->timeout.expires = jiffies + i->master->helper->timeout*HZ; 1242 i->timeout.expires = jiffies + master_help->helper->timeout*HZ;
1246 add_timer(&i->timeout); 1243 add_timer(&i->timeout);
1247 return 1; 1244 return 1;
1248} 1245}
@@ -1251,8 +1248,11 @@ int nf_conntrack_expect_related(struct nf_conntrack_expect *expect)
1251{ 1248{
1252 struct nf_conntrack_expect *i; 1249 struct nf_conntrack_expect *i;
1253 struct nf_conn *master = expect->master; 1250 struct nf_conn *master = expect->master;
1251 struct nf_conn_help *master_help = nfct_help(master);
1254 int ret; 1252 int ret;
1255 1253
1254 NF_CT_ASSERT(master_help);
1255
1256 DEBUGP("nf_conntrack_expect_related %p\n", related_to); 1256 DEBUGP("nf_conntrack_expect_related %p\n", related_to);
1257 DEBUGP("tuple: "); NF_CT_DUMP_TUPLE(&expect->tuple); 1257 DEBUGP("tuple: "); NF_CT_DUMP_TUPLE(&expect->tuple);
1258 DEBUGP("mask: "); NF_CT_DUMP_TUPLE(&expect->mask); 1258 DEBUGP("mask: "); NF_CT_DUMP_TUPLE(&expect->mask);
@@ -1271,8 +1271,8 @@ int nf_conntrack_expect_related(struct nf_conntrack_expect *expect)
1271 } 1271 }
1272 } 1272 }
1273 /* Will be over limit? */ 1273 /* Will be over limit? */
1274 if (master->helper->max_expected && 1274 if (master_help->helper->max_expected &&
1275 master->expecting >= master->helper->max_expected) 1275 master_help->expecting >= master_help->helper->max_expected)
1276 evict_oldest_expect(master); 1276 evict_oldest_expect(master);
1277 1277
1278 nf_conntrack_expect_insert(expect); 1278 nf_conntrack_expect_insert(expect);
@@ -1283,24 +1283,6 @@ out:
1283 return ret; 1283 return ret;
1284} 1284}
1285 1285
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) 1286int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
1305{ 1287{
1306 int ret; 1288 int ret;
@@ -1308,9 +1290,8 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
1308 1290
1309 ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help", 1291 ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help",
1310 sizeof(struct nf_conn) 1292 sizeof(struct nf_conn)
1311 + sizeof(union nf_conntrack_help) 1293 + sizeof(struct nf_conn_help)
1312 + __alignof__(union nf_conntrack_help), 1294 + __alignof__(struct nf_conn_help));
1313 init_conntrack_for_helper);
1314 if (ret < 0) { 1295 if (ret < 0) {
1315 printk(KERN_ERR "nf_conntrack_helper_reigster: Unable to create slab cache for conntracks\n"); 1296 printk(KERN_ERR "nf_conntrack_helper_reigster: Unable to create slab cache for conntracks\n");
1316 return ret; 1297 return ret;
@@ -1338,9 +1319,12 @@ __nf_conntrack_helper_find_byname(const char *name)
1338static inline int unhelp(struct nf_conntrack_tuple_hash *i, 1319static inline int unhelp(struct nf_conntrack_tuple_hash *i,
1339 const struct nf_conntrack_helper *me) 1320 const struct nf_conntrack_helper *me)
1340{ 1321{
1341 if (nf_ct_tuplehash_to_ctrack(i)->helper == me) { 1322 struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i);
1342 nf_conntrack_event(IPCT_HELPER, nf_ct_tuplehash_to_ctrack(i)); 1323 struct nf_conn_help *help = nfct_help(ct);
1343 nf_ct_tuplehash_to_ctrack(i)->helper = NULL; 1324
1325 if (help && help->helper == me) {
1326 nf_conntrack_event(IPCT_HELPER, ct);
1327 help->helper = NULL;
1344 } 1328 }
1345 return 0; 1329 return 0;
1346} 1330}
@@ -1356,7 +1340,8 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
1356 1340
1357 /* Get rid of expectations */ 1341 /* Get rid of expectations */
1358 list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) { 1342 list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) {
1359 if (exp->master->helper == me && del_timer(&exp->timeout)) { 1343 struct nf_conn_help *help = nfct_help(exp->master);
1344 if (help->helper == me && del_timer(&exp->timeout)) {
1360 nf_ct_unlink_expect(exp); 1345 nf_ct_unlink_expect(exp);
1361 nf_conntrack_expect_put(exp); 1346 nf_conntrack_expect_put(exp);
1362 } 1347 }
@@ -1423,6 +1408,8 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
1423 1408
1424#include <linux/netfilter/nfnetlink.h> 1409#include <linux/netfilter/nfnetlink.h>
1425#include <linux/netfilter/nfnetlink_conntrack.h> 1410#include <linux/netfilter/nfnetlink_conntrack.h>
1411#include <linux/mutex.h>
1412
1426 1413
1427/* Generic function for tcp/udp/sctp/dccp and alike. This needs to be 1414/* 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 1415 * in ip_conntrack_core, since we don't want the protocols to autoload
@@ -1697,7 +1684,7 @@ int __init nf_conntrack_init(void)
1697 } 1684 }
1698 1685
1699 ret = nf_conntrack_register_cache(NF_CT_F_BASIC, "nf_conntrack:basic", 1686 ret = nf_conntrack_register_cache(NF_CT_F_BASIC, "nf_conntrack:basic",
1700 sizeof(struct nf_conn), NULL); 1687 sizeof(struct nf_conn));
1701 if (ret < 0) { 1688 if (ret < 0) {
1702 printk(KERN_ERR "Unable to create nf_conn slab cache\n"); 1689 printk(KERN_ERR "Unable to create nf_conn slab cache\n");
1703 goto err_free_hash; 1690 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..5eadf009bb15 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -2,7 +2,7 @@
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 by Pablo Neira Ayuso <pablo@eurodev.net>
8 * 8 *
@@ -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
@@ -165,15 +165,16 @@ static inline int
165ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct) 165ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct)
166{ 166{
167 struct nfattr *nest_helper; 167 struct nfattr *nest_helper;
168 const struct nf_conn_help *help = nfct_help(ct);
168 169
169 if (!ct->helper) 170 if (!help || !help->helper)
170 return 0; 171 return 0;
171 172
172 nest_helper = NFA_NEST(skb, CTA_HELP); 173 nest_helper = NFA_NEST(skb, CTA_HELP);
173 NFA_PUT(skb, CTA_HELP_NAME, strlen(ct->helper->name), ct->helper->name); 174 NFA_PUT(skb, CTA_HELP_NAME, strlen(help->helper->name), help->helper->name);
174 175
175 if (ct->helper->to_nfattr) 176 if (help->helper->to_nfattr)
176 ct->helper->to_nfattr(skb, ct); 177 help->helper->to_nfattr(skb, ct);
177 178
178 NFA_NEST_END(skb, nest_helper); 179 NFA_NEST_END(skb, nest_helper);
179 180
@@ -337,9 +338,10 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
337 group = NFNLGRP_CONNTRACK_UPDATE; 338 group = NFNLGRP_CONNTRACK_UPDATE;
338 } else 339 } else
339 return NOTIFY_DONE; 340 return NOTIFY_DONE;
340 341
341 /* FIXME: Check if there are any listeners before, don't hurt performance */ 342 if (!nfnetlink_has_listeners(group))
342 343 return NOTIFY_DONE;
344
343 skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); 345 skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
344 if (!skb) 346 if (!skb)
345 return NOTIFY_DONE; 347 return NOTIFY_DONE;
@@ -903,11 +905,17 @@ static inline int
903ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[]) 905ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
904{ 906{
905 struct nf_conntrack_helper *helper; 907 struct nf_conntrack_helper *helper;
908 struct nf_conn_help *help = nfct_help(ct);
906 char *helpname; 909 char *helpname;
907 int err; 910 int err;
908 911
909 DEBUGP("entered %s\n", __FUNCTION__); 912 DEBUGP("entered %s\n", __FUNCTION__);
910 913
914 if (!help) {
915 /* FIXME: we need to reallocate and rehash */
916 return -EBUSY;
917 }
918
911 /* don't change helper of sibling connections */ 919 /* don't change helper of sibling connections */
912 if (ct->master) 920 if (ct->master)
913 return -EINVAL; 921 return -EINVAL;
@@ -924,18 +932,18 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
924 return -EINVAL; 932 return -EINVAL;
925 } 933 }
926 934
927 if (ct->helper) { 935 if (help->helper) {
928 if (!helper) { 936 if (!helper) {
929 /* we had a helper before ... */ 937 /* we had a helper before ... */
930 nf_ct_remove_expectations(ct); 938 nf_ct_remove_expectations(ct);
931 ct->helper = NULL; 939 help->helper = NULL;
932 } else { 940 } else {
933 /* need to zero data of old helper */ 941 /* need to zero data of old helper */
934 memset(&ct->help, 0, sizeof(ct->help)); 942 memset(&help->help, 0, sizeof(help->help));
935 } 943 }
936 } 944 }
937 945
938 ct->helper = helper; 946 help->helper = helper;
939 947
940 return 0; 948 return 0;
941} 949}
@@ -1050,14 +1058,9 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
1050 ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); 1058 ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
1051#endif 1059#endif
1052 1060
1053 ct->helper = nf_ct_helper_find_get(rtuple);
1054
1055 add_timer(&ct->timeout); 1061 add_timer(&ct->timeout);
1056 nf_conntrack_hash_insert(ct); 1062 nf_conntrack_hash_insert(ct);
1057 1063
1058 if (ct->helper)
1059 nf_ct_helper_put(ct->helper);
1060
1061 DEBUGP("conntrack with id %u inserted\n", ct->id); 1064 DEBUGP("conntrack with id %u inserted\n", ct->id);
1062 return 0; 1065 return 0;
1063 1066
@@ -1417,7 +1420,8 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
1417 } 1420 }
1418 list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, 1421 list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list,
1419 list) { 1422 list) {
1420 if (exp->master->helper == h 1423 struct nf_conn_help *m_help = nfct_help(exp->master);
1424 if (m_help->helper == h
1421 && del_timer(&exp->timeout)) { 1425 && del_timer(&exp->timeout)) {
1422 nf_ct_unlink_expect(exp); 1426 nf_ct_unlink_expect(exp);
1423 nf_conntrack_expect_put(exp); 1427 nf_conntrack_expect_put(exp);
@@ -1452,6 +1456,7 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3)
1452 struct nf_conntrack_tuple_hash *h = NULL; 1456 struct nf_conntrack_tuple_hash *h = NULL;
1453 struct nf_conntrack_expect *exp; 1457 struct nf_conntrack_expect *exp;
1454 struct nf_conn *ct; 1458 struct nf_conn *ct;
1459 struct nf_conn_help *help;
1455 int err = 0; 1460 int err = 0;
1456 1461
1457 DEBUGP("entered %s\n", __FUNCTION__); 1462 DEBUGP("entered %s\n", __FUNCTION__);
@@ -1472,8 +1477,9 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3)
1472 if (!h) 1477 if (!h)
1473 return -ENOENT; 1478 return -ENOENT;
1474 ct = nf_ct_tuplehash_to_ctrack(h); 1479 ct = nf_ct_tuplehash_to_ctrack(h);
1480 help = nfct_help(ct);
1475 1481
1476 if (!ct->helper) { 1482 if (!help || !help->helper) {
1477 /* such conntrack hasn't got any helper, abort */ 1483 /* such conntrack hasn't got any helper, abort */
1478 err = -EINVAL; 1484 err = -EINVAL;
1479 goto out; 1485 goto out;
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 617599aeeead..290d5a0c559b 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -839,7 +839,6 @@ EXPORT_SYMBOL(nf_conntrack_l3proto_unregister);
839EXPORT_SYMBOL(nf_conntrack_protocol_register); 839EXPORT_SYMBOL(nf_conntrack_protocol_register);
840EXPORT_SYMBOL(nf_conntrack_protocol_unregister); 840EXPORT_SYMBOL(nf_conntrack_protocol_unregister);
841EXPORT_SYMBOL(nf_ct_invert_tuplepr); 841EXPORT_SYMBOL(nf_ct_invert_tuplepr);
842EXPORT_SYMBOL(nf_conntrack_alter_reply);
843EXPORT_SYMBOL(nf_conntrack_destroyed); 842EXPORT_SYMBOL(nf_conntrack_destroyed);
844EXPORT_SYMBOL(need_conntrack); 843EXPORT_SYMBOL(need_conntrack);
845EXPORT_SYMBOL(nf_conntrack_helper_register); 844EXPORT_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/x_tables.c b/net/netfilter/x_tables.c
index d7817afc6b96..750b92829766 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -52,6 +52,12 @@ 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(int af, struct xt_target *target)
@@ -158,18 +164,12 @@ struct xt_target *xt_find_target(int af, const char *name, u8 revision)
158} 164}
159EXPORT_SYMBOL(xt_find_target); 165EXPORT_SYMBOL(xt_find_target);
160 166
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) 167struct xt_target *xt_request_find_target(int af, const char *name, u8 revision)
168{ 168{
169 struct xt_target *target; 169 struct xt_target *target;
170 170
171 target = try_then_request_module(xt_find_target(af, name, revision), 171 target = try_then_request_module(xt_find_target(af, name, revision),
172 xt_prefix[af], name); 172 "%st_%s", xt_prefix[af], name);
173 if (IS_ERR(target) || !target) 173 if (IS_ERR(target) || !target)
174 return NULL; 174 return NULL;
175 return target; 175 return target;
@@ -237,6 +237,64 @@ int xt_find_revision(int af, const char *name, u8 revision, int target,
237} 237}
238EXPORT_SYMBOL_GPL(xt_find_revision); 238EXPORT_SYMBOL_GPL(xt_find_revision);
239 239
240int xt_check_match(const struct xt_match *match, unsigned short family,
241 unsigned int size, const char *table, unsigned int hook_mask,
242 unsigned short proto, int inv_proto)
243{
244 if (XT_ALIGN(match->matchsize) != size) {
245 printk("%s_tables: %s match: invalid size %Zu != %u\n",
246 xt_prefix[family], match->name,
247 XT_ALIGN(match->matchsize), size);
248 return -EINVAL;
249 }
250 if (match->table && strcmp(match->table, table)) {
251 printk("%s_tables: %s match: only valid in %s table, not %s\n",
252 xt_prefix[family], match->name, match->table, table);
253 return -EINVAL;
254 }
255 if (match->hooks && (hook_mask & ~match->hooks) != 0) {
256 printk("%s_tables: %s match: bad hook_mask %u\n",
257 xt_prefix[family], match->name, hook_mask);
258 return -EINVAL;
259 }
260 if (match->proto && (match->proto != proto || inv_proto)) {
261 printk("%s_tables: %s match: only valid for protocol %u\n",
262 xt_prefix[family], match->name, match->proto);
263 return -EINVAL;
264 }
265 return 0;
266}
267EXPORT_SYMBOL_GPL(xt_check_match);
268
269int xt_check_target(const struct xt_target *target, unsigned short family,
270 unsigned int size, const char *table, unsigned int hook_mask,
271 unsigned short proto, int inv_proto)
272{
273 if (XT_ALIGN(target->targetsize) != size) {
274 printk("%s_tables: %s target: invalid size %Zu != %u\n",
275 xt_prefix[family], target->name,
276 XT_ALIGN(target->targetsize), size);
277 return -EINVAL;
278 }
279 if (target->table && strcmp(target->table, table)) {
280 printk("%s_tables: %s target: only valid in %s table, not %s\n",
281 xt_prefix[family], target->name, target->table, table);
282 return -EINVAL;
283 }
284 if (target->hooks && (hook_mask & ~target->hooks) != 0) {
285 printk("%s_tables: %s target: bad hook_mask %u\n",
286 xt_prefix[family], target->name, hook_mask);
287 return -EINVAL;
288 }
289 if (target->proto && (target->proto != proto || inv_proto)) {
290 printk("%s_tables: %s target: only valid for protocol %u\n",
291 xt_prefix[family], target->name, target->proto);
292 return -EINVAL;
293 }
294 return 0;
295}
296EXPORT_SYMBOL_GPL(xt_check_target);
297
240struct xt_table_info *xt_alloc_table_info(unsigned int size) 298struct xt_table_info *xt_alloc_table_info(unsigned int size)
241{ 299{
242 struct xt_table_info *newinfo; 300 struct xt_table_info *newinfo;
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index 78ee266a12ee..3224ed87d4c7 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,22 @@ 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),
77 .me = THIS_MODULE, 50 .me = THIS_MODULE,
78}; 51};
79static struct xt_target classify6_reg = { 52static struct xt_target classify6_reg = {
80 .name = "CLASSIFY", 53 .name = "CLASSIFY",
81 .target = target, 54 .target = target,
82 .checkentry = checkentry, 55 .targetsize = sizeof(struct xt_classify_target_info),
56 .table = "mangle",
57 .hooks = (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) |
58 (1 << NF_IP_POST_ROUTING),
83 .me = THIS_MODULE, 59 .me = THIS_MODULE,
84}; 60};
85 61
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index 22506e376be5..df2486a3efd5 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,19 @@ 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 .me = THIS_MODULE
109}; 106};
107
110static struct xt_target connmark6_reg = { 108static struct xt_target connmark6_reg = {
111 .name = "CONNMARK", 109 .name = "CONNMARK",
112 .target = &target, 110 .target = target,
113 .checkentry = &checkentry, 111 .targetsize = sizeof(struct xt_connmark_target_info),
114 .me = THIS_MODULE 112 .checkentry = checkentry,
113 .me = THIS_MODULE
115}; 114};
116 115
117static int __init init(void) 116static int __init init(void)
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c
index 0c11ee9550f3..dcb5266efae0 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,18 +105,18 @@ 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,
143 .revision = 0, 122 .revision = 0,
@@ -146,6 +125,8 @@ static struct xt_target ipt_mark_reg_v0 = {
146static struct xt_target ipt_mark_reg_v1 = { 125static struct xt_target ipt_mark_reg_v1 = {
147 .name = "MARK", 126 .name = "MARK",
148 .target = target_v1, 127 .target = target_v1,
128 .targetsize = sizeof(struct xt_mark_target_info_v1),
129 .table = "mangle",
149 .checkentry = checkentry_v1, 130 .checkentry = checkentry_v1,
150 .me = THIS_MODULE, 131 .me = THIS_MODULE,
151 .revision = 1, 132 .revision = 1,
@@ -154,6 +135,8 @@ static struct xt_target ipt_mark_reg_v1 = {
154static struct xt_target ip6t_mark_reg_v0 = { 135static struct xt_target ip6t_mark_reg_v0 = {
155 .name = "MARK", 136 .name = "MARK",
156 .target = target_v0, 137 .target = target_v0,
138 .targetsize = sizeof(struct xt_mark_target_info),
139 .table = "mangle",
157 .checkentry = checkentry_v0, 140 .checkentry = checkentry_v0,
158 .me = THIS_MODULE, 141 .me = THIS_MODULE,
159 .revision = 0, 142 .revision = 0,
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index 8b76b6f8d1e4..39a963edf16b 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,41 +37,24 @@ 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),
60 .me = THIS_MODULE, 44 .me = THIS_MODULE,
61}; 45};
62 46
63static struct xt_target ip6t_NFQ_reg = { 47static struct xt_target ip6t_NFQ_reg = {
64 .name = "NFQUEUE", 48 .name = "NFQUEUE",
65 .target = target, 49 .target = target,
66 .checkentry = checkentry, 50 .targetsize = sizeof(struct xt_NFQ_info),
67 .me = THIS_MODULE, 51 .me = THIS_MODULE,
68}; 52};
69 53
70static struct xt_target arpt_NFQ_reg = { 54static struct xt_target arpt_NFQ_reg = {
71 .name = "NFQUEUE", 55 .name = "NFQUEUE",
72 .target = target, 56 .target = target,
73 .checkentry = checkentry, 57 .targetsize = sizeof(struct xt_NFQ_info),
74 .me = THIS_MODULE, 58 .me = THIS_MODULE,
75}; 59};
76 60
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index 24d477afa939..b8634e3f6169 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,38 +34,20 @@ 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 .me = THIS_MODULE,
42{
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}; 43};
63static struct xt_target notrack6_reg = { 44
64 .name = "NOTRACK", 45static struct xt_target notrack6_reg = {
65 .target = target, 46 .name = "NOTRACK",
66 .checkentry = checkentry, 47 .target = target,
67 .me = THIS_MODULE, 48 .targetsize = 0,
49 .table = "raw",
50 .me = THIS_MODULE,
68}; 51};
69 52
70static int __init init(void) 53static int __init init(void)
diff --git a/net/netfilter/xt_comment.c b/net/netfilter/xt_comment.c
index 4ba6fd65c6e9..03d9d741231c 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,17 @@ 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),
48 .me = THIS_MODULE 36 .me = THIS_MODULE
49}; 37};
50 38
51static struct xt_match comment6_match = { 39static struct xt_match comment6_match = {
52 .name = "comment", 40 .name = "comment",
53 .match = match, 41 .match = match,
54 .checkentry = checkentry, 42 .matchsize = sizeof(struct xt_comment_info),
55 .me = THIS_MODULE 43 .me = THIS_MODULE
56}; 44};
57 45
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index 150d2a4b0f71..f34ecb9485c7 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,14 +145,16 @@ 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 .me = THIS_MODULE 151 .me = THIS_MODULE
152}; 152};
153static struct xt_match connbytes6_match = { 153static struct xt_match connbytes6_match = {
154 .name = "connbytes", 154 .name = "connbytes",
155 .match = &match, 155 .match = match,
156 .checkentry = &check, 156 .checkentry = check,
157 .matchsize = sizeof(struct xt_connbytes_info),
157 .me = THIS_MODULE 158 .me = THIS_MODULE
158}; 159};
159 160
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index d06e925032da..51822471e919 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,37 +53,36 @@ 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
69 return 1; 67 return 1;
70} 68}
71 69
72static struct xt_match connmark_match = { 70static struct xt_match connmark_match = {
73 .name = "connmark", 71 .name = "connmark",
74 .match = &match, 72 .match = match,
75 .checkentry = &checkentry, 73 .matchsize = sizeof(struct xt_connmark_info),
76 .me = THIS_MODULE 74 .checkentry = checkentry,
75 .me = THIS_MODULE
77}; 76};
77
78static struct xt_match connmark6_match = { 78static struct xt_match connmark6_match = {
79 .name = "connmark", 79 .name = "connmark",
80 .match = &match, 80 .match = match,
81 .checkentry = &checkentry, 81 .matchsize = sizeof(struct xt_connmark_info),
82 .me = THIS_MODULE 82 .checkentry = checkentry,
83 .me = THIS_MODULE
83}; 84};
84 85
85
86static int __init init(void) 86static int __init init(void)
87{ 87{
88 int ret; 88 int ret;
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index ffdebc95eb95..39fc29496e00 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,10 @@ 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,
205 const void *ip,
206 void *matchinfo,
207 unsigned int matchsize,
208 unsigned int hook_mask)
209{
210 if (matchsize != XT_ALIGN(sizeof(struct xt_conntrack_info)))
211 return 0;
212
213 return 1;
214}
215
216static struct xt_match conntrack_match = { 206static struct xt_match conntrack_match = {
217 .name = "conntrack", 207 .name = "conntrack",
218 .match = &match, 208 .match = match,
219 .checkentry = &check, 209 .matchsize = sizeof(struct xt_conntrack_info),
220 .me = THIS_MODULE, 210 .me = THIS_MODULE,
221}; 211};
222 212
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
index 779f42fc9524..db6b70cdc770 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,34 @@ 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,
175 .me = THIS_MODULE, 152 .me = THIS_MODULE,
176}; 153};
177static struct xt_match dccp6_match = 154static struct xt_match dccp6_match =
178{ 155{
179 .name = "dccp", 156 .name = "dccp",
180 .match = &match, 157 .match = match,
181 .checkentry = &checkentry6, 158 .matchsize = sizeof(struct xt_dccp_info),
159 .proto = IPPROTO_DCCP,
160 .checkentry = checkentry,
182 .me = THIS_MODULE, 161 .me = THIS_MODULE,
183}; 162};
184 163
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
index 38b6715e1db4..ef8e54d40c92 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,6 +137,7 @@ 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)
@@ -140,24 +145,21 @@ static int check(const char *tablename,
140 struct xt_helper_info *info = matchinfo; 145 struct xt_helper_info *info = matchinfo;
141 146
142 info->name[29] = '\0'; 147 info->name[29] = '\0';
143
144 /* verify size */
145 if (matchsize != XT_ALIGN(sizeof(struct xt_helper_info)))
146 return 0;
147
148 return 1; 148 return 1;
149} 149}
150 150
151static struct xt_match helper_match = { 151static struct xt_match helper_match = {
152 .name = "helper", 152 .name = "helper",
153 .match = &match, 153 .match = match,
154 .checkentry = &check, 154 .matchsize = sizeof(struct xt_helper_info),
155 .checkentry = check,
155 .me = THIS_MODULE, 156 .me = THIS_MODULE,
156}; 157};
157static struct xt_match helper6_match = { 158static struct xt_match helper6_match = {
158 .name = "helper", 159 .name = "helper",
159 .match = &match, 160 .match = match,
160 .checkentry = &check, 161 .matchsize = sizeof(struct xt_helper_info),
162 .checkentry = check,
161 .me = THIS_MODULE, 163 .me = THIS_MODULE,
162}; 164};
163 165
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c
index 39c8faea63de..b9e60f041a64 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,29 +52,17 @@ 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),
70 .me = THIS_MODULE, 59 .me = THIS_MODULE,
71}; 60};
61
72static struct xt_match length6_match = { 62static struct xt_match length6_match = {
73 .name = "length", 63 .name = "length",
74 .match = &match6, 64 .match = match6,
75 .checkentry = &checkentry, 65 .matchsize = sizeof(struct xt_length_info),
76 .me = THIS_MODULE, 66 .me = THIS_MODULE,
77}; 67};
78 68
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index 15e40506bc3a..3049e6f8889e 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,12 +139,14 @@ 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 .me = THIS_MODULE, 144 .me = THIS_MODULE,
145}; 145};
146static struct xt_match limit6_reg = { 146static struct xt_match limit6_reg = {
147 .name = "limit", 147 .name = "limit",
148 .match = ipt_limit_match, 148 .match = ipt_limit_match,
149 .matchsize = sizeof(struct xt_rateinfo),
149 .checkentry = ipt_limit_checkentry, 150 .checkentry = ipt_limit_checkentry,
150 .me = THIS_MODULE, 151 .me = THIS_MODULE,
151}; 152};
diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c
index 0461dcb5fc7a..b4559a46dce8 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,37 +43,20 @@ 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),
70 .me = THIS_MODULE, 52 .me = THIS_MODULE,
71}; 53};
72static struct xt_match mac6_match = { 54static struct xt_match mac6_match = {
73 .name = "mac", 55 .name = "mac",
74 .match = &match, 56 .match = match,
75 .checkentry = &ipt_mac_checkentry, 57 .matchsize = sizeof(struct xt_mac_info),
58 .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) |
59 (1 << NF_IP_FORWARD),
76 .me = THIS_MODULE, 60 .me = THIS_MODULE,
77}; 61};
78 62
diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c
index 2a0ac62b72c8..c1a8f0f587f0 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,34 +37,33 @@ 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,
60 .me = THIS_MODULE, 59 .me = THIS_MODULE,
61}; 60};
62 61
63static struct xt_match mark6_match = { 62static struct xt_match mark6_match = {
64 .name = "mark", 63 .name = "mark",
65 .match = &match, 64 .match = match,
66 .checkentry = &checkentry, 65 .matchsize = sizeof(struct xt_mark_info),
66 .checkentry = checkentry,
67 .me = THIS_MODULE, 67 .me = THIS_MODULE,
68}; 68};
69 69
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index 19bb57c14dfe..f788e8e76254 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,17 @@ 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,
123 .me = THIS_MODULE, 124 .me = THIS_MODULE,
124}; 125};
125 126
126static struct xt_match physdev6_match = { 127static struct xt_match physdev6_match = {
127 .name = "physdev", 128 .name = "physdev",
128 .match = &match, 129 .match = match,
129 .checkentry = &checkentry, 130 .matchsize = sizeof(struct xt_physdev_info),
131 .checkentry = checkentry,
130 .me = THIS_MODULE, 132 .me = THIS_MODULE,
131}; 133};
132 134
diff --git a/net/netfilter/xt_pkttype.c b/net/netfilter/xt_pkttype.c
index ab1b2630f97d..f38638dfd139 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,32 +33,20 @@ 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),
51 .me = THIS_MODULE, 40 .me = THIS_MODULE,
52}; 41};
42
53static struct xt_match pkttype6_match = { 43static struct xt_match pkttype6_match = {
54 .name = "pkttype", 44 .name = "pkttype",
55 .match = &match, 45 .match = match,
56 .checkentry = &checkentry, 46 .matchsize = sizeof(struct xt_pkttype_info),
57 .me = THIS_MODULE, 47 .me = THIS_MODULE,
58}; 48};
59 49
60
61static int __init init(void) 50static int __init init(void)
62{ 51{
63 int ret; 52 int ret;
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
new file mode 100644
index 000000000000..1ec22082f04d
--- /dev/null
+++ b/net/netfilter/xt_policy.c
@@ -0,0 +1,209 @@
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.a4) &&
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 .me = THIS_MODULE,
176};
177
178static struct xt_match policy6_match = {
179 .name = "policy",
180 .family = AF_INET6,
181 .match = match,
182 .matchsize = sizeof(struct xt_policy_info),
183 .checkentry = checkentry,
184 .me = THIS_MODULE,
185};
186
187static int __init init(void)
188{
189 int ret;
190
191 ret = xt_register_match(AF_INET, &policy_match);
192 if (ret)
193 return ret;
194 ret = xt_register_match(AF_INET6, &policy6_match);
195 if (ret)
196 xt_unregister_match(AF_INET, &policy_match);
197 return ret;
198}
199
200static void __exit fini(void)
201{
202 xt_unregister_match(AF_INET6, &policy6_match);
203 xt_unregister_match(AF_INET, &policy_match);
204}
205
206module_init(init);
207module_exit(fini);
208MODULE_ALIAS("ipt_policy");
209MODULE_ALIAS("ip6t_policy");
diff --git a/net/netfilter/xt_realm.c b/net/netfilter/xt_realm.c
index 2b7e1781d34d..57815a07db67 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,30 +39,12 @@ 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),
65 .me = THIS_MODULE 48 .me = THIS_MODULE
66}; 49};
67 50
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index 10fbfc5ba758..f5d698ba03ca 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,47 +180,23 @@ 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 .me = THIS_MODULE
194 const struct xt_sctp_info *info;
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}; 190};
227 191
192static struct xt_match sctp6_match = {
193 .name = "sctp",
194 .match = match,
195 .matchsize = sizeof(struct xt_sctp_info),
196 .proto = IPPROTO_SCTP,
197 .checkentry = checkentry,
198 .me = THIS_MODULE
199};
228 200
229static int __init init(void) 201static int __init init(void)
230{ 202{
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c
index 39ce808d40ef..b8ec00cd51fc 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,
@@ -43,29 +44,17 @@ match(const struct sk_buff *skb,
43 return (sinfo->statemask & statebit); 44 return (sinfo->statemask & statebit);
44} 45}
45 46
46static int check(const char *tablename,
47 const void *ip,
48 void *matchinfo,
49 unsigned int matchsize,
50 unsigned int hook_mask)
51{
52 if (matchsize != XT_ALIGN(sizeof(struct xt_state_info)))
53 return 0;
54
55 return 1;
56}
57
58static struct xt_match state_match = { 47static struct xt_match state_match = {
59 .name = "state", 48 .name = "state",
60 .match = &match, 49 .match = match,
61 .checkentry = &check, 50 .matchsize = sizeof(struct xt_state_info),
62 .me = THIS_MODULE, 51 .me = THIS_MODULE,
63}; 52};
64 53
65static struct xt_match state6_match = { 54static struct xt_match state6_match = {
66 .name = "state", 55 .name = "state",
67 .match = &match, 56 .match = match,
68 .checkentry = &check, 57 .matchsize = sizeof(struct xt_state_info),
69 .me = THIS_MODULE, 58 .me = THIS_MODULE,
70}; 59};
71 60
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c
index 7c7d5c8807d6..fccbad6a7f40 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,6 +75,7 @@ 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,
80 .me = THIS_MODULE 81 .me = THIS_MODULE
@@ -82,6 +83,7 @@ static struct xt_match string_match = {
82static struct xt_match string6_match = { 83static struct xt_match string6_match = {
83 .name = "string", 84 .name = "string",
84 .match = match, 85 .match = match,
86 .matchsize = sizeof(struct xt_string_info),
85 .checkentry = checkentry, 87 .checkentry = checkentry,
86 .destroy = destroy, 88 .destroy = destroy,
87 .me = THIS_MODULE 89 .me = THIS_MODULE
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index acf7f533e9f1..4925fc98f4ae 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,19 @@ 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,
140 .me = THIS_MODULE, 101 .me = THIS_MODULE,
141}; 102};
142 103
143static struct xt_match tcpmss6_match = { 104static struct xt_match tcpmss6_match = {
144 .name = "tcpmss", 105 .name = "tcpmss",
145 .match = &match, 106 .match = match,
146 .checkentry = &checkentry6, 107 .matchsize = sizeof(struct xt_tcpmss_match_info),
108 .proto = IPPROTO_TCP,
147 .me = THIS_MODULE, 109 .me = THIS_MODULE,
148}; 110};
149 111
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
index 669c8113cc60..b5cd0dd4e41f 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,87 +188,49 @@ 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 .checkentry = tcp_checkentry,
273 .me = THIS_MODULE, 208 .me = THIS_MODULE,
274}; 209};
210
275static struct xt_match tcp6_matchstruct = { 211static struct xt_match tcp6_matchstruct = {
276 .name = "tcp", 212 .name = "tcp",
277 .match = &tcp_match, 213 .match = tcp_match,
278 .checkentry = &tcp6_checkentry, 214 .matchsize = sizeof(struct xt_tcp),
215 .proto = IPPROTO_TCP,
216 .checkentry = tcp_checkentry,
279 .me = THIS_MODULE, 217 .me = THIS_MODULE,
280}; 218};
281 219
282static struct xt_match udp_matchstruct = { 220static struct xt_match udp_matchstruct = {
283 .name = "udp", 221 .name = "udp",
284 .match = &udp_match, 222 .match = udp_match,
285 .checkentry = &udp_checkentry, 223 .matchsize = sizeof(struct xt_udp),
224 .proto = IPPROTO_UDP,
225 .checkentry = udp_checkentry,
286 .me = THIS_MODULE, 226 .me = THIS_MODULE,
287}; 227};
288static struct xt_match udp6_matchstruct = { 228static struct xt_match udp6_matchstruct = {
289 .name = "udp", 229 .name = "udp",
290 .match = &udp_match, 230 .match = udp_match,
291 .checkentry = &udp6_checkentry, 231 .matchsize = sizeof(struct xt_udp),
232 .proto = IPPROTO_UDP,
233 .checkentry = udp_checkentry,
292 .me = THIS_MODULE, 234 .me = THIS_MODULE,
293}; 235};
294 236
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/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..e3c21d5ec288 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>
@@ -348,8 +349,8 @@ static struct dentry_operations sockfs_dentry_operations = {
348/* 349/*
349 * Obtains the first available file descriptor and sets it up for use. 350 * Obtains the first available file descriptor and sets it up for use.
350 * 351 *
351 * This function creates file structure and maps it to fd space 352 * These functions create file structures and maps them to fd space
352 * of current process. On success it returns file descriptor 353 * of the current process. On success it returns file descriptor
353 * and file struct implicitly stored in sock->file. 354 * and file struct implicitly stored in sock->file.
354 * Note that another thread may close file descriptor before we return 355 * 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 356 * from this function. We use the fact that now we do not refer
@@ -362,53 +363,90 @@ static struct dentry_operations sockfs_dentry_operations = {
362 * but we take care of internal coherence yet. 363 * but we take care of internal coherence yet.
363 */ 364 */
364 365
365int sock_map_fd(struct socket *sock) 366static int sock_alloc_fd(struct file **filep)
366{ 367{
367 int fd; 368 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 369
375 fd = get_unused_fd(); 370 fd = get_unused_fd();
376 if (fd >= 0) { 371 if (likely(fd >= 0)) {
377 struct file *file = get_empty_filp(); 372 struct file *file = get_empty_filp();
378 373
379 if (!file) { 374 *filep = file;
375 if (unlikely(!file)) {
380 put_unused_fd(fd); 376 put_unused_fd(fd);
381 fd = -ENFILE; 377 return -ENFILE;
382 goto out;
383 } 378 }
379 } else
380 *filep = NULL;
381 return fd;
382}
383
384static int sock_attach_fd(struct socket *sock, struct file *file)
385{
386 struct qstr this;
387 char name[32];
388
389 this.len = sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino);
390 this.name = name;
391 this.hash = SOCK_INODE(sock)->i_ino;
384 392
385 this.len = sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino); 393 file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this);
386 this.name = name; 394 if (unlikely(!file->f_dentry))
387 this.hash = SOCK_INODE(sock)->i_ino; 395 return -ENOMEM;
396
397 file->f_dentry->d_op = &sockfs_dentry_operations;
398 d_add(file->f_dentry, SOCK_INODE(sock));
399 file->f_vfsmnt = mntget(sock_mnt);
400 file->f_mapping = file->f_dentry->d_inode->i_mapping;
401
402 sock->file = file;
403 file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops;
404 file->f_mode = FMODE_READ | FMODE_WRITE;
405 file->f_flags = O_RDWR;
406 file->f_pos = 0;
407 file->private_data = sock;
408
409 return 0;
410}
388 411
389 file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this); 412int sock_map_fd(struct socket *sock)
390 if (!file->f_dentry) { 413{
391 put_filp(file); 414 struct file *newfile;
415 int fd = sock_alloc_fd(&newfile);
416
417 if (likely(fd >= 0)) {
418 int err = sock_attach_fd(sock, newfile);
419
420 if (unlikely(err < 0)) {
421 put_filp(newfile);
392 put_unused_fd(fd); 422 put_unused_fd(fd);
393 fd = -ENOMEM; 423 return err;
394 goto out;
395 } 424 }
396 file->f_dentry->d_op = &sockfs_dentry_operations; 425 fd_install(fd, newfile);
397 d_add(file->f_dentry, SOCK_INODE(sock)); 426 }
398 file->f_vfsmnt = mntget(sock_mnt); 427 return fd;
399 file->f_mapping = file->f_dentry->d_inode->i_mapping; 428}
400 429
401 sock->file = file; 430static struct socket *sock_from_file(struct file *file, int *err)
402 file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops; 431{
403 file->f_mode = FMODE_READ | FMODE_WRITE; 432 struct inode *inode;
404 file->f_flags = O_RDWR; 433 struct socket *sock;
405 file->f_pos = 0; 434
406 file->private_data = sock; 435 if (file->f_op == &socket_file_ops)
407 fd_install(fd, file); 436 return file->private_data; /* set in sock_map_fd */
437
438 inode = file->f_dentry->d_inode;
439 if (!S_ISSOCK(inode->i_mode)) {
440 *err = -ENOTSOCK;
441 return NULL;
408 } 442 }
409 443
410out: 444 sock = SOCKET_I(inode);
411 return fd; 445 if (sock->file != file) {
446 printk(KERN_ERR "socki_lookup: socket file changed!\n");
447 sock->file = file;
448 }
449 return sock;
412} 450}
413 451
414/** 452/**
@@ -427,31 +465,31 @@ out:
427struct socket *sockfd_lookup(int fd, int *err) 465struct socket *sockfd_lookup(int fd, int *err)
428{ 466{
429 struct file *file; 467 struct file *file;
430 struct inode *inode;
431 struct socket *sock; 468 struct socket *sock;
432 469
433 if (!(file = fget(fd))) 470 if (!(file = fget(fd))) {
434 {
435 *err = -EBADF; 471 *err = -EBADF;
436 return NULL; 472 return NULL;
437 } 473 }
438 474 sock = sock_from_file(file, err);
439 if (file->f_op == &socket_file_ops) 475 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); 476 fput(file);
446 return NULL; 477 return sock;
447 } 478}
448 479
449 sock = SOCKET_I(inode); 480static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
450 if (sock->file != file) { 481{
451 printk(KERN_ERR "socki_lookup: socket file changed!\n"); 482 struct file *file;
452 sock->file = file; 483 struct socket *sock;
484
485 file = fget_light(fd, fput_needed);
486 if (file) {
487 sock = sock_from_file(file, err);
488 if (sock)
489 return sock;
490 fput_light(file, *fput_needed);
453 } 491 }
454 return sock; 492 return NULL;
455} 493}
456 494
457/** 495/**
@@ -789,36 +827,36 @@ static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf,
789 * with module unload. 827 * with module unload.
790 */ 828 */
791 829
792static DECLARE_MUTEX(br_ioctl_mutex); 830static DEFINE_MUTEX(br_ioctl_mutex);
793static int (*br_ioctl_hook)(unsigned int cmd, void __user *arg) = NULL; 831static int (*br_ioctl_hook)(unsigned int cmd, void __user *arg) = NULL;
794 832
795void brioctl_set(int (*hook)(unsigned int, void __user *)) 833void brioctl_set(int (*hook)(unsigned int, void __user *))
796{ 834{
797 down(&br_ioctl_mutex); 835 mutex_lock(&br_ioctl_mutex);
798 br_ioctl_hook = hook; 836 br_ioctl_hook = hook;
799 up(&br_ioctl_mutex); 837 mutex_unlock(&br_ioctl_mutex);
800} 838}
801EXPORT_SYMBOL(brioctl_set); 839EXPORT_SYMBOL(brioctl_set);
802 840
803static DECLARE_MUTEX(vlan_ioctl_mutex); 841static DEFINE_MUTEX(vlan_ioctl_mutex);
804static int (*vlan_ioctl_hook)(void __user *arg); 842static int (*vlan_ioctl_hook)(void __user *arg);
805 843
806void vlan_ioctl_set(int (*hook)(void __user *)) 844void vlan_ioctl_set(int (*hook)(void __user *))
807{ 845{
808 down(&vlan_ioctl_mutex); 846 mutex_lock(&vlan_ioctl_mutex);
809 vlan_ioctl_hook = hook; 847 vlan_ioctl_hook = hook;
810 up(&vlan_ioctl_mutex); 848 mutex_unlock(&vlan_ioctl_mutex);
811} 849}
812EXPORT_SYMBOL(vlan_ioctl_set); 850EXPORT_SYMBOL(vlan_ioctl_set);
813 851
814static DECLARE_MUTEX(dlci_ioctl_mutex); 852static DEFINE_MUTEX(dlci_ioctl_mutex);
815static int (*dlci_ioctl_hook)(unsigned int, void __user *); 853static int (*dlci_ioctl_hook)(unsigned int, void __user *);
816 854
817void dlci_ioctl_set(int (*hook)(unsigned int, void __user *)) 855void dlci_ioctl_set(int (*hook)(unsigned int, void __user *))
818{ 856{
819 down(&dlci_ioctl_mutex); 857 mutex_lock(&dlci_ioctl_mutex);
820 dlci_ioctl_hook = hook; 858 dlci_ioctl_hook = hook;
821 up(&dlci_ioctl_mutex); 859 mutex_unlock(&dlci_ioctl_mutex);
822} 860}
823EXPORT_SYMBOL(dlci_ioctl_set); 861EXPORT_SYMBOL(dlci_ioctl_set);
824 862
@@ -862,10 +900,10 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
862 if (!br_ioctl_hook) 900 if (!br_ioctl_hook)
863 request_module("bridge"); 901 request_module("bridge");
864 902
865 down(&br_ioctl_mutex); 903 mutex_lock(&br_ioctl_mutex);
866 if (br_ioctl_hook) 904 if (br_ioctl_hook)
867 err = br_ioctl_hook(cmd, argp); 905 err = br_ioctl_hook(cmd, argp);
868 up(&br_ioctl_mutex); 906 mutex_unlock(&br_ioctl_mutex);
869 break; 907 break;
870 case SIOCGIFVLAN: 908 case SIOCGIFVLAN:
871 case SIOCSIFVLAN: 909 case SIOCSIFVLAN:
@@ -873,10 +911,10 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
873 if (!vlan_ioctl_hook) 911 if (!vlan_ioctl_hook)
874 request_module("8021q"); 912 request_module("8021q");
875 913
876 down(&vlan_ioctl_mutex); 914 mutex_lock(&vlan_ioctl_mutex);
877 if (vlan_ioctl_hook) 915 if (vlan_ioctl_hook)
878 err = vlan_ioctl_hook(argp); 916 err = vlan_ioctl_hook(argp);
879 up(&vlan_ioctl_mutex); 917 mutex_unlock(&vlan_ioctl_mutex);
880 break; 918 break;
881 case SIOCGIFDIVERT: 919 case SIOCGIFDIVERT:
882 case SIOCSIFDIVERT: 920 case SIOCSIFDIVERT:
@@ -890,9 +928,9 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
890 request_module("dlci"); 928 request_module("dlci");
891 929
892 if (dlci_ioctl_hook) { 930 if (dlci_ioctl_hook) {
893 down(&dlci_ioctl_mutex); 931 mutex_lock(&dlci_ioctl_mutex);
894 err = dlci_ioctl_hook(cmd, argp); 932 err = dlci_ioctl_hook(cmd, argp);
895 up(&dlci_ioctl_mutex); 933 mutex_unlock(&dlci_ioctl_mutex);
896 } 934 }
897 break; 935 break;
898 default: 936 default:
@@ -1286,19 +1324,17 @@ asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
1286{ 1324{
1287 struct socket *sock; 1325 struct socket *sock;
1288 char address[MAX_SOCK_ADDR]; 1326 char address[MAX_SOCK_ADDR];
1289 int err; 1327 int err, fput_needed;
1290 1328
1291 if((sock = sockfd_lookup(fd,&err))!=NULL) 1329 if((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL)
1292 { 1330 {
1293 if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) { 1331 if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) {
1294 err = security_socket_bind(sock, (struct sockaddr *)address, addrlen); 1332 err = security_socket_bind(sock, (struct sockaddr *)address, addrlen);
1295 if (err) { 1333 if (!err)
1296 sockfd_put(sock); 1334 err = sock->ops->bind(sock,
1297 return err; 1335 (struct sockaddr *)address, addrlen);
1298 }
1299 err = sock->ops->bind(sock, (struct sockaddr *)address, addrlen);
1300 } 1336 }
1301 sockfd_put(sock); 1337 fput_light(sock->file, fput_needed);
1302 } 1338 }
1303 return err; 1339 return err;
1304} 1340}
@@ -1315,20 +1351,17 @@ int sysctl_somaxconn = SOMAXCONN;
1315asmlinkage long sys_listen(int fd, int backlog) 1351asmlinkage long sys_listen(int fd, int backlog)
1316{ 1352{
1317 struct socket *sock; 1353 struct socket *sock;
1318 int err; 1354 int err, fput_needed;
1319 1355
1320 if ((sock = sockfd_lookup(fd, &err)) != NULL) { 1356 if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
1321 if ((unsigned) backlog > sysctl_somaxconn) 1357 if ((unsigned) backlog > sysctl_somaxconn)
1322 backlog = sysctl_somaxconn; 1358 backlog = sysctl_somaxconn;
1323 1359
1324 err = security_socket_listen(sock, backlog); 1360 err = security_socket_listen(sock, backlog);
1325 if (err) { 1361 if (!err)
1326 sockfd_put(sock); 1362 err = sock->ops->listen(sock, backlog);
1327 return err;
1328 }
1329 1363
1330 err=sock->ops->listen(sock, backlog); 1364 fput_light(sock->file, fput_needed);
1331 sockfd_put(sock);
1332 } 1365 }
1333 return err; 1366 return err;
1334} 1367}
@@ -1349,10 +1382,11 @@ asmlinkage long sys_listen(int fd, int backlog)
1349asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen) 1382asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen)
1350{ 1383{
1351 struct socket *sock, *newsock; 1384 struct socket *sock, *newsock;
1352 int err, len; 1385 struct file *newfile;
1386 int err, len, newfd, fput_needed;
1353 char address[MAX_SOCK_ADDR]; 1387 char address[MAX_SOCK_ADDR];
1354 1388
1355 sock = sockfd_lookup(fd, &err); 1389 sock = sockfd_lookup_light(fd, &err, &fput_needed);
1356 if (!sock) 1390 if (!sock)
1357 goto out; 1391 goto out;
1358 1392
@@ -1369,35 +1403,48 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _
1369 */ 1403 */
1370 __module_get(newsock->ops->owner); 1404 __module_get(newsock->ops->owner);
1371 1405
1406 newfd = sock_alloc_fd(&newfile);
1407 if (unlikely(newfd < 0)) {
1408 err = newfd;
1409 goto out_release;
1410 }
1411
1412 err = sock_attach_fd(newsock, newfile);
1413 if (err < 0)
1414 goto out_fd;
1415
1372 err = security_socket_accept(sock, newsock); 1416 err = security_socket_accept(sock, newsock);
1373 if (err) 1417 if (err)
1374 goto out_release; 1418 goto out_fd;
1375 1419
1376 err = sock->ops->accept(sock, newsock, sock->file->f_flags); 1420 err = sock->ops->accept(sock, newsock, sock->file->f_flags);
1377 if (err < 0) 1421 if (err < 0)
1378 goto out_release; 1422 goto out_fd;
1379 1423
1380 if (upeer_sockaddr) { 1424 if (upeer_sockaddr) {
1381 if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) { 1425 if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) {
1382 err = -ECONNABORTED; 1426 err = -ECONNABORTED;
1383 goto out_release; 1427 goto out_fd;
1384 } 1428 }
1385 err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen); 1429 err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen);
1386 if (err < 0) 1430 if (err < 0)
1387 goto out_release; 1431 goto out_fd;
1388 } 1432 }
1389 1433
1390 /* File flags are not inherited via accept() unlike another OSes. */ 1434 /* File flags are not inherited via accept() unlike another OSes. */
1391 1435
1392 if ((err = sock_map_fd(newsock)) < 0) 1436 fd_install(newfd, newfile);
1393 goto out_release; 1437 err = newfd;
1394 1438
1395 security_socket_post_accept(sock, newsock); 1439 security_socket_post_accept(sock, newsock);
1396 1440
1397out_put: 1441out_put:
1398 sockfd_put(sock); 1442 fput_light(sock->file, fput_needed);
1399out: 1443out:
1400 return err; 1444 return err;
1445out_fd:
1446 put_filp(newfile);
1447 put_unused_fd(newfd);
1401out_release: 1448out_release:
1402 sock_release(newsock); 1449 sock_release(newsock);
1403 goto out_put; 1450 goto out_put;
@@ -1420,9 +1467,9 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrl
1420{ 1467{
1421 struct socket *sock; 1468 struct socket *sock;
1422 char address[MAX_SOCK_ADDR]; 1469 char address[MAX_SOCK_ADDR];
1423 int err; 1470 int err, fput_needed;
1424 1471
1425 sock = sockfd_lookup(fd, &err); 1472 sock = sockfd_lookup_light(fd, &err, &fput_needed);
1426 if (!sock) 1473 if (!sock)
1427 goto out; 1474 goto out;
1428 err = move_addr_to_kernel(uservaddr, addrlen, address); 1475 err = move_addr_to_kernel(uservaddr, addrlen, address);
@@ -1436,7 +1483,7 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrl
1436 err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen, 1483 err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen,
1437 sock->file->f_flags); 1484 sock->file->f_flags);
1438out_put: 1485out_put:
1439 sockfd_put(sock); 1486 fput_light(sock->file, fput_needed);
1440out: 1487out:
1441 return err; 1488 return err;
1442} 1489}
@@ -1450,9 +1497,9 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int _
1450{ 1497{
1451 struct socket *sock; 1498 struct socket *sock;
1452 char address[MAX_SOCK_ADDR]; 1499 char address[MAX_SOCK_ADDR];
1453 int len, err; 1500 int len, err, fput_needed;
1454 1501
1455 sock = sockfd_lookup(fd, &err); 1502 sock = sockfd_lookup_light(fd, &err, &fput_needed);
1456 if (!sock) 1503 if (!sock)
1457 goto out; 1504 goto out;
1458 1505
@@ -1466,7 +1513,7 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int _
1466 err = move_addr_to_user(address, len, usockaddr, usockaddr_len); 1513 err = move_addr_to_user(address, len, usockaddr, usockaddr_len);
1467 1514
1468out_put: 1515out_put:
1469 sockfd_put(sock); 1516 fput_light(sock->file, fput_needed);
1470out: 1517out:
1471 return err; 1518 return err;
1472} 1519}
@@ -1480,20 +1527,19 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int _
1480{ 1527{
1481 struct socket *sock; 1528 struct socket *sock;
1482 char address[MAX_SOCK_ADDR]; 1529 char address[MAX_SOCK_ADDR];
1483 int len, err; 1530 int len, err, fput_needed;
1484 1531
1485 if ((sock = sockfd_lookup(fd, &err))!=NULL) 1532 if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
1486 {
1487 err = security_socket_getpeername(sock); 1533 err = security_socket_getpeername(sock);
1488 if (err) { 1534 if (err) {
1489 sockfd_put(sock); 1535 fput_light(sock->file, fput_needed);
1490 return err; 1536 return err;
1491 } 1537 }
1492 1538
1493 err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1); 1539 err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1);
1494 if (!err) 1540 if (!err)
1495 err=move_addr_to_user(address,len, usockaddr, usockaddr_len); 1541 err=move_addr_to_user(address,len, usockaddr, usockaddr_len);
1496 sockfd_put(sock); 1542 fput_light(sock->file, fput_needed);
1497 } 1543 }
1498 return err; 1544 return err;
1499} 1545}
@@ -1512,10 +1558,16 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag
1512 int err; 1558 int err;
1513 struct msghdr msg; 1559 struct msghdr msg;
1514 struct iovec iov; 1560 struct iovec iov;
1515 1561 int fput_needed;
1516 sock = sockfd_lookup(fd, &err); 1562 struct file *sock_file;
1563
1564 sock_file = fget_light(fd, &fput_needed);
1565 if (!sock_file)
1566 return -EBADF;
1567
1568 sock = sock_from_file(sock_file, &err);
1517 if (!sock) 1569 if (!sock)
1518 goto out; 1570 goto out_put;
1519 iov.iov_base=buff; 1571 iov.iov_base=buff;
1520 iov.iov_len=len; 1572 iov.iov_len=len;
1521 msg.msg_name=NULL; 1573 msg.msg_name=NULL;
@@ -1524,8 +1576,7 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag
1524 msg.msg_control=NULL; 1576 msg.msg_control=NULL;
1525 msg.msg_controllen=0; 1577 msg.msg_controllen=0;
1526 msg.msg_namelen=0; 1578 msg.msg_namelen=0;
1527 if(addr) 1579 if (addr) {
1528 {
1529 err = move_addr_to_kernel(addr, addr_len, address); 1580 err = move_addr_to_kernel(addr, addr_len, address);
1530 if (err < 0) 1581 if (err < 0)
1531 goto out_put; 1582 goto out_put;
@@ -1538,8 +1589,7 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag
1538 err = sock_sendmsg(sock, &msg, len); 1589 err = sock_sendmsg(sock, &msg, len);
1539 1590
1540out_put: 1591out_put:
1541 sockfd_put(sock); 1592 fput_light(sock_file, fput_needed);
1542out:
1543 return err; 1593 return err;
1544} 1594}
1545 1595
@@ -1566,8 +1616,14 @@ asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned f
1566 struct msghdr msg; 1616 struct msghdr msg;
1567 char address[MAX_SOCK_ADDR]; 1617 char address[MAX_SOCK_ADDR];
1568 int err,err2; 1618 int err,err2;
1619 struct file *sock_file;
1620 int fput_needed;
1569 1621
1570 sock = sockfd_lookup(fd, &err); 1622 sock_file = fget_light(fd, &fput_needed);
1623 if (!sock_file)
1624 return -EBADF;
1625
1626 sock = sock_from_file(sock_file, &err);
1571 if (!sock) 1627 if (!sock)
1572 goto out; 1628 goto out;
1573 1629
@@ -1589,8 +1645,8 @@ asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned f
1589 if(err2<0) 1645 if(err2<0)
1590 err=err2; 1646 err=err2;
1591 } 1647 }
1592 sockfd_put(sock);
1593out: 1648out:
1649 fput_light(sock_file, fput_needed);
1594 return err; 1650 return err;
1595} 1651}
1596 1652
@@ -1610,25 +1666,24 @@ asmlinkage long sys_recv(int fd, void __user * ubuf, size_t size, unsigned flags
1610 1666
1611asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen) 1667asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen)
1612{ 1668{
1613 int err; 1669 int err, fput_needed;
1614 struct socket *sock; 1670 struct socket *sock;
1615 1671
1616 if (optlen < 0) 1672 if (optlen < 0)
1617 return -EINVAL; 1673 return -EINVAL;
1618 1674
1619 if ((sock = sockfd_lookup(fd, &err))!=NULL) 1675 if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL)
1620 { 1676 {
1621 err = security_socket_setsockopt(sock,level,optname); 1677 err = security_socket_setsockopt(sock,level,optname);
1622 if (err) { 1678 if (err)
1623 sockfd_put(sock); 1679 goto out_put;
1624 return err;
1625 }
1626 1680
1627 if (level == SOL_SOCKET) 1681 if (level == SOL_SOCKET)
1628 err=sock_setsockopt(sock,level,optname,optval,optlen); 1682 err=sock_setsockopt(sock,level,optname,optval,optlen);
1629 else 1683 else
1630 err=sock->ops->setsockopt(sock, level, optname, optval, optlen); 1684 err=sock->ops->setsockopt(sock, level, optname, optval, optlen);
1631 sockfd_put(sock); 1685out_put:
1686 fput_light(sock->file, fput_needed);
1632 } 1687 }
1633 return err; 1688 return err;
1634} 1689}
@@ -1640,23 +1695,20 @@ asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optv
1640 1695
1641asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen) 1696asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen)
1642{ 1697{
1643 int err; 1698 int err, fput_needed;
1644 struct socket *sock; 1699 struct socket *sock;
1645 1700
1646 if ((sock = sockfd_lookup(fd, &err))!=NULL) 1701 if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
1647 { 1702 err = security_socket_getsockopt(sock, level, optname);
1648 err = security_socket_getsockopt(sock, level, 1703 if (err)
1649 optname); 1704 goto out_put;
1650 if (err) {
1651 sockfd_put(sock);
1652 return err;
1653 }
1654 1705
1655 if (level == SOL_SOCKET) 1706 if (level == SOL_SOCKET)
1656 err=sock_getsockopt(sock,level,optname,optval,optlen); 1707 err=sock_getsockopt(sock,level,optname,optval,optlen);
1657 else 1708 else
1658 err=sock->ops->getsockopt(sock, level, optname, optval, optlen); 1709 err=sock->ops->getsockopt(sock, level, optname, optval, optlen);
1659 sockfd_put(sock); 1710out_put:
1711 fput_light(sock->file, fput_needed);
1660 } 1712 }
1661 return err; 1713 return err;
1662} 1714}
@@ -1668,19 +1720,15 @@ asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optv
1668 1720
1669asmlinkage long sys_shutdown(int fd, int how) 1721asmlinkage long sys_shutdown(int fd, int how)
1670{ 1722{
1671 int err; 1723 int err, fput_needed;
1672 struct socket *sock; 1724 struct socket *sock;
1673 1725
1674 if ((sock = sockfd_lookup(fd, &err))!=NULL) 1726 if ((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL)
1675 { 1727 {
1676 err = security_socket_shutdown(sock, how); 1728 err = security_socket_shutdown(sock, how);
1677 if (err) { 1729 if (!err)
1678 sockfd_put(sock); 1730 err = sock->ops->shutdown(sock, how);
1679 return err; 1731 fput_light(sock->file, fput_needed);
1680 }
1681
1682 err=sock->ops->shutdown(sock, how);
1683 sockfd_put(sock);
1684 } 1732 }
1685 return err; 1733 return err;
1686} 1734}
@@ -1709,6 +1757,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
1709 unsigned char *ctl_buf = ctl; 1757 unsigned char *ctl_buf = ctl;
1710 struct msghdr msg_sys; 1758 struct msghdr msg_sys;
1711 int err, ctl_len, iov_size, total_len; 1759 int err, ctl_len, iov_size, total_len;
1760 int fput_needed;
1712 1761
1713 err = -EFAULT; 1762 err = -EFAULT;
1714 if (MSG_CMSG_COMPAT & flags) { 1763 if (MSG_CMSG_COMPAT & flags) {
@@ -1717,7 +1766,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))) 1766 } else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
1718 return -EFAULT; 1767 return -EFAULT;
1719 1768
1720 sock = sockfd_lookup(fd, &err); 1769 sock = sockfd_lookup_light(fd, &err, &fput_needed);
1721 if (!sock) 1770 if (!sock)
1722 goto out; 1771 goto out;
1723 1772
@@ -1785,7 +1834,7 @@ out_freeiov:
1785 if (iov != iovstack) 1834 if (iov != iovstack)
1786 sock_kfree_s(sock->sk, iov, iov_size); 1835 sock_kfree_s(sock->sk, iov, iov_size);
1787out_put: 1836out_put:
1788 sockfd_put(sock); 1837 fput_light(sock->file, fput_needed);
1789out: 1838out:
1790 return err; 1839 return err;
1791} 1840}
@@ -1803,6 +1852,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flag
1803 struct msghdr msg_sys; 1852 struct msghdr msg_sys;
1804 unsigned long cmsg_ptr; 1853 unsigned long cmsg_ptr;
1805 int err, iov_size, total_len, len; 1854 int err, iov_size, total_len, len;
1855 int fput_needed;
1806 1856
1807 /* kernel mode address */ 1857 /* kernel mode address */
1808 char addr[MAX_SOCK_ADDR]; 1858 char addr[MAX_SOCK_ADDR];
@@ -1818,7 +1868,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))) 1868 if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
1819 return -EFAULT; 1869 return -EFAULT;
1820 1870
1821 sock = sockfd_lookup(fd, &err); 1871 sock = sockfd_lookup_light(fd, &err, &fput_needed);
1822 if (!sock) 1872 if (!sock)
1823 goto out; 1873 goto out;
1824 1874
@@ -1885,7 +1935,7 @@ out_freeiov:
1885 if (iov != iovstack) 1935 if (iov != iovstack)
1886 sock_kfree_s(sock->sk, iov, iov_size); 1936 sock_kfree_s(sock->sk, iov, iov_size);
1887out_put: 1937out_put:
1888 sockfd_put(sock); 1938 fput_light(sock->file, fput_needed);
1889out: 1939out:
1890 return err; 1940 return err;
1891} 1941}
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 e838d042f7f5..dff07795bd16 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;
67static struct workqueue_struct *rpciod_workqueue; 68static struct workqueue_struct *rpciod_workqueue;
68 69
@@ -1047,7 +1048,7 @@ rpciod_up(void)
1047 struct workqueue_struct *wq; 1048 struct workqueue_struct *wq;
1048 int error = 0; 1049 int error = 0;
1049 1050
1050 down(&rpciod_sema); 1051 mutex_lock(&rpciod_mutex);
1051 dprintk("rpciod_up: users %d\n", rpciod_users); 1052 dprintk("rpciod_up: users %d\n", rpciod_users);
1052 rpciod_users++; 1053 rpciod_users++;
1053 if (rpciod_workqueue) 1054 if (rpciod_workqueue)
@@ -1070,14 +1071,14 @@ rpciod_up(void)
1070 rpciod_workqueue = wq; 1071 rpciod_workqueue = wq;
1071 error = 0; 1072 error = 0;
1072out: 1073out:
1073 up(&rpciod_sema); 1074 mutex_unlock(&rpciod_mutex);
1074 return error; 1075 return error;
1075} 1076}
1076 1077
1077void 1078void
1078rpciod_down(void) 1079rpciod_down(void)
1079{ 1080{
1080 down(&rpciod_sema); 1081 mutex_lock(&rpciod_mutex);
1081 dprintk("rpciod_down sema %d\n", rpciod_users); 1082 dprintk("rpciod_down sema %d\n", rpciod_users);
1082 if (rpciod_users) { 1083 if (rpciod_users) {
1083 if (--rpciod_users) 1084 if (--rpciod_users)
@@ -1094,7 +1095,7 @@ rpciod_down(void)
1094 destroy_workqueue(rpciod_workqueue); 1095 destroy_workqueue(rpciod_workqueue);
1095 rpciod_workqueue = NULL; 1096 rpciod_workqueue = NULL;
1096 out: 1097 out:
1097 up(&rpciod_sema); 1098 mutex_unlock(&rpciod_mutex);
1098} 1099}
1099 1100
1100#ifdef RPC_DEBUG 1101#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/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
diff --git a/security/dummy.c b/security/dummy.c
index f1a5bd98bf10..a678f094b72d 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -763,8 +763,14 @@ static int dummy_socket_sock_rcv_skb (struct sock *sk, struct sk_buff *skb)
763 return 0; 763 return 0;
764} 764}
765 765
766static int dummy_socket_getpeersec(struct socket *sock, char __user *optval, 766static int dummy_socket_getpeersec_stream(struct socket *sock, char __user *optval,
767 int __user *optlen, unsigned len) 767 int __user *optlen, unsigned len)
768{
769 return -ENOPROTOOPT;
770}
771
772static int dummy_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata,
773 u32 *seclen)
768{ 774{
769 return -ENOPROTOOPT; 775 return -ENOPROTOOPT;
770} 776}
@@ -1002,7 +1008,8 @@ void security_fixup_ops (struct security_operations *ops)
1002 set_to_dummy_if_null(ops, socket_getsockopt); 1008 set_to_dummy_if_null(ops, socket_getsockopt);
1003 set_to_dummy_if_null(ops, socket_shutdown); 1009 set_to_dummy_if_null(ops, socket_shutdown);
1004 set_to_dummy_if_null(ops, socket_sock_rcv_skb); 1010 set_to_dummy_if_null(ops, socket_sock_rcv_skb);
1005 set_to_dummy_if_null(ops, socket_getpeersec); 1011 set_to_dummy_if_null(ops, socket_getpeersec_stream);
1012 set_to_dummy_if_null(ops, socket_getpeersec_dgram);
1006 set_to_dummy_if_null(ops, sk_alloc_security); 1013 set_to_dummy_if_null(ops, sk_alloc_security);
1007 set_to_dummy_if_null(ops, sk_free_security); 1014 set_to_dummy_if_null(ops, sk_free_security);
1008 set_to_dummy_if_null(ops, sk_getsid); 1015 set_to_dummy_if_null(ops, sk_getsid);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b65c201e9ff5..5b16196f2823 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3318,24 +3318,38 @@ out:
3318 return err; 3318 return err;
3319} 3319}
3320 3320
3321static int selinux_socket_getpeersec(struct socket *sock, char __user *optval, 3321static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
3322 int __user *optlen, unsigned len) 3322 int __user *optlen, unsigned len)
3323{ 3323{
3324 int err = 0; 3324 int err = 0;
3325 char *scontext; 3325 char *scontext;
3326 u32 scontext_len; 3326 u32 scontext_len;
3327 struct sk_security_struct *ssec; 3327 struct sk_security_struct *ssec;
3328 struct inode_security_struct *isec; 3328 struct inode_security_struct *isec;
3329 u32 peer_sid = 0;
3329 3330
3330 isec = SOCK_INODE(sock)->i_security; 3331 isec = SOCK_INODE(sock)->i_security;
3331 if (isec->sclass != SECCLASS_UNIX_STREAM_SOCKET) { 3332
3333 /* if UNIX_STREAM check peer_sid, if TCP check dst for labelled sa */
3334 if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET) {
3335 ssec = sock->sk->sk_security;
3336 peer_sid = ssec->peer_sid;
3337 }
3338 else if (isec->sclass == SECCLASS_TCP_SOCKET) {
3339 peer_sid = selinux_socket_getpeer_stream(sock->sk);
3340
3341 if (peer_sid == SECSID_NULL) {
3342 err = -ENOPROTOOPT;
3343 goto out;
3344 }
3345 }
3346 else {
3332 err = -ENOPROTOOPT; 3347 err = -ENOPROTOOPT;
3333 goto out; 3348 goto out;
3334 } 3349 }
3335 3350
3336 ssec = sock->sk->sk_security; 3351 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
3337 3352
3338 err = security_sid_to_context(ssec->peer_sid, &scontext, &scontext_len);
3339 if (err) 3353 if (err)
3340 goto out; 3354 goto out;
3341 3355
@@ -3356,6 +3370,23 @@ out:
3356 return err; 3370 return err;
3357} 3371}
3358 3372
3373static int selinux_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, u32 *seclen)
3374{
3375 int err = 0;
3376 u32 peer_sid = selinux_socket_getpeer_dgram(skb);
3377
3378 if (peer_sid == SECSID_NULL)
3379 return -EINVAL;
3380
3381 err = security_sid_to_context(peer_sid, secdata, seclen);
3382 if (err)
3383 return err;
3384
3385 return 0;
3386}
3387
3388
3389
3359static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) 3390static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
3360{ 3391{
3361 return sk_alloc_security(sk, family, priority); 3392 return sk_alloc_security(sk, family, priority);
@@ -4344,7 +4375,8 @@ static struct security_operations selinux_ops = {
4344 .socket_setsockopt = selinux_socket_setsockopt, 4375 .socket_setsockopt = selinux_socket_setsockopt,
4345 .socket_shutdown = selinux_socket_shutdown, 4376 .socket_shutdown = selinux_socket_shutdown,
4346 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb, 4377 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
4347 .socket_getpeersec = selinux_socket_getpeersec, 4378 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
4379 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
4348 .sk_alloc_security = selinux_sk_alloc_security, 4380 .sk_alloc_security = selinux_sk_alloc_security,
4349 .sk_free_security = selinux_sk_free_security, 4381 .sk_free_security = selinux_sk_free_security,
4350 .sk_getsid = selinux_sk_getsid_security, 4382 .sk_getsid = selinux_sk_getsid_security,
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 8e87996c6dd5..c10f1fc41502 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -39,6 +39,8 @@ static inline u32 selinux_no_sk_sid(struct flowi *fl)
39#ifdef CONFIG_SECURITY_NETWORK_XFRM 39#ifdef CONFIG_SECURITY_NETWORK_XFRM
40int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb); 40int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb);
41int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb); 41int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb);
42u32 selinux_socket_getpeer_stream(struct sock *sk);
43u32 selinux_socket_getpeer_dgram(struct sk_buff *skb);
42#else 44#else
43static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb) 45static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb)
44{ 46{
@@ -49,6 +51,16 @@ static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb)
49{ 51{
50 return NF_ACCEPT; 52 return NF_ACCEPT;
51} 53}
54
55static inline int selinux_socket_getpeer_stream(struct sock *sk)
56{
57 return SECSID_NULL;
58}
59
60static inline int selinux_socket_getpeer_dgram(struct sk_buff *skb)
61{
62 return SECSID_NULL;
63}
52#endif 64#endif
53 65
54#endif /* _SELINUX_XFRM_H_ */ 66#endif /* _SELINUX_XFRM_H_ */
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index 69b9329b2054..85e399259832 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -88,8 +88,15 @@ static struct nlmsg_perm nlmsg_xfrm_perms[] =
88 { XFRM_MSG_DELPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, 88 { XFRM_MSG_DELPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
89 { XFRM_MSG_GETPOLICY, NETLINK_XFRM_SOCKET__NLMSG_READ }, 89 { XFRM_MSG_GETPOLICY, NETLINK_XFRM_SOCKET__NLMSG_READ },
90 { XFRM_MSG_ALLOCSPI, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, 90 { XFRM_MSG_ALLOCSPI, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
91 { XFRM_MSG_ACQUIRE, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
92 { XFRM_MSG_EXPIRE, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
91 { XFRM_MSG_UPDPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, 93 { XFRM_MSG_UPDPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
92 { XFRM_MSG_UPDSA, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, 94 { XFRM_MSG_UPDSA, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
95 { XFRM_MSG_POLEXPIRE, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
96 { XFRM_MSG_FLUSHSA, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
97 { XFRM_MSG_FLUSHPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
98 { XFRM_MSG_NEWAE, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
99 { XFRM_MSG_GETAE, NETLINK_XFRM_SOCKET__NLMSG_READ },
93}; 100};
94 101
95static struct nlmsg_perm nlmsg_audit_perms[] = 102static struct nlmsg_perm nlmsg_audit_perms[] =
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index b2af7ca496c1..dfab6c886698 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -225,6 +225,74 @@ void selinux_xfrm_state_free(struct xfrm_state *x)
225} 225}
226 226
227/* 227/*
228 * SELinux internal function to retrieve the context of a connected
229 * (sk->sk_state == TCP_ESTABLISHED) TCP socket based on its security
230 * association used to connect to the remote socket.
231 *
232 * Retrieve via getsockopt SO_PEERSEC.
233 */
234u32 selinux_socket_getpeer_stream(struct sock *sk)
235{
236 struct dst_entry *dst, *dst_test;
237 u32 peer_sid = SECSID_NULL;
238
239 if (sk->sk_state != TCP_ESTABLISHED)
240 goto out;
241
242 dst = sk_dst_get(sk);
243 if (!dst)
244 goto out;
245
246 for (dst_test = dst; dst_test != 0;
247 dst_test = dst_test->child) {
248 struct xfrm_state *x = dst_test->xfrm;
249
250 if (x && selinux_authorizable_xfrm(x)) {
251 struct xfrm_sec_ctx *ctx = x->security;
252 peer_sid = ctx->ctx_sid;
253 break;
254 }
255 }
256 dst_release(dst);
257
258out:
259 return peer_sid;
260}
261
262/*
263 * SELinux internal function to retrieve the context of a UDP packet
264 * based on its security association used to connect to the remote socket.
265 *
266 * Retrieve via setsockopt IP_PASSSEC and recvmsg with control message
267 * type SCM_SECURITY.
268 */
269u32 selinux_socket_getpeer_dgram(struct sk_buff *skb)
270{
271 struct sec_path *sp;
272
273 if (skb == NULL)
274 return SECSID_NULL;
275
276 if (skb->sk->sk_protocol != IPPROTO_UDP)
277 return SECSID_NULL;
278
279 sp = skb->sp;
280 if (sp) {
281 int i;
282
283 for (i = sp->len-1; i >= 0; i--) {
284 struct xfrm_state *x = sp->x[i].xvec;
285 if (selinux_authorizable_xfrm(x)) {
286 struct xfrm_sec_ctx *ctx = x->security;
287 return ctx->ctx_sid;
288 }
289 }
290 }
291
292 return SECSID_NULL;
293}
294
295/*
228 * LSM hook that controls access to unlabelled packets. If 296 * LSM hook that controls access to unlabelled packets. If
229 * a xfrm_state is authorizable (defined by macro) then it was 297 * a xfrm_state is authorizable (defined by macro) then it was
230 * already authorized by the IPSec process. If not, then 298 * already authorized by the IPSec process. If not, then