summaryrefslogtreecommitdiff
path: root/include/net
diff options
context:
space:
mode:
Diffstat (limited to 'include/net')
-rw-r--r--include/net/9p/9p.h577
-rw-r--r--include/net/9p/client.h271
-rw-r--r--include/net/9p/transport.h67
-rw-r--r--include/net/act_api.h126
-rw-r--r--include/net/activity_stats.h25
-rw-r--r--include/net/addrconf.h285
-rw-r--r--include/net/af_ieee802154.h62
-rw-r--r--include/net/af_rxrpc.h54
-rw-r--r--include/net/af_unix.h78
-rw-r--r--include/net/ah.h25
-rw-r--r--include/net/arp.h59
-rw-r--r--include/net/atmclip.h52
-rw-r--r--include/net/ax25.h451
-rw-r--r--include/net/ax88796.h31
-rw-r--r--include/net/bluetooth/bluetooth.h290
-rw-r--r--include/net/bluetooth/hci.h1441
-rw-r--r--include/net/bluetooth/hci_core.h1080
-rw-r--r--include/net/bluetooth/hci_mon.h51
-rw-r--r--include/net/bluetooth/l2cap.h865
-rw-r--r--include/net/bluetooth/mgmt.h462
-rw-r--r--include/net/bluetooth/rfcomm.h372
-rw-r--r--include/net/bluetooth/sco.h81
-rw-r--r--include/net/bluetooth/smp.h146
-rw-r--r--include/net/caif/caif_dev.h128
-rw-r--r--include/net/caif/caif_device.h55
-rw-r--r--include/net/caif/caif_hsi.h161
-rw-r--r--include/net/caif/caif_layer.h279
-rw-r--r--include/net/caif/caif_shm.h26
-rw-r--r--include/net/caif/caif_spi.h155
-rw-r--r--include/net/caif/cfcnfg.h90
-rw-r--r--include/net/caif/cfctrl.h130
-rw-r--r--include/net/caif/cffrml.h21
-rw-r--r--include/net/caif/cfmuxl.h20
-rw-r--r--include/net/caif/cfpkt.h198
-rw-r--r--include/net/caif/cfserl.h12
-rw-r--r--include/net/caif/cfsrvl.h65
-rw-r--r--include/net/cfg80211-wext.h55
-rw-r--r--include/net/cfg80211.h3399
-rw-r--r--include/net/checksum.h121
-rw-r--r--include/net/cipso_ipv4.h319
-rw-r--r--include/net/cls_cgroup.h70
-rw-r--r--include/net/compat.h63
-rw-r--r--include/net/datalink.h18
-rw-r--r--include/net/dcbevent.h49
-rw-r--r--include/net/dcbnl.h102
-rw-r--r--include/net/dn.h233
-rw-r--r--include/net/dn_dev.h198
-rw-r--r--include/net/dn_fib.h184
-rw-r--r--include/net/dn_neigh.h28
-rw-r--r--include/net/dn_nsp.h201
-rw-r--r--include/net/dn_route.h117
-rw-r--r--include/net/dsa.h201
-rw-r--r--include/net/dsfield.h54
-rw-r--r--include/net/dst.h473
-rw-r--r--include/net/dst_ops.h68
-rw-r--r--include/net/esp.h25
-rw-r--r--include/net/ethoc.h22
-rw-r--r--include/net/fib_rules.h119
-rw-r--r--include/net/flow.h226
-rw-r--r--include/net/flow_keys.h16
-rw-r--r--include/net/garp.h130
-rw-r--r--include/net/gen_stats.h50
-rw-r--r--include/net/genetlink.h317
-rw-r--r--include/net/gre.h18
-rw-r--r--include/net/icmp.h48
-rw-r--r--include/net/ieee80211_radiotap.h283
-rw-r--r--include/net/ieee802154.h166
-rw-r--r--include/net/ieee802154_netdev.h121
-rw-r--r--include/net/if_inet6.h304
-rw-r--r--include/net/inet6_connection_sock.h45
-rw-r--r--include/net/inet6_hashtables.h114
-rw-r--r--include/net/inet_common.h44
-rw-r--r--include/net/inet_connection_sock.h339
-rw-r--r--include/net/inet_ecn.h148
-rw-r--r--include/net/inet_frag.h74
-rw-r--r--include/net/inet_hashtables.h402
-rw-r--r--include/net/inet_sock.h253
-rw-r--r--include/net/inet_timewait_sock.h229
-rw-r--r--include/net/inetpeer.h129
-rw-r--r--include/net/ip.h475
-rw-r--r--include/net/ip6_checksum.h94
-rw-r--r--include/net/ip6_fib.h288
-rw-r--r--include/net/ip6_route.h195
-rw-r--r--include/net/ip6_tunnel.h32
-rw-r--r--include/net/ip_fib.h285
-rw-r--r--include/net/ip_vs.h1426
-rw-r--r--include/net/ipcomp.h29
-rw-r--r--include/net/ipconfig.h25
-rw-r--r--include/net/ipip.h67
-rw-r--r--include/net/ipv6.h688
-rw-r--r--include/net/ipx.h160
-rw-r--r--include/net/irda/af_irda.h87
-rw-r--r--include/net/irda/crc.h29
-rw-r--r--include/net/irda/discovery.h97
-rw-r--r--include/net/irda/ircomm_core.h108
-rw-r--r--include/net/irda/ircomm_event.h85
-rw-r--r--include/net/irda/ircomm_lmp.h38
-rw-r--r--include/net/irda/ircomm_param.h149
-rw-r--r--include/net/irda/ircomm_ttp.h39
-rw-r--r--include/net/irda/ircomm_tty.h138
-rw-r--r--include/net/irda/ircomm_tty_attach.h94
-rw-r--r--include/net/irda/irda.h131
-rw-r--r--include/net/irda/irda_device.h287
-rw-r--r--include/net/irda/iriap.h108
-rw-r--r--include/net/irda/iriap_event.h85
-rw-r--r--include/net/irda/irias_object.h108
-rw-r--r--include/net/irda/irlan_client.h42
-rw-r--r--include/net/irda/irlan_common.h229
-rw-r--r--include/net/irda/irlan_eth.h32
-rw-r--r--include/net/irda/irlan_event.h81
-rw-r--r--include/net/irda/irlan_filter.h35
-rw-r--r--include/net/irda/irlan_provider.h52
-rw-r--r--include/net/irda/irlap.h311
-rw-r--r--include/net/irda/irlap_event.h131
-rw-r--r--include/net/irda/irlap_frame.h169
-rw-r--r--include/net/irda/irlmp.h294
-rw-r--r--include/net/irda/irlmp_event.h98
-rw-r--r--include/net/irda/irlmp_frame.h62
-rw-r--r--include/net/irda/irmod.h109
-rw-r--r--include/net/irda/irqueue.h96
-rw-r--r--include/net/irda/irttp.h210
-rw-r--r--include/net/irda/parameters.h102
-rw-r--r--include/net/irda/qos.h103
-rw-r--r--include/net/irda/timer.h105
-rw-r--r--include/net/irda/wrapper.h58
-rw-r--r--include/net/iucv/af_iucv.h155
-rw-r--r--include/net/iucv/iucv.h495
-rw-r--r--include/net/iw_handler.h587
-rw-r--r--include/net/lapb.h152
-rw-r--r--include/net/lib80211.h124
-rw-r--r--include/net/llc.h159
-rw-r--r--include/net/llc_c_ac.h202
-rw-r--r--include/net/llc_c_ev.h269
-rw-r--r--include/net/llc_c_st.h48
-rw-r--r--include/net/llc_conn.h122
-rw-r--r--include/net/llc_if.h99
-rw-r--r--include/net/llc_pdu.h437
-rw-r--r--include/net/llc_s_ac.h39
-rw-r--r--include/net/llc_s_ev.h67
-rw-r--r--include/net/llc_s_st.h32
-rw-r--r--include/net/llc_sap.h36
-rw-r--r--include/net/mac80211.h3713
-rw-r--r--include/net/mip6.h54
-rw-r--r--include/net/mld.h75
-rw-r--r--include/net/ndisc.h183
-rw-r--r--include/net/neighbour.h407
-rw-r--r--include/net/net_namespace.h292
-rw-r--r--include/net/net_ratelimit.h8
-rw-r--r--include/net/netdma.h32
-rw-r--r--include/net/netevent.h30
-rw-r--r--include/net/netfilter/ipv4/nf_conntrack_ipv4.h24
-rw-r--r--include/net/netfilter/ipv4/nf_defrag_ipv4.h6
-rw-r--r--include/net/netfilter/ipv6/nf_conntrack_icmpv6.h20
-rw-r--r--include/net/netfilter/ipv6/nf_conntrack_ipv6.h13
-rw-r--r--include/net/netfilter/ipv6/nf_defrag_ipv6.h16
-rw-r--r--include/net/netfilter/nf_conntrack.h336
-rw-r--r--include/net/netfilter/nf_conntrack_acct.h63
-rw-r--r--include/net/netfilter/nf_conntrack_core.h79
-rw-r--r--include/net/netfilter/nf_conntrack_ecache.h245
-rw-r--r--include/net/netfilter/nf_conntrack_expect.h111
-rw-r--r--include/net/netfilter/nf_conntrack_extend.h110
-rw-r--r--include/net/netfilter/nf_conntrack_helper.h85
-rw-r--r--include/net/netfilter/nf_conntrack_l3proto.h95
-rw-r--r--include/net/netfilter/nf_conntrack_l4proto.h152
-rw-r--r--include/net/netfilter/nf_conntrack_timeout.h78
-rw-r--r--include/net/netfilter/nf_conntrack_timestamp.h65
-rw-r--r--include/net/netfilter/nf_conntrack_tuple.h186
-rw-r--r--include/net/netfilter/nf_conntrack_zones.h25
-rw-r--r--include/net/netfilter/nf_log.h65
-rw-r--r--include/net/netfilter/nf_nat.h69
-rw-r--r--include/net/netfilter/nf_nat_core.h36
-rw-r--r--include/net/netfilter/nf_nat_helper.h57
-rw-r--r--include/net/netfilter/nf_nat_protocol.h67
-rw-r--r--include/net/netfilter/nf_nat_rule.h15
-rw-r--r--include/net/netfilter/nf_queue.h34
-rw-r--r--include/net/netfilter/nf_tproxy_core.h208
-rw-r--r--include/net/netfilter/nfnetlink_log.h16
-rw-r--r--include/net/netfilter/xt_log.h54
-rw-r--r--include/net/netfilter/xt_rateest.h22
-rw-r--r--include/net/netlabel.h590
-rw-r--r--include/net/netlink.h1072
-rw-r--r--include/net/netns/conntrack.h37
-rw-r--r--include/net/netns/core.h16
-rw-r--r--include/net/netns/dccp.h11
-rw-r--r--include/net/netns/generic.h48
-rw-r--r--include/net/netns/hash.h21
-rw-r--r--include/net/netns/ipv4.h72
-rw-r--r--include/net/netns/ipv6.h70
-rw-r--r--include/net/netns/mib.h28
-rw-r--r--include/net/netns/packet.h15
-rw-r--r--include/net/netns/unix.h13
-rw-r--r--include/net/netns/x_tables.h18
-rw-r--r--include/net/netns/xfrm.h64
-rw-r--r--include/net/netprio_cgroup.h88
-rw-r--r--include/net/netrom.h270
-rw-r--r--include/net/nexthop.h33
-rw-r--r--include/net/nfc/nci.h364
-rw-r--r--include/net/nfc/nci_core.h199
-rw-r--r--include/net/nfc/nfc.h188
-rw-r--r--include/net/nl802154.h126
-rw-r--r--include/net/p8022.h13
-rw-r--r--include/net/phonet/gprs.h38
-rw-r--r--include/net/phonet/pep.h168
-rw-r--r--include/net/phonet/phonet.h119
-rw-r--r--include/net/phonet/pn_dev.h62
-rw-r--r--include/net/ping.h99
-rw-r--r--include/net/pkt_cls.h359
-rw-r--r--include/net/pkt_sched.h115
-rw-r--r--include/net/protocol.h110
-rw-r--r--include/net/psnap.h11
-rw-r--r--include/net/raw.h75
-rw-r--r--include/net/rawv6.h20
-rw-r--r--include/net/red.h405
-rw-r--r--include/net/regulatory.h122
-rw-r--r--include/net/request_sock.h258
-rw-r--r--include/net/rose.h241
-rw-r--r--include/net/route.h324
-rw-r--r--include/net/rtnetlink.h133
-rw-r--r--include/net/sch_generic.h674
-rw-r--r--include/net/scm.h131
-rw-r--r--include/net/sctp/auth.h127
-rw-r--r--include/net/sctp/checksum.h83
-rw-r--r--include/net/sctp/command.h225
-rw-r--r--include/net/sctp/constants.h442
-rw-r--r--include/net/sctp/sctp.h720
-rw-r--r--include/net/sctp/sm.h448
-rw-r--r--include/net/sctp/structs.h2037
-rw-r--r--include/net/sctp/tsnmap.h178
-rw-r--r--include/net/sctp/ulpevent.h171
-rw-r--r--include/net/sctp/ulpqueue.h94
-rw-r--r--include/net/sctp/user.h744
-rw-r--r--include/net/secure_seq.h20
-rw-r--r--include/net/slhc_vj.h183
-rw-r--r--include/net/snmp.h217
-rw-r--r--include/net/sock.h2157
-rw-r--r--include/net/stp.h14
-rw-r--r--include/net/tc_act/tc_csum.h15
-rw-r--r--include/net/tc_act/tc_defact.h14
-rw-r--r--include/net/tc_act/tc_gact.h17
-rw-r--r--include/net/tc_act/tc_ipt.h17
-rw-r--r--include/net/tc_act/tc_mirred.h17
-rw-r--r--include/net/tc_act/tc_nat.h21
-rw-r--r--include/net/tc_act/tc_pedit.h15
-rw-r--r--include/net/tc_act/tc_skbedit.h36
-rw-r--r--include/net/tcp.h1581
-rw-r--r--include/net/tcp_memcontrol.h19
-rw-r--r--include/net/tcp_states.h50
-rw-r--r--include/net/timewait_sock.h51
-rw-r--r--include/net/transp_v6.h61
-rw-r--r--include/net/udp.h270
-rw-r--r--include/net/udplite.h132
-rw-r--r--include/net/wext.h60
-rw-r--r--include/net/wimax.h519
-rw-r--r--include/net/wpan-phy.h82
-rw-r--r--include/net/x25.h323
-rw-r--r--include/net/x25device.h17
-rw-r--r--include/net/xfrm.h1693
257 files changed, 55391 insertions, 0 deletions
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h
new file mode 100644
index 00000000..7184853c
--- /dev/null
+++ b/include/net/9p/9p.h
@@ -0,0 +1,577 @@
+/*
+ * include/net/9p/9p.h
+ *
+ * 9P protocol definitions.
+ *
+ * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#ifndef NET_9P_H
+#define NET_9P_H
+
+/**
+ * enum p9_debug_flags - bits for mount time debug parameter
+ * @P9_DEBUG_ERROR: more verbose error messages including original error string
+ * @P9_DEBUG_9P: 9P protocol tracing
+ * @P9_DEBUG_VFS: VFS API tracing
+ * @P9_DEBUG_CONV: protocol conversion tracing
+ * @P9_DEBUG_MUX: trace management of concurrent transactions
+ * @P9_DEBUG_TRANS: transport tracing
+ * @P9_DEBUG_SLABS: memory management tracing
+ * @P9_DEBUG_FCALL: verbose dump of protocol messages
+ * @P9_DEBUG_FID: fid allocation/deallocation tracking
+ * @P9_DEBUG_PKT: packet marshalling/unmarshalling
+ * @P9_DEBUG_FSC: FS-cache tracing
+ * @P9_DEBUG_VPKT: Verbose packet debugging (full packet dump)
+ *
+ * These flags are passed at mount time to turn on various levels of
+ * verbosity and tracing which will be output to the system logs.
+ */
+
+enum p9_debug_flags {
+ P9_DEBUG_ERROR = (1<<0),
+ P9_DEBUG_9P = (1<<2),
+ P9_DEBUG_VFS = (1<<3),
+ P9_DEBUG_CONV = (1<<4),
+ P9_DEBUG_MUX = (1<<5),
+ P9_DEBUG_TRANS = (1<<6),
+ P9_DEBUG_SLABS = (1<<7),
+ P9_DEBUG_FCALL = (1<<8),
+ P9_DEBUG_FID = (1<<9),
+ P9_DEBUG_PKT = (1<<10),
+ P9_DEBUG_FSC = (1<<11),
+ P9_DEBUG_VPKT = (1<<12),
+};
+
+#ifdef CONFIG_NET_9P_DEBUG
+extern unsigned int p9_debug_level;
+__printf(3, 4)
+void _p9_debug(enum p9_debug_flags level, const char *func,
+ const char *fmt, ...);
+#define p9_debug(level, fmt, ...) \
+ _p9_debug(level, __func__, fmt, ##__VA_ARGS__)
+#else
+#define p9_debug(level, fmt, ...) \
+ no_printk(fmt, ##__VA_ARGS__)
+#endif
+
+/**
+ * enum p9_msg_t - 9P message types
+ * @P9_TLERROR: not used
+ * @P9_RLERROR: response for any failed request for 9P2000.L
+ * @P9_TSTATFS: file system status request
+ * @P9_RSTATFS: file system status response
+ * @P9_TSYMLINK: make symlink request
+ * @P9_RSYMLINK: make symlink response
+ * @P9_TMKNOD: create a special file object request
+ * @P9_RMKNOD: create a special file object response
+ * @P9_TLCREATE: prepare a handle for I/O on an new file for 9P2000.L
+ * @P9_RLCREATE: response with file access information for 9P2000.L
+ * @P9_TRENAME: rename request
+ * @P9_RRENAME: rename response
+ * @P9_TMKDIR: create a directory request
+ * @P9_RMKDIR: create a directory response
+ * @P9_TVERSION: version handshake request
+ * @P9_RVERSION: version handshake response
+ * @P9_TAUTH: request to establish authentication channel
+ * @P9_RAUTH: response with authentication information
+ * @P9_TATTACH: establish user access to file service
+ * @P9_RATTACH: response with top level handle to file hierarchy
+ * @P9_TERROR: not used
+ * @P9_RERROR: response for any failed request
+ * @P9_TFLUSH: request to abort a previous request
+ * @P9_RFLUSH: response when previous request has been cancelled
+ * @P9_TWALK: descend a directory hierarchy
+ * @P9_RWALK: response with new handle for position within hierarchy
+ * @P9_TOPEN: prepare a handle for I/O on an existing file
+ * @P9_ROPEN: response with file access information
+ * @P9_TCREATE: prepare a handle for I/O on a new file
+ * @P9_RCREATE: response with file access information
+ * @P9_TREAD: request to transfer data from a file or directory
+ * @P9_RREAD: response with data requested
+ * @P9_TWRITE: reuqest to transfer data to a file
+ * @P9_RWRITE: response with out much data was transferred to file
+ * @P9_TCLUNK: forget about a handle to an entity within the file system
+ * @P9_RCLUNK: response when server has forgotten about the handle
+ * @P9_TREMOVE: request to remove an entity from the hierarchy
+ * @P9_RREMOVE: response when server has removed the entity
+ * @P9_TSTAT: request file entity attributes
+ * @P9_RSTAT: response with file entity attributes
+ * @P9_TWSTAT: request to update file entity attributes
+ * @P9_RWSTAT: response when file entity attributes are updated
+ *
+ * There are 14 basic operations in 9P2000, paired as
+ * requests and responses. The one special case is ERROR
+ * as there is no @P9_TERROR request for clients to transmit to
+ * the server, but the server may respond to any other request
+ * with an @P9_RERROR.
+ *
+ * See Also: http://plan9.bell-labs.com/sys/man/5/INDEX.html
+ */
+
+enum p9_msg_t {
+ P9_TLERROR = 6,
+ P9_RLERROR,
+ P9_TSTATFS = 8,
+ P9_RSTATFS,
+ P9_TLOPEN = 12,
+ P9_RLOPEN,
+ P9_TLCREATE = 14,
+ P9_RLCREATE,
+ P9_TSYMLINK = 16,
+ P9_RSYMLINK,
+ P9_TMKNOD = 18,
+ P9_RMKNOD,
+ P9_TRENAME = 20,
+ P9_RRENAME,
+ P9_TREADLINK = 22,
+ P9_RREADLINK,
+ P9_TGETATTR = 24,
+ P9_RGETATTR,
+ P9_TSETATTR = 26,
+ P9_RSETATTR,
+ P9_TXATTRWALK = 30,
+ P9_RXATTRWALK,
+ P9_TXATTRCREATE = 32,
+ P9_RXATTRCREATE,
+ P9_TREADDIR = 40,
+ P9_RREADDIR,
+ P9_TFSYNC = 50,
+ P9_RFSYNC,
+ P9_TLOCK = 52,
+ P9_RLOCK,
+ P9_TGETLOCK = 54,
+ P9_RGETLOCK,
+ P9_TLINK = 70,
+ P9_RLINK,
+ P9_TMKDIR = 72,
+ P9_RMKDIR,
+ P9_TRENAMEAT = 74,
+ P9_RRENAMEAT,
+ P9_TUNLINKAT = 76,
+ P9_RUNLINKAT,
+ P9_TVERSION = 100,
+ P9_RVERSION,
+ P9_TAUTH = 102,
+ P9_RAUTH,
+ P9_TATTACH = 104,
+ P9_RATTACH,
+ P9_TERROR = 106,
+ P9_RERROR,
+ P9_TFLUSH = 108,
+ P9_RFLUSH,
+ P9_TWALK = 110,
+ P9_RWALK,
+ P9_TOPEN = 112,
+ P9_ROPEN,
+ P9_TCREATE = 114,
+ P9_RCREATE,
+ P9_TREAD = 116,
+ P9_RREAD,
+ P9_TWRITE = 118,
+ P9_RWRITE,
+ P9_TCLUNK = 120,
+ P9_RCLUNK,
+ P9_TREMOVE = 122,
+ P9_RREMOVE,
+ P9_TSTAT = 124,
+ P9_RSTAT,
+ P9_TWSTAT = 126,
+ P9_RWSTAT,
+};
+
+/**
+ * enum p9_open_mode_t - 9P open modes
+ * @P9_OREAD: open file for reading only
+ * @P9_OWRITE: open file for writing only
+ * @P9_ORDWR: open file for reading or writing
+ * @P9_OEXEC: open file for execution
+ * @P9_OTRUNC: truncate file to zero-length before opening it
+ * @P9_OREXEC: close the file when an exec(2) system call is made
+ * @P9_ORCLOSE: remove the file when the file is closed
+ * @P9_OAPPEND: open the file and seek to the end
+ * @P9_OEXCL: only create a file, do not open it
+ *
+ * 9P open modes differ slightly from Posix standard modes.
+ * In particular, there are extra modes which specify different
+ * semantic behaviors than may be available on standard Posix
+ * systems. For example, @P9_OREXEC and @P9_ORCLOSE are modes that
+ * most likely will not be issued from the Linux VFS client, but may
+ * be supported by servers.
+ *
+ * See Also: http://plan9.bell-labs.com/magic/man2html/2/open
+ */
+
+enum p9_open_mode_t {
+ P9_OREAD = 0x00,
+ P9_OWRITE = 0x01,
+ P9_ORDWR = 0x02,
+ P9_OEXEC = 0x03,
+ P9_OTRUNC = 0x10,
+ P9_OREXEC = 0x20,
+ P9_ORCLOSE = 0x40,
+ P9_OAPPEND = 0x80,
+ P9_OEXCL = 0x1000,
+};
+
+/**
+ * enum p9_perm_t - 9P permissions
+ * @P9_DMDIR: mode bit for directories
+ * @P9_DMAPPEND: mode bit for is append-only
+ * @P9_DMEXCL: mode bit for excluse use (only one open handle allowed)
+ * @P9_DMMOUNT: mode bit for mount points
+ * @P9_DMAUTH: mode bit for authentication file
+ * @P9_DMTMP: mode bit for non-backed-up files
+ * @P9_DMSYMLINK: mode bit for symbolic links (9P2000.u)
+ * @P9_DMLINK: mode bit for hard-link (9P2000.u)
+ * @P9_DMDEVICE: mode bit for device files (9P2000.u)
+ * @P9_DMNAMEDPIPE: mode bit for named pipe (9P2000.u)
+ * @P9_DMSOCKET: mode bit for socket (9P2000.u)
+ * @P9_DMSETUID: mode bit for setuid (9P2000.u)
+ * @P9_DMSETGID: mode bit for setgid (9P2000.u)
+ * @P9_DMSETVTX: mode bit for sticky bit (9P2000.u)
+ *
+ * 9P permissions differ slightly from Posix standard modes.
+ *
+ * See Also: http://plan9.bell-labs.com/magic/man2html/2/stat
+ */
+enum p9_perm_t {
+ P9_DMDIR = 0x80000000,
+ P9_DMAPPEND = 0x40000000,
+ P9_DMEXCL = 0x20000000,
+ P9_DMMOUNT = 0x10000000,
+ P9_DMAUTH = 0x08000000,
+ P9_DMTMP = 0x04000000,
+/* 9P2000.u extensions */
+ P9_DMSYMLINK = 0x02000000,
+ P9_DMLINK = 0x01000000,
+ P9_DMDEVICE = 0x00800000,
+ P9_DMNAMEDPIPE = 0x00200000,
+ P9_DMSOCKET = 0x00100000,
+ P9_DMSETUID = 0x00080000,
+ P9_DMSETGID = 0x00040000,
+ P9_DMSETVTX = 0x00010000,
+};
+
+/* 9p2000.L open flags */
+#define P9_DOTL_RDONLY 00000000
+#define P9_DOTL_WRONLY 00000001
+#define P9_DOTL_RDWR 00000002
+#define P9_DOTL_NOACCESS 00000003
+#define P9_DOTL_CREATE 00000100
+#define P9_DOTL_EXCL 00000200
+#define P9_DOTL_NOCTTY 00000400
+#define P9_DOTL_TRUNC 00001000
+#define P9_DOTL_APPEND 00002000
+#define P9_DOTL_NONBLOCK 00004000
+#define P9_DOTL_DSYNC 00010000
+#define P9_DOTL_FASYNC 00020000
+#define P9_DOTL_DIRECT 00040000
+#define P9_DOTL_LARGEFILE 00100000
+#define P9_DOTL_DIRECTORY 00200000
+#define P9_DOTL_NOFOLLOW 00400000
+#define P9_DOTL_NOATIME 01000000
+#define P9_DOTL_CLOEXEC 02000000
+#define P9_DOTL_SYNC 04000000
+
+/* 9p2000.L at flags */
+#define P9_DOTL_AT_REMOVEDIR 0x200
+
+/* 9p2000.L lock type */
+#define P9_LOCK_TYPE_RDLCK 0
+#define P9_LOCK_TYPE_WRLCK 1
+#define P9_LOCK_TYPE_UNLCK 2
+
+/**
+ * enum p9_qid_t - QID types
+ * @P9_QTDIR: directory
+ * @P9_QTAPPEND: append-only
+ * @P9_QTEXCL: excluse use (only one open handle allowed)
+ * @P9_QTMOUNT: mount points
+ * @P9_QTAUTH: authentication file
+ * @P9_QTTMP: non-backed-up files
+ * @P9_QTSYMLINK: symbolic links (9P2000.u)
+ * @P9_QTLINK: hard-link (9P2000.u)
+ * @P9_QTFILE: normal files
+ *
+ * QID types are a subset of permissions - they are primarily
+ * used to differentiate semantics for a file system entity via
+ * a jump-table. Their value is also the most significant 16 bits
+ * of the permission_t
+ *
+ * See Also: http://plan9.bell-labs.com/magic/man2html/2/stat
+ */
+enum p9_qid_t {
+ P9_QTDIR = 0x80,
+ P9_QTAPPEND = 0x40,
+ P9_QTEXCL = 0x20,
+ P9_QTMOUNT = 0x10,
+ P9_QTAUTH = 0x08,
+ P9_QTTMP = 0x04,
+ P9_QTSYMLINK = 0x02,
+ P9_QTLINK = 0x01,
+ P9_QTFILE = 0x00,
+};
+
+/* 9P Magic Numbers */
+#define P9_NOTAG (u16)(~0)
+#define P9_NOFID (u32)(~0)
+#define P9_MAXWELEM 16
+
+/* ample room for Twrite/Rread header */
+#define P9_IOHDRSZ 24
+
+/* Room for readdir header */
+#define P9_READDIRHDRSZ 24
+
+/* size of header for zero copy read/write */
+#define P9_ZC_HDR_SZ 4096
+
+/**
+ * struct p9_qid - file system entity information
+ * @type: 8-bit type &p9_qid_t
+ * @version: 16-bit monotonically incrementing version number
+ * @path: 64-bit per-server-unique ID for a file system element
+ *
+ * qids are identifiers used by 9P servers to track file system
+ * entities. The type is used to differentiate semantics for operations
+ * on the entity (ie. read means something different on a directory than
+ * on a file). The path provides a server unique index for an entity
+ * (roughly analogous to an inode number), while the version is updated
+ * every time a file is modified and can be used to maintain cache
+ * coherency between clients and serves.
+ * Servers will often differentiate purely synthetic entities by setting
+ * their version to 0, signaling that they should never be cached and
+ * should be accessed synchronously.
+ *
+ * See Also://plan9.bell-labs.com/magic/man2html/2/stat
+ */
+
+struct p9_qid {
+ u8 type;
+ u32 version;
+ u64 path;
+};
+
+/**
+ * struct p9_wstat - file system metadata information
+ * @size: length prefix for this stat structure instance
+ * @type: the type of the server (equivalent to a major number)
+ * @dev: the sub-type of the server (equivalent to a minor number)
+ * @qid: unique id from the server of type &p9_qid
+ * @mode: Plan 9 format permissions of type &p9_perm_t
+ * @atime: Last access/read time
+ * @mtime: Last modify/write time
+ * @length: file length
+ * @name: last element of path (aka filename)
+ * @uid: owner name
+ * @gid: group owner
+ * @muid: last modifier
+ * @extension: area used to encode extended UNIX support
+ * @n_uid: numeric user id of owner (part of 9p2000.u extension)
+ * @n_gid: numeric group id (part of 9p2000.u extension)
+ * @n_muid: numeric user id of laster modifier (part of 9p2000.u extension)
+ *
+ * See Also: http://plan9.bell-labs.com/magic/man2html/2/stat
+ */
+
+struct p9_wstat {
+ u16 size;
+ u16 type;
+ u32 dev;
+ struct p9_qid qid;
+ u32 mode;
+ u32 atime;
+ u32 mtime;
+ u64 length;
+ char *name;
+ char *uid;
+ char *gid;
+ char *muid;
+ char *extension; /* 9p2000.u extensions */
+ u32 n_uid; /* 9p2000.u extensions */
+ u32 n_gid; /* 9p2000.u extensions */
+ u32 n_muid; /* 9p2000.u extensions */
+};
+
+struct p9_stat_dotl {
+ u64 st_result_mask;
+ struct p9_qid qid;
+ u32 st_mode;
+ u32 st_uid;
+ u32 st_gid;
+ u64 st_nlink;
+ u64 st_rdev;
+ u64 st_size;
+ u64 st_blksize;
+ u64 st_blocks;
+ u64 st_atime_sec;
+ u64 st_atime_nsec;
+ u64 st_mtime_sec;
+ u64 st_mtime_nsec;
+ u64 st_ctime_sec;
+ u64 st_ctime_nsec;
+ u64 st_btime_sec;
+ u64 st_btime_nsec;
+ u64 st_gen;
+ u64 st_data_version;
+};
+
+#define P9_STATS_MODE 0x00000001ULL
+#define P9_STATS_NLINK 0x00000002ULL
+#define P9_STATS_UID 0x00000004ULL
+#define P9_STATS_GID 0x00000008ULL
+#define P9_STATS_RDEV 0x00000010ULL
+#define P9_STATS_ATIME 0x00000020ULL
+#define P9_STATS_MTIME 0x00000040ULL
+#define P9_STATS_CTIME 0x00000080ULL
+#define P9_STATS_INO 0x00000100ULL
+#define P9_STATS_SIZE 0x00000200ULL
+#define P9_STATS_BLOCKS 0x00000400ULL
+
+#define P9_STATS_BTIME 0x00000800ULL
+#define P9_STATS_GEN 0x00001000ULL
+#define P9_STATS_DATA_VERSION 0x00002000ULL
+
+#define P9_STATS_BASIC 0x000007ffULL /* Mask for fields up to BLOCKS */
+#define P9_STATS_ALL 0x00003fffULL /* Mask for All fields above */
+
+/**
+ * struct p9_iattr_dotl - P9 inode attribute for setattr
+ * @valid: bitfield specifying which fields are valid
+ * same as in struct iattr
+ * @mode: File permission bits
+ * @uid: user id of owner
+ * @gid: group id
+ * @size: File size
+ * @atime_sec: Last access time, seconds
+ * @atime_nsec: Last access time, nanoseconds
+ * @mtime_sec: Last modification time, seconds
+ * @mtime_nsec: Last modification time, nanoseconds
+ */
+
+struct p9_iattr_dotl {
+ u32 valid;
+ u32 mode;
+ u32 uid;
+ u32 gid;
+ u64 size;
+ u64 atime_sec;
+ u64 atime_nsec;
+ u64 mtime_sec;
+ u64 mtime_nsec;
+};
+
+#define P9_LOCK_SUCCESS 0
+#define P9_LOCK_BLOCKED 1
+#define P9_LOCK_ERROR 2
+#define P9_LOCK_GRACE 3
+
+#define P9_LOCK_FLAGS_BLOCK 1
+#define P9_LOCK_FLAGS_RECLAIM 2
+
+/* struct p9_flock: POSIX lock structure
+ * @type - type of lock
+ * @flags - lock flags
+ * @start - starting offset of the lock
+ * @length - number of bytes
+ * @proc_id - process id which wants to take lock
+ * @client_id - client id
+ */
+
+struct p9_flock {
+ u8 type;
+ u32 flags;
+ u64 start;
+ u64 length;
+ u32 proc_id;
+ char *client_id;
+};
+
+/* struct p9_getlock: getlock structure
+ * @type - type of lock
+ * @start - starting offset of the lock
+ * @length - number of bytes
+ * @proc_id - process id which wants to take lock
+ * @client_id - client id
+ */
+
+struct p9_getlock {
+ u8 type;
+ u64 start;
+ u64 length;
+ u32 proc_id;
+ char *client_id;
+};
+
+struct p9_rstatfs {
+ u32 type;
+ u32 bsize;
+ u64 blocks;
+ u64 bfree;
+ u64 bavail;
+ u64 files;
+ u64 ffree;
+ u64 fsid;
+ u32 namelen;
+};
+
+/**
+ * struct p9_fcall - primary packet structure
+ * @size: prefixed length of the structure
+ * @id: protocol operating identifier of type &p9_msg_t
+ * @tag: transaction id of the request
+ * @offset: used by marshalling routines to track current position in buffer
+ * @capacity: used by marshalling routines to track total malloc'd capacity
+ * @sdata: payload
+ *
+ * &p9_fcall represents the structure for all 9P RPC
+ * transactions. Requests are packaged into fcalls, and reponses
+ * must be extracted from them.
+ *
+ * See Also: http://plan9.bell-labs.com/magic/man2html/2/fcall
+ */
+
+struct p9_fcall {
+ u32 size;
+ u8 id;
+ u16 tag;
+
+ size_t offset;
+ size_t capacity;
+
+ u8 *sdata;
+};
+
+struct p9_idpool;
+
+int p9_errstr2errno(char *errstr, int len);
+
+struct p9_idpool *p9_idpool_create(void);
+void p9_idpool_destroy(struct p9_idpool *);
+int p9_idpool_get(struct p9_idpool *p);
+void p9_idpool_put(int id, struct p9_idpool *p);
+int p9_idpool_check(int id, struct p9_idpool *p);
+
+int p9_error_init(void);
+int p9_trans_fd_init(void);
+void p9_trans_fd_exit(void);
+#endif /* NET_9P_H */
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
new file mode 100644
index 00000000..fc9b90b0
--- /dev/null
+++ b/include/net/9p/client.h
@@ -0,0 +1,271 @@
+/*
+ * include/net/9p/client.h
+ *
+ * 9P Client Definitions
+ *
+ * Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#ifndef NET_9P_CLIENT_H
+#define NET_9P_CLIENT_H
+
+/* Number of requests per row */
+#define P9_ROW_MAXTAG 255
+
+/** enum p9_proto_versions - 9P protocol versions
+ * @p9_proto_legacy: 9P Legacy mode, pre-9P2000.u
+ * @p9_proto_2000u: 9P2000.u extension
+ * @p9_proto_2000L: 9P2000.L extension
+ */
+
+enum p9_proto_versions{
+ p9_proto_legacy,
+ p9_proto_2000u,
+ p9_proto_2000L,
+};
+
+
+/**
+ * enum p9_trans_status - different states of underlying transports
+ * @Connected: transport is connected and healthy
+ * @Disconnected: transport has been disconnected
+ * @Hung: transport is connected by wedged
+ *
+ * This enumeration details the various states a transport
+ * instatiation can be in.
+ */
+
+enum p9_trans_status {
+ Connected,
+ BeginDisconnect,
+ Disconnected,
+ Hung,
+};
+
+/**
+ * enum p9_req_status_t - status of a request
+ * @REQ_STATUS_IDLE: request slot unused
+ * @REQ_STATUS_ALLOC: request has been allocated but not sent
+ * @REQ_STATUS_UNSENT: request waiting to be sent
+ * @REQ_STATUS_SENT: request sent to server
+ * @REQ_STATUS_FLSH: a flush has been sent for this request
+ * @REQ_STATUS_RCVD: response received from server
+ * @REQ_STATUS_FLSHD: request has been flushed
+ * @REQ_STATUS_ERROR: request encountered an error on the client side
+ *
+ * The @REQ_STATUS_IDLE state is used to mark a request slot as unused
+ * but use is actually tracked by the idpool structure which handles tag
+ * id allocation.
+ *
+ */
+
+enum p9_req_status_t {
+ REQ_STATUS_IDLE,
+ REQ_STATUS_ALLOC,
+ REQ_STATUS_UNSENT,
+ REQ_STATUS_SENT,
+ REQ_STATUS_FLSH,
+ REQ_STATUS_RCVD,
+ REQ_STATUS_FLSHD,
+ REQ_STATUS_ERROR,
+};
+
+/**
+ * struct p9_req_t - request slots
+ * @status: status of this request slot
+ * @t_err: transport error
+ * @flush_tag: tag of request being flushed (for flush requests)
+ * @wq: wait_queue for the client to block on for this request
+ * @tc: the request fcall structure
+ * @rc: the response fcall structure
+ * @aux: transport specific data (provided for trans_fd migration)
+ * @req_list: link for higher level objects to chain requests
+ *
+ * Transport use an array to track outstanding requests
+ * instead of a list. While this may incurr overhead during initial
+ * allocation or expansion, it makes request lookup much easier as the
+ * tag id is a index into an array. (We use tag+1 so that we can accommodate
+ * the -1 tag for the T_VERSION request).
+ * This also has the nice effect of only having to allocate wait_queues
+ * once, instead of constantly allocating and freeing them. Its possible
+ * other resources could benefit from this scheme as well.
+ *
+ */
+
+struct p9_req_t {
+ int status;
+ int t_err;
+ wait_queue_head_t *wq;
+ struct p9_fcall *tc;
+ struct p9_fcall *rc;
+ void *aux;
+
+ struct list_head req_list;
+};
+
+/**
+ * struct p9_client - per client instance state
+ * @lock: protect @fidlist
+ * @msize: maximum data size negotiated by protocol
+ * @dotu: extension flags negotiated by protocol
+ * @proto_version: 9P protocol version to use
+ * @trans_mod: module API instantiated with this client
+ * @trans: tranport instance state and API
+ * @conn: connection state information used by trans_fd
+ * @fidpool: fid handle accounting for session
+ * @fidlist: List of active fid handles
+ * @tagpool - transaction id accounting for session
+ * @reqs - 2D array of requests
+ * @max_tag - current maximum tag id allocated
+ *
+ * The client structure is used to keep track of various per-client
+ * state that has been instantiated.
+ * In order to minimize per-transaction overhead we use a
+ * simple array to lookup requests instead of a hash table
+ * or linked list. In order to support larger number of
+ * transactions, we make this a 2D array, allocating new rows
+ * when we need to grow the total number of the transactions.
+ *
+ * Each row is 256 requests and we'll support up to 256 rows for
+ * a total of 64k concurrent requests per session.
+ *
+ * Bugs: duplicated data and potentially unnecessary elements.
+ */
+
+struct p9_client {
+ spinlock_t lock; /* protect client structure */
+ unsigned int msize;
+ unsigned char proto_version;
+ struct p9_trans_module *trans_mod;
+ enum p9_trans_status status;
+ void *trans;
+ struct p9_conn *conn;
+
+ struct p9_idpool *fidpool;
+ struct list_head fidlist;
+
+ struct p9_idpool *tagpool;
+ struct p9_req_t *reqs[P9_ROW_MAXTAG];
+ int max_tag;
+};
+
+/**
+ * struct p9_fid - file system entity handle
+ * @clnt: back pointer to instantiating &p9_client
+ * @fid: numeric identifier for this handle
+ * @mode: current mode of this fid (enum?)
+ * @qid: the &p9_qid server identifier this handle points to
+ * @iounit: the server reported maximum transaction size for this file
+ * @uid: the numeric uid of the local user who owns this handle
+ * @rdir: readdir accounting structure (allocated on demand)
+ * @flist: per-client-instance fid tracking
+ * @dlist: per-dentry fid tracking
+ *
+ * TODO: This needs lots of explanation.
+ */
+
+struct p9_fid {
+ struct p9_client *clnt;
+ u32 fid;
+ int mode;
+ struct p9_qid qid;
+ u32 iounit;
+ uid_t uid;
+
+ void *rdir;
+
+ struct list_head flist;
+ struct list_head dlist; /* list of all fids attached to a dentry */
+};
+
+/**
+ * struct p9_dirent - directory entry structure
+ * @qid: The p9 server qid for this dirent
+ * @d_off: offset to the next dirent
+ * @d_type: type of file
+ * @d_name: file name
+ */
+
+struct p9_dirent {
+ struct p9_qid qid;
+ u64 d_off;
+ unsigned char d_type;
+ char d_name[256];
+};
+
+int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb);
+int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid,
+ const char *name);
+int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name,
+ struct p9_fid *newdirfid, const char *new_name);
+struct p9_client *p9_client_create(const char *dev_name, char *options);
+void p9_client_destroy(struct p9_client *clnt);
+void p9_client_disconnect(struct p9_client *clnt);
+void p9_client_begin_disconnect(struct p9_client *clnt);
+struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
+ char *uname, u32 n_uname, char *aname);
+struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
+ char **wnames, int clone);
+int p9_client_open(struct p9_fid *fid, int mode);
+int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
+ char *extension);
+int p9_client_link(struct p9_fid *fid, struct p9_fid *oldfid, char *newname);
+int p9_client_symlink(struct p9_fid *fid, char *name, char *symname, gid_t gid,
+ struct p9_qid *qid);
+int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode,
+ gid_t gid, struct p9_qid *qid);
+int p9_client_clunk(struct p9_fid *fid);
+int p9_client_fsync(struct p9_fid *fid, int datasync);
+int p9_client_remove(struct p9_fid *fid);
+int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags);
+int p9_client_read(struct p9_fid *fid, char *data, char __user *udata,
+ u64 offset, u32 count);
+int p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
+ u64 offset, u32 count);
+int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset);
+int p9dirent_read(struct p9_client *clnt, char *buf, int len,
+ struct p9_dirent *dirent);
+struct p9_wstat *p9_client_stat(struct p9_fid *fid);
+int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst);
+int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *attr);
+
+struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,
+ u64 request_mask);
+
+int p9_client_mknod_dotl(struct p9_fid *oldfid, char *name, int mode,
+ dev_t rdev, gid_t gid, struct p9_qid *);
+int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode,
+ gid_t gid, struct p9_qid *);
+int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status);
+int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *fl);
+struct p9_req_t *p9_tag_lookup(struct p9_client *, u16);
+void p9_client_cb(struct p9_client *c, struct p9_req_t *req);
+
+int p9_parse_header(struct p9_fcall *, int32_t *, int8_t *, int16_t *, int);
+int p9stat_read(struct p9_client *, char *, int, struct p9_wstat *);
+void p9stat_free(struct p9_wstat *);
+
+int p9_is_proto_dotu(struct p9_client *clnt);
+int p9_is_proto_dotl(struct p9_client *clnt);
+struct p9_fid *p9_client_xattrwalk(struct p9_fid *, const char *, u64 *);
+int p9_client_xattrcreate(struct p9_fid *, const char *, u64, int);
+int p9_client_readlink(struct p9_fid *fid, char **target);
+
+#endif /* NET_9P_CLIENT_H */
diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h
new file mode 100644
index 00000000..adcbb20f
--- /dev/null
+++ b/include/net/9p/transport.h
@@ -0,0 +1,67 @@
+/*
+ * include/net/9p/transport.h
+ *
+ * Transport Definition
+ *
+ * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
+ * Copyright (C) 2004-2008 by Eric Van Hensbergen <ericvh@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#ifndef NET_9P_TRANSPORT_H
+#define NET_9P_TRANSPORT_H
+
+/**
+ * struct p9_trans_module - transport module interface
+ * @list: used to maintain a list of currently available transports
+ * @name: the human-readable name of the transport
+ * @maxsize: transport provided maximum packet size
+ * @pref: Preferences of this transport
+ * @def: set if this transport should be considered the default
+ * @create: member function to create a new connection on this transport
+ * @close: member function to discard a connection on this transport
+ * @request: member function to issue a request to the transport
+ * @cancel: member function to cancel a request (if it hasn't been sent)
+ *
+ * This is the basic API for a transport module which is registered by the
+ * transport module with the 9P core network module and used by the client
+ * to instantiate a new connection on a transport.
+ *
+ * The transport module list is protected by v9fs_trans_lock.
+ */
+
+struct p9_trans_module {
+ struct list_head list;
+ char *name; /* name of transport */
+ int maxsize; /* max message size of transport */
+ int def; /* this transport should be default */
+ struct module *owner;
+ int (*create)(struct p9_client *, const char *, char *);
+ void (*close) (struct p9_client *);
+ int (*request) (struct p9_client *, struct p9_req_t *req);
+ int (*cancel) (struct p9_client *, struct p9_req_t *req);
+ int (*zc_request)(struct p9_client *, struct p9_req_t *,
+ char *, char *, int , int, int, int);
+};
+
+void v9fs_register_trans(struct p9_trans_module *m);
+void v9fs_unregister_trans(struct p9_trans_module *m);
+struct p9_trans_module *v9fs_get_trans_by_name(char *s);
+struct p9_trans_module *v9fs_get_default_trans(void);
+void v9fs_put_trans(struct p9_trans_module *m);
+#endif /* NET_9P_TRANSPORT_H */
diff --git a/include/net/act_api.h b/include/net/act_api.h
new file mode 100644
index 00000000..c739531e
--- /dev/null
+++ b/include/net/act_api.h
@@ -0,0 +1,126 @@
+#ifndef __NET_ACT_API_H
+#define __NET_ACT_API_H
+
+/*
+ * Public police action API for classifiers/qdiscs
+ */
+
+#include <net/sch_generic.h>
+#include <net/pkt_sched.h>
+
+struct tcf_common {
+ struct tcf_common *tcfc_next;
+ u32 tcfc_index;
+ int tcfc_refcnt;
+ int tcfc_bindcnt;
+ u32 tcfc_capab;
+ int tcfc_action;
+ struct tcf_t tcfc_tm;
+ struct gnet_stats_basic_packed tcfc_bstats;
+ struct gnet_stats_queue tcfc_qstats;
+ struct gnet_stats_rate_est tcfc_rate_est;
+ spinlock_t tcfc_lock;
+ struct rcu_head tcfc_rcu;
+};
+#define tcf_next common.tcfc_next
+#define tcf_index common.tcfc_index
+#define tcf_refcnt common.tcfc_refcnt
+#define tcf_bindcnt common.tcfc_bindcnt
+#define tcf_capab common.tcfc_capab
+#define tcf_action common.tcfc_action
+#define tcf_tm common.tcfc_tm
+#define tcf_bstats common.tcfc_bstats
+#define tcf_qstats common.tcfc_qstats
+#define tcf_rate_est common.tcfc_rate_est
+#define tcf_lock common.tcfc_lock
+#define tcf_rcu common.tcfc_rcu
+
+struct tcf_police {
+ struct tcf_common common;
+ int tcfp_result;
+ u32 tcfp_ewma_rate;
+ u32 tcfp_burst;
+ u32 tcfp_mtu;
+ u32 tcfp_toks;
+ u32 tcfp_ptoks;
+ psched_time_t tcfp_t_c;
+ struct qdisc_rate_table *tcfp_R_tab;
+ struct qdisc_rate_table *tcfp_P_tab;
+};
+#define to_police(pc) \
+ container_of(pc, struct tcf_police, common)
+
+struct tcf_hashinfo {
+ struct tcf_common **htab;
+ unsigned int hmask;
+ rwlock_t *lock;
+};
+
+static inline unsigned int tcf_hash(u32 index, unsigned int hmask)
+{
+ return index & hmask;
+}
+
+#ifdef CONFIG_NET_CLS_ACT
+
+#define ACT_P_CREATED 1
+#define ACT_P_DELETED 1
+
+struct tcf_act_hdr {
+ struct tcf_common common;
+};
+
+struct tc_action {
+ void *priv;
+ const struct tc_action_ops *ops;
+ __u32 type; /* for backward compat(TCA_OLD_COMPAT) */
+ __u32 order;
+ struct tc_action *next;
+};
+
+#define TCA_CAP_NONE 0
+struct tc_action_ops {
+ struct tc_action_ops *next;
+ struct tcf_hashinfo *hinfo;
+ char kind[IFNAMSIZ];
+ __u32 type; /* TBD to match kind */
+ __u32 capab; /* capabilities includes 4 bit version */
+ struct module *owner;
+ int (*act)(struct sk_buff *, const struct tc_action *, struct tcf_result *);
+ int (*get_stats)(struct sk_buff *, struct tc_action *);
+ int (*dump)(struct sk_buff *, struct tc_action *, int, int);
+ int (*cleanup)(struct tc_action *, int bind);
+ int (*lookup)(struct tc_action *, u32);
+ int (*init)(struct nlattr *, struct nlattr *, struct tc_action *, int , int);
+ int (*walk)(struct sk_buff *, struct netlink_callback *, int, struct tc_action *);
+};
+
+extern struct tcf_common *tcf_hash_lookup(u32 index,
+ struct tcf_hashinfo *hinfo);
+extern void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo);
+extern int tcf_hash_release(struct tcf_common *p, int bind,
+ struct tcf_hashinfo *hinfo);
+extern int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb,
+ int type, struct tc_action *a);
+extern u32 tcf_hash_new_index(u32 *idx_gen, struct tcf_hashinfo *hinfo);
+extern int tcf_hash_search(struct tc_action *a, u32 index);
+extern struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a,
+ int bind, struct tcf_hashinfo *hinfo);
+extern struct tcf_common *tcf_hash_create(u32 index, struct nlattr *est,
+ struct tc_action *a, int size,
+ int bind, u32 *idx_gen,
+ struct tcf_hashinfo *hinfo);
+extern void tcf_hash_insert(struct tcf_common *p, struct tcf_hashinfo *hinfo);
+
+extern int tcf_register_action(struct tc_action_ops *a);
+extern int tcf_unregister_action(struct tc_action_ops *a);
+extern void tcf_action_destroy(struct tc_action *a, int bind);
+extern int tcf_action_exec(struct sk_buff *skb, const struct tc_action *a, struct tcf_result *res);
+extern struct tc_action *tcf_action_init(struct nlattr *nla, struct nlattr *est, char *n, int ovr, int bind);
+extern struct tc_action *tcf_action_init_1(struct nlattr *nla, struct nlattr *est, char *n, int ovr, int bind);
+extern int tcf_action_dump(struct sk_buff *skb, struct tc_action *a, int, int);
+extern int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
+extern int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
+extern int tcf_action_copy_stats (struct sk_buff *,struct tc_action *, int);
+#endif /* CONFIG_NET_CLS_ACT */
+#endif
diff --git a/include/net/activity_stats.h b/include/net/activity_stats.h
new file mode 100644
index 00000000..10e4c150
--- /dev/null
+++ b/include/net/activity_stats.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Author: Mike Chan (mike@android.com)
+ */
+
+#ifndef __activity_stats_h
+#define __activity_stats_h
+
+#ifdef CONFIG_NET_ACTIVITY_STATS
+void activity_stats_update(void);
+#else
+#define activity_stats_update(void) {}
+#endif
+
+#endif /* _NET_ACTIVITY_STATS_H */
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
new file mode 100644
index 00000000..757a1763
--- /dev/null
+++ b/include/net/addrconf.h
@@ -0,0 +1,285 @@
+#ifndef _ADDRCONF_H
+#define _ADDRCONF_H
+
+#define MAX_RTR_SOLICITATIONS 3
+#define RTR_SOLICITATION_INTERVAL (4*HZ)
+
+#define MIN_VALID_LIFETIME (2*3600) /* 2 hours */
+
+#define TEMP_VALID_LIFETIME (7*86400)
+#define TEMP_PREFERRED_LIFETIME (86400)
+#define REGEN_MAX_RETRY (3)
+#define MAX_DESYNC_FACTOR (600)
+
+#define ADDR_CHECK_FREQUENCY (120*HZ)
+
+#define IPV6_MAX_ADDRESSES 16
+
+#include <linux/in.h>
+#include <linux/in6.h>
+
+struct prefix_info {
+ __u8 type;
+ __u8 length;
+ __u8 prefix_len;
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+ __u8 onlink : 1,
+ autoconf : 1,
+ reserved : 6;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 reserved : 6,
+ autoconf : 1,
+ onlink : 1;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+ __be32 valid;
+ __be32 prefered;
+ __be32 reserved2;
+
+ struct in6_addr prefix;
+};
+
+
+#include <linux/netdevice.h>
+#include <net/if_inet6.h>
+#include <net/ipv6.h>
+
+#define IN6_ADDR_HSIZE 16
+
+extern int addrconf_init(void);
+extern void addrconf_cleanup(void);
+
+extern int addrconf_add_ifaddr(struct net *net,
+ void __user *arg);
+extern int addrconf_del_ifaddr(struct net *net,
+ void __user *arg);
+extern int addrconf_set_dstaddr(struct net *net,
+ void __user *arg);
+
+extern int ipv6_chk_addr(struct net *net,
+ const struct in6_addr *addr,
+ struct net_device *dev,
+ int strict);
+
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+extern int ipv6_chk_home_addr(struct net *net,
+ const struct in6_addr *addr);
+#endif
+
+extern int ipv6_chk_prefix(const struct in6_addr *addr,
+ struct net_device *dev);
+
+extern struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net,
+ const struct in6_addr *addr,
+ struct net_device *dev,
+ int strict);
+
+extern int ipv6_dev_get_saddr(struct net *net,
+ struct net_device *dev,
+ const struct in6_addr *daddr,
+ unsigned int srcprefs,
+ struct in6_addr *saddr);
+extern int ipv6_get_lladdr(struct net_device *dev,
+ struct in6_addr *addr,
+ unsigned char banned_flags);
+extern int ipv6_rcv_saddr_equal(const struct sock *sk,
+ const struct sock *sk2);
+extern void addrconf_join_solict(struct net_device *dev,
+ const struct in6_addr *addr);
+extern void addrconf_leave_solict(struct inet6_dev *idev,
+ const struct in6_addr *addr);
+
+static inline unsigned long addrconf_timeout_fixup(u32 timeout,
+ unsigned unit)
+{
+ if (timeout == 0xffffffff)
+ return ~0UL;
+
+ /*
+ * Avoid arithmetic overflow.
+ * Assuming unit is constant and non-zero, this "if" statement
+ * will go away on 64bit archs.
+ */
+ if (0xfffffffe > LONG_MAX / unit && timeout > LONG_MAX / unit)
+ return LONG_MAX / unit;
+
+ return timeout;
+}
+
+static inline int addrconf_finite_timeout(unsigned long timeout)
+{
+ return ~timeout;
+}
+
+/*
+ * IPv6 Address Label subsystem (addrlabel.c)
+ */
+extern int ipv6_addr_label_init(void);
+extern void ipv6_addr_label_cleanup(void);
+extern void ipv6_addr_label_rtnl_register(void);
+extern u32 ipv6_addr_label(struct net *net,
+ const struct in6_addr *addr,
+ int type, int ifindex);
+
+/*
+ * multicast prototypes (mcast.c)
+ */
+extern int ipv6_sock_mc_join(struct sock *sk, int ifindex,
+ const struct in6_addr *addr);
+extern int ipv6_sock_mc_drop(struct sock *sk, int ifindex,
+ const struct in6_addr *addr);
+extern void ipv6_sock_mc_close(struct sock *sk);
+extern int inet6_mc_check(struct sock *sk,
+ const struct in6_addr *mc_addr,
+ const struct in6_addr *src_addr);
+
+extern int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr);
+extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr);
+extern int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr);
+extern void ipv6_mc_up(struct inet6_dev *idev);
+extern void ipv6_mc_down(struct inet6_dev *idev);
+extern void ipv6_mc_unmap(struct inet6_dev *idev);
+extern void ipv6_mc_remap(struct inet6_dev *idev);
+extern void ipv6_mc_init_dev(struct inet6_dev *idev);
+extern void ipv6_mc_destroy_dev(struct inet6_dev *idev);
+extern void addrconf_dad_failure(struct inet6_ifaddr *ifp);
+
+extern int ipv6_chk_mcast_addr(struct net_device *dev,
+ const struct in6_addr *group,
+ const struct in6_addr *src_addr);
+extern int ipv6_is_mld(struct sk_buff *skb, int nexthdr);
+
+extern void addrconf_prefix_rcv(struct net_device *dev,
+ u8 *opt, int len, bool sllao);
+
+/*
+ * anycast prototypes (anycast.c)
+ */
+extern int ipv6_sock_ac_join(struct sock *sk,int ifindex, const struct in6_addr *addr);
+extern int ipv6_sock_ac_drop(struct sock *sk,int ifindex, const struct in6_addr *addr);
+extern void ipv6_sock_ac_close(struct sock *sk);
+
+extern int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr);
+extern int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr);
+extern int ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
+ const struct in6_addr *addr);
+
+
+/* Device notifier */
+extern int register_inet6addr_notifier(struct notifier_block *nb);
+extern int unregister_inet6addr_notifier(struct notifier_block *nb);
+
+/**
+ * __in6_dev_get - get inet6_dev pointer from netdevice
+ * @dev: network device
+ *
+ * Caller must hold rcu_read_lock or RTNL, because this function
+ * does not take a reference on the inet6_dev.
+ */
+static inline struct inet6_dev *__in6_dev_get(const struct net_device *dev)
+{
+ return rcu_dereference_rtnl(dev->ip6_ptr);
+}
+
+/**
+ * in6_dev_get - get inet6_dev pointer from netdevice
+ * @dev: network device
+ *
+ * This version can be used in any context, and takes a reference
+ * on the inet6_dev. Callers must use in6_dev_put() later to
+ * release this reference.
+ */
+static inline struct inet6_dev *in6_dev_get(const struct net_device *dev)
+{
+ struct inet6_dev *idev;
+
+ rcu_read_lock();
+ idev = rcu_dereference(dev->ip6_ptr);
+ if (idev)
+ atomic_inc(&idev->refcnt);
+ rcu_read_unlock();
+ return idev;
+}
+
+extern void in6_dev_finish_destroy(struct inet6_dev *idev);
+
+static inline void in6_dev_put(struct inet6_dev *idev)
+{
+ if (atomic_dec_and_test(&idev->refcnt))
+ in6_dev_finish_destroy(idev);
+}
+
+static inline void __in6_dev_put(struct inet6_dev *idev)
+{
+ atomic_dec(&idev->refcnt);
+}
+
+static inline void in6_dev_hold(struct inet6_dev *idev)
+{
+ atomic_inc(&idev->refcnt);
+}
+
+extern void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp);
+
+static inline void in6_ifa_put(struct inet6_ifaddr *ifp)
+{
+ if (atomic_dec_and_test(&ifp->refcnt))
+ inet6_ifa_finish_destroy(ifp);
+}
+
+static inline void __in6_ifa_put(struct inet6_ifaddr *ifp)
+{
+ atomic_dec(&ifp->refcnt);
+}
+
+static inline void in6_ifa_hold(struct inet6_ifaddr *ifp)
+{
+ atomic_inc(&ifp->refcnt);
+}
+
+
+/*
+ * compute link-local solicited-node multicast address
+ */
+
+static inline void addrconf_addr_solict_mult(const struct in6_addr *addr,
+ struct in6_addr *solicited)
+{
+ ipv6_addr_set(solicited,
+ htonl(0xFF020000), 0,
+ htonl(0x1),
+ htonl(0xFF000000) | addr->s6_addr32[3]);
+}
+
+static inline int ipv6_addr_is_multicast(const struct in6_addr *addr)
+{
+ return (addr->s6_addr32[0] & htonl(0xFF000000)) == htonl(0xFF000000);
+}
+
+static inline int ipv6_addr_is_ll_all_nodes(const struct in6_addr *addr)
+{
+ return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
+ addr->s6_addr32[1] | addr->s6_addr32[2] |
+ (addr->s6_addr32[3] ^ htonl(0x00000001))) == 0;
+}
+
+static inline int ipv6_addr_is_ll_all_routers(const struct in6_addr *addr)
+{
+ return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
+ addr->s6_addr32[1] | addr->s6_addr32[2] |
+ (addr->s6_addr32[3] ^ htonl(0x00000002))) == 0;
+}
+
+static inline int ipv6_addr_is_isatap(const struct in6_addr *addr)
+{
+ return (addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE);
+}
+
+#ifdef CONFIG_PROC_FS
+extern int if6_proc_init(void);
+extern void if6_proc_exit(void);
+#endif
+
+#endif
diff --git a/include/net/af_ieee802154.h b/include/net/af_ieee802154.h
new file mode 100644
index 00000000..75e64c7a
--- /dev/null
+++ b/include/net/af_ieee802154.h
@@ -0,0 +1,62 @@
+/*
+ * IEEE 802.15.4 inteface for userspace
+ *
+ * Copyright 2007, 2008 Siemens AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by:
+ * Sergey Lapin <slapin@ossfans.org>
+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
+ */
+
+#ifndef _AF_IEEE802154_H
+#define _AF_IEEE802154_H
+
+#include <linux/socket.h> /* for sa_family_t */
+
+enum {
+ IEEE802154_ADDR_NONE = 0x0,
+ /* RESERVED = 0x01, */
+ IEEE802154_ADDR_SHORT = 0x2, /* 16-bit address + PANid */
+ IEEE802154_ADDR_LONG = 0x3, /* 64-bit address + PANid */
+};
+
+/* address length, octets */
+#define IEEE802154_ADDR_LEN 8
+
+struct ieee802154_addr {
+ int addr_type;
+ u16 pan_id;
+ union {
+ u8 hwaddr[IEEE802154_ADDR_LEN];
+ u16 short_addr;
+ };
+};
+
+#define IEEE802154_PANID_BROADCAST 0xffff
+#define IEEE802154_ADDR_BROADCAST 0xffff
+#define IEEE802154_ADDR_UNDEF 0xfffe
+
+struct sockaddr_ieee802154 {
+ sa_family_t family; /* AF_IEEE802154 */
+ struct ieee802154_addr addr;
+};
+
+/* get/setsockopt */
+#define SOL_IEEE802154 0
+
+#define WPAN_WANTACK 0
+
+#endif
diff --git a/include/net/af_rxrpc.h b/include/net/af_rxrpc.h
new file mode 100644
index 00000000..03e6e945
--- /dev/null
+++ b/include/net/af_rxrpc.h
@@ -0,0 +1,54 @@
+/* RxRPC kernel service interface definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _NET_RXRPC_H
+#define _NET_RXRPC_H
+
+#include <linux/rxrpc.h>
+
+struct rxrpc_call;
+
+/*
+ * the mark applied to socket buffers that may be intercepted
+ */
+enum {
+ RXRPC_SKB_MARK_DATA, /* data message */
+ RXRPC_SKB_MARK_FINAL_ACK, /* final ACK received message */
+ RXRPC_SKB_MARK_BUSY, /* server busy message */
+ RXRPC_SKB_MARK_REMOTE_ABORT, /* remote abort message */
+ RXRPC_SKB_MARK_NET_ERROR, /* network error message */
+ RXRPC_SKB_MARK_LOCAL_ERROR, /* local error message */
+ RXRPC_SKB_MARK_NEW_CALL, /* local error message */
+};
+
+typedef void (*rxrpc_interceptor_t)(struct sock *, unsigned long,
+ struct sk_buff *);
+extern void rxrpc_kernel_intercept_rx_messages(struct socket *,
+ rxrpc_interceptor_t);
+extern struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *,
+ struct sockaddr_rxrpc *,
+ struct key *,
+ unsigned long,
+ gfp_t);
+extern int rxrpc_kernel_send_data(struct rxrpc_call *, struct msghdr *,
+ size_t);
+extern void rxrpc_kernel_abort_call(struct rxrpc_call *, u32);
+extern void rxrpc_kernel_end_call(struct rxrpc_call *);
+extern bool rxrpc_kernel_is_data_last(struct sk_buff *);
+extern u32 rxrpc_kernel_get_abort_code(struct sk_buff *);
+extern int rxrpc_kernel_get_error_number(struct sk_buff *);
+extern void rxrpc_kernel_data_delivered(struct sk_buff *);
+extern void rxrpc_kernel_free_skb(struct sk_buff *);
+extern struct rxrpc_call *rxrpc_kernel_accept_call(struct socket *,
+ unsigned long);
+extern int rxrpc_kernel_reject_call(struct socket *);
+
+#endif /* _NET_RXRPC_H */
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
new file mode 100644
index 00000000..ca68e2ce
--- /dev/null
+++ b/include/net/af_unix.h
@@ -0,0 +1,78 @@
+#ifndef __LINUX_NET_AFUNIX_H
+#define __LINUX_NET_AFUNIX_H
+
+#include <linux/socket.h>
+#include <linux/un.h>
+#include <linux/mutex.h>
+#include <net/sock.h>
+
+extern void unix_inflight(struct file *fp);
+extern void unix_notinflight(struct file *fp);
+extern void unix_gc(void);
+extern void wait_for_unix_gc(void);
+extern struct sock *unix_get_socket(struct file *filp);
+extern struct sock *unix_peer_get(struct sock *);
+
+#define UNIX_HASH_SIZE 256
+
+extern unsigned int unix_tot_inflight;
+extern spinlock_t unix_table_lock;
+extern struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1];
+
+struct unix_address {
+ atomic_t refcnt;
+ int len;
+ unsigned hash;
+ struct sockaddr_un name[0];
+};
+
+struct unix_skb_parms {
+ struct pid *pid; /* Skb credentials */
+ const struct cred *cred;
+ struct scm_fp_list *fp; /* Passed files */
+#ifdef CONFIG_SECURITY_NETWORK
+ u32 secid; /* Security ID */
+#endif
+};
+
+#define UNIXCB(skb) (*(struct unix_skb_parms *)&((skb)->cb))
+#define UNIXSID(skb) (&UNIXCB((skb)).secid)
+
+#define unix_state_lock(s) spin_lock(&unix_sk(s)->lock)
+#define unix_state_unlock(s) spin_unlock(&unix_sk(s)->lock)
+#define unix_state_lock_nested(s) \
+ spin_lock_nested(&unix_sk(s)->lock, \
+ SINGLE_DEPTH_NESTING)
+
+/* The AF_UNIX socket */
+struct unix_sock {
+ /* WARNING: sk has to be the first member */
+ struct sock sk;
+ struct unix_address *addr;
+ struct path path;
+ struct mutex readlock;
+ struct sock *peer;
+ struct sock *other;
+ struct list_head link;
+ atomic_long_t inflight;
+ spinlock_t lock;
+ unsigned int gc_candidate : 1;
+ unsigned int gc_maybe_cycle : 1;
+ unsigned char recursion_level;
+ struct socket_wq peer_wq;
+};
+#define unix_sk(__sk) ((struct unix_sock *)__sk)
+
+#define peer_wait peer_wq.wait
+
+long unix_inq_len(struct sock *sk);
+long unix_outq_len(struct sock *sk);
+
+#ifdef CONFIG_SYSCTL
+extern int unix_sysctl_register(struct net *net);
+extern void unix_sysctl_unregister(struct net *net);
+#else
+static inline int unix_sysctl_register(struct net *net) { return 0; }
+static inline void unix_sysctl_unregister(struct net *net) {}
+#endif
+#endif
diff --git a/include/net/ah.h b/include/net/ah.h
new file mode 100644
index 00000000..ca95b989
--- /dev/null
+++ b/include/net/ah.h
@@ -0,0 +1,25 @@
+#ifndef _NET_AH_H
+#define _NET_AH_H
+
+#include <linux/skbuff.h>
+
+/* This is the maximum truncated ICV length that we know of. */
+#define MAX_AH_AUTH_LEN 64
+
+struct crypto_ahash;
+
+struct ah_data {
+ int icv_full_len;
+ int icv_trunc_len;
+
+ struct crypto_ahash *ahash;
+};
+
+struct ip_auth_hdr;
+
+static inline struct ip_auth_hdr *ip_auth_hdr(const struct sk_buff *skb)
+{
+ return (struct ip_auth_hdr *)skb_transport_header(skb);
+}
+
+#endif
diff --git a/include/net/arp.h b/include/net/arp.h
new file mode 100644
index 00000000..4a1f3fb5
--- /dev/null
+++ b/include/net/arp.h
@@ -0,0 +1,59 @@
+/* linux/net/inet/arp.h */
+#ifndef _ARP_H
+#define _ARP_H
+
+#include <linux/if_arp.h>
+#include <net/neighbour.h>
+
+
+extern struct neigh_table arp_tbl;
+
+static inline u32 arp_hashfn(u32 key, const struct net_device *dev, u32 hash_rnd)
+{
+ u32 val = key ^ dev->ifindex;
+
+ return val * hash_rnd;
+}
+
+static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32 key)
+{
+ struct neigh_hash_table *nht;
+ struct neighbour *n;
+ u32 hash_val;
+
+ rcu_read_lock_bh();
+ nht = rcu_dereference_bh(arp_tbl.nht);
+ hash_val = arp_hashfn(key, dev, nht->hash_rnd[0]) >> (32 - nht->hash_shift);
+ for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
+ n != NULL;
+ n = rcu_dereference_bh(n->next)) {
+ if (n->dev == dev && *(u32 *)n->primary_key == key) {
+ if (!atomic_inc_not_zero(&n->refcnt))
+ n = NULL;
+ break;
+ }
+ }
+ rcu_read_unlock_bh();
+
+ return n;
+}
+
+extern void arp_init(void);
+extern int arp_find(unsigned char *haddr, struct sk_buff *skb);
+extern int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg);
+extern void arp_send(int type, int ptype, __be32 dest_ip,
+ struct net_device *dev, __be32 src_ip,
+ const unsigned char *dest_hw,
+ const unsigned char *src_hw, const unsigned char *th);
+extern int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir);
+extern void arp_ifdown(struct net_device *dev);
+
+extern struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
+ struct net_device *dev, __be32 src_ip,
+ const unsigned char *dest_hw,
+ const unsigned char *src_hw,
+ const unsigned char *target_hw);
+extern void arp_xmit(struct sk_buff *skb);
+int arp_invalidate(struct net_device *dev, __be32 ip);
+
+#endif /* _ARP_H */
diff --git a/include/net/atmclip.h b/include/net/atmclip.h
new file mode 100644
index 00000000..5865924d
--- /dev/null
+++ b/include/net/atmclip.h
@@ -0,0 +1,52 @@
+/* net/atm/atmarp.h - RFC1577 ATM ARP */
+
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
+
+
+#ifndef _ATMCLIP_H
+#define _ATMCLIP_H
+
+#include <linux/netdevice.h>
+#include <linux/atm.h>
+#include <linux/atmdev.h>
+#include <linux/atmarp.h>
+#include <linux/spinlock.h>
+#include <net/neighbour.h>
+
+
+#define CLIP_VCC(vcc) ((struct clip_vcc *) ((vcc)->user_back))
+
+struct sk_buff;
+
+struct clip_vcc {
+ struct atm_vcc *vcc; /* VCC descriptor */
+ struct atmarp_entry *entry; /* ATMARP table entry, NULL if IP addr.
+ isn't known yet */
+ int xoff; /* 1 if send buffer is full */
+ unsigned char encap; /* 0: NULL, 1: LLC/SNAP */
+ unsigned long last_use; /* last send or receive operation */
+ unsigned long idle_timeout; /* keep open idle for so many jiffies*/
+ void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb);
+ /* keep old push fn for chaining */
+ void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb);
+ /* keep old pop fn for chaining */
+ struct clip_vcc *next; /* next VCC */
+};
+
+
+struct atmarp_entry {
+ struct clip_vcc *vccs; /* active VCCs; NULL if resolution is
+ pending */
+ unsigned long expires; /* entry expiration time */
+ struct neighbour *neigh; /* neighbour back-pointer */
+};
+
+#define PRIV(dev) ((struct clip_priv *) netdev_priv(dev))
+
+struct clip_priv {
+ int number; /* for convenience ... */
+ spinlock_t xoff_lock; /* ensures that pop is atomic (SMP) */
+ struct net_device *next; /* next CLIP interface */
+};
+
+#endif
diff --git a/include/net/ax25.h b/include/net/ax25.h
new file mode 100644
index 00000000..94e09d36
--- /dev/null
+++ b/include/net/ax25.h
@@ -0,0 +1,451 @@
+/*
+ * Declarations of AX.25 type objects.
+ *
+ * Alan Cox (GW4PTS) 10/11/93
+ */
+#ifndef _AX25_H
+#define _AX25_H
+
+#include <linux/ax25.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/atomic.h>
+
+#define AX25_T1CLAMPLO 1
+#define AX25_T1CLAMPHI (30 * HZ)
+
+#define AX25_BPQ_HEADER_LEN 16
+#define AX25_KISS_HEADER_LEN 1
+
+#define AX25_HEADER_LEN 17
+#define AX25_ADDR_LEN 7
+#define AX25_DIGI_HEADER_LEN (AX25_MAX_DIGIS * AX25_ADDR_LEN)
+#define AX25_MAX_HEADER_LEN (AX25_HEADER_LEN + AX25_DIGI_HEADER_LEN)
+
+/* AX.25 Protocol IDs */
+#define AX25_P_ROSE 0x01
+#define AX25_P_VJCOMP 0x06 /* Compressed TCP/IP packet */
+ /* Van Jacobsen (RFC 1144) */
+#define AX25_P_VJUNCOMP 0x07 /* Uncompressed TCP/IP packet */
+ /* Van Jacobsen (RFC 1144) */
+#define AX25_P_SEGMENT 0x08 /* Segmentation fragment */
+#define AX25_P_TEXNET 0xc3 /* TEXTNET datagram protocol */
+#define AX25_P_LQ 0xc4 /* Link Quality Protocol */
+#define AX25_P_ATALK 0xca /* Appletalk */
+#define AX25_P_ATALK_ARP 0xcb /* Appletalk ARP */
+#define AX25_P_IP 0xcc /* ARPA Internet Protocol */
+#define AX25_P_ARP 0xcd /* ARPA Address Resolution */
+#define AX25_P_FLEXNET 0xce /* FlexNet */
+#define AX25_P_NETROM 0xcf /* NET/ROM */
+#define AX25_P_TEXT 0xF0 /* No layer 3 protocol impl. */
+
+/* AX.25 Segment control values */
+#define AX25_SEG_REM 0x7F
+#define AX25_SEG_FIRST 0x80
+
+#define AX25_CBIT 0x80 /* Command/Response bit */
+#define AX25_EBIT 0x01 /* HDLC Address Extension bit */
+#define AX25_HBIT 0x80 /* Has been repeated bit */
+
+#define AX25_SSSID_SPARE 0x60 /* Unused bits in SSID for standard AX.25 */
+#define AX25_ESSID_SPARE 0x20 /* Unused bits in SSID for extended AX.25 */
+#define AX25_DAMA_FLAG 0x20 /* Well, it is *NOT* unused! (dl1bke 951121 */
+
+#define AX25_COND_ACK_PENDING 0x01
+#define AX25_COND_REJECT 0x02
+#define AX25_COND_PEER_RX_BUSY 0x04
+#define AX25_COND_OWN_RX_BUSY 0x08
+#define AX25_COND_DAMA_MODE 0x10
+
+#ifndef _LINUX_NETDEVICE_H
+#include <linux/netdevice.h>
+#endif
+
+/* Upper sub-layer (LAPB) definitions */
+
+/* Control field templates */
+#define AX25_I 0x00 /* Information frames */
+#define AX25_S 0x01 /* Supervisory frames */
+#define AX25_RR 0x01 /* Receiver ready */
+#define AX25_RNR 0x05 /* Receiver not ready */
+#define AX25_REJ 0x09 /* Reject */
+#define AX25_U 0x03 /* Unnumbered frames */
+#define AX25_SABM 0x2f /* Set Asynchronous Balanced Mode */
+#define AX25_SABME 0x6f /* Set Asynchronous Balanced Mode Extended */
+#define AX25_DISC 0x43 /* Disconnect */
+#define AX25_DM 0x0f /* Disconnected mode */
+#define AX25_UA 0x63 /* Unnumbered acknowledge */
+#define AX25_FRMR 0x87 /* Frame reject */
+#define AX25_UI 0x03 /* Unnumbered information */
+#define AX25_XID 0xaf /* Exchange information */
+#define AX25_TEST 0xe3 /* Test */
+
+#define AX25_PF 0x10 /* Poll/final bit for standard AX.25 */
+#define AX25_EPF 0x01 /* Poll/final bit for extended AX.25 */
+
+#define AX25_ILLEGAL 0x100 /* Impossible to be a real frame type */
+
+#define AX25_POLLOFF 0
+#define AX25_POLLON 1
+
+/* AX25 L2 C-bit */
+#define AX25_COMMAND 1
+#define AX25_RESPONSE 2
+
+/* Define Link State constants. */
+
+enum {
+ AX25_STATE_0, /* Listening */
+ AX25_STATE_1, /* SABM sent */
+ AX25_STATE_2, /* DISC sent */
+ AX25_STATE_3, /* Established */
+ AX25_STATE_4 /* Recovery */
+};
+
+#define AX25_MODULUS 8 /* Standard AX.25 modulus */
+#define AX25_EMODULUS 128 /* Extended AX.25 modulus */
+
+enum {
+ AX25_PROTO_STD_SIMPLEX,
+ AX25_PROTO_STD_DUPLEX,
+#ifdef CONFIG_AX25_DAMA_SLAVE
+ AX25_PROTO_DAMA_SLAVE,
+#ifdef CONFIG_AX25_DAMA_MASTER
+ AX25_PROTO_DAMA_MASTER,
+#define AX25_PROTO_MAX AX25_PROTO_DAMA_MASTER
+#endif
+#endif
+ __AX25_PROTO_MAX,
+ AX25_PROTO_MAX = __AX25_PROTO_MAX -1
+};
+
+enum {
+ AX25_VALUES_IPDEFMODE, /* 0=DG 1=VC */
+ AX25_VALUES_AXDEFMODE, /* 0=Normal 1=Extended Seq Nos */
+ AX25_VALUES_BACKOFF, /* 0=None 1=Linear 2=Exponential */
+ AX25_VALUES_CONMODE, /* Allow connected modes - 0=No 1=no "PID text" 2=all PIDs */
+ AX25_VALUES_WINDOW, /* Default window size for standard AX.25 */
+ AX25_VALUES_EWINDOW, /* Default window size for extended AX.25 */
+ AX25_VALUES_T1, /* Default T1 timeout value */
+ AX25_VALUES_T2, /* Default T2 timeout value */
+ AX25_VALUES_T3, /* Default T3 timeout value */
+ AX25_VALUES_IDLE, /* Connected mode idle timer */
+ AX25_VALUES_N2, /* Default N2 value */
+ AX25_VALUES_PACLEN, /* AX.25 MTU */
+ AX25_VALUES_PROTOCOL, /* Std AX.25, DAMA Slave, DAMA Master */
+ AX25_VALUES_DS_TIMEOUT, /* DAMA Slave timeout */
+ AX25_MAX_VALUES /* THIS MUST REMAIN THE LAST ENTRY OF THIS LIST */
+};
+
+#define AX25_DEF_IPDEFMODE 0 /* Datagram */
+#define AX25_DEF_AXDEFMODE 0 /* Normal */
+#define AX25_DEF_BACKOFF 1 /* Linear backoff */
+#define AX25_DEF_CONMODE 2 /* Connected mode allowed */
+#define AX25_DEF_WINDOW 2 /* Window=2 */
+#define AX25_DEF_EWINDOW 32 /* Module-128 Window=32 */
+#define AX25_DEF_T1 10000 /* T1=10s */
+#define AX25_DEF_T2 3000 /* T2=3s */
+#define AX25_DEF_T3 300000 /* T3=300s */
+#define AX25_DEF_N2 10 /* N2=10 */
+#define AX25_DEF_IDLE 0 /* Idle=None */
+#define AX25_DEF_PACLEN 256 /* Paclen=256 */
+#define AX25_DEF_PROTOCOL AX25_PROTO_STD_SIMPLEX /* Standard AX.25 */
+#define AX25_DEF_DS_TIMEOUT 180000 /* DAMA timeout 3 minutes */
+
+typedef struct ax25_uid_assoc {
+ struct hlist_node uid_node;
+ atomic_t refcount;
+ uid_t uid;
+ ax25_address call;
+} ax25_uid_assoc;
+
+#define ax25_uid_for_each(__ax25, node, list) \
+ hlist_for_each_entry(__ax25, node, list, uid_node)
+
+#define ax25_uid_hold(ax25) \
+ atomic_inc(&((ax25)->refcount))
+
+static inline void ax25_uid_put(ax25_uid_assoc *assoc)
+{
+ if (atomic_dec_and_test(&assoc->refcount)) {
+ kfree(assoc);
+ }
+}
+
+typedef struct {
+ ax25_address calls[AX25_MAX_DIGIS];
+ unsigned char repeated[AX25_MAX_DIGIS];
+ unsigned char ndigi;
+ signed char lastrepeat;
+} ax25_digi;
+
+typedef struct ax25_route {
+ struct ax25_route *next;
+ atomic_t refcount;
+ ax25_address callsign;
+ struct net_device *dev;
+ ax25_digi *digipeat;
+ char ip_mode;
+} ax25_route;
+
+static inline void ax25_hold_route(ax25_route *ax25_rt)
+{
+ atomic_inc(&ax25_rt->refcount);
+}
+
+extern void __ax25_put_route(ax25_route *ax25_rt);
+
+static inline void ax25_put_route(ax25_route *ax25_rt)
+{
+ if (atomic_dec_and_test(&ax25_rt->refcount))
+ __ax25_put_route(ax25_rt);
+}
+
+typedef struct {
+ char slave; /* slave_mode? */
+ struct timer_list slave_timer; /* timeout timer */
+ unsigned short slave_timeout; /* when? */
+} ax25_dama_info;
+
+struct ctl_table;
+
+typedef struct ax25_dev {
+ struct ax25_dev *next;
+ struct net_device *dev;
+ struct net_device *forward;
+ struct ctl_table *systable;
+ int values[AX25_MAX_VALUES];
+#if defined(CONFIG_AX25_DAMA_SLAVE) || defined(CONFIG_AX25_DAMA_MASTER)
+ ax25_dama_info dama;
+#endif
+} ax25_dev;
+
+typedef struct ax25_cb {
+ struct hlist_node ax25_node;
+ ax25_address source_addr, dest_addr;
+ ax25_digi *digipeat;
+ ax25_dev *ax25_dev;
+ unsigned char iamdigi;
+ unsigned char state, modulus, pidincl;
+ unsigned short vs, vr, va;
+ unsigned char condition, backoff;
+ unsigned char n2, n2count;
+ struct timer_list t1timer, t2timer, t3timer, idletimer;
+ unsigned long t1, t2, t3, idle, rtt;
+ unsigned short paclen, fragno, fraglen;
+ struct sk_buff_head write_queue;
+ struct sk_buff_head reseq_queue;
+ struct sk_buff_head ack_queue;
+ struct sk_buff_head frag_queue;
+ unsigned char window;
+ struct timer_list timer, dtimer;
+ struct sock *sk; /* Backlink to socket */
+ atomic_t refcount;
+} ax25_cb;
+
+#define ax25_sk(__sk) ((ax25_cb *)(__sk)->sk_protinfo)
+
+#define ax25_for_each(__ax25, node, list) \
+ hlist_for_each_entry(__ax25, node, list, ax25_node)
+
+#define ax25_cb_hold(__ax25) \
+ atomic_inc(&((__ax25)->refcount))
+
+static __inline__ void ax25_cb_put(ax25_cb *ax25)
+{
+ if (atomic_dec_and_test(&ax25->refcount)) {
+ kfree(ax25->digipeat);
+ kfree(ax25);
+ }
+}
+
+static inline __be16 ax25_type_trans(struct sk_buff *skb, struct net_device *dev)
+{
+ skb->dev = dev;
+ skb_reset_mac_header(skb);
+ skb->pkt_type = PACKET_HOST;
+ return htons(ETH_P_AX25);
+}
+
+/* af_ax25.c */
+extern struct hlist_head ax25_list;
+extern spinlock_t ax25_list_lock;
+extern void ax25_cb_add(ax25_cb *);
+struct sock *ax25_find_listener(ax25_address *, int, struct net_device *, int);
+struct sock *ax25_get_socket(ax25_address *, ax25_address *, int);
+extern ax25_cb *ax25_find_cb(ax25_address *, ax25_address *, ax25_digi *, struct net_device *);
+extern void ax25_send_to_raw(ax25_address *, struct sk_buff *, int);
+extern void ax25_destroy_socket(ax25_cb *);
+extern ax25_cb * __must_check ax25_create_cb(void);
+extern void ax25_fillin_cb(ax25_cb *, ax25_dev *);
+extern struct sock *ax25_make_new(struct sock *, struct ax25_dev *);
+
+/* ax25_addr.c */
+extern const ax25_address ax25_bcast;
+extern const ax25_address ax25_defaddr;
+extern const ax25_address null_ax25_address;
+extern char *ax2asc(char *buf, const ax25_address *);
+extern void asc2ax(ax25_address *addr, const char *callsign);
+extern int ax25cmp(const ax25_address *, const ax25_address *);
+extern int ax25digicmp(const ax25_digi *, const ax25_digi *);
+extern const unsigned char *ax25_addr_parse(const unsigned char *, int,
+ ax25_address *, ax25_address *, ax25_digi *, int *, int *);
+extern int ax25_addr_build(unsigned char *, const ax25_address *,
+ const ax25_address *, const ax25_digi *, int, int);
+extern int ax25_addr_size(const ax25_digi *);
+extern void ax25_digi_invert(const ax25_digi *, ax25_digi *);
+
+/* ax25_dev.c */
+extern ax25_dev *ax25_dev_list;
+extern spinlock_t ax25_dev_lock;
+
+static inline ax25_dev *ax25_dev_ax25dev(struct net_device *dev)
+{
+ return dev->ax25_ptr;
+}
+
+extern ax25_dev *ax25_addr_ax25dev(ax25_address *);
+extern void ax25_dev_device_up(struct net_device *);
+extern void ax25_dev_device_down(struct net_device *);
+extern int ax25_fwd_ioctl(unsigned int, struct ax25_fwd_struct *);
+extern struct net_device *ax25_fwd_dev(struct net_device *);
+extern void ax25_dev_free(void);
+
+/* ax25_ds_in.c */
+extern int ax25_ds_frame_in(ax25_cb *, struct sk_buff *, int);
+
+/* ax25_ds_subr.c */
+extern void ax25_ds_nr_error_recovery(ax25_cb *);
+extern void ax25_ds_enquiry_response(ax25_cb *);
+extern void ax25_ds_establish_data_link(ax25_cb *);
+extern void ax25_dev_dama_off(ax25_dev *);
+extern void ax25_dama_on(ax25_cb *);
+extern void ax25_dama_off(ax25_cb *);
+
+/* ax25_ds_timer.c */
+extern void ax25_ds_setup_timer(ax25_dev *);
+extern void ax25_ds_set_timer(ax25_dev *);
+extern void ax25_ds_del_timer(ax25_dev *);
+extern void ax25_ds_timer(ax25_cb *);
+extern void ax25_ds_t1_timeout(ax25_cb *);
+extern void ax25_ds_heartbeat_expiry(ax25_cb *);
+extern void ax25_ds_t3timer_expiry(ax25_cb *);
+extern void ax25_ds_idletimer_expiry(ax25_cb *);
+
+/* ax25_iface.c */
+
+struct ax25_protocol {
+ struct ax25_protocol *next;
+ unsigned int pid;
+ int (*func)(struct sk_buff *, ax25_cb *);
+};
+
+extern void ax25_register_pid(struct ax25_protocol *ap);
+extern void ax25_protocol_release(unsigned int);
+
+struct ax25_linkfail {
+ struct hlist_node lf_node;
+ void (*func)(ax25_cb *, int);
+};
+
+extern void ax25_linkfail_register(struct ax25_linkfail *lf);
+extern void ax25_linkfail_release(struct ax25_linkfail *lf);
+extern int __must_check ax25_listen_register(ax25_address *,
+ struct net_device *);
+extern void ax25_listen_release(ax25_address *, struct net_device *);
+extern int (*ax25_protocol_function(unsigned int))(struct sk_buff *, ax25_cb *);
+extern int ax25_listen_mine(ax25_address *, struct net_device *);
+extern void ax25_link_failed(ax25_cb *, int);
+extern int ax25_protocol_is_registered(unsigned int);
+
+/* ax25_in.c */
+extern int ax25_rx_iframe(ax25_cb *, struct sk_buff *);
+extern int ax25_kiss_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *);
+
+/* ax25_ip.c */
+extern int ax25_hard_header(struct sk_buff *, struct net_device *,
+ unsigned short, const void *,
+ const void *, unsigned int);
+extern int ax25_rebuild_header(struct sk_buff *);
+extern const struct header_ops ax25_header_ops;
+
+/* ax25_out.c */
+extern ax25_cb *ax25_send_frame(struct sk_buff *, int, ax25_address *, ax25_address *, ax25_digi *, struct net_device *);
+extern void ax25_output(ax25_cb *, int, struct sk_buff *);
+extern void ax25_kick(ax25_cb *);
+extern void ax25_transmit_buffer(ax25_cb *, struct sk_buff *, int);
+extern void ax25_queue_xmit(struct sk_buff *skb, struct net_device *dev);
+extern int ax25_check_iframes_acked(ax25_cb *, unsigned short);
+
+/* ax25_route.c */
+extern void ax25_rt_device_down(struct net_device *);
+extern int ax25_rt_ioctl(unsigned int, void __user *);
+extern const struct file_operations ax25_route_fops;
+extern ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev);
+extern int ax25_rt_autobind(ax25_cb *, ax25_address *);
+extern struct sk_buff *ax25_rt_build_path(struct sk_buff *, ax25_address *, ax25_address *, ax25_digi *);
+extern void ax25_rt_free(void);
+
+/* ax25_std_in.c */
+extern int ax25_std_frame_in(ax25_cb *, struct sk_buff *, int);
+
+/* ax25_std_subr.c */
+extern void ax25_std_nr_error_recovery(ax25_cb *);
+extern void ax25_std_establish_data_link(ax25_cb *);
+extern void ax25_std_transmit_enquiry(ax25_cb *);
+extern void ax25_std_enquiry_response(ax25_cb *);
+extern void ax25_std_timeout_response(ax25_cb *);
+
+/* ax25_std_timer.c */
+extern void ax25_std_heartbeat_expiry(ax25_cb *);
+extern void ax25_std_t1timer_expiry(ax25_cb *);
+extern void ax25_std_t2timer_expiry(ax25_cb *);
+extern void ax25_std_t3timer_expiry(ax25_cb *);
+extern void ax25_std_idletimer_expiry(ax25_cb *);
+
+/* ax25_subr.c */
+extern void ax25_clear_queues(ax25_cb *);
+extern void ax25_frames_acked(ax25_cb *, unsigned short);
+extern void ax25_requeue_frames(ax25_cb *);
+extern int ax25_validate_nr(ax25_cb *, unsigned short);
+extern int ax25_decode(ax25_cb *, struct sk_buff *, int *, int *, int *);
+extern void ax25_send_control(ax25_cb *, int, int, int);
+extern void ax25_return_dm(struct net_device *, ax25_address *, ax25_address *, ax25_digi *);
+extern void ax25_calculate_t1(ax25_cb *);
+extern void ax25_calculate_rtt(ax25_cb *);
+extern void ax25_disconnect(ax25_cb *, int);
+
+/* ax25_timer.c */
+extern void ax25_setup_timers(ax25_cb *);
+extern void ax25_start_heartbeat(ax25_cb *);
+extern void ax25_start_t1timer(ax25_cb *);
+extern void ax25_start_t2timer(ax25_cb *);
+extern void ax25_start_t3timer(ax25_cb *);
+extern void ax25_start_idletimer(ax25_cb *);
+extern void ax25_stop_heartbeat(ax25_cb *);
+extern void ax25_stop_t1timer(ax25_cb *);
+extern void ax25_stop_t2timer(ax25_cb *);
+extern void ax25_stop_t3timer(ax25_cb *);
+extern void ax25_stop_idletimer(ax25_cb *);
+extern int ax25_t1timer_running(ax25_cb *);
+extern unsigned long ax25_display_timer(struct timer_list *);
+
+/* ax25_uid.c */
+extern int ax25_uid_policy;
+extern ax25_uid_assoc *ax25_findbyuid(uid_t);
+extern int __must_check ax25_uid_ioctl(int, struct sockaddr_ax25 *);
+extern const struct file_operations ax25_uid_fops;
+extern void ax25_uid_free(void);
+
+/* sysctl_net_ax25.c */
+#ifdef CONFIG_SYSCTL
+extern void ax25_register_sysctl(void);
+extern void ax25_unregister_sysctl(void);
+#else
+static inline void ax25_register_sysctl(void) {};
+static inline void ax25_unregister_sysctl(void) {};
+#endif /* CONFIG_SYSCTL */
+
+#endif
diff --git a/include/net/ax88796.h b/include/net/ax88796.h
new file mode 100644
index 00000000..b9a3beca
--- /dev/null
+++ b/include/net/ax88796.h
@@ -0,0 +1,31 @@
+/* include/net/ax88796.h
+ *
+ * Copyright 2005 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#ifndef __NET_AX88796_PLAT_H
+#define __NET_AX88796_PLAT_H
+
+#define AXFLG_HAS_EEPROM (1<<0)
+#define AXFLG_MAC_FROMDEV (1<<1) /* device already has MAC */
+#define AXFLG_HAS_93CX6 (1<<2) /* use eeprom_93cx6 driver */
+#define AXFLG_MAC_FROMPLATFORM (1<<3) /* MAC given by platform data */
+
+struct ax_plat_data {
+ unsigned int flags;
+ unsigned char wordlength; /* 1 or 2 */
+ unsigned char dcr_val; /* default value for DCR */
+ unsigned char rcr_val; /* default value for RCR */
+ unsigned char gpoc_val; /* default value for GPOC */
+ u32 *reg_offsets; /* register offsets */
+ u8 *mac_addr; /* MAC addr (only used when
+ AXFLG_MAC_FROMPLATFORM is used */
+};
+
+#endif /* __NET_AX88796_PLAT_H */
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
new file mode 100644
index 00000000..a65910bd
--- /dev/null
+++ b/include/net/bluetooth/bluetooth.h
@@ -0,0 +1,290 @@
+/*
+ BlueZ - Bluetooth protocol stack for Linux
+ Copyright (C) 2000-2001 Qualcomm Incorporated
+
+ Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+ CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ SOFTWARE IS DISCLAIMED.
+*/
+
+#ifndef __BLUETOOTH_H
+#define __BLUETOOTH_H
+
+#include <asm/types.h>
+#include <asm/byteorder.h>
+#include <linux/list.h>
+#include <linux/poll.h>
+#include <net/sock.h>
+
+#ifndef AF_BLUETOOTH
+#define AF_BLUETOOTH 31
+#define PF_BLUETOOTH AF_BLUETOOTH
+#endif
+
+/* Bluetooth versions */
+#define BLUETOOTH_VER_1_1 1
+#define BLUETOOTH_VER_1_2 2
+#define BLUETOOTH_VER_2_0 3
+
+/* Reserv for core and drivers use */
+#define BT_SKB_RESERVE 8
+
+#define BTPROTO_L2CAP 0
+#define BTPROTO_HCI 1
+#define BTPROTO_SCO 2
+#define BTPROTO_RFCOMM 3
+#define BTPROTO_BNEP 4
+#define BTPROTO_CMTP 5
+#define BTPROTO_HIDP 6
+#define BTPROTO_AVDTP 7
+
+#define SOL_HCI 0
+#define SOL_L2CAP 6
+#define SOL_SCO 17
+#define SOL_RFCOMM 18
+
+#define BT_SECURITY 4
+struct bt_security {
+ __u8 level;
+ __u8 key_size;
+};
+#define BT_SECURITY_SDP 0
+#define BT_SECURITY_LOW 1
+#define BT_SECURITY_MEDIUM 2
+#define BT_SECURITY_HIGH 3
+
+#define BT_DEFER_SETUP 7
+
+#define BT_FLUSHABLE 8
+
+#define BT_FLUSHABLE_OFF 0
+#define BT_FLUSHABLE_ON 1
+
+#define BT_POWER 9
+struct bt_power {
+ __u8 force_active;
+};
+#define BT_POWER_FORCE_ACTIVE_OFF 0
+#define BT_POWER_FORCE_ACTIVE_ON 1
+
+#define BT_CHANNEL_POLICY 10
+
+/* BR/EDR only (default policy)
+ * AMP controllers cannot be used.
+ * Channel move requests from the remote device are denied.
+ * If the L2CAP channel is currently using AMP, move the channel to BR/EDR.
+ */
+#define BT_CHANNEL_POLICY_BREDR_ONLY 0
+
+/* BR/EDR Preferred
+ * Allow use of AMP controllers.
+ * If the L2CAP channel is currently on AMP, move it to BR/EDR.
+ * Channel move requests from the remote device are allowed.
+ */
+#define BT_CHANNEL_POLICY_BREDR_PREFERRED 1
+
+/* AMP Preferred
+ * Allow use of AMP controllers
+ * If the L2CAP channel is currently on BR/EDR and AMP controller
+ * resources are available, initiate a channel move to AMP.
+ * Channel move requests from the remote device are allowed.
+ * If the L2CAP socket has not been connected yet, try to create
+ * and configure the channel directly on an AMP controller rather
+ * than BR/EDR.
+ */
+#define BT_CHANNEL_POLICY_AMP_PREFERRED 2
+
+__printf(1, 2)
+int bt_info(const char *fmt, ...);
+__printf(1, 2)
+int bt_err(const char *fmt, ...);
+
+#define BT_INFO(fmt, ...) bt_info(fmt "\n", ##__VA_ARGS__)
+#define BT_ERR(fmt, ...) bt_err(fmt "\n", ##__VA_ARGS__)
+#define BT_DBG(fmt, ...) pr_debug(fmt "\n", ##__VA_ARGS__)
+
+/* Connection and socket states */
+enum {
+ BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */
+ BT_OPEN,
+ BT_BOUND,
+ BT_LISTEN,
+ BT_CONNECT,
+ BT_CONNECT2,
+ BT_CONFIG,
+ BT_DISCONN,
+ BT_CLOSED
+};
+
+/* If unused will be removed by compiler */
+static inline const char *state_to_string(int state)
+{
+ switch (state) {
+ case BT_CONNECTED:
+ return "BT_CONNECTED";
+ case BT_OPEN:
+ return "BT_OPEN";
+ case BT_BOUND:
+ return "BT_BOUND";
+ case BT_LISTEN:
+ return "BT_LISTEN";
+ case BT_CONNECT:
+ return "BT_CONNECT";
+ case BT_CONNECT2:
+ return "BT_CONNECT2";
+ case BT_CONFIG:
+ return "BT_CONFIG";
+ case BT_DISCONN:
+ return "BT_DISCONN";
+ case BT_CLOSED:
+ return "BT_CLOSED";
+ }
+
+ return "invalid state";
+}
+
+/* BD Address */
+typedef struct {
+ __u8 b[6];
+} __packed bdaddr_t;
+
+#define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0}})
+#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}})
+
+/* Copy, swap, convert BD Address */
+static inline int bacmp(bdaddr_t *ba1, bdaddr_t *ba2)
+{
+ return memcmp(ba1, ba2, sizeof(bdaddr_t));
+}
+static inline void bacpy(bdaddr_t *dst, bdaddr_t *src)
+{
+ memcpy(dst, src, sizeof(bdaddr_t));
+}
+
+void baswap(bdaddr_t *dst, bdaddr_t *src);
+char *batostr(bdaddr_t *ba);
+bdaddr_t *strtoba(char *str);
+
+/* Common socket structures and functions */
+
+#define bt_sk(__sk) ((struct bt_sock *) __sk)
+
+struct bt_sock {
+ struct sock sk;
+ bdaddr_t src;
+ bdaddr_t dst;
+ struct list_head accept_q;
+ struct sock *parent;
+ u32 defer_setup;
+ bool suspended;
+};
+
+struct bt_sock_list {
+ struct hlist_head head;
+ rwlock_t lock;
+};
+
+int bt_sock_register(int proto, const struct net_proto_family *ops);
+int bt_sock_unregister(int proto);
+void bt_sock_link(struct bt_sock_list *l, struct sock *s);
+void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
+int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *msg, size_t len, int flags);
+int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *msg, size_t len, int flags);
+uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait);
+int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
+int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo);
+
+void bt_accept_enqueue(struct sock *parent, struct sock *sk);
+void bt_accept_unlink(struct sock *sk);
+struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock);
+
+/* Skb helpers */
+struct bt_skb_cb {
+ __u8 pkt_type;
+ __u8 incoming;
+ __u16 expect;
+ __u16 tx_seq;
+ __u8 retries;
+ __u8 sar;
+ __u8 force_active;
+};
+#define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
+
+static inline struct sk_buff *bt_skb_alloc(unsigned int len, gfp_t how)
+{
+ struct sk_buff *skb;
+
+ if ((skb = alloc_skb(len + BT_SKB_RESERVE, how))) {
+ skb_reserve(skb, BT_SKB_RESERVE);
+ bt_cb(skb)->incoming = 0;
+ }
+ return skb;
+}
+
+static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk,
+ unsigned long len, int nb, int *err)
+{
+ struct sk_buff *skb;
+
+ release_sock(sk);
+ if ((skb = sock_alloc_send_skb(sk, len + BT_SKB_RESERVE, nb, err))) {
+ skb_reserve(skb, BT_SKB_RESERVE);
+ bt_cb(skb)->incoming = 0;
+ }
+ lock_sock(sk);
+
+ if (!skb && *err)
+ return NULL;
+
+ *err = sock_error(sk);
+ if (*err)
+ goto out;
+
+ if (sk->sk_shutdown) {
+ *err = -ECONNRESET;
+ goto out;
+ }
+
+ return skb;
+
+out:
+ kfree_skb(skb);
+ return NULL;
+}
+
+int bt_to_errno(__u16 code);
+
+extern int hci_sock_init(void);
+extern void hci_sock_cleanup(void);
+
+extern int bt_sysfs_init(void);
+extern void bt_sysfs_cleanup(void);
+
+extern struct dentry *bt_debugfs;
+
+int l2cap_init(void);
+void l2cap_exit(void);
+
+int sco_init(void);
+void sco_exit(void);
+
+void bt_sock_reclassify_lock(struct sock *sk, int proto);
+
+#endif /* __BLUETOOTH_H */
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
new file mode 100644
index 00000000..78132a8a
--- /dev/null
+++ b/include/net/bluetooth/hci.h
@@ -0,0 +1,1441 @@
+/*
+ BlueZ - Bluetooth protocol stack for Linux
+ Copyright (C) 2000-2001 Qualcomm Incorporated
+
+ Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+ CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ SOFTWARE IS DISCLAIMED.
+*/
+
+#ifndef __HCI_H
+#define __HCI_H
+
+#define HCI_MAX_ACL_SIZE 1024
+#define HCI_MAX_SCO_SIZE 255
+#define HCI_MAX_EVENT_SIZE 260
+#define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4)
+
+/* HCI dev events */
+#define HCI_DEV_REG 1
+#define HCI_DEV_UNREG 2
+#define HCI_DEV_UP 3
+#define HCI_DEV_DOWN 4
+#define HCI_DEV_SUSPEND 5
+#define HCI_DEV_RESUME 6
+
+/* HCI notify events */
+#define HCI_NOTIFY_CONN_ADD 1
+#define HCI_NOTIFY_CONN_DEL 2
+#define HCI_NOTIFY_VOICE_SETTING 3
+
+/* HCI bus types */
+#define HCI_VIRTUAL 0
+#define HCI_USB 1
+#define HCI_PCCARD 2
+#define HCI_UART 3
+#define HCI_RS232 4
+#define HCI_PCI 5
+#define HCI_SDIO 6
+
+/* HCI controller types */
+#define HCI_BREDR 0x00
+#define HCI_AMP 0x01
+
+/* HCI device quirks */
+enum {
+ HCI_QUIRK_NO_RESET,
+ HCI_QUIRK_RAW_DEVICE,
+ HCI_QUIRK_FIXUP_BUFFER_SIZE
+};
+
+/* HCI device flags */
+enum {
+ HCI_UP,
+ HCI_INIT,
+ HCI_RUNNING,
+
+ HCI_PSCAN,
+ HCI_ISCAN,
+ HCI_AUTH,
+ HCI_ENCRYPT,
+ HCI_INQUIRY,
+
+ HCI_RAW,
+
+ HCI_RESET,
+};
+
+/*
+ * BR/EDR and/or LE controller flags: the flags defined here should represent
+ * states from the controller.
+ */
+enum {
+ HCI_SETUP,
+ HCI_AUTO_OFF,
+ HCI_MGMT,
+ HCI_PAIRABLE,
+ HCI_SERVICE_CACHE,
+ HCI_LINK_KEYS,
+ HCI_DEBUG_KEYS,
+ HCI_UNREGISTER,
+
+ HCI_LE_SCAN,
+ HCI_SSP_ENABLED,
+ HCI_HS_ENABLED,
+ HCI_LE_ENABLED,
+ HCI_CONNECTABLE,
+ HCI_DISCOVERABLE,
+ HCI_LINK_SECURITY,
+ HCI_PENDING_CLASS,
+};
+
+/* HCI ioctl defines */
+#define HCIDEVUP _IOW('H', 201, int)
+#define HCIDEVDOWN _IOW('H', 202, int)
+#define HCIDEVRESET _IOW('H', 203, int)
+#define HCIDEVRESTAT _IOW('H', 204, int)
+
+#define HCIGETDEVLIST _IOR('H', 210, int)
+#define HCIGETDEVINFO _IOR('H', 211, int)
+#define HCIGETCONNLIST _IOR('H', 212, int)
+#define HCIGETCONNINFO _IOR('H', 213, int)
+#define HCIGETAUTHINFO _IOR('H', 215, int)
+
+#define HCISETRAW _IOW('H', 220, int)
+#define HCISETSCAN _IOW('H', 221, int)
+#define HCISETAUTH _IOW('H', 222, int)
+#define HCISETENCRYPT _IOW('H', 223, int)
+#define HCISETPTYPE _IOW('H', 224, int)
+#define HCISETLINKPOL _IOW('H', 225, int)
+#define HCISETLINKMODE _IOW('H', 226, int)
+#define HCISETACLMTU _IOW('H', 227, int)
+#define HCISETSCOMTU _IOW('H', 228, int)
+
+#define HCIBLOCKADDR _IOW('H', 230, int)
+#define HCIUNBLOCKADDR _IOW('H', 231, int)
+
+#define HCIINQUIRY _IOR('H', 240, int)
+
+/* HCI timeouts */
+#define HCI_CONNECT_TIMEOUT (40000) /* 40 seconds */
+#define HCI_DISCONN_TIMEOUT (2000) /* 2 seconds */
+#define HCI_PAIRING_TIMEOUT (60000) /* 60 seconds */
+#define HCI_IDLE_TIMEOUT (6000) /* 6 seconds */
+#define HCI_INIT_TIMEOUT (10000) /* 10 seconds */
+#define HCI_CMD_TIMEOUT (1000) /* 1 seconds */
+#define HCI_ACL_TX_TIMEOUT (45000) /* 45 seconds */
+
+/* HCI data types */
+#define HCI_COMMAND_PKT 0x01
+#define HCI_ACLDATA_PKT 0x02
+#define HCI_SCODATA_PKT 0x03
+#define HCI_EVENT_PKT 0x04
+#define HCI_VENDOR_PKT 0xff
+
+/* HCI packet types */
+#define HCI_DM1 0x0008
+#define HCI_DM3 0x0400
+#define HCI_DM5 0x4000
+#define HCI_DH1 0x0010
+#define HCI_DH3 0x0800
+#define HCI_DH5 0x8000
+
+#define HCI_HV1 0x0020
+#define HCI_HV2 0x0040
+#define HCI_HV3 0x0080
+
+#define SCO_PTYPE_MASK (HCI_HV1 | HCI_HV2 | HCI_HV3)
+#define ACL_PTYPE_MASK (~SCO_PTYPE_MASK)
+
+/* eSCO packet types */
+#define ESCO_HV1 0x0001
+#define ESCO_HV2 0x0002
+#define ESCO_HV3 0x0004
+#define ESCO_EV3 0x0008
+#define ESCO_EV4 0x0010
+#define ESCO_EV5 0x0020
+#define ESCO_2EV3 0x0040
+#define ESCO_3EV3 0x0080
+#define ESCO_2EV5 0x0100
+#define ESCO_3EV5 0x0200
+
+#define SCO_ESCO_MASK (ESCO_HV1 | ESCO_HV2 | ESCO_HV3)
+#define EDR_ESCO_MASK (ESCO_2EV3 | ESCO_3EV3 | ESCO_2EV5 | ESCO_3EV5)
+#define ALL_ESCO_MASK (SCO_ESCO_MASK | ESCO_EV3 | ESCO_EV4 | ESCO_EV5 | \
+ EDR_ESCO_MASK)
+
+/* ACL flags */
+#define ACL_START_NO_FLUSH 0x00
+#define ACL_CONT 0x01
+#define ACL_START 0x02
+#define ACL_ACTIVE_BCAST 0x04
+#define ACL_PICO_BCAST 0x08
+
+/* Baseband links */
+#define SCO_LINK 0x00
+#define ACL_LINK 0x01
+#define ESCO_LINK 0x02
+/* Low Energy links do not have defined link type. Use invented one */
+#define LE_LINK 0x80
+
+/* LMP features */
+#define LMP_3SLOT 0x01
+#define LMP_5SLOT 0x02
+#define LMP_ENCRYPT 0x04
+#define LMP_SOFFSET 0x08
+#define LMP_TACCURACY 0x10
+#define LMP_RSWITCH 0x20
+#define LMP_HOLD 0x40
+#define LMP_SNIFF 0x80
+
+#define LMP_PARK 0x01
+#define LMP_RSSI 0x02
+#define LMP_QUALITY 0x04
+#define LMP_SCO 0x08
+#define LMP_HV2 0x10
+#define LMP_HV3 0x20
+#define LMP_ULAW 0x40
+#define LMP_ALAW 0x80
+
+#define LMP_CVSD 0x01
+#define LMP_PSCHEME 0x02
+#define LMP_PCONTROL 0x04
+
+#define LMP_RSSI_INQ 0x40
+#define LMP_ESCO 0x80
+
+#define LMP_EV4 0x01
+#define LMP_EV5 0x02
+#define LMP_NO_BREDR 0x20
+#define LMP_LE 0x40
+
+#define LMP_SNIFF_SUBR 0x02
+#define LMP_PAUSE_ENC 0x04
+#define LMP_EDR_ESCO_2M 0x20
+#define LMP_EDR_ESCO_3M 0x40
+#define LMP_EDR_3S_ESCO 0x80
+
+#define LMP_EXT_INQ 0x01
+#define LMP_SIMUL_LE_BR 0x02
+#define LMP_SIMPLE_PAIR 0x08
+#define LMP_NO_FLUSH 0x40
+
+#define LMP_LSTO 0x01
+#define LMP_INQ_TX_PWR 0x02
+#define LMP_EXTFEATURES 0x80
+
+/* Extended LMP features */
+#define LMP_HOST_SSP 0x01
+#define LMP_HOST_LE 0x02
+#define LMP_HOST_LE_BREDR 0x04
+
+/* Connection modes */
+#define HCI_CM_ACTIVE 0x0000
+#define HCI_CM_HOLD 0x0001
+#define HCI_CM_SNIFF 0x0002
+#define HCI_CM_PARK 0x0003
+
+/* Link policies */
+#define HCI_LP_RSWITCH 0x0001
+#define HCI_LP_HOLD 0x0002
+#define HCI_LP_SNIFF 0x0004
+#define HCI_LP_PARK 0x0008
+
+/* Link modes */
+#define HCI_LM_ACCEPT 0x8000
+#define HCI_LM_MASTER 0x0001
+#define HCI_LM_AUTH 0x0002
+#define HCI_LM_ENCRYPT 0x0004
+#define HCI_LM_TRUSTED 0x0008
+#define HCI_LM_RELIABLE 0x0010
+#define HCI_LM_SECURE 0x0020
+
+/* Authentication types */
+#define HCI_AT_NO_BONDING 0x00
+#define HCI_AT_NO_BONDING_MITM 0x01
+#define HCI_AT_DEDICATED_BONDING 0x02
+#define HCI_AT_DEDICATED_BONDING_MITM 0x03
+#define HCI_AT_GENERAL_BONDING 0x04
+#define HCI_AT_GENERAL_BONDING_MITM 0x05
+
+/* Link Key types */
+#define HCI_LK_COMBINATION 0x00
+#define HCI_LK_LOCAL_UNIT 0x01
+#define HCI_LK_REMOTE_UNIT 0x02
+#define HCI_LK_DEBUG_COMBINATION 0x03
+#define HCI_LK_UNAUTH_COMBINATION 0x04
+#define HCI_LK_AUTH_COMBINATION 0x05
+#define HCI_LK_CHANGED_COMBINATION 0x06
+/* The spec doesn't define types for SMP keys, the _MASTER suffix is implied */
+#define HCI_SMP_STK 0x80
+#define HCI_SMP_STK_SLAVE 0x81
+#define HCI_SMP_LTK 0x82
+#define HCI_SMP_LTK_SLAVE 0x83
+
+/* ---- HCI Error Codes ---- */
+#define HCI_ERROR_AUTH_FAILURE 0x05
+#define HCI_ERROR_REJ_BAD_ADDR 0x0f
+#define HCI_ERROR_REMOTE_USER_TERM 0x13
+#define HCI_ERROR_LOCAL_HOST_TERM 0x16
+#define HCI_ERROR_PAIRING_NOT_ALLOWED 0x18
+
+/* Flow control modes */
+#define HCI_FLOW_CTL_MODE_PACKET_BASED 0x00
+#define HCI_FLOW_CTL_MODE_BLOCK_BASED 0x01
+
+/* Extended Inquiry Response field types */
+#define EIR_FLAGS 0x01 /* flags */
+#define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */
+#define EIR_UUID16_ALL 0x03 /* 16-bit UUID, all listed */
+#define EIR_UUID32_SOME 0x04 /* 32-bit UUID, more available */
+#define EIR_UUID32_ALL 0x05 /* 32-bit UUID, all listed */
+#define EIR_UUID128_SOME 0x06 /* 128-bit UUID, more available */
+#define EIR_UUID128_ALL 0x07 /* 128-bit UUID, all listed */
+#define EIR_NAME_SHORT 0x08 /* shortened local name */
+#define EIR_NAME_COMPLETE 0x09 /* complete local name */
+#define EIR_TX_POWER 0x0A /* transmit power level */
+#define EIR_CLASS_OF_DEV 0x0D /* Class of Device */
+#define EIR_SSP_HASH_C 0x0E /* Simple Pairing Hash C */
+#define EIR_SSP_RAND_R 0x0F /* Simple Pairing Randomizer R */
+#define EIR_DEVICE_ID 0x10 /* device ID */
+
+/* ----- HCI Commands ---- */
+#define HCI_OP_NOP 0x0000
+
+#define HCI_OP_INQUIRY 0x0401
+struct hci_cp_inquiry {
+ __u8 lap[3];
+ __u8 length;
+ __u8 num_rsp;
+} __packed;
+
+#define HCI_OP_INQUIRY_CANCEL 0x0402
+
+#define HCI_OP_EXIT_PERIODIC_INQ 0x0404
+
+#define HCI_OP_CREATE_CONN 0x0405
+struct hci_cp_create_conn {
+ bdaddr_t bdaddr;
+ __le16 pkt_type;
+ __u8 pscan_rep_mode;
+ __u8 pscan_mode;
+ __le16 clock_offset;
+ __u8 role_switch;
+} __packed;
+
+#define HCI_OP_DISCONNECT 0x0406
+struct hci_cp_disconnect {
+ __le16 handle;
+ __u8 reason;
+} __packed;
+
+#define HCI_OP_ADD_SCO 0x0407
+struct hci_cp_add_sco {
+ __le16 handle;
+ __le16 pkt_type;
+} __packed;
+
+#define HCI_OP_CREATE_CONN_CANCEL 0x0408
+struct hci_cp_create_conn_cancel {
+ bdaddr_t bdaddr;
+} __packed;
+
+#define HCI_OP_ACCEPT_CONN_REQ 0x0409
+struct hci_cp_accept_conn_req {
+ bdaddr_t bdaddr;
+ __u8 role;
+} __packed;
+
+#define HCI_OP_REJECT_CONN_REQ 0x040a
+struct hci_cp_reject_conn_req {
+ bdaddr_t bdaddr;
+ __u8 reason;
+} __packed;
+
+#define HCI_OP_LINK_KEY_REPLY 0x040b
+struct hci_cp_link_key_reply {
+ bdaddr_t bdaddr;
+ __u8 link_key[16];
+} __packed;
+
+#define HCI_OP_LINK_KEY_NEG_REPLY 0x040c
+struct hci_cp_link_key_neg_reply {
+ bdaddr_t bdaddr;
+} __packed;
+
+#define HCI_OP_PIN_CODE_REPLY 0x040d
+struct hci_cp_pin_code_reply {
+ bdaddr_t bdaddr;
+ __u8 pin_len;
+ __u8 pin_code[16];
+} __packed;
+struct hci_rp_pin_code_reply {
+ __u8 status;
+ bdaddr_t bdaddr;
+} __packed;
+
+#define HCI_OP_PIN_CODE_NEG_REPLY 0x040e
+struct hci_cp_pin_code_neg_reply {
+ bdaddr_t bdaddr;
+} __packed;
+struct hci_rp_pin_code_neg_reply {
+ __u8 status;
+ bdaddr_t bdaddr;
+} __packed;
+
+#define HCI_OP_CHANGE_CONN_PTYPE 0x040f
+struct hci_cp_change_conn_ptype {
+ __le16 handle;
+ __le16 pkt_type;
+} __packed;
+
+#define HCI_OP_AUTH_REQUESTED 0x0411
+struct hci_cp_auth_requested {
+ __le16 handle;
+} __packed;
+
+#define HCI_OP_SET_CONN_ENCRYPT 0x0413
+struct hci_cp_set_conn_encrypt {
+ __le16 handle;
+ __u8 encrypt;
+} __packed;
+
+#define HCI_OP_CHANGE_CONN_LINK_KEY 0x0415
+struct hci_cp_change_conn_link_key {
+ __le16 handle;
+} __packed;
+
+#define HCI_OP_REMOTE_NAME_REQ 0x0419
+struct hci_cp_remote_name_req {
+ bdaddr_t bdaddr;
+ __u8 pscan_rep_mode;
+ __u8 pscan_mode;
+ __le16 clock_offset;
+} __packed;
+
+#define HCI_OP_REMOTE_NAME_REQ_CANCEL 0x041a
+struct hci_cp_remote_name_req_cancel {
+ bdaddr_t bdaddr;
+} __packed;
+
+#define HCI_OP_READ_REMOTE_FEATURES 0x041b
+struct hci_cp_read_remote_features {
+ __le16 handle;
+} __packed;
+
+#define HCI_OP_READ_REMOTE_EXT_FEATURES 0x041c
+struct hci_cp_read_remote_ext_features {
+ __le16 handle;
+ __u8 page;
+} __packed;
+
+#define HCI_OP_READ_REMOTE_VERSION 0x041d
+struct hci_cp_read_remote_version {
+ __le16 handle;
+} __packed;
+
+#define HCI_OP_SETUP_SYNC_CONN 0x0428
+struct hci_cp_setup_sync_conn {
+ __le16 handle;
+ __le32 tx_bandwidth;
+ __le32 rx_bandwidth;
+ __le16 max_latency;
+ __le16 voice_setting;
+ __u8 retrans_effort;
+ __le16 pkt_type;
+} __packed;
+
+#define HCI_OP_ACCEPT_SYNC_CONN_REQ 0x0429
+struct hci_cp_accept_sync_conn_req {
+ bdaddr_t bdaddr;
+ __le32 tx_bandwidth;
+ __le32 rx_bandwidth;
+ __le16 max_latency;
+ __le16 content_format;
+ __u8 retrans_effort;
+ __le16 pkt_type;
+} __packed;
+
+#define HCI_OP_REJECT_SYNC_CONN_REQ 0x042a
+struct hci_cp_reject_sync_conn_req {
+ bdaddr_t bdaddr;
+ __u8 reason;
+} __packed;
+
+#define HCI_OP_IO_CAPABILITY_REPLY 0x042b
+struct hci_cp_io_capability_reply {
+ bdaddr_t bdaddr;
+ __u8 capability;
+ __u8 oob_data;
+ __u8 authentication;
+} __packed;
+
+#define HCI_OP_USER_CONFIRM_REPLY 0x042c
+struct hci_cp_user_confirm_reply {
+ bdaddr_t bdaddr;
+} __packed;
+struct hci_rp_user_confirm_reply {
+ __u8 status;
+ bdaddr_t bdaddr;
+} __packed;
+
+#define HCI_OP_USER_CONFIRM_NEG_REPLY 0x042d
+
+#define HCI_OP_USER_PASSKEY_REPLY 0x042e
+struct hci_cp_user_passkey_reply {
+ bdaddr_t bdaddr;
+ __le32 passkey;
+} __packed;
+
+#define HCI_OP_USER_PASSKEY_NEG_REPLY 0x042f
+
+#define HCI_OP_REMOTE_OOB_DATA_REPLY 0x0430
+struct hci_cp_remote_oob_data_reply {
+ bdaddr_t bdaddr;
+ __u8 hash[16];
+ __u8 randomizer[16];
+} __packed;
+
+#define HCI_OP_REMOTE_OOB_DATA_NEG_REPLY 0x0433
+struct hci_cp_remote_oob_data_neg_reply {
+ bdaddr_t bdaddr;
+} __packed;
+
+#define HCI_OP_IO_CAPABILITY_NEG_REPLY 0x0434
+struct hci_cp_io_capability_neg_reply {
+ bdaddr_t bdaddr;
+ __u8 reason;
+} __packed;
+
+#define HCI_OP_SNIFF_MODE 0x0803
+struct hci_cp_sniff_mode {
+ __le16 handle;
+ __le16 max_interval;
+ __le16 min_interval;
+ __le16 attempt;
+ __le16 timeout;
+} __packed;
+
+#define HCI_OP_EXIT_SNIFF_MODE 0x0804
+struct hci_cp_exit_sniff_mode {
+ __le16 handle;
+} __packed;
+
+#define HCI_OP_ROLE_DISCOVERY 0x0809
+struct hci_cp_role_discovery {
+ __le16 handle;
+} __packed;
+struct hci_rp_role_discovery {
+ __u8 status;
+ __le16 handle;
+ __u8 role;
+} __packed;
+
+#define HCI_OP_SWITCH_ROLE 0x080b
+struct hci_cp_switch_role {
+ bdaddr_t bdaddr;
+ __u8 role;
+} __packed;
+
+#define HCI_OP_READ_LINK_POLICY 0x080c
+struct hci_cp_read_link_policy {
+ __le16 handle;
+} __packed;
+struct hci_rp_read_link_policy {
+ __u8 status;
+ __le16 handle;
+ __le16 policy;
+} __packed;
+
+#define HCI_OP_WRITE_LINK_POLICY 0x080d
+struct hci_cp_write_link_policy {
+ __le16 handle;
+ __le16 policy;
+} __packed;
+struct hci_rp_write_link_policy {
+ __u8 status;
+ __le16 handle;
+} __packed;
+
+#define HCI_OP_READ_DEF_LINK_POLICY 0x080e
+struct hci_rp_read_def_link_policy {
+ __u8 status;
+ __le16 policy;
+} __packed;
+
+#define HCI_OP_WRITE_DEF_LINK_POLICY 0x080f
+struct hci_cp_write_def_link_policy {
+ __le16 policy;
+} __packed;
+
+#define HCI_OP_SNIFF_SUBRATE 0x0811
+struct hci_cp_sniff_subrate {
+ __le16 handle;
+ __le16 max_latency;
+ __le16 min_remote_timeout;
+ __le16 min_local_timeout;
+} __packed;
+
+#define HCI_OP_SET_EVENT_MASK 0x0c01
+struct hci_cp_set_event_mask {
+ __u8 mask[8];
+} __packed;
+
+#define HCI_OP_RESET 0x0c03
+
+#define HCI_OP_SET_EVENT_FLT 0x0c05
+struct hci_cp_set_event_flt {
+ __u8 flt_type;
+ __u8 cond_type;
+ __u8 condition[0];
+} __packed;
+
+/* Filter types */
+#define HCI_FLT_CLEAR_ALL 0x00
+#define HCI_FLT_INQ_RESULT 0x01
+#define HCI_FLT_CONN_SETUP 0x02
+
+/* CONN_SETUP Condition types */
+#define HCI_CONN_SETUP_ALLOW_ALL 0x00
+#define HCI_CONN_SETUP_ALLOW_CLASS 0x01
+#define HCI_CONN_SETUP_ALLOW_BDADDR 0x02
+
+/* CONN_SETUP Conditions */
+#define HCI_CONN_SETUP_AUTO_OFF 0x01
+#define HCI_CONN_SETUP_AUTO_ON 0x02
+
+#define HCI_OP_DELETE_STORED_LINK_KEY 0x0c12
+struct hci_cp_delete_stored_link_key {
+ bdaddr_t bdaddr;
+ __u8 delete_all;
+} __packed;
+
+#define HCI_MAX_NAME_LENGTH 248
+
+#define HCI_OP_WRITE_LOCAL_NAME 0x0c13
+struct hci_cp_write_local_name {
+ __u8 name[HCI_MAX_NAME_LENGTH];
+} __packed;
+
+#define HCI_OP_READ_LOCAL_NAME 0x0c14
+struct hci_rp_read_local_name {
+ __u8 status;
+ __u8 name[HCI_MAX_NAME_LENGTH];
+} __packed;
+
+#define HCI_OP_WRITE_CA_TIMEOUT 0x0c16
+
+#define HCI_OP_WRITE_PG_TIMEOUT 0x0c18
+
+#define HCI_OP_WRITE_SCAN_ENABLE 0x0c1a
+ #define SCAN_DISABLED 0x00
+ #define SCAN_INQUIRY 0x01
+ #define SCAN_PAGE 0x02
+
+#define HCI_OP_READ_AUTH_ENABLE 0x0c1f
+
+#define HCI_OP_WRITE_AUTH_ENABLE 0x0c20
+ #define AUTH_DISABLED 0x00
+ #define AUTH_ENABLED 0x01
+
+#define HCI_OP_READ_ENCRYPT_MODE 0x0c21
+
+#define HCI_OP_WRITE_ENCRYPT_MODE 0x0c22
+ #define ENCRYPT_DISABLED 0x00
+ #define ENCRYPT_P2P 0x01
+ #define ENCRYPT_BOTH 0x02
+
+#define HCI_OP_READ_CLASS_OF_DEV 0x0c23
+struct hci_rp_read_class_of_dev {
+ __u8 status;
+ __u8 dev_class[3];
+} __packed;
+
+#define HCI_OP_WRITE_CLASS_OF_DEV 0x0c24
+struct hci_cp_write_class_of_dev {
+ __u8 dev_class[3];
+} __packed;
+
+#define HCI_OP_READ_VOICE_SETTING 0x0c25
+struct hci_rp_read_voice_setting {
+ __u8 status;
+ __le16 voice_setting;
+} __packed;
+
+#define HCI_OP_WRITE_VOICE_SETTING 0x0c26
+struct hci_cp_write_voice_setting {
+ __le16 voice_setting;
+} __packed;
+
+#define HCI_OP_HOST_BUFFER_SIZE 0x0c33
+struct hci_cp_host_buffer_size {
+ __le16 acl_mtu;
+ __u8 sco_mtu;
+ __le16 acl_max_pkt;
+ __le16 sco_max_pkt;
+} __packed;
+
+#define HCI_OP_WRITE_INQUIRY_MODE 0x0c45
+
+#define HCI_MAX_EIR_LENGTH 240
+
+#define HCI_OP_WRITE_EIR 0x0c52
+struct hci_cp_write_eir {
+ __u8 fec;
+ __u8 data[HCI_MAX_EIR_LENGTH];
+} __packed;
+
+#define HCI_OP_READ_SSP_MODE 0x0c55
+struct hci_rp_read_ssp_mode {
+ __u8 status;
+ __u8 mode;
+} __packed;
+
+#define HCI_OP_WRITE_SSP_MODE 0x0c56
+struct hci_cp_write_ssp_mode {
+ __u8 mode;
+} __packed;
+
+#define HCI_OP_READ_LOCAL_OOB_DATA 0x0c57
+struct hci_rp_read_local_oob_data {
+ __u8 status;
+ __u8 hash[16];
+ __u8 randomizer[16];
+} __packed;
+
+#define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58
+
+#define HCI_OP_READ_FLOW_CONTROL_MODE 0x0c66
+struct hci_rp_read_flow_control_mode {
+ __u8 status;
+ __u8 mode;
+} __packed;
+
+#define HCI_OP_WRITE_LE_HOST_SUPPORTED 0x0c6d
+struct hci_cp_write_le_host_supported {
+ __u8 le;
+ __u8 simul;
+} __packed;
+
+#define HCI_OP_READ_LOCAL_VERSION 0x1001
+struct hci_rp_read_local_version {
+ __u8 status;
+ __u8 hci_ver;
+ __le16 hci_rev;
+ __u8 lmp_ver;
+ __le16 manufacturer;
+ __le16 lmp_subver;
+} __packed;
+
+#define HCI_OP_READ_LOCAL_COMMANDS 0x1002
+struct hci_rp_read_local_commands {
+ __u8 status;
+ __u8 commands[64];
+} __packed;
+
+#define HCI_OP_READ_LOCAL_FEATURES 0x1003
+struct hci_rp_read_local_features {
+ __u8 status;
+ __u8 features[8];
+} __packed;
+
+#define HCI_OP_READ_LOCAL_EXT_FEATURES 0x1004
+struct hci_cp_read_local_ext_features {
+ __u8 page;
+} __packed;
+struct hci_rp_read_local_ext_features {
+ __u8 status;
+ __u8 page;
+ __u8 max_page;
+ __u8 features[8];
+} __packed;
+
+#define HCI_OP_READ_BUFFER_SIZE 0x1005
+struct hci_rp_read_buffer_size {
+ __u8 status;
+ __le16 acl_mtu;
+ __u8 sco_mtu;
+ __le16 acl_max_pkt;
+ __le16 sco_max_pkt;
+} __packed;
+
+#define HCI_OP_READ_BD_ADDR 0x1009
+struct hci_rp_read_bd_addr {
+ __u8 status;
+ bdaddr_t bdaddr;
+} __packed;
+
+#define HCI_OP_READ_DATA_BLOCK_SIZE 0x100a
+struct hci_rp_read_data_block_size {
+ __u8 status;
+ __le16 max_acl_len;
+ __le16 block_len;
+ __le16 num_blocks;
+} __packed;
+
+#define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY 0x0c1c
+struct hci_cp_write_page_scan_activity {
+ __le16 interval;
+ __le16 window;
+} __packed;
+
+#define HCI_OP_WRITE_PAGE_SCAN_TYPE 0x0c47
+ #define PAGE_SCAN_TYPE_STANDARD 0x00
+ #define PAGE_SCAN_TYPE_INTERLACED 0x01
+
+#define HCI_OP_READ_LOCAL_AMP_INFO 0x1409
+struct hci_rp_read_local_amp_info {
+ __u8 status;
+ __u8 amp_status;
+ __le32 total_bw;
+ __le32 max_bw;
+ __le32 min_latency;
+ __le32 max_pdu;
+ __u8 amp_type;
+ __le16 pal_cap;
+ __le16 max_assoc_size;
+ __le32 max_flush_to;
+ __le32 be_flush_to;
+} __packed;
+
+#define HCI_OP_LE_SET_EVENT_MASK 0x2001
+struct hci_cp_le_set_event_mask {
+ __u8 mask[8];
+} __packed;
+
+#define HCI_OP_LE_READ_BUFFER_SIZE 0x2002
+struct hci_rp_le_read_buffer_size {
+ __u8 status;
+ __le16 le_mtu;
+ __u8 le_max_pkt;
+} __packed;
+
+#define HCI_OP_LE_SET_SCAN_PARAM 0x200b
+struct hci_cp_le_set_scan_param {
+ __u8 type;
+ __le16 interval;
+ __le16 window;
+ __u8 own_address_type;
+ __u8 filter_policy;
+} __packed;
+
+#define LE_SCANNING_DISABLED 0x00
+#define LE_SCANNING_ENABLED 0x01
+
+#define HCI_OP_LE_SET_SCAN_ENABLE 0x200c
+struct hci_cp_le_set_scan_enable {
+ __u8 enable;
+ __u8 filter_dup;
+} __packed;
+
+#define HCI_OP_LE_CREATE_CONN 0x200d
+struct hci_cp_le_create_conn {
+ __le16 scan_interval;
+ __le16 scan_window;
+ __u8 filter_policy;
+ __u8 peer_addr_type;
+ bdaddr_t peer_addr;
+ __u8 own_address_type;
+ __le16 conn_interval_min;
+ __le16 conn_interval_max;
+ __le16 conn_latency;
+ __le16 supervision_timeout;
+ __le16 min_ce_len;
+ __le16 max_ce_len;
+} __packed;
+
+#define HCI_OP_LE_CREATE_CONN_CANCEL 0x200e
+
+#define HCI_OP_LE_CONN_UPDATE 0x2013
+struct hci_cp_le_conn_update {
+ __le16 handle;
+ __le16 conn_interval_min;
+ __le16 conn_interval_max;
+ __le16 conn_latency;
+ __le16 supervision_timeout;
+ __le16 min_ce_len;
+ __le16 max_ce_len;
+} __packed;
+
+#define HCI_OP_LE_START_ENC 0x2019
+struct hci_cp_le_start_enc {
+ __le16 handle;
+ __u8 rand[8];
+ __le16 ediv;
+ __u8 ltk[16];
+} __packed;
+
+#define HCI_OP_LE_LTK_REPLY 0x201a
+struct hci_cp_le_ltk_reply {
+ __le16 handle;
+ __u8 ltk[16];
+} __packed;
+struct hci_rp_le_ltk_reply {
+ __u8 status;
+ __le16 handle;
+} __packed;
+
+#define HCI_OP_LE_LTK_NEG_REPLY 0x201b
+struct hci_cp_le_ltk_neg_reply {
+ __le16 handle;
+} __packed;
+struct hci_rp_le_ltk_neg_reply {
+ __u8 status;
+ __le16 handle;
+} __packed;
+
+/* ---- HCI Events ---- */
+#define HCI_EV_INQUIRY_COMPLETE 0x01
+
+#define HCI_EV_INQUIRY_RESULT 0x02
+struct inquiry_info {
+ bdaddr_t bdaddr;
+ __u8 pscan_rep_mode;
+ __u8 pscan_period_mode;
+ __u8 pscan_mode;
+ __u8 dev_class[3];
+ __le16 clock_offset;
+} __packed;
+
+#define HCI_EV_CONN_COMPLETE 0x03
+struct hci_ev_conn_complete {
+ __u8 status;
+ __le16 handle;
+ bdaddr_t bdaddr;
+ __u8 link_type;
+ __u8 encr_mode;
+} __packed;
+
+#define HCI_EV_CONN_REQUEST 0x04
+struct hci_ev_conn_request {
+ bdaddr_t bdaddr;
+ __u8 dev_class[3];
+ __u8 link_type;
+} __packed;
+
+#define HCI_EV_DISCONN_COMPLETE 0x05
+struct hci_ev_disconn_complete {
+ __u8 status;
+ __le16 handle;
+ __u8 reason;
+} __packed;
+
+#define HCI_EV_AUTH_COMPLETE 0x06
+struct hci_ev_auth_complete {
+ __u8 status;
+ __le16 handle;
+} __packed;
+
+#define HCI_EV_REMOTE_NAME 0x07
+struct hci_ev_remote_name {
+ __u8 status;
+ bdaddr_t bdaddr;
+ __u8 name[HCI_MAX_NAME_LENGTH];
+} __packed;
+
+#define HCI_EV_ENCRYPT_CHANGE 0x08
+struct hci_ev_encrypt_change {
+ __u8 status;
+ __le16 handle;
+ __u8 encrypt;
+} __packed;
+
+#define HCI_EV_CHANGE_LINK_KEY_COMPLETE 0x09
+struct hci_ev_change_link_key_complete {
+ __u8 status;
+ __le16 handle;
+} __packed;
+
+#define HCI_EV_REMOTE_FEATURES 0x0b
+struct hci_ev_remote_features {
+ __u8 status;
+ __le16 handle;
+ __u8 features[8];
+} __packed;
+
+#define HCI_EV_REMOTE_VERSION 0x0c
+struct hci_ev_remote_version {
+ __u8 status;
+ __le16 handle;
+ __u8 lmp_ver;
+ __le16 manufacturer;
+ __le16 lmp_subver;
+} __packed;
+
+#define HCI_EV_QOS_SETUP_COMPLETE 0x0d
+struct hci_qos {
+ __u8 service_type;
+ __u32 token_rate;
+ __u32 peak_bandwidth;
+ __u32 latency;
+ __u32 delay_variation;
+} __packed;
+struct hci_ev_qos_setup_complete {
+ __u8 status;
+ __le16 handle;
+ struct hci_qos qos;
+} __packed;
+
+#define HCI_EV_CMD_COMPLETE 0x0e
+struct hci_ev_cmd_complete {
+ __u8 ncmd;
+ __le16 opcode;
+} __packed;
+
+#define HCI_EV_CMD_STATUS 0x0f
+struct hci_ev_cmd_status {
+ __u8 status;
+ __u8 ncmd;
+ __le16 opcode;
+} __packed;
+
+#define HCI_EV_ROLE_CHANGE 0x12
+struct hci_ev_role_change {
+ __u8 status;
+ bdaddr_t bdaddr;
+ __u8 role;
+} __packed;
+
+#define HCI_EV_NUM_COMP_PKTS 0x13
+struct hci_comp_pkts_info {
+ __le16 handle;
+ __le16 count;
+} __packed;
+
+struct hci_ev_num_comp_pkts {
+ __u8 num_hndl;
+ struct hci_comp_pkts_info handles[0];
+} __packed;
+
+#define HCI_EV_MODE_CHANGE 0x14
+struct hci_ev_mode_change {
+ __u8 status;
+ __le16 handle;
+ __u8 mode;
+ __le16 interval;
+} __packed;
+
+#define HCI_EV_PIN_CODE_REQ 0x16
+struct hci_ev_pin_code_req {
+ bdaddr_t bdaddr;
+} __packed;
+
+#define HCI_EV_LINK_KEY_REQ 0x17
+struct hci_ev_link_key_req {
+ bdaddr_t bdaddr;
+} __packed;
+
+#define HCI_EV_LINK_KEY_NOTIFY 0x18
+struct hci_ev_link_key_notify {
+ bdaddr_t bdaddr;
+ __u8 link_key[16];
+ __u8 key_type;
+} __packed;
+
+#define HCI_EV_CLOCK_OFFSET 0x1c
+struct hci_ev_clock_offset {
+ __u8 status;
+ __le16 handle;
+ __le16 clock_offset;
+} __packed;
+
+#define HCI_EV_PKT_TYPE_CHANGE 0x1d
+struct hci_ev_pkt_type_change {
+ __u8 status;
+ __le16 handle;
+ __le16 pkt_type;
+} __packed;
+
+#define HCI_EV_PSCAN_REP_MODE 0x20
+struct hci_ev_pscan_rep_mode {
+ bdaddr_t bdaddr;
+ __u8 pscan_rep_mode;
+} __packed;
+
+#define HCI_EV_INQUIRY_RESULT_WITH_RSSI 0x22
+struct inquiry_info_with_rssi {
+ bdaddr_t bdaddr;
+ __u8 pscan_rep_mode;
+ __u8 pscan_period_mode;
+ __u8 dev_class[3];
+ __le16 clock_offset;
+ __s8 rssi;
+} __packed;
+struct inquiry_info_with_rssi_and_pscan_mode {
+ bdaddr_t bdaddr;
+ __u8 pscan_rep_mode;
+ __u8 pscan_period_mode;
+ __u8 pscan_mode;
+ __u8 dev_class[3];
+ __le16 clock_offset;
+ __s8 rssi;
+} __packed;
+
+#define HCI_EV_REMOTE_EXT_FEATURES 0x23
+struct hci_ev_remote_ext_features {
+ __u8 status;
+ __le16 handle;
+ __u8 page;
+ __u8 max_page;
+ __u8 features[8];
+} __packed;
+
+#define HCI_EV_SYNC_CONN_COMPLETE 0x2c
+struct hci_ev_sync_conn_complete {
+ __u8 status;
+ __le16 handle;
+ bdaddr_t bdaddr;
+ __u8 link_type;
+ __u8 tx_interval;
+ __u8 retrans_window;
+ __le16 rx_pkt_len;
+ __le16 tx_pkt_len;
+ __u8 air_mode;
+} __packed;
+
+#define HCI_EV_SYNC_CONN_CHANGED 0x2d
+struct hci_ev_sync_conn_changed {
+ __u8 status;
+ __le16 handle;
+ __u8 tx_interval;
+ __u8 retrans_window;
+ __le16 rx_pkt_len;
+ __le16 tx_pkt_len;
+} __packed;
+
+#define HCI_EV_SNIFF_SUBRATE 0x2e
+struct hci_ev_sniff_subrate {
+ __u8 status;
+ __le16 handle;
+ __le16 max_tx_latency;
+ __le16 max_rx_latency;
+ __le16 max_remote_timeout;
+ __le16 max_local_timeout;
+} __packed;
+
+#define HCI_EV_EXTENDED_INQUIRY_RESULT 0x2f
+struct extended_inquiry_info {
+ bdaddr_t bdaddr;
+ __u8 pscan_rep_mode;
+ __u8 pscan_period_mode;
+ __u8 dev_class[3];
+ __le16 clock_offset;
+ __s8 rssi;
+ __u8 data[240];
+} __packed;
+
+#define HCI_EV_IO_CAPA_REQUEST 0x31
+struct hci_ev_io_capa_request {
+ bdaddr_t bdaddr;
+} __packed;
+
+#define HCI_EV_IO_CAPA_REPLY 0x32
+struct hci_ev_io_capa_reply {
+ bdaddr_t bdaddr;
+ __u8 capability;
+ __u8 oob_data;
+ __u8 authentication;
+} __packed;
+
+#define HCI_EV_USER_CONFIRM_REQUEST 0x33
+struct hci_ev_user_confirm_req {
+ bdaddr_t bdaddr;
+ __le32 passkey;
+} __packed;
+
+#define HCI_EV_USER_PASSKEY_REQUEST 0x34
+struct hci_ev_user_passkey_req {
+ bdaddr_t bdaddr;
+} __packed;
+
+#define HCI_EV_REMOTE_OOB_DATA_REQUEST 0x35
+struct hci_ev_remote_oob_data_request {
+ bdaddr_t bdaddr;
+} __packed;
+
+#define HCI_EV_SIMPLE_PAIR_COMPLETE 0x36
+struct hci_ev_simple_pair_complete {
+ __u8 status;
+ bdaddr_t bdaddr;
+} __packed;
+
+#define HCI_EV_REMOTE_HOST_FEATURES 0x3d
+struct hci_ev_remote_host_features {
+ bdaddr_t bdaddr;
+ __u8 features[8];
+} __packed;
+
+#define HCI_EV_LE_META 0x3e
+struct hci_ev_le_meta {
+ __u8 subevent;
+} __packed;
+
+#define HCI_EV_NUM_COMP_BLOCKS 0x48
+struct hci_comp_blocks_info {
+ __le16 handle;
+ __le16 pkts;
+ __le16 blocks;
+} __packed;
+
+struct hci_ev_num_comp_blocks {
+ __le16 num_blocks;
+ __u8 num_hndl;
+ struct hci_comp_blocks_info handles[0];
+} __packed;
+
+/* Low energy meta events */
+#define HCI_EV_LE_CONN_COMPLETE 0x01
+struct hci_ev_le_conn_complete {
+ __u8 status;
+ __le16 handle;
+ __u8 role;
+ __u8 bdaddr_type;
+ bdaddr_t bdaddr;
+ __le16 interval;
+ __le16 latency;
+ __le16 supervision_timeout;
+ __u8 clk_accurancy;
+} __packed;
+
+#define HCI_EV_LE_LTK_REQ 0x05
+struct hci_ev_le_ltk_req {
+ __le16 handle;
+ __u8 random[8];
+ __le16 ediv;
+} __packed;
+
+/* Advertising report event types */
+#define ADV_IND 0x00
+#define ADV_DIRECT_IND 0x01
+#define ADV_SCAN_IND 0x02
+#define ADV_NONCONN_IND 0x03
+#define ADV_SCAN_RSP 0x04
+
+#define ADDR_LE_DEV_PUBLIC 0x00
+#define ADDR_LE_DEV_RANDOM 0x01
+
+#define HCI_EV_LE_ADVERTISING_REPORT 0x02
+struct hci_ev_le_advertising_info {
+ __u8 evt_type;
+ __u8 bdaddr_type;
+ bdaddr_t bdaddr;
+ __u8 length;
+ __u8 data[0];
+} __packed;
+
+/* Internal events generated by Bluetooth stack */
+#define HCI_EV_STACK_INTERNAL 0xfd
+struct hci_ev_stack_internal {
+ __u16 type;
+ __u8 data[0];
+} __packed;
+
+#define HCI_EV_SI_DEVICE 0x01
+struct hci_ev_si_device {
+ __u16 event;
+ __u16 dev_id;
+} __packed;
+
+#define HCI_EV_SI_SECURITY 0x02
+struct hci_ev_si_security {
+ __u16 event;
+ __u16 proto;
+ __u16 subproto;
+ __u8 incoming;
+} __packed;
+
+/* ---- HCI Packet structures ---- */
+#define HCI_COMMAND_HDR_SIZE 3
+#define HCI_EVENT_HDR_SIZE 2
+#define HCI_ACL_HDR_SIZE 4
+#define HCI_SCO_HDR_SIZE 3
+
+struct hci_command_hdr {
+ __le16 opcode; /* OCF & OGF */
+ __u8 plen;
+} __packed;
+
+struct hci_event_hdr {
+ __u8 evt;
+ __u8 plen;
+} __packed;
+
+struct hci_acl_hdr {
+ __le16 handle; /* Handle & Flags(PB, BC) */
+ __le16 dlen;
+} __packed;
+
+struct hci_sco_hdr {
+ __le16 handle;
+ __u8 dlen;
+} __packed;
+
+#include <linux/skbuff.h>
+static inline struct hci_event_hdr *hci_event_hdr(const struct sk_buff *skb)
+{
+ return (struct hci_event_hdr *) skb->data;
+}
+
+static inline struct hci_acl_hdr *hci_acl_hdr(const struct sk_buff *skb)
+{
+ return (struct hci_acl_hdr *) skb->data;
+}
+
+static inline struct hci_sco_hdr *hci_sco_hdr(const struct sk_buff *skb)
+{
+ return (struct hci_sco_hdr *) skb->data;
+}
+
+/* Command opcode pack/unpack */
+#define hci_opcode_pack(ogf, ocf) (__u16) ((ocf & 0x03ff)|(ogf << 10))
+#define hci_opcode_ogf(op) (op >> 10)
+#define hci_opcode_ocf(op) (op & 0x03ff)
+
+/* ACL handle and flags pack/unpack */
+#define hci_handle_pack(h, f) (__u16) ((h & 0x0fff)|(f << 12))
+#define hci_handle(h) (h & 0x0fff)
+#define hci_flags(h) (h >> 12)
+
+/* ---- HCI Sockets ---- */
+
+/* Socket options */
+#define HCI_DATA_DIR 1
+#define HCI_FILTER 2
+#define HCI_TIME_STAMP 3
+
+/* CMSG flags */
+#define HCI_CMSG_DIR 0x0001
+#define HCI_CMSG_TSTAMP 0x0002
+
+struct sockaddr_hci {
+ sa_family_t hci_family;
+ unsigned short hci_dev;
+ unsigned short hci_channel;
+};
+#define HCI_DEV_NONE 0xffff
+
+#define HCI_CHANNEL_RAW 0
+#define HCI_CHANNEL_MONITOR 2
+#define HCI_CHANNEL_CONTROL 3
+
+struct hci_filter {
+ unsigned long type_mask;
+ unsigned long event_mask[2];
+ __le16 opcode;
+};
+
+struct hci_ufilter {
+ __u32 type_mask;
+ __u32 event_mask[2];
+ __le16 opcode;
+};
+
+#define HCI_FLT_TYPE_BITS 31
+#define HCI_FLT_EVENT_BITS 63
+#define HCI_FLT_OGF_BITS 63
+#define HCI_FLT_OCF_BITS 127
+
+/* ---- HCI Ioctl requests structures ---- */
+struct hci_dev_stats {
+ __u32 err_rx;
+ __u32 err_tx;
+ __u32 cmd_tx;
+ __u32 evt_rx;
+ __u32 acl_tx;
+ __u32 acl_rx;
+ __u32 sco_tx;
+ __u32 sco_rx;
+ __u32 byte_rx;
+ __u32 byte_tx;
+};
+
+struct hci_dev_info {
+ __u16 dev_id;
+ char name[8];
+
+ bdaddr_t bdaddr;
+
+ __u32 flags;
+ __u8 type;
+
+ __u8 features[8];
+
+ __u32 pkt_type;
+ __u32 link_policy;
+ __u32 link_mode;
+
+ __u16 acl_mtu;
+ __u16 acl_pkts;
+ __u16 sco_mtu;
+ __u16 sco_pkts;
+
+ struct hci_dev_stats stat;
+};
+
+struct hci_conn_info {
+ __u16 handle;
+ bdaddr_t bdaddr;
+ __u8 type;
+ __u8 out;
+ __u16 state;
+ __u32 link_mode;
+ __u32 mtu;
+ __u32 cnt;
+ __u32 pkts;
+};
+
+struct hci_dev_req {
+ __u16 dev_id;
+ __u32 dev_opt;
+};
+
+struct hci_dev_list_req {
+ __u16 dev_num;
+ struct hci_dev_req dev_req[0]; /* hci_dev_req structures */
+};
+
+struct hci_conn_list_req {
+ __u16 dev_id;
+ __u16 conn_num;
+ struct hci_conn_info conn_info[0];
+};
+
+struct hci_conn_info_req {
+ bdaddr_t bdaddr;
+ __u8 type;
+ struct hci_conn_info conn_info[0];
+};
+
+struct hci_auth_info_req {
+ bdaddr_t bdaddr;
+ __u8 type;
+};
+
+struct hci_inquiry_req {
+ __u16 dev_id;
+ __u16 flags;
+ __u8 lap[3];
+ __u8 length;
+ __u8 num_rsp;
+};
+#define IREQ_CACHE_FLUSH 0x0001
+
+extern bool enable_hs;
+extern bool enable_le;
+
+#endif /* __HCI_H */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
new file mode 100644
index 00000000..392b2cab
--- /dev/null
+++ b/include/net/bluetooth/hci_core.h
@@ -0,0 +1,1080 @@
+/*
+ BlueZ - Bluetooth protocol stack for Linux
+ Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
+
+ Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+ CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ SOFTWARE IS DISCLAIMED.
+*/
+
+#ifndef __HCI_CORE_H
+#define __HCI_CORE_H
+
+#include <linux/interrupt.h>
+#include <net/bluetooth/hci.h>
+
+/* HCI priority */
+#define HCI_PRIO_MAX 7
+
+/* HCI Core structures */
+struct inquiry_data {
+ bdaddr_t bdaddr;
+ __u8 pscan_rep_mode;
+ __u8 pscan_period_mode;
+ __u8 pscan_mode;
+ __u8 dev_class[3];
+ __le16 clock_offset;
+ __s8 rssi;
+ __u8 ssp_mode;
+};
+
+struct inquiry_entry {
+ struct list_head all; /* inq_cache.all */
+ struct list_head list; /* unknown or resolve */
+ enum {
+ NAME_NOT_KNOWN,
+ NAME_NEEDED,
+ NAME_PENDING,
+ NAME_KNOWN,
+ } name_state;
+ __u32 timestamp;
+ struct inquiry_data data;
+};
+
+struct discovery_state {
+ int type;
+ enum {
+ DISCOVERY_STOPPED,
+ DISCOVERY_STARTING,
+ DISCOVERY_FINDING,
+ DISCOVERY_RESOLVING,
+ DISCOVERY_STOPPING,
+ } state;
+ struct list_head all; /* All devices found during inquiry */
+ struct list_head unknown; /* Name state not known */
+ struct list_head resolve; /* Name needs to be resolved */
+ __u32 timestamp;
+};
+
+struct hci_conn_hash {
+ struct list_head list;
+ unsigned int acl_num;
+ unsigned int sco_num;
+ unsigned int le_num;
+};
+
+struct bdaddr_list {
+ struct list_head list;
+ bdaddr_t bdaddr;
+};
+
+struct bt_uuid {
+ struct list_head list;
+ u8 uuid[16];
+ u8 svc_hint;
+};
+
+struct smp_ltk {
+ struct list_head list;
+ bdaddr_t bdaddr;
+ u8 bdaddr_type;
+ u8 authenticated;
+ u8 type;
+ u8 enc_size;
+ __le16 ediv;
+ u8 rand[8];
+ u8 val[16];
+} __packed;
+
+struct link_key {
+ struct list_head list;
+ bdaddr_t bdaddr;
+ u8 type;
+ u8 val[16];
+ u8 pin_len;
+};
+
+struct oob_data {
+ struct list_head list;
+ bdaddr_t bdaddr;
+ u8 hash[16];
+ u8 randomizer[16];
+};
+
+struct adv_entry {
+ struct list_head list;
+ bdaddr_t bdaddr;
+ u8 bdaddr_type;
+};
+
+struct le_scan_params {
+ u8 type;
+ u16 interval;
+ u16 window;
+ int timeout;
+};
+
+#define HCI_MAX_SHORT_NAME_LENGTH 10
+
+#define NUM_REASSEMBLY 4
+struct hci_dev {
+ struct list_head list;
+ struct mutex lock;
+
+ char name[8];
+ unsigned long flags;
+ __u16 id;
+ __u8 bus;
+ __u8 dev_type;
+ bdaddr_t bdaddr;
+ __u8 dev_name[HCI_MAX_NAME_LENGTH];
+ __u8 short_name[HCI_MAX_SHORT_NAME_LENGTH];
+ __u8 eir[HCI_MAX_EIR_LENGTH];
+ __u8 dev_class[3];
+ __u8 major_class;
+ __u8 minor_class;
+ __u8 features[8];
+ __u8 host_features[8];
+ __u8 commands[64];
+ __u8 hci_ver;
+ __u16 hci_rev;
+ __u8 lmp_ver;
+ __u16 manufacturer;
+ __le16 lmp_subver;
+ __u16 voice_setting;
+ __u8 io_capability;
+
+ __u16 pkt_type;
+ __u16 esco_type;
+ __u16 link_policy;
+ __u16 link_mode;
+
+ __u32 idle_timeout;
+ __u16 sniff_min_interval;
+ __u16 sniff_max_interval;
+
+ __u8 amp_status;
+ __u32 amp_total_bw;
+ __u32 amp_max_bw;
+ __u32 amp_min_latency;
+ __u32 amp_max_pdu;
+ __u8 amp_type;
+ __u16 amp_pal_cap;
+ __u16 amp_assoc_size;
+ __u32 amp_max_flush_to;
+ __u32 amp_be_flush_to;
+
+ __u8 flow_ctl_mode;
+
+ unsigned int auto_accept_delay;
+
+ unsigned long quirks;
+
+ atomic_t cmd_cnt;
+ unsigned int acl_cnt;
+ unsigned int sco_cnt;
+ unsigned int le_cnt;
+
+ unsigned int acl_mtu;
+ unsigned int sco_mtu;
+ unsigned int le_mtu;
+ unsigned int acl_pkts;
+ unsigned int sco_pkts;
+ unsigned int le_pkts;
+
+ __u16 block_len;
+ __u16 block_mtu;
+ __u16 num_blocks;
+ __u16 block_cnt;
+
+ unsigned long acl_last_tx;
+ unsigned long sco_last_tx;
+ unsigned long le_last_tx;
+
+ struct workqueue_struct *workqueue;
+
+ struct work_struct power_on;
+ struct delayed_work power_off;
+
+ __u16 discov_timeout;
+ struct delayed_work discov_off;
+
+ struct delayed_work service_cache;
+
+ struct timer_list cmd_timer;
+
+ struct work_struct rx_work;
+ struct work_struct cmd_work;
+ struct work_struct tx_work;
+
+ struct sk_buff_head rx_q;
+ struct sk_buff_head raw_q;
+ struct sk_buff_head cmd_q;
+
+ struct sk_buff *sent_cmd;
+ struct sk_buff *reassembly[NUM_REASSEMBLY];
+
+ struct mutex req_lock;
+ wait_queue_head_t req_wait_q;
+ __u32 req_status;
+ __u32 req_result;
+
+ __u16 init_last_cmd;
+
+ struct list_head mgmt_pending;
+
+ struct discovery_state discovery;
+ struct hci_conn_hash conn_hash;
+ struct list_head blacklist;
+
+ struct list_head uuids;
+
+ struct list_head link_keys;
+
+ struct list_head long_term_keys;
+
+ struct list_head remote_oob_data;
+
+ struct list_head adv_entries;
+ struct delayed_work adv_work;
+
+ struct hci_dev_stats stat;
+
+ struct sk_buff_head driver_init;
+
+ void *core_data;
+
+ atomic_t promisc;
+
+ struct dentry *debugfs;
+
+ struct device *parent;
+ struct device dev;
+
+ struct rfkill *rfkill;
+
+ unsigned long dev_flags;
+
+ struct delayed_work le_scan_disable;
+
+ struct work_struct le_scan;
+ struct le_scan_params le_scan_params;
+
+ int (*open)(struct hci_dev *hdev);
+ int (*close)(struct hci_dev *hdev);
+ int (*flush)(struct hci_dev *hdev);
+ int (*send)(struct sk_buff *skb);
+ void (*notify)(struct hci_dev *hdev, unsigned int evt);
+ int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
+};
+
+struct hci_conn {
+ struct list_head list;
+
+ atomic_t refcnt;
+
+ bdaddr_t dst;
+ __u8 dst_type;
+ __u16 handle;
+ __u16 state;
+ __u8 mode;
+ __u8 type;
+ bool out;
+ __u8 attempt;
+ __u8 dev_class[3];
+ __u8 features[8];
+ __u16 interval;
+ __u16 pkt_type;
+ __u16 link_policy;
+ __u32 link_mode;
+ __u8 key_type;
+ __u8 auth_type;
+ __u8 sec_level;
+ __u8 pending_sec_level;
+ __u8 pin_length;
+ __u8 enc_key_size;
+ __u8 io_capability;
+ __u16 disc_timeout;
+ unsigned long flags;
+
+ __u8 remote_cap;
+ __u8 remote_auth;
+ bool flush_key;
+
+ unsigned int sent;
+
+ struct sk_buff_head data_q;
+ struct list_head chan_list;
+
+ struct delayed_work disc_work;
+ struct timer_list idle_timer;
+ struct timer_list auto_accept_timer;
+
+ struct device dev;
+ atomic_t devref;
+
+ struct hci_dev *hdev;
+ void *l2cap_data;
+ void *sco_data;
+ void *smp_conn;
+
+ struct hci_conn *link;
+
+ void (*connect_cfm_cb) (struct hci_conn *conn, u8 status);
+ void (*security_cfm_cb) (struct hci_conn *conn, u8 status);
+ void (*disconn_cfm_cb) (struct hci_conn *conn, u8 reason);
+};
+
+struct hci_chan {
+ struct list_head list;
+
+ struct hci_conn *conn;
+ struct sk_buff_head data_q;
+ unsigned int sent;
+};
+
+extern struct list_head hci_dev_list;
+extern struct list_head hci_cb_list;
+extern rwlock_t hci_dev_list_lock;
+extern rwlock_t hci_cb_list_lock;
+
+/* ----- HCI interface to upper protocols ----- */
+extern int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
+extern int l2cap_connect_cfm(struct hci_conn *hcon, u8 status);
+extern int l2cap_disconn_ind(struct hci_conn *hcon);
+extern int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason);
+extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
+extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags);
+
+extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
+extern int sco_connect_cfm(struct hci_conn *hcon, __u8 status);
+extern int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
+extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
+
+/* ----- Inquiry cache ----- */
+#define INQUIRY_CACHE_AGE_MAX (HZ*30) /* 30 seconds */
+#define INQUIRY_ENTRY_AGE_MAX (HZ*60) /* 60 seconds */
+
+static inline void discovery_init(struct hci_dev *hdev)
+{
+ hdev->discovery.state = DISCOVERY_STOPPED;
+ INIT_LIST_HEAD(&hdev->discovery.all);
+ INIT_LIST_HEAD(&hdev->discovery.unknown);
+ INIT_LIST_HEAD(&hdev->discovery.resolve);
+}
+
+bool hci_discovery_active(struct hci_dev *hdev);
+
+void hci_discovery_set_state(struct hci_dev *hdev, int state);
+
+static inline int inquiry_cache_empty(struct hci_dev *hdev)
+{
+ return list_empty(&hdev->discovery.all);
+}
+
+static inline long inquiry_cache_age(struct hci_dev *hdev)
+{
+ struct discovery_state *c = &hdev->discovery;
+ return jiffies - c->timestamp;
+}
+
+static inline long inquiry_entry_age(struct inquiry_entry *e)
+{
+ return jiffies - e->timestamp;
+}
+
+struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev,
+ bdaddr_t *bdaddr);
+struct inquiry_entry *hci_inquiry_cache_lookup_unknown(struct hci_dev *hdev,
+ bdaddr_t *bdaddr);
+struct inquiry_entry *hci_inquiry_cache_lookup_resolve(struct hci_dev *hdev,
+ bdaddr_t *bdaddr,
+ int state);
+void hci_inquiry_cache_update_resolve(struct hci_dev *hdev,
+ struct inquiry_entry *ie);
+bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
+ bool name_known, bool *ssp);
+
+/* ----- HCI Connections ----- */
+enum {
+ HCI_CONN_AUTH_PEND,
+ HCI_CONN_REAUTH_PEND,
+ HCI_CONN_ENCRYPT_PEND,
+ HCI_CONN_RSWITCH_PEND,
+ HCI_CONN_MODE_CHANGE_PEND,
+ HCI_CONN_SCO_SETUP_PEND,
+ HCI_CONN_LE_SMP_PEND,
+ HCI_CONN_MGMT_CONNECTED,
+ HCI_CONN_SSP_ENABLED,
+ HCI_CONN_POWER_SAVE,
+ HCI_CONN_REMOTE_OOB,
+};
+
+static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
+{
+ struct hci_dev *hdev = conn->hdev;
+ return (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
+ test_bit(HCI_CONN_SSP_ENABLED, &conn->flags));
+}
+
+static inline void hci_conn_hash_init(struct hci_dev *hdev)
+{
+ struct hci_conn_hash *h = &hdev->conn_hash;
+ INIT_LIST_HEAD(&h->list);
+ h->acl_num = 0;
+ h->sco_num = 0;
+ h->le_num = 0;
+}
+
+static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
+{
+ struct hci_conn_hash *h = &hdev->conn_hash;
+ list_add_rcu(&c->list, &h->list);
+ switch (c->type) {
+ case ACL_LINK:
+ h->acl_num++;
+ break;
+ case LE_LINK:
+ h->le_num++;
+ break;
+ case SCO_LINK:
+ case ESCO_LINK:
+ h->sco_num++;
+ break;
+ }
+}
+
+static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
+{
+ struct hci_conn_hash *h = &hdev->conn_hash;
+
+ list_del_rcu(&c->list);
+ synchronize_rcu();
+
+ switch (c->type) {
+ case ACL_LINK:
+ h->acl_num--;
+ break;
+ case LE_LINK:
+ h->le_num--;
+ break;
+ case SCO_LINK:
+ case ESCO_LINK:
+ h->sco_num--;
+ break;
+ }
+}
+
+static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type)
+{
+ struct hci_conn_hash *h = &hdev->conn_hash;
+ switch (type) {
+ case ACL_LINK:
+ return h->acl_num;
+ case LE_LINK:
+ return h->le_num;
+ case SCO_LINK:
+ case ESCO_LINK:
+ return h->sco_num;
+ default:
+ return 0;
+ }
+}
+
+static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
+ __u16 handle)
+{
+ struct hci_conn_hash *h = &hdev->conn_hash;
+ struct hci_conn *c;
+
+ rcu_read_lock();
+
+ list_for_each_entry_rcu(c, &h->list, list) {
+ if (c->handle == handle) {
+ rcu_read_unlock();
+ return c;
+ }
+ }
+ rcu_read_unlock();
+
+ return NULL;
+}
+
+static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
+ __u8 type, bdaddr_t *ba)
+{
+ struct hci_conn_hash *h = &hdev->conn_hash;
+ struct hci_conn *c;
+
+ rcu_read_lock();
+
+ list_for_each_entry_rcu(c, &h->list, list) {
+ if (c->type == type && !bacmp(&c->dst, ba)) {
+ rcu_read_unlock();
+ return c;
+ }
+ }
+
+ rcu_read_unlock();
+
+ return NULL;
+}
+
+static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
+ __u8 type, __u16 state)
+{
+ struct hci_conn_hash *h = &hdev->conn_hash;
+ struct hci_conn *c;
+
+ rcu_read_lock();
+
+ list_for_each_entry_rcu(c, &h->list, list) {
+ if (c->type == type && c->state == state) {
+ rcu_read_unlock();
+ return c;
+ }
+ }
+
+ rcu_read_unlock();
+
+ return NULL;
+}
+
+void hci_acl_connect(struct hci_conn *conn);
+void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
+void hci_add_sco(struct hci_conn *conn, __u16 handle);
+void hci_setup_sync(struct hci_conn *conn, __u16 handle);
+void hci_sco_setup(struct hci_conn *conn, __u8 status);
+
+struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type,
+ __u16 pkt_type, bdaddr_t *dst);
+int hci_conn_del(struct hci_conn *conn);
+void hci_conn_hash_flush(struct hci_dev *hdev);
+void hci_conn_check_pending(struct hci_dev *hdev);
+
+struct hci_chan *hci_chan_create(struct hci_conn *conn);
+int hci_chan_del(struct hci_chan *chan);
+void hci_chan_list_flush(struct hci_conn *conn);
+
+struct hci_conn *hci_connect(struct hci_dev *hdev, int type,
+ __u16 pkt_type, bdaddr_t *dst,
+ __u8 sec_level, __u8 auth_type);
+int hci_conn_check_link_mode(struct hci_conn *conn);
+int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level);
+int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
+int hci_conn_change_link_key(struct hci_conn *conn);
+int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
+
+void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
+
+void hci_conn_hold_device(struct hci_conn *conn);
+void hci_conn_put_device(struct hci_conn *conn);
+
+static inline void hci_conn_hold(struct hci_conn *conn)
+{
+ atomic_inc(&conn->refcnt);
+ cancel_delayed_work(&conn->disc_work);
+}
+
+static inline void hci_conn_put(struct hci_conn *conn)
+{
+ if (atomic_dec_and_test(&conn->refcnt)) {
+ unsigned long timeo;
+ if (conn->type == ACL_LINK || conn->type == LE_LINK) {
+ del_timer(&conn->idle_timer);
+ if (conn->state == BT_CONNECTED) {
+ timeo = msecs_to_jiffies(conn->disc_timeout);
+ if (!conn->out)
+ timeo *= 20;
+ } else {
+ timeo = msecs_to_jiffies(10);
+ }
+ } else {
+ timeo = msecs_to_jiffies(10);
+ }
+ cancel_delayed_work(&conn->disc_work);
+ queue_delayed_work(conn->hdev->workqueue,
+ &conn->disc_work, timeo);
+ }
+}
+
+/* ----- HCI Devices ----- */
+static inline void hci_dev_put(struct hci_dev *d)
+{
+ put_device(&d->dev);
+}
+
+static inline struct hci_dev *hci_dev_hold(struct hci_dev *d)
+{
+ get_device(&d->dev);
+ return d;
+}
+
+#define hci_dev_lock(d) mutex_lock(&d->lock)
+#define hci_dev_unlock(d) mutex_unlock(&d->lock)
+
+#define to_hci_dev(d) container_of(d, struct hci_dev, dev)
+#define to_hci_conn(c) container_of(c, struct hci_conn, dev)
+
+static inline void *hci_get_drvdata(struct hci_dev *hdev)
+{
+ return dev_get_drvdata(&hdev->dev);
+}
+
+static inline void hci_set_drvdata(struct hci_dev *hdev, void *data)
+{
+ dev_set_drvdata(&hdev->dev, data);
+}
+
+struct hci_dev *hci_dev_get(int index);
+struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst);
+
+struct hci_dev *hci_alloc_dev(void);
+void hci_free_dev(struct hci_dev *hdev);
+int hci_register_dev(struct hci_dev *hdev);
+void hci_unregister_dev(struct hci_dev *hdev);
+int hci_suspend_dev(struct hci_dev *hdev);
+int hci_resume_dev(struct hci_dev *hdev);
+int hci_dev_open(__u16 dev);
+int hci_dev_close(__u16 dev);
+int hci_dev_reset(__u16 dev);
+int hci_dev_reset_stat(__u16 dev);
+int hci_dev_cmd(unsigned int cmd, void __user *arg);
+int hci_get_dev_list(void __user *arg);
+int hci_get_dev_info(void __user *arg);
+int hci_get_conn_list(void __user *arg);
+int hci_get_conn_info(struct hci_dev *hdev, void __user *arg);
+int hci_get_auth_info(struct hci_dev *hdev, void __user *arg);
+int hci_inquiry(void __user *arg);
+
+struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_blacklist_clear(struct hci_dev *hdev);
+int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
+int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
+
+int hci_uuids_clear(struct hci_dev *hdev);
+
+int hci_link_keys_clear(struct hci_dev *hdev);
+struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
+ bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len);
+struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]);
+int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type,
+ int new_key, u8 authenticated, u8 tk[16], u8 enc_size, u16 ediv,
+ u8 rand[8]);
+struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 addr_type);
+int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_smp_ltks_clear(struct hci_dev *hdev);
+int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
+
+int hci_remote_oob_data_clear(struct hci_dev *hdev);
+struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
+ bdaddr_t *bdaddr);
+int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
+ u8 *randomizer);
+int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
+
+#define ADV_CLEAR_TIMEOUT (3*60*HZ) /* Three minutes */
+int hci_adv_entries_clear(struct hci_dev *hdev);
+struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_add_adv_entry(struct hci_dev *hdev,
+ struct hci_ev_le_advertising_info *ev);
+
+void hci_del_off_timer(struct hci_dev *hdev);
+
+void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
+
+int hci_recv_frame(struct sk_buff *skb);
+int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count);
+int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count);
+
+void hci_init_sysfs(struct hci_dev *hdev);
+int hci_add_sysfs(struct hci_dev *hdev);
+void hci_del_sysfs(struct hci_dev *hdev);
+void hci_conn_init_sysfs(struct hci_conn *conn);
+void hci_conn_add_sysfs(struct hci_conn *conn);
+void hci_conn_del_sysfs(struct hci_conn *conn);
+
+#define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->parent = (pdev))
+
+/* ----- LMP capabilities ----- */
+#define lmp_rswitch_capable(dev) ((dev)->features[0] & LMP_RSWITCH)
+#define lmp_encrypt_capable(dev) ((dev)->features[0] & LMP_ENCRYPT)
+#define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF)
+#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
+#define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO)
+#define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR)
+#define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH)
+#define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE)
+#define lmp_bredr_capable(dev) (!((dev)->features[4] & LMP_NO_BREDR))
+
+/* ----- Extended LMP capabilities ----- */
+#define lmp_host_le_capable(dev) ((dev)->host_features[0] & LMP_HOST_LE)
+
+/* ----- HCI protocols ----- */
+static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ __u8 type)
+{
+ switch (type) {
+ case ACL_LINK:
+ return l2cap_connect_ind(hdev, bdaddr);
+
+ case SCO_LINK:
+ case ESCO_LINK:
+ return sco_connect_ind(hdev, bdaddr);
+
+ default:
+ BT_ERR("unknown link type %d", type);
+ return -EINVAL;
+ }
+}
+
+static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status)
+{
+ switch (conn->type) {
+ case ACL_LINK:
+ case LE_LINK:
+ l2cap_connect_cfm(conn, status);
+ break;
+
+ case SCO_LINK:
+ case ESCO_LINK:
+ sco_connect_cfm(conn, status);
+ break;
+
+ default:
+ BT_ERR("unknown link type %d", conn->type);
+ break;
+ }
+
+ if (conn->connect_cfm_cb)
+ conn->connect_cfm_cb(conn, status);
+}
+
+static inline int hci_proto_disconn_ind(struct hci_conn *conn)
+{
+ if (conn->type != ACL_LINK && conn->type != LE_LINK)
+ return HCI_ERROR_REMOTE_USER_TERM;
+
+ return l2cap_disconn_ind(conn);
+}
+
+static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason)
+{
+ switch (conn->type) {
+ case ACL_LINK:
+ case LE_LINK:
+ l2cap_disconn_cfm(conn, reason);
+ break;
+
+ case SCO_LINK:
+ case ESCO_LINK:
+ sco_disconn_cfm(conn, reason);
+ break;
+
+ default:
+ BT_ERR("unknown link type %d", conn->type);
+ break;
+ }
+
+ if (conn->disconn_cfm_cb)
+ conn->disconn_cfm_cb(conn, reason);
+}
+
+static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
+{
+ __u8 encrypt;
+
+ if (conn->type != ACL_LINK && conn->type != LE_LINK)
+ return;
+
+ if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
+ return;
+
+ encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;
+ l2cap_security_cfm(conn, status, encrypt);
+
+ if (conn->security_cfm_cb)
+ conn->security_cfm_cb(conn, status);
+}
+
+static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status,
+ __u8 encrypt)
+{
+ if (conn->type != ACL_LINK && conn->type != LE_LINK)
+ return;
+
+ l2cap_security_cfm(conn, status, encrypt);
+
+ if (conn->security_cfm_cb)
+ conn->security_cfm_cb(conn, status);
+}
+
+/* ----- HCI callbacks ----- */
+struct hci_cb {
+ struct list_head list;
+
+ char *name;
+
+ void (*security_cfm) (struct hci_conn *conn, __u8 status,
+ __u8 encrypt);
+ void (*key_change_cfm) (struct hci_conn *conn, __u8 status);
+ void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
+};
+
+static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
+{
+ struct list_head *p;
+ __u8 encrypt;
+
+ hci_proto_auth_cfm(conn, status);
+
+ if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
+ return;
+
+ encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;
+
+ read_lock(&hci_cb_list_lock);
+ list_for_each(p, &hci_cb_list) {
+ struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+ if (cb->security_cfm)
+ cb->security_cfm(conn, status, encrypt);
+ }
+ read_unlock(&hci_cb_list_lock);
+}
+
+static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
+ __u8 encrypt)
+{
+ struct list_head *p;
+
+ if (conn->sec_level == BT_SECURITY_SDP)
+ conn->sec_level = BT_SECURITY_LOW;
+
+ if (conn->pending_sec_level > conn->sec_level)
+ conn->sec_level = conn->pending_sec_level;
+
+ hci_proto_encrypt_cfm(conn, status, encrypt);
+
+ read_lock(&hci_cb_list_lock);
+ list_for_each(p, &hci_cb_list) {
+ struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+ if (cb->security_cfm)
+ cb->security_cfm(conn, status, encrypt);
+ }
+ read_unlock(&hci_cb_list_lock);
+}
+
+static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
+{
+ struct list_head *p;
+
+ read_lock(&hci_cb_list_lock);
+ list_for_each(p, &hci_cb_list) {
+ struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+ if (cb->key_change_cfm)
+ cb->key_change_cfm(conn, status);
+ }
+ read_unlock(&hci_cb_list_lock);
+}
+
+static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
+ __u8 role)
+{
+ struct list_head *p;
+
+ read_lock(&hci_cb_list_lock);
+ list_for_each(p, &hci_cb_list) {
+ struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+ if (cb->role_switch_cfm)
+ cb->role_switch_cfm(conn, status, role);
+ }
+ read_unlock(&hci_cb_list_lock);
+}
+
+static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type)
+{
+ size_t parsed = 0;
+
+ if (data_len < 2)
+ return false;
+
+ while (parsed < data_len - 1) {
+ u8 field_len = data[0];
+
+ if (field_len == 0)
+ break;
+
+ parsed += field_len + 1;
+
+ if (parsed > data_len)
+ break;
+
+ if (data[1] == type)
+ return true;
+
+ data += field_len + 1;
+ }
+
+ return false;
+}
+
+static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
+ u8 data_len)
+{
+ eir[eir_len++] = sizeof(type) + data_len;
+ eir[eir_len++] = type;
+ memcpy(&eir[eir_len], data, data_len);
+ eir_len += data_len;
+
+ return eir_len;
+}
+
+int hci_register_cb(struct hci_cb *hcb);
+int hci_unregister_cb(struct hci_cb *hcb);
+
+int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param);
+void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags);
+void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
+
+void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
+
+/* ----- HCI Sockets ----- */
+void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb);
+void hci_send_to_control(struct sk_buff *skb, struct sock *skip_sk);
+void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb);
+
+void hci_sock_dev_event(struct hci_dev *hdev, int event);
+
+/* Management interface */
+#define MGMT_ADDR_BREDR 0x00
+#define MGMT_ADDR_LE_PUBLIC 0x01
+#define MGMT_ADDR_LE_RANDOM 0x02
+#define MGMT_ADDR_INVALID 0xff
+
+#define DISCOV_TYPE_BREDR (BIT(MGMT_ADDR_BREDR))
+#define DISCOV_TYPE_LE (BIT(MGMT_ADDR_LE_PUBLIC) | \
+ BIT(MGMT_ADDR_LE_RANDOM))
+#define DISCOV_TYPE_INTERLEAVED (BIT(MGMT_ADDR_BREDR) | \
+ BIT(MGMT_ADDR_LE_PUBLIC) | \
+ BIT(MGMT_ADDR_LE_RANDOM))
+
+int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len);
+int mgmt_index_added(struct hci_dev *hdev);
+int mgmt_index_removed(struct hci_dev *hdev);
+int mgmt_powered(struct hci_dev *hdev, u8 powered);
+int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable);
+int mgmt_connectable(struct hci_dev *hdev, u8 connectable);
+int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status);
+int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
+ bool persistent);
+int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
+ u8 addr_type, u32 flags, u8 *name, u8 name_len,
+ u8 *dev_class);
+int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 link_type, u8 addr_type);
+int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 link_type, u8 addr_type, u8 status);
+int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
+ u8 addr_type, u8 status);
+int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure);
+int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 status);
+int mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 status);
+int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 link_type, u8 addr_type, __le32 value,
+ u8 confirm_hint);
+int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 link_type, u8 addr_type, u8 status);
+int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 link_type, u8 addr_type, u8 status);
+int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 link_type, u8 addr_type);
+int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 link_type, u8 addr_type, u8 status);
+int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 link_type, u8 addr_type, u8 status);
+int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
+ u8 addr_type, u8 status);
+int mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status);
+int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
+int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
+ u8 status);
+int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status);
+int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
+ u8 *randomizer, u8 status);
+int mgmt_le_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
+int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
+ u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
+ u8 ssp, u8 *eir, u16 eir_len);
+int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
+ u8 addr_type, s8 rssi, u8 *name, u8 name_len);
+int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status);
+int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status);
+int mgmt_discovering(struct hci_dev *hdev, u8 discovering);
+int mgmt_interleaved_discovery(struct hci_dev *hdev);
+int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
+int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
+
+int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent);
+
+/* HCI info for socket */
+#define hci_pi(sk) ((struct hci_pinfo *) sk)
+
+struct hci_pinfo {
+ struct bt_sock bt;
+ struct hci_dev *hdev;
+ struct hci_filter filter;
+ __u32 cmsg_mask;
+ unsigned short channel;
+};
+
+/* HCI security filter */
+#define HCI_SFLT_MAX_OGF 5
+
+struct hci_sec_filter {
+ __u32 type_mask;
+ __u32 event_mask[2];
+ __u32 ocf_mask[HCI_SFLT_MAX_OGF + 1][4];
+};
+
+/* ----- HCI requests ----- */
+#define HCI_REQ_DONE 0
+#define HCI_REQ_PEND 1
+#define HCI_REQ_CANCELED 2
+
+#define hci_req_lock(d) mutex_lock(&d->req_lock)
+#define hci_req_unlock(d) mutex_unlock(&d->req_lock)
+
+void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result);
+
+void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
+ u16 latency, u16 to_multiplier);
+void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
+ __u8 ltk[16]);
+void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]);
+void hci_le_ltk_neg_reply(struct hci_conn *conn);
+
+int hci_do_inquiry(struct hci_dev *hdev, u8 length);
+int hci_cancel_inquiry(struct hci_dev *hdev);
+int hci_le_scan(struct hci_dev *hdev, u8 type, u16 interval, u16 window,
+ int timeout);
+
+#endif /* __HCI_CORE_H */
diff --git a/include/net/bluetooth/hci_mon.h b/include/net/bluetooth/hci_mon.h
new file mode 100644
index 00000000..77d1e576
--- /dev/null
+++ b/include/net/bluetooth/hci_mon.h
@@ -0,0 +1,51 @@
+/*
+ BlueZ - Bluetooth protocol stack for Linux
+
+ Copyright (C) 2011-2012 Intel Corporation
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+ CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ SOFTWARE IS DISCLAIMED.
+*/
+
+#ifndef __HCI_MON_H
+#define __HCI_MON_H
+
+struct hci_mon_hdr {
+ __le16 opcode;
+ __le16 index;
+ __le16 len;
+} __packed;
+#define HCI_MON_HDR_SIZE 6
+
+#define HCI_MON_NEW_INDEX 0
+#define HCI_MON_DEL_INDEX 1
+#define HCI_MON_COMMAND_PKT 2
+#define HCI_MON_EVENT_PKT 3
+#define HCI_MON_ACL_TX_PKT 4
+#define HCI_MON_ACL_RX_PKT 5
+#define HCI_MON_SCO_TX_PKT 6
+#define HCI_MON_SCO_RX_PKT 7
+
+struct hci_mon_new_index {
+ __u8 type;
+ __u8 bus;
+ bdaddr_t bdaddr;
+ char name[8];
+} __packed;
+#define HCI_MON_NEW_INDEX_SIZE 16
+
+#endif /* __HCI_MON_H */
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
new file mode 100644
index 00000000..9b242c6b
--- /dev/null
+++ b/include/net/bluetooth/l2cap.h
@@ -0,0 +1,865 @@
+/*
+ BlueZ - Bluetooth protocol stack for Linux
+ Copyright (C) 2000-2001 Qualcomm Incorporated
+ Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
+ Copyright (C) 2010 Google Inc.
+
+ Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+ CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ SOFTWARE IS DISCLAIMED.
+*/
+
+#ifndef __L2CAP_H
+#define __L2CAP_H
+
+#include <asm/unaligned.h>
+
+/* L2CAP defaults */
+#define L2CAP_DEFAULT_MTU 672
+#define L2CAP_DEFAULT_MIN_MTU 48
+#define L2CAP_DEFAULT_FLUSH_TO 0xffff
+#define L2CAP_DEFAULT_TX_WINDOW 63
+#define L2CAP_DEFAULT_EXT_WINDOW 0x3FFF
+#define L2CAP_DEFAULT_MAX_TX 3
+#define L2CAP_DEFAULT_RETRANS_TO 2000 /* 2 seconds */
+#define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */
+#define L2CAP_DEFAULT_MAX_PDU_SIZE 1009 /* Sized for 3-DH5 packet */
+#define L2CAP_DEFAULT_ACK_TO 200
+#define L2CAP_LE_DEFAULT_MTU 23
+#define L2CAP_DEFAULT_MAX_SDU_SIZE 0xFFFF
+#define L2CAP_DEFAULT_SDU_ITIME 0xFFFFFFFF
+#define L2CAP_DEFAULT_ACC_LAT 0xFFFFFFFF
+
+#define L2CAP_DISC_TIMEOUT msecs_to_jiffies(100)
+#define L2CAP_DISC_REJ_TIMEOUT msecs_to_jiffies(5000)
+#define L2CAP_ENC_TIMEOUT msecs_to_jiffies(5000)
+#define L2CAP_CONN_TIMEOUT msecs_to_jiffies(40000)
+#define L2CAP_INFO_TIMEOUT msecs_to_jiffies(4000)
+
+/* L2CAP socket address */
+struct sockaddr_l2 {
+ sa_family_t l2_family;
+ __le16 l2_psm;
+ bdaddr_t l2_bdaddr;
+ __le16 l2_cid;
+};
+
+/* L2CAP socket options */
+#define L2CAP_OPTIONS 0x01
+struct l2cap_options {
+ __u16 omtu;
+ __u16 imtu;
+ __u16 flush_to;
+ __u8 mode;
+ __u8 fcs;
+ __u8 max_tx;
+ __u16 txwin_size;
+};
+
+#define L2CAP_CONNINFO 0x02
+struct l2cap_conninfo {
+ __u16 hci_handle;
+ __u8 dev_class[3];
+};
+
+#define L2CAP_LM 0x03
+#define L2CAP_LM_MASTER 0x0001
+#define L2CAP_LM_AUTH 0x0002
+#define L2CAP_LM_ENCRYPT 0x0004
+#define L2CAP_LM_TRUSTED 0x0008
+#define L2CAP_LM_RELIABLE 0x0010
+#define L2CAP_LM_SECURE 0x0020
+
+/* L2CAP command codes */
+#define L2CAP_COMMAND_REJ 0x01
+#define L2CAP_CONN_REQ 0x02
+#define L2CAP_CONN_RSP 0x03
+#define L2CAP_CONF_REQ 0x04
+#define L2CAP_CONF_RSP 0x05
+#define L2CAP_DISCONN_REQ 0x06
+#define L2CAP_DISCONN_RSP 0x07
+#define L2CAP_ECHO_REQ 0x08
+#define L2CAP_ECHO_RSP 0x09
+#define L2CAP_INFO_REQ 0x0a
+#define L2CAP_INFO_RSP 0x0b
+#define L2CAP_CREATE_CHAN_REQ 0x0c
+#define L2CAP_CREATE_CHAN_RSP 0x0d
+#define L2CAP_MOVE_CHAN_REQ 0x0e
+#define L2CAP_MOVE_CHAN_RSP 0x0f
+#define L2CAP_MOVE_CHAN_CFM 0x10
+#define L2CAP_MOVE_CHAN_CFM_RSP 0x11
+#define L2CAP_CONN_PARAM_UPDATE_REQ 0x12
+#define L2CAP_CONN_PARAM_UPDATE_RSP 0x13
+
+/* L2CAP extended feature mask */
+#define L2CAP_FEAT_FLOWCTL 0x00000001
+#define L2CAP_FEAT_RETRANS 0x00000002
+#define L2CAP_FEAT_BIDIR_QOS 0x00000004
+#define L2CAP_FEAT_ERTM 0x00000008
+#define L2CAP_FEAT_STREAMING 0x00000010
+#define L2CAP_FEAT_FCS 0x00000020
+#define L2CAP_FEAT_EXT_FLOW 0x00000040
+#define L2CAP_FEAT_FIXED_CHAN 0x00000080
+#define L2CAP_FEAT_EXT_WINDOW 0x00000100
+#define L2CAP_FEAT_UCD 0x00000200
+
+/* L2CAP checksum option */
+#define L2CAP_FCS_NONE 0x00
+#define L2CAP_FCS_CRC16 0x01
+
+/* L2CAP fixed channels */
+#define L2CAP_FC_L2CAP 0x02
+#define L2CAP_FC_A2MP 0x08
+
+/* L2CAP Control Field bit masks */
+#define L2CAP_CTRL_SAR 0xC000
+#define L2CAP_CTRL_REQSEQ 0x3F00
+#define L2CAP_CTRL_TXSEQ 0x007E
+#define L2CAP_CTRL_SUPERVISE 0x000C
+
+#define L2CAP_CTRL_RETRANS 0x0080
+#define L2CAP_CTRL_FINAL 0x0080
+#define L2CAP_CTRL_POLL 0x0010
+#define L2CAP_CTRL_FRAME_TYPE 0x0001 /* I- or S-Frame */
+
+#define L2CAP_CTRL_TXSEQ_SHIFT 1
+#define L2CAP_CTRL_SUPER_SHIFT 2
+#define L2CAP_CTRL_REQSEQ_SHIFT 8
+#define L2CAP_CTRL_SAR_SHIFT 14
+
+/* L2CAP Extended Control Field bit mask */
+#define L2CAP_EXT_CTRL_TXSEQ 0xFFFC0000
+#define L2CAP_EXT_CTRL_SAR 0x00030000
+#define L2CAP_EXT_CTRL_SUPERVISE 0x00030000
+#define L2CAP_EXT_CTRL_REQSEQ 0x0000FFFC
+
+#define L2CAP_EXT_CTRL_POLL 0x00040000
+#define L2CAP_EXT_CTRL_FINAL 0x00000002
+#define L2CAP_EXT_CTRL_FRAME_TYPE 0x00000001 /* I- or S-Frame */
+
+#define L2CAP_EXT_CTRL_REQSEQ_SHIFT 2
+#define L2CAP_EXT_CTRL_SAR_SHIFT 16
+#define L2CAP_EXT_CTRL_SUPER_SHIFT 16
+#define L2CAP_EXT_CTRL_TXSEQ_SHIFT 18
+
+/* L2CAP Supervisory Function */
+#define L2CAP_SUPER_RR 0x00
+#define L2CAP_SUPER_REJ 0x01
+#define L2CAP_SUPER_RNR 0x02
+#define L2CAP_SUPER_SREJ 0x03
+
+/* L2CAP Segmentation and Reassembly */
+#define L2CAP_SAR_UNSEGMENTED 0x00
+#define L2CAP_SAR_START 0x01
+#define L2CAP_SAR_END 0x02
+#define L2CAP_SAR_CONTINUE 0x03
+
+/* L2CAP Command rej. reasons */
+#define L2CAP_REJ_NOT_UNDERSTOOD 0x0000
+#define L2CAP_REJ_MTU_EXCEEDED 0x0001
+#define L2CAP_REJ_INVALID_CID 0x0002
+
+/* L2CAP structures */
+struct l2cap_hdr {
+ __le16 len;
+ __le16 cid;
+} __packed;
+#define L2CAP_HDR_SIZE 4
+#define L2CAP_ENH_HDR_SIZE 6
+#define L2CAP_EXT_HDR_SIZE 8
+
+#define L2CAP_FCS_SIZE 2
+#define L2CAP_SDULEN_SIZE 2
+#define L2CAP_PSMLEN_SIZE 2
+
+struct l2cap_cmd_hdr {
+ __u8 code;
+ __u8 ident;
+ __le16 len;
+} __packed;
+#define L2CAP_CMD_HDR_SIZE 4
+
+struct l2cap_cmd_rej_unk {
+ __le16 reason;
+} __packed;
+
+struct l2cap_cmd_rej_mtu {
+ __le16 reason;
+ __le16 max_mtu;
+} __packed;
+
+struct l2cap_cmd_rej_cid {
+ __le16 reason;
+ __le16 scid;
+ __le16 dcid;
+} __packed;
+
+struct l2cap_conn_req {
+ __le16 psm;
+ __le16 scid;
+} __packed;
+
+struct l2cap_conn_rsp {
+ __le16 dcid;
+ __le16 scid;
+ __le16 result;
+ __le16 status;
+} __packed;
+
+/* channel indentifier */
+#define L2CAP_CID_SIGNALING 0x0001
+#define L2CAP_CID_CONN_LESS 0x0002
+#define L2CAP_CID_LE_DATA 0x0004
+#define L2CAP_CID_LE_SIGNALING 0x0005
+#define L2CAP_CID_SMP 0x0006
+#define L2CAP_CID_DYN_START 0x0040
+#define L2CAP_CID_DYN_END 0xffff
+
+/* connect/create channel results */
+#define L2CAP_CR_SUCCESS 0x0000
+#define L2CAP_CR_PEND 0x0001
+#define L2CAP_CR_BAD_PSM 0x0002
+#define L2CAP_CR_SEC_BLOCK 0x0003
+#define L2CAP_CR_NO_MEM 0x0004
+#define L2CAP_CR_BAD_AMP 0x0005
+
+/* connect/create channel status */
+#define L2CAP_CS_NO_INFO 0x0000
+#define L2CAP_CS_AUTHEN_PEND 0x0001
+#define L2CAP_CS_AUTHOR_PEND 0x0002
+
+struct l2cap_conf_req {
+ __le16 dcid;
+ __le16 flags;
+ __u8 data[0];
+} __packed;
+
+struct l2cap_conf_rsp {
+ __le16 scid;
+ __le16 flags;
+ __le16 result;
+ __u8 data[0];
+} __packed;
+
+#define L2CAP_CONF_SUCCESS 0x0000
+#define L2CAP_CONF_UNACCEPT 0x0001
+#define L2CAP_CONF_REJECT 0x0002
+#define L2CAP_CONF_UNKNOWN 0x0003
+#define L2CAP_CONF_PENDING 0x0004
+#define L2CAP_CONF_EFS_REJECT 0x0005
+
+struct l2cap_conf_opt {
+ __u8 type;
+ __u8 len;
+ __u8 val[0];
+} __packed;
+#define L2CAP_CONF_OPT_SIZE 2
+
+#define L2CAP_CONF_HINT 0x80
+#define L2CAP_CONF_MASK 0x7f
+
+#define L2CAP_CONF_MTU 0x01
+#define L2CAP_CONF_FLUSH_TO 0x02
+#define L2CAP_CONF_QOS 0x03
+#define L2CAP_CONF_RFC 0x04
+#define L2CAP_CONF_FCS 0x05
+#define L2CAP_CONF_EFS 0x06
+#define L2CAP_CONF_EWS 0x07
+
+#define L2CAP_CONF_MAX_SIZE 22
+
+struct l2cap_conf_rfc {
+ __u8 mode;
+ __u8 txwin_size;
+ __u8 max_transmit;
+ __le16 retrans_timeout;
+ __le16 monitor_timeout;
+ __le16 max_pdu_size;
+} __packed;
+
+#define L2CAP_MODE_BASIC 0x00
+#define L2CAP_MODE_RETRANS 0x01
+#define L2CAP_MODE_FLOWCTL 0x02
+#define L2CAP_MODE_ERTM 0x03
+#define L2CAP_MODE_STREAMING 0x04
+
+struct l2cap_conf_efs {
+ __u8 id;
+ __u8 stype;
+ __le16 msdu;
+ __le32 sdu_itime;
+ __le32 acc_lat;
+ __le32 flush_to;
+} __packed;
+
+#define L2CAP_SERV_NOTRAFIC 0x00
+#define L2CAP_SERV_BESTEFFORT 0x01
+#define L2CAP_SERV_GUARANTEED 0x02
+
+#define L2CAP_BESTEFFORT_ID 0x01
+
+struct l2cap_disconn_req {
+ __le16 dcid;
+ __le16 scid;
+} __packed;
+
+struct l2cap_disconn_rsp {
+ __le16 dcid;
+ __le16 scid;
+} __packed;
+
+struct l2cap_info_req {
+ __le16 type;
+} __packed;
+
+struct l2cap_info_rsp {
+ __le16 type;
+ __le16 result;
+ __u8 data[0];
+} __packed;
+
+struct l2cap_create_chan_req {
+ __le16 psm;
+ __le16 scid;
+ __u8 amp_id;
+} __packed;
+
+struct l2cap_create_chan_rsp {
+ __le16 dcid;
+ __le16 scid;
+ __le16 result;
+ __le16 status;
+} __packed;
+
+struct l2cap_move_chan_req {
+ __le16 icid;
+ __u8 dest_amp_id;
+} __packed;
+
+struct l2cap_move_chan_rsp {
+ __le16 icid;
+ __le16 result;
+} __packed;
+
+#define L2CAP_MR_SUCCESS 0x0000
+#define L2CAP_MR_PEND 0x0001
+#define L2CAP_MR_BAD_ID 0x0002
+#define L2CAP_MR_SAME_ID 0x0003
+#define L2CAP_MR_NOT_SUPP 0x0004
+#define L2CAP_MR_COLLISION 0x0005
+#define L2CAP_MR_NOT_ALLOWED 0x0006
+
+struct l2cap_move_chan_cfm {
+ __le16 icid;
+ __le16 result;
+} __packed;
+
+#define L2CAP_MC_CONFIRMED 0x0000
+#define L2CAP_MC_UNCONFIRMED 0x0001
+
+struct l2cap_move_chan_cfm_rsp {
+ __le16 icid;
+} __packed;
+
+/* info type */
+#define L2CAP_IT_CL_MTU 0x0001
+#define L2CAP_IT_FEAT_MASK 0x0002
+#define L2CAP_IT_FIXED_CHAN 0x0003
+
+/* info result */
+#define L2CAP_IR_SUCCESS 0x0000
+#define L2CAP_IR_NOTSUPP 0x0001
+
+struct l2cap_conn_param_update_req {
+ __le16 min;
+ __le16 max;
+ __le16 latency;
+ __le16 to_multiplier;
+} __packed;
+
+struct l2cap_conn_param_update_rsp {
+ __le16 result;
+} __packed;
+
+/* Connection Parameters result */
+#define L2CAP_CONN_PARAM_ACCEPTED 0x0000
+#define L2CAP_CONN_PARAM_REJECTED 0x0001
+
+/* ----- L2CAP channels and connections ----- */
+struct srej_list {
+ __u16 tx_seq;
+ struct list_head list;
+};
+
+struct l2cap_chan {
+ struct sock *sk;
+
+ struct l2cap_conn *conn;
+
+ __u8 state;
+
+ atomic_t refcnt;
+
+ __le16 psm;
+ __u16 dcid;
+ __u16 scid;
+
+ __u16 imtu;
+ __u16 omtu;
+ __u16 flush_to;
+ __u8 mode;
+ __u8 chan_type;
+ __u8 chan_policy;
+
+ __le16 sport;
+
+ __u8 sec_level;
+
+ __u8 ident;
+
+ __u8 conf_req[64];
+ __u8 conf_len;
+ __u8 num_conf_req;
+ __u8 num_conf_rsp;
+
+ __u8 fcs;
+
+ __u16 tx_win;
+ __u16 tx_win_max;
+ __u8 max_tx;
+ __u16 retrans_timeout;
+ __u16 monitor_timeout;
+ __u16 mps;
+
+ unsigned long conf_state;
+ unsigned long conn_state;
+ unsigned long flags;
+
+ __u16 next_tx_seq;
+ __u16 expected_ack_seq;
+ __u16 expected_tx_seq;
+ __u16 buffer_seq;
+ __u16 buffer_seq_srej;
+ __u16 srej_save_reqseq;
+ __u16 frames_sent;
+ __u16 unacked_frames;
+ __u8 retry_count;
+ __u8 num_acked;
+ __u16 sdu_len;
+ struct sk_buff *sdu;
+ struct sk_buff *sdu_last_frag;
+
+ __u16 remote_tx_win;
+ __u8 remote_max_tx;
+ __u16 remote_mps;
+
+ __u8 local_id;
+ __u8 local_stype;
+ __u16 local_msdu;
+ __u32 local_sdu_itime;
+ __u32 local_acc_lat;
+ __u32 local_flush_to;
+
+ __u8 remote_id;
+ __u8 remote_stype;
+ __u16 remote_msdu;
+ __u32 remote_sdu_itime;
+ __u32 remote_acc_lat;
+ __u32 remote_flush_to;
+
+ struct delayed_work chan_timer;
+ struct delayed_work retrans_timer;
+ struct delayed_work monitor_timer;
+ struct delayed_work ack_timer;
+
+ struct sk_buff *tx_send_head;
+ struct sk_buff_head tx_q;
+ struct sk_buff_head srej_q;
+ struct list_head srej_l;
+
+ struct list_head list;
+ struct list_head global_l;
+
+ void *data;
+ struct l2cap_ops *ops;
+ struct mutex lock;
+};
+
+struct l2cap_ops {
+ char *name;
+
+ struct l2cap_chan *(*new_connection) (void *data);
+ int (*recv) (void *data, struct sk_buff *skb);
+ void (*close) (void *data);
+ void (*state_change) (void *data, int state);
+ struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan,
+ unsigned long len, int nb, int *err);
+
+};
+
+struct l2cap_conn {
+ struct hci_conn *hcon;
+ struct hci_chan *hchan;
+
+ bdaddr_t *dst;
+ bdaddr_t *src;
+
+ unsigned int mtu;
+
+ __u32 feat_mask;
+ __u8 fixed_chan_mask;
+
+ __u8 info_state;
+ __u8 info_ident;
+
+ struct delayed_work info_timer;
+
+ spinlock_t lock;
+
+ struct sk_buff *rx_skb;
+ __u32 rx_len;
+ __u8 tx_ident;
+
+ __u8 disc_reason;
+
+ struct delayed_work security_timer;
+ struct smp_chan *smp_chan;
+
+ struct list_head chan_l;
+ struct mutex chan_lock;
+};
+
+#define L2CAP_INFO_CL_MTU_REQ_SENT 0x01
+#define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x04
+#define L2CAP_INFO_FEAT_MASK_REQ_DONE 0x08
+
+#define L2CAP_CHAN_RAW 1
+#define L2CAP_CHAN_CONN_LESS 2
+#define L2CAP_CHAN_CONN_ORIENTED 3
+
+/* ----- L2CAP socket info ----- */
+#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
+
+struct l2cap_pinfo {
+ struct bt_sock bt;
+ struct l2cap_chan *chan;
+ struct sk_buff *rx_busy_skb;
+};
+
+enum {
+ CONF_REQ_SENT,
+ CONF_INPUT_DONE,
+ CONF_OUTPUT_DONE,
+ CONF_MTU_DONE,
+ CONF_MODE_DONE,
+ CONF_CONNECT_PEND,
+ CONF_NO_FCS_RECV,
+ CONF_STATE2_DEVICE,
+ CONF_EWS_RECV,
+ CONF_LOC_CONF_PEND,
+ CONF_REM_CONF_PEND,
+};
+
+#define L2CAP_CONF_MAX_CONF_REQ 2
+#define L2CAP_CONF_MAX_CONF_RSP 2
+
+enum {
+ CONN_SREJ_SENT,
+ CONN_WAIT_F,
+ CONN_SREJ_ACT,
+ CONN_SEND_PBIT,
+ CONN_REMOTE_BUSY,
+ CONN_LOCAL_BUSY,
+ CONN_REJ_ACT,
+ CONN_SEND_FBIT,
+ CONN_RNR_SENT,
+};
+
+/* Definitions for flags in l2cap_chan */
+enum {
+ FLAG_ROLE_SWITCH,
+ FLAG_FORCE_ACTIVE,
+ FLAG_FORCE_RELIABLE,
+ FLAG_FLUSHABLE,
+ FLAG_EXT_CTRL,
+ FLAG_EFS_ENABLE,
+};
+
+static inline void l2cap_chan_hold(struct l2cap_chan *c)
+{
+ atomic_inc(&c->refcnt);
+}
+
+static inline void l2cap_chan_put(struct l2cap_chan *c)
+{
+ if (atomic_dec_and_test(&c->refcnt))
+ kfree(c);
+}
+
+static inline void l2cap_chan_lock(struct l2cap_chan *chan)
+{
+ mutex_lock(&chan->lock);
+}
+
+static inline void l2cap_chan_unlock(struct l2cap_chan *chan)
+{
+ mutex_unlock(&chan->lock);
+}
+
+static inline void l2cap_set_timer(struct l2cap_chan *chan,
+ struct delayed_work *work, long timeout)
+{
+ BT_DBG("chan %p state %s timeout %ld", chan,
+ state_to_string(chan->state), timeout);
+
+ if (!cancel_delayed_work(work))
+ l2cap_chan_hold(chan);
+ schedule_delayed_work(work, timeout);
+}
+
+static inline bool l2cap_clear_timer(struct l2cap_chan *chan,
+ struct delayed_work *work)
+{
+ bool ret;
+
+ ret = cancel_delayed_work(work);
+ if (ret)
+ l2cap_chan_put(chan);
+
+ return ret;
+}
+
+#define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t))
+#define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer)
+#define __set_retrans_timer(c) l2cap_set_timer(c, &c->retrans_timer, \
+ msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO));
+#define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer)
+#define __set_monitor_timer(c) l2cap_set_timer(c, &c->monitor_timer, \
+ msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO));
+#define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer)
+#define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \
+ msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO));
+#define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer)
+
+static inline int __seq_offset(struct l2cap_chan *chan, __u16 seq1, __u16 seq2)
+{
+ int offset;
+
+ offset = (seq1 - seq2) % (chan->tx_win_max + 1);
+ if (offset < 0)
+ offset += (chan->tx_win_max + 1);
+
+ return offset;
+}
+
+static inline __u16 __next_seq(struct l2cap_chan *chan, __u16 seq)
+{
+ return (seq + 1) % (chan->tx_win_max + 1);
+}
+
+static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
+{
+ int sub;
+
+ sub = (ch->next_tx_seq - ch->expected_ack_seq) % 64;
+
+ if (sub < 0)
+ sub += 64;
+
+ return sub == ch->remote_tx_win;
+}
+
+static inline __u16 __get_reqseq(struct l2cap_chan *chan, __u32 ctrl)
+{
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ return (ctrl & L2CAP_EXT_CTRL_REQSEQ) >>
+ L2CAP_EXT_CTRL_REQSEQ_SHIFT;
+ else
+ return (ctrl & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
+}
+
+static inline __u32 __set_reqseq(struct l2cap_chan *chan, __u32 reqseq)
+{
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ return (reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT) &
+ L2CAP_EXT_CTRL_REQSEQ;
+ else
+ return (reqseq << L2CAP_CTRL_REQSEQ_SHIFT) & L2CAP_CTRL_REQSEQ;
+}
+
+static inline __u16 __get_txseq(struct l2cap_chan *chan, __u32 ctrl)
+{
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ return (ctrl & L2CAP_EXT_CTRL_TXSEQ) >>
+ L2CAP_EXT_CTRL_TXSEQ_SHIFT;
+ else
+ return (ctrl & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
+}
+
+static inline __u32 __set_txseq(struct l2cap_chan *chan, __u32 txseq)
+{
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ return (txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT) &
+ L2CAP_EXT_CTRL_TXSEQ;
+ else
+ return (txseq << L2CAP_CTRL_TXSEQ_SHIFT) & L2CAP_CTRL_TXSEQ;
+}
+
+static inline bool __is_sframe(struct l2cap_chan *chan, __u32 ctrl)
+{
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ return ctrl & L2CAP_EXT_CTRL_FRAME_TYPE;
+ else
+ return ctrl & L2CAP_CTRL_FRAME_TYPE;
+}
+
+static inline __u32 __set_sframe(struct l2cap_chan *chan)
+{
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ return L2CAP_EXT_CTRL_FRAME_TYPE;
+ else
+ return L2CAP_CTRL_FRAME_TYPE;
+}
+
+static inline __u8 __get_ctrl_sar(struct l2cap_chan *chan, __u32 ctrl)
+{
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ return (ctrl & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
+ else
+ return (ctrl & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
+}
+
+static inline __u32 __set_ctrl_sar(struct l2cap_chan *chan, __u32 sar)
+{
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ return (sar << L2CAP_EXT_CTRL_SAR_SHIFT) & L2CAP_EXT_CTRL_SAR;
+ else
+ return (sar << L2CAP_CTRL_SAR_SHIFT) & L2CAP_CTRL_SAR;
+}
+
+static inline bool __is_sar_start(struct l2cap_chan *chan, __u32 ctrl)
+{
+ return __get_ctrl_sar(chan, ctrl) == L2CAP_SAR_START;
+}
+
+static inline __u32 __get_sar_mask(struct l2cap_chan *chan)
+{
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ return L2CAP_EXT_CTRL_SAR;
+ else
+ return L2CAP_CTRL_SAR;
+}
+
+static inline __u8 __get_ctrl_super(struct l2cap_chan *chan, __u32 ctrl)
+{
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ return (ctrl & L2CAP_EXT_CTRL_SUPERVISE) >>
+ L2CAP_EXT_CTRL_SUPER_SHIFT;
+ else
+ return (ctrl & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
+}
+
+static inline __u32 __set_ctrl_super(struct l2cap_chan *chan, __u32 super)
+{
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ return (super << L2CAP_EXT_CTRL_SUPER_SHIFT) &
+ L2CAP_EXT_CTRL_SUPERVISE;
+ else
+ return (super << L2CAP_CTRL_SUPER_SHIFT) &
+ L2CAP_CTRL_SUPERVISE;
+}
+
+static inline __u32 __set_ctrl_final(struct l2cap_chan *chan)
+{
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ return L2CAP_EXT_CTRL_FINAL;
+ else
+ return L2CAP_CTRL_FINAL;
+}
+
+static inline bool __is_ctrl_final(struct l2cap_chan *chan, __u32 ctrl)
+{
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ return ctrl & L2CAP_EXT_CTRL_FINAL;
+ else
+ return ctrl & L2CAP_CTRL_FINAL;
+}
+
+static inline __u32 __set_ctrl_poll(struct l2cap_chan *chan)
+{
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ return L2CAP_EXT_CTRL_POLL;
+ else
+ return L2CAP_CTRL_POLL;
+}
+
+static inline bool __is_ctrl_poll(struct l2cap_chan *chan, __u32 ctrl)
+{
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ return ctrl & L2CAP_EXT_CTRL_POLL;
+ else
+ return ctrl & L2CAP_CTRL_POLL;
+}
+
+static inline __u32 __get_control(struct l2cap_chan *chan, void *p)
+{
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ return get_unaligned_le32(p);
+ else
+ return get_unaligned_le16(p);
+}
+
+static inline void __put_control(struct l2cap_chan *chan, __u32 control,
+ void *p)
+{
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ return put_unaligned_le32(control, p);
+ else
+ return put_unaligned_le16(control, p);
+}
+
+static inline __u8 __ctrl_size(struct l2cap_chan *chan)
+{
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ return L2CAP_EXT_HDR_SIZE - L2CAP_HDR_SIZE;
+ else
+ return L2CAP_ENH_HDR_SIZE - L2CAP_HDR_SIZE;
+}
+
+extern bool disable_ertm;
+
+int l2cap_init_sockets(void);
+void l2cap_cleanup_sockets(void);
+
+void __l2cap_connect_rsp_defer(struct l2cap_chan *chan);
+int __l2cap_wait_ack(struct sock *sk);
+
+int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
+int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid);
+
+struct l2cap_chan *l2cap_chan_create(struct sock *sk);
+void l2cap_chan_close(struct l2cap_chan *chan, int reason);
+void l2cap_chan_destroy(struct l2cap_chan *chan);
+int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
+ bdaddr_t *dst);
+int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
+ u32 priority);
+void l2cap_chan_busy(struct l2cap_chan *chan, int busy);
+int l2cap_chan_check_security(struct l2cap_chan *chan);
+
+#endif /* __L2CAP_H */
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
new file mode 100644
index 00000000..ebfd91fc
--- /dev/null
+++ b/include/net/bluetooth/mgmt.h
@@ -0,0 +1,462 @@
+/*
+ BlueZ - Bluetooth protocol stack for Linux
+
+ Copyright (C) 2010 Nokia Corporation
+ Copyright (C) 2011-2012 Intel Corporation
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+ CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ SOFTWARE IS DISCLAIMED.
+*/
+
+#define MGMT_INDEX_NONE 0xFFFF
+
+#define MGMT_STATUS_SUCCESS 0x00
+#define MGMT_STATUS_UNKNOWN_COMMAND 0x01
+#define MGMT_STATUS_NOT_CONNECTED 0x02
+#define MGMT_STATUS_FAILED 0x03
+#define MGMT_STATUS_CONNECT_FAILED 0x04
+#define MGMT_STATUS_AUTH_FAILED 0x05
+#define MGMT_STATUS_NOT_PAIRED 0x06
+#define MGMT_STATUS_NO_RESOURCES 0x07
+#define MGMT_STATUS_TIMEOUT 0x08
+#define MGMT_STATUS_ALREADY_CONNECTED 0x09
+#define MGMT_STATUS_BUSY 0x0a
+#define MGMT_STATUS_REJECTED 0x0b
+#define MGMT_STATUS_NOT_SUPPORTED 0x0c
+#define MGMT_STATUS_INVALID_PARAMS 0x0d
+#define MGMT_STATUS_DISCONNECTED 0x0e
+#define MGMT_STATUS_NOT_POWERED 0x0f
+#define MGMT_STATUS_CANCELLED 0x10
+#define MGMT_STATUS_INVALID_INDEX 0x11
+
+struct mgmt_hdr {
+ __le16 opcode;
+ __le16 index;
+ __le16 len;
+} __packed;
+
+struct mgmt_addr_info {
+ bdaddr_t bdaddr;
+ __u8 type;
+} __packed;
+#define MGMT_ADDR_INFO_SIZE 7
+
+#define MGMT_OP_READ_VERSION 0x0001
+#define MGMT_READ_VERSION_SIZE 0
+struct mgmt_rp_read_version {
+ __u8 version;
+ __le16 revision;
+} __packed;
+
+#define MGMT_OP_READ_COMMANDS 0x0002
+#define MGMT_READ_COMMANDS_SIZE 0
+struct mgmt_rp_read_commands {
+ __le16 num_commands;
+ __le16 num_events;
+ __le16 opcodes[0];
+} __packed;
+
+#define MGMT_OP_READ_INDEX_LIST 0x0003
+#define MGMT_READ_INDEX_LIST_SIZE 0
+struct mgmt_rp_read_index_list {
+ __le16 num_controllers;
+ __le16 index[0];
+} __packed;
+
+/* Reserve one extra byte for names in management messages so that they
+ * are always guaranteed to be nul-terminated */
+#define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1)
+#define MGMT_MAX_SHORT_NAME_LENGTH (HCI_MAX_SHORT_NAME_LENGTH + 1)
+
+#define MGMT_SETTING_POWERED 0x00000001
+#define MGMT_SETTING_CONNECTABLE 0x00000002
+#define MGMT_SETTING_FAST_CONNECTABLE 0x00000004
+#define MGMT_SETTING_DISCOVERABLE 0x00000008
+#define MGMT_SETTING_PAIRABLE 0x00000010
+#define MGMT_SETTING_LINK_SECURITY 0x00000020
+#define MGMT_SETTING_SSP 0x00000040
+#define MGMT_SETTING_BREDR 0x00000080
+#define MGMT_SETTING_HS 0x00000100
+#define MGMT_SETTING_LE 0x00000200
+
+#define MGMT_OP_READ_INFO 0x0004
+#define MGMT_READ_INFO_SIZE 0
+struct mgmt_rp_read_info {
+ bdaddr_t bdaddr;
+ __u8 version;
+ __le16 manufacturer;
+ __le32 supported_settings;
+ __le32 current_settings;
+ __u8 dev_class[3];
+ __u8 name[MGMT_MAX_NAME_LENGTH];
+ __u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH];
+} __packed;
+
+struct mgmt_mode {
+ __u8 val;
+} __packed;
+
+#define MGMT_SETTING_SIZE 1
+
+#define MGMT_OP_SET_POWERED 0x0005
+
+#define MGMT_OP_SET_DISCOVERABLE 0x0006
+struct mgmt_cp_set_discoverable {
+ __u8 val;
+ __le16 timeout;
+} __packed;
+#define MGMT_SET_DISCOVERABLE_SIZE 3
+
+#define MGMT_OP_SET_CONNECTABLE 0x0007
+
+#define MGMT_OP_SET_FAST_CONNECTABLE 0x0008
+
+#define MGMT_OP_SET_PAIRABLE 0x0009
+
+#define MGMT_OP_SET_LINK_SECURITY 0x000A
+
+#define MGMT_OP_SET_SSP 0x000B
+
+#define MGMT_OP_SET_HS 0x000C
+
+#define MGMT_OP_SET_LE 0x000D
+#define MGMT_OP_SET_DEV_CLASS 0x000E
+struct mgmt_cp_set_dev_class {
+ __u8 major;
+ __u8 minor;
+} __packed;
+#define MGMT_SET_DEV_CLASS_SIZE 2
+
+#define MGMT_OP_SET_LOCAL_NAME 0x000F
+struct mgmt_cp_set_local_name {
+ __u8 name[MGMT_MAX_NAME_LENGTH];
+ __u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH];
+} __packed;
+#define MGMT_SET_LOCAL_NAME_SIZE 260
+
+#define MGMT_OP_ADD_UUID 0x0010
+struct mgmt_cp_add_uuid {
+ __u8 uuid[16];
+ __u8 svc_hint;
+} __packed;
+#define MGMT_ADD_UUID_SIZE 17
+
+#define MGMT_OP_REMOVE_UUID 0x0011
+struct mgmt_cp_remove_uuid {
+ __u8 uuid[16];
+} __packed;
+#define MGMT_REMOVE_UUID_SIZE 16
+
+struct mgmt_link_key_info {
+ struct mgmt_addr_info addr;
+ __u8 type;
+ __u8 val[16];
+ __u8 pin_len;
+} __packed;
+
+#define MGMT_OP_LOAD_LINK_KEYS 0x0012
+struct mgmt_cp_load_link_keys {
+ __u8 debug_keys;
+ __le16 key_count;
+ struct mgmt_link_key_info keys[0];
+} __packed;
+#define MGMT_LOAD_LINK_KEYS_SIZE 3
+
+struct mgmt_ltk_info {
+ struct mgmt_addr_info addr;
+ __u8 authenticated;
+ __u8 master;
+ __u8 enc_size;
+ __le16 ediv;
+ __u8 rand[8];
+ __u8 val[16];
+} __packed;
+
+#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0013
+struct mgmt_cp_load_long_term_keys {
+ __le16 key_count;
+ struct mgmt_ltk_info keys[0];
+} __packed;
+#define MGMT_LOAD_LONG_TERM_KEYS_SIZE 2
+
+#define MGMT_OP_DISCONNECT 0x0014
+struct mgmt_cp_disconnect {
+ struct mgmt_addr_info addr;
+} __packed;
+#define MGMT_DISCONNECT_SIZE MGMT_ADDR_INFO_SIZE
+struct mgmt_rp_disconnect {
+ struct mgmt_addr_info addr;
+} __packed;
+
+#define MGMT_OP_GET_CONNECTIONS 0x0015
+#define MGMT_GET_CONNECTIONS_SIZE 0
+struct mgmt_rp_get_connections {
+ __le16 conn_count;
+ struct mgmt_addr_info addr[0];
+} __packed;
+
+#define MGMT_OP_PIN_CODE_REPLY 0x0016
+struct mgmt_cp_pin_code_reply {
+ struct mgmt_addr_info addr;
+ __u8 pin_len;
+ __u8 pin_code[16];
+} __packed;
+#define MGMT_PIN_CODE_REPLY_SIZE (MGMT_ADDR_INFO_SIZE + 17)
+struct mgmt_rp_pin_code_reply {
+ struct mgmt_addr_info addr;
+} __packed;
+
+#define MGMT_OP_PIN_CODE_NEG_REPLY 0x0017
+struct mgmt_cp_pin_code_neg_reply {
+ struct mgmt_addr_info addr;
+} __packed;
+#define MGMT_PIN_CODE_NEG_REPLY_SIZE MGMT_ADDR_INFO_SIZE
+
+#define MGMT_OP_SET_IO_CAPABILITY 0x0018
+struct mgmt_cp_set_io_capability {
+ __u8 io_capability;
+} __packed;
+#define MGMT_SET_IO_CAPABILITY_SIZE 1
+
+#define MGMT_OP_PAIR_DEVICE 0x0019
+struct mgmt_cp_pair_device {
+ struct mgmt_addr_info addr;
+ __u8 io_cap;
+} __packed;
+#define MGMT_PAIR_DEVICE_SIZE (MGMT_ADDR_INFO_SIZE + 1)
+struct mgmt_rp_pair_device {
+ struct mgmt_addr_info addr;
+} __packed;
+
+#define MGMT_OP_CANCEL_PAIR_DEVICE 0x001A
+#define MGMT_CANCEL_PAIR_DEVICE_SIZE MGMT_ADDR_INFO_SIZE
+
+#define MGMT_OP_UNPAIR_DEVICE 0x001B
+struct mgmt_cp_unpair_device {
+ struct mgmt_addr_info addr;
+ __u8 disconnect;
+} __packed;
+#define MGMT_UNPAIR_DEVICE_SIZE (MGMT_ADDR_INFO_SIZE + 1)
+struct mgmt_rp_unpair_device {
+ struct mgmt_addr_info addr;
+};
+
+#define MGMT_OP_USER_CONFIRM_REPLY 0x001C
+struct mgmt_cp_user_confirm_reply {
+ struct mgmt_addr_info addr;
+} __packed;
+#define MGMT_USER_CONFIRM_REPLY_SIZE MGMT_ADDR_INFO_SIZE
+struct mgmt_rp_user_confirm_reply {
+ struct mgmt_addr_info addr;
+} __packed;
+
+#define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x001D
+struct mgmt_cp_user_confirm_neg_reply {
+ struct mgmt_addr_info addr;
+} __packed;
+#define MGMT_USER_CONFIRM_NEG_REPLY_SIZE MGMT_ADDR_INFO_SIZE
+
+#define MGMT_OP_USER_PASSKEY_REPLY 0x001E
+struct mgmt_cp_user_passkey_reply {
+ struct mgmt_addr_info addr;
+ __le32 passkey;
+} __packed;
+#define MGMT_USER_PASSKEY_REPLY_SIZE (MGMT_ADDR_INFO_SIZE + 4)
+struct mgmt_rp_user_passkey_reply {
+ struct mgmt_addr_info addr;
+} __packed;
+
+#define MGMT_OP_USER_PASSKEY_NEG_REPLY 0x001F
+struct mgmt_cp_user_passkey_neg_reply {
+ struct mgmt_addr_info addr;
+} __packed;
+#define MGMT_USER_PASSKEY_NEG_REPLY_SIZE MGMT_ADDR_INFO_SIZE
+
+#define MGMT_OP_READ_LOCAL_OOB_DATA 0x0020
+#define MGMT_READ_LOCAL_OOB_DATA_SIZE 0
+struct mgmt_rp_read_local_oob_data {
+ __u8 hash[16];
+ __u8 randomizer[16];
+} __packed;
+
+#define MGMT_OP_ADD_REMOTE_OOB_DATA 0x0021
+struct mgmt_cp_add_remote_oob_data {
+ struct mgmt_addr_info addr;
+ __u8 hash[16];
+ __u8 randomizer[16];
+} __packed;
+#define MGMT_ADD_REMOTE_OOB_DATA_SIZE (MGMT_ADDR_INFO_SIZE + 32)
+
+#define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x0022
+struct mgmt_cp_remove_remote_oob_data {
+ struct mgmt_addr_info addr;
+} __packed;
+#define MGMT_REMOVE_REMOTE_OOB_DATA_SIZE MGMT_ADDR_INFO_SIZE
+
+#define MGMT_OP_START_DISCOVERY 0x0023
+struct mgmt_cp_start_discovery {
+ __u8 type;
+} __packed;
+#define MGMT_START_DISCOVERY_SIZE 1
+
+#define MGMT_OP_STOP_DISCOVERY 0x0024
+struct mgmt_cp_stop_discovery {
+ __u8 type;
+} __packed;
+#define MGMT_STOP_DISCOVERY_SIZE 1
+
+#define MGMT_OP_CONFIRM_NAME 0x0025
+struct mgmt_cp_confirm_name {
+ struct mgmt_addr_info addr;
+ __u8 name_known;
+} __packed;
+#define MGMT_CONFIRM_NAME_SIZE (MGMT_ADDR_INFO_SIZE + 1)
+struct mgmt_rp_confirm_name {
+ struct mgmt_addr_info addr;
+} __packed;
+
+#define MGMT_OP_BLOCK_DEVICE 0x0026
+struct mgmt_cp_block_device {
+ struct mgmt_addr_info addr;
+} __packed;
+#define MGMT_BLOCK_DEVICE_SIZE MGMT_ADDR_INFO_SIZE
+
+#define MGMT_OP_UNBLOCK_DEVICE 0x0027
+struct mgmt_cp_unblock_device {
+ struct mgmt_addr_info addr;
+} __packed;
+#define MGMT_UNBLOCK_DEVICE_SIZE MGMT_ADDR_INFO_SIZE
+
+#define MGMT_EV_CMD_COMPLETE 0x0001
+struct mgmt_ev_cmd_complete {
+ __le16 opcode;
+ __u8 status;
+ __u8 data[0];
+} __packed;
+
+#define MGMT_EV_CMD_STATUS 0x0002
+struct mgmt_ev_cmd_status {
+ __le16 opcode;
+ __u8 status;
+} __packed;
+
+#define MGMT_EV_CONTROLLER_ERROR 0x0003
+struct mgmt_ev_controller_error {
+ __u8 error_code;
+} __packed;
+
+#define MGMT_EV_INDEX_ADDED 0x0004
+
+#define MGMT_EV_INDEX_REMOVED 0x0005
+
+#define MGMT_EV_NEW_SETTINGS 0x0006
+
+#define MGMT_EV_CLASS_OF_DEV_CHANGED 0x0007
+struct mgmt_ev_class_of_dev_changed {
+ __u8 dev_class[3];
+};
+
+#define MGMT_EV_LOCAL_NAME_CHANGED 0x0008
+struct mgmt_ev_local_name_changed {
+ __u8 name[MGMT_MAX_NAME_LENGTH];
+ __u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH];
+} __packed;
+
+#define MGMT_EV_NEW_LINK_KEY 0x0009
+struct mgmt_ev_new_link_key {
+ __u8 store_hint;
+ struct mgmt_link_key_info key;
+} __packed;
+
+#define MGMT_EV_NEW_LONG_TERM_KEY 0x000A
+struct mgmt_ev_new_long_term_key {
+ __u8 store_hint;
+ struct mgmt_ltk_info key;
+} __packed;
+
+#define MGMT_EV_DEVICE_CONNECTED 0x000B
+struct mgmt_ev_device_connected {
+ struct mgmt_addr_info addr;
+ __le32 flags;
+ __le16 eir_len;
+ __u8 eir[0];
+} __packed;
+
+#define MGMT_EV_DEVICE_DISCONNECTED 0x000C
+
+#define MGMT_EV_CONNECT_FAILED 0x000D
+struct mgmt_ev_connect_failed {
+ struct mgmt_addr_info addr;
+ __u8 status;
+} __packed;
+
+#define MGMT_EV_PIN_CODE_REQUEST 0x000E
+struct mgmt_ev_pin_code_request {
+ struct mgmt_addr_info addr;
+ __u8 secure;
+} __packed;
+
+#define MGMT_EV_USER_CONFIRM_REQUEST 0x000F
+struct mgmt_ev_user_confirm_request {
+ struct mgmt_addr_info addr;
+ __u8 confirm_hint;
+ __le32 value;
+} __packed;
+
+#define MGMT_EV_USER_PASSKEY_REQUEST 0x0010
+struct mgmt_ev_user_passkey_request {
+ struct mgmt_addr_info addr;
+} __packed;
+
+#define MGMT_EV_AUTH_FAILED 0x0011
+struct mgmt_ev_auth_failed {
+ struct mgmt_addr_info addr;
+ __u8 status;
+} __packed;
+
+#define MGMT_DEV_FOUND_CONFIRM_NAME 0x01
+#define MGMT_DEV_FOUND_LEGACY_PAIRING 0x02
+
+#define MGMT_EV_DEVICE_FOUND 0x0012
+struct mgmt_ev_device_found {
+ struct mgmt_addr_info addr;
+ __s8 rssi;
+ __u8 flags[4];
+ __le16 eir_len;
+ __u8 eir[0];
+} __packed;
+
+#define MGMT_EV_DISCOVERING 0x0013
+struct mgmt_ev_discovering {
+ __u8 type;
+ __u8 discovering;
+} __packed;
+
+#define MGMT_EV_DEVICE_BLOCKED 0x0014
+struct mgmt_ev_device_blocked {
+ struct mgmt_addr_info addr;
+} __packed;
+
+#define MGMT_EV_DEVICE_UNBLOCKED 0x0015
+struct mgmt_ev_device_unblocked {
+ struct mgmt_addr_info addr;
+} __packed;
+
+#define MGMT_EV_DEVICE_UNPAIRED 0x0016
+struct mgmt_ev_device_unpaired {
+ struct mgmt_addr_info addr;
+} __packed;
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
new file mode 100644
index 00000000..e2e3ecad
--- /dev/null
+++ b/include/net/bluetooth/rfcomm.h
@@ -0,0 +1,372 @@
+/*
+ RFCOMM implementation for Linux Bluetooth stack (BlueZ)
+ Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
+ Copyright (C) 2002 Marcel Holtmann <marcel@holtmann.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+ CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ SOFTWARE IS DISCLAIMED.
+*/
+
+#ifndef __RFCOMM_H
+#define __RFCOMM_H
+
+#define RFCOMM_PSM 3
+
+#define RFCOMM_CONN_TIMEOUT (HZ * 30)
+#define RFCOMM_DISC_TIMEOUT (HZ * 20)
+#define RFCOMM_AUTH_TIMEOUT (HZ * 25)
+#define RFCOMM_IDLE_TIMEOUT (HZ * 2)
+
+#define RFCOMM_DEFAULT_MTU 127
+#define RFCOMM_DEFAULT_CREDITS 7
+
+#define RFCOMM_MAX_L2CAP_MTU 1013
+#define RFCOMM_MAX_CREDITS 40
+
+#define RFCOMM_SKB_HEAD_RESERVE 8
+#define RFCOMM_SKB_TAIL_RESERVE 2
+#define RFCOMM_SKB_RESERVE (RFCOMM_SKB_HEAD_RESERVE + RFCOMM_SKB_TAIL_RESERVE)
+
+#define RFCOMM_SABM 0x2f
+#define RFCOMM_DISC 0x43
+#define RFCOMM_UA 0x63
+#define RFCOMM_DM 0x0f
+#define RFCOMM_UIH 0xef
+
+#define RFCOMM_TEST 0x08
+#define RFCOMM_FCON 0x28
+#define RFCOMM_FCOFF 0x18
+#define RFCOMM_MSC 0x38
+#define RFCOMM_RPN 0x24
+#define RFCOMM_RLS 0x14
+#define RFCOMM_PN 0x20
+#define RFCOMM_NSC 0x04
+
+#define RFCOMM_V24_FC 0x02
+#define RFCOMM_V24_RTC 0x04
+#define RFCOMM_V24_RTR 0x08
+#define RFCOMM_V24_IC 0x40
+#define RFCOMM_V24_DV 0x80
+
+#define RFCOMM_RPN_BR_2400 0x0
+#define RFCOMM_RPN_BR_4800 0x1
+#define RFCOMM_RPN_BR_7200 0x2
+#define RFCOMM_RPN_BR_9600 0x3
+#define RFCOMM_RPN_BR_19200 0x4
+#define RFCOMM_RPN_BR_38400 0x5
+#define RFCOMM_RPN_BR_57600 0x6
+#define RFCOMM_RPN_BR_115200 0x7
+#define RFCOMM_RPN_BR_230400 0x8
+
+#define RFCOMM_RPN_DATA_5 0x0
+#define RFCOMM_RPN_DATA_6 0x1
+#define RFCOMM_RPN_DATA_7 0x2
+#define RFCOMM_RPN_DATA_8 0x3
+
+#define RFCOMM_RPN_STOP_1 0
+#define RFCOMM_RPN_STOP_15 1
+
+#define RFCOMM_RPN_PARITY_NONE 0x0
+#define RFCOMM_RPN_PARITY_ODD 0x1
+#define RFCOMM_RPN_PARITY_EVEN 0x3
+#define RFCOMM_RPN_PARITY_MARK 0x5
+#define RFCOMM_RPN_PARITY_SPACE 0x7
+
+#define RFCOMM_RPN_FLOW_NONE 0x00
+
+#define RFCOMM_RPN_XON_CHAR 0x11
+#define RFCOMM_RPN_XOFF_CHAR 0x13
+
+#define RFCOMM_RPN_PM_BITRATE 0x0001
+#define RFCOMM_RPN_PM_DATA 0x0002
+#define RFCOMM_RPN_PM_STOP 0x0004
+#define RFCOMM_RPN_PM_PARITY 0x0008
+#define RFCOMM_RPN_PM_PARITY_TYPE 0x0010
+#define RFCOMM_RPN_PM_XON 0x0020
+#define RFCOMM_RPN_PM_XOFF 0x0040
+#define RFCOMM_RPN_PM_FLOW 0x3F00
+
+#define RFCOMM_RPN_PM_ALL 0x3F7F
+
+struct rfcomm_hdr {
+ u8 addr;
+ u8 ctrl;
+ u8 len; /* Actual size can be 2 bytes */
+} __packed;
+
+struct rfcomm_cmd {
+ u8 addr;
+ u8 ctrl;
+ u8 len;
+ u8 fcs;
+} __packed;
+
+struct rfcomm_mcc {
+ u8 type;
+ u8 len;
+} __packed;
+
+struct rfcomm_pn {
+ u8 dlci;
+ u8 flow_ctrl;
+ u8 priority;
+ u8 ack_timer;
+ __le16 mtu;
+ u8 max_retrans;
+ u8 credits;
+} __packed;
+
+struct rfcomm_rpn {
+ u8 dlci;
+ u8 bit_rate;
+ u8 line_settings;
+ u8 flow_ctrl;
+ u8 xon_char;
+ u8 xoff_char;
+ __le16 param_mask;
+} __packed;
+
+struct rfcomm_rls {
+ u8 dlci;
+ u8 status;
+} __packed;
+
+struct rfcomm_msc {
+ u8 dlci;
+ u8 v24_sig;
+} __packed;
+
+/* ---- Core structures, flags etc ---- */
+
+struct rfcomm_session {
+ struct list_head list;
+ struct socket *sock;
+ struct timer_list timer;
+ unsigned long state;
+ unsigned long flags;
+ atomic_t refcnt;
+ int initiator;
+
+ /* Default DLC parameters */
+ int cfc;
+ uint mtu;
+
+ struct list_head dlcs;
+};
+
+struct rfcomm_dlc {
+ struct list_head list;
+ struct rfcomm_session *session;
+ struct sk_buff_head tx_queue;
+ struct timer_list timer;
+
+ spinlock_t lock;
+ unsigned long state;
+ unsigned long flags;
+ atomic_t refcnt;
+ u8 dlci;
+ u8 addr;
+ u8 priority;
+ u8 v24_sig;
+ u8 remote_v24_sig;
+ u8 mscex;
+ u8 out;
+ u8 sec_level;
+ u8 role_switch;
+ u32 defer_setup;
+
+ uint mtu;
+ uint cfc;
+ uint rx_credits;
+ uint tx_credits;
+
+ void *owner;
+
+ void (*data_ready)(struct rfcomm_dlc *d, struct sk_buff *skb);
+ void (*state_change)(struct rfcomm_dlc *d, int err);
+ void (*modem_status)(struct rfcomm_dlc *d, u8 v24_sig);
+};
+
+/* DLC and session flags */
+#define RFCOMM_RX_THROTTLED 0
+#define RFCOMM_TX_THROTTLED 1
+#define RFCOMM_TIMED_OUT 2
+#define RFCOMM_MSC_PENDING 3
+#define RFCOMM_SEC_PENDING 4
+#define RFCOMM_AUTH_PENDING 5
+#define RFCOMM_AUTH_ACCEPT 6
+#define RFCOMM_AUTH_REJECT 7
+#define RFCOMM_DEFER_SETUP 8
+#define RFCOMM_ENC_DROP 9
+
+/* Scheduling flags and events */
+#define RFCOMM_SCHED_WAKEUP 31
+
+/* MSC exchange flags */
+#define RFCOMM_MSCEX_TX 1
+#define RFCOMM_MSCEX_RX 2
+#define RFCOMM_MSCEX_OK (RFCOMM_MSCEX_TX + RFCOMM_MSCEX_RX)
+
+/* CFC states */
+#define RFCOMM_CFC_UNKNOWN -1
+#define RFCOMM_CFC_DISABLED 0
+#define RFCOMM_CFC_ENABLED RFCOMM_MAX_CREDITS
+
+/* ---- RFCOMM SEND RPN ---- */
+int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
+ u8 bit_rate, u8 data_bits, u8 stop_bits,
+ u8 parity, u8 flow_ctrl_settings,
+ u8 xon_char, u8 xoff_char, u16 param_mask);
+
+/* ---- RFCOMM DLCs (channels) ---- */
+struct rfcomm_dlc *rfcomm_dlc_alloc(gfp_t prio);
+void rfcomm_dlc_free(struct rfcomm_dlc *d);
+int rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
+ u8 channel);
+int rfcomm_dlc_close(struct rfcomm_dlc *d, int reason);
+int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb);
+int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig);
+int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig);
+void rfcomm_dlc_accept(struct rfcomm_dlc *d);
+
+#define rfcomm_dlc_lock(d) spin_lock(&d->lock)
+#define rfcomm_dlc_unlock(d) spin_unlock(&d->lock)
+
+static inline void rfcomm_dlc_hold(struct rfcomm_dlc *d)
+{
+ atomic_inc(&d->refcnt);
+}
+
+static inline void rfcomm_dlc_put(struct rfcomm_dlc *d)
+{
+ if (atomic_dec_and_test(&d->refcnt))
+ rfcomm_dlc_free(d);
+}
+
+extern void __rfcomm_dlc_throttle(struct rfcomm_dlc *d);
+extern void __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d);
+
+static inline void rfcomm_dlc_throttle(struct rfcomm_dlc *d)
+{
+ if (!test_and_set_bit(RFCOMM_RX_THROTTLED, &d->flags))
+ __rfcomm_dlc_throttle(d);
+}
+
+static inline void rfcomm_dlc_unthrottle(struct rfcomm_dlc *d)
+{
+ if (test_and_clear_bit(RFCOMM_RX_THROTTLED, &d->flags))
+ __rfcomm_dlc_unthrottle(d);
+}
+
+/* ---- RFCOMM sessions ---- */
+void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src,
+ bdaddr_t *dst);
+
+static inline void rfcomm_session_hold(struct rfcomm_session *s)
+{
+ atomic_inc(&s->refcnt);
+}
+
+/* ---- RFCOMM sockets ---- */
+struct sockaddr_rc {
+ sa_family_t rc_family;
+ bdaddr_t rc_bdaddr;
+ u8 rc_channel;
+};
+
+#define RFCOMM_CONNINFO 0x02
+struct rfcomm_conninfo {
+ __u16 hci_handle;
+ __u8 dev_class[3];
+};
+
+#define RFCOMM_LM 0x03
+#define RFCOMM_LM_MASTER 0x0001
+#define RFCOMM_LM_AUTH 0x0002
+#define RFCOMM_LM_ENCRYPT 0x0004
+#define RFCOMM_LM_TRUSTED 0x0008
+#define RFCOMM_LM_RELIABLE 0x0010
+#define RFCOMM_LM_SECURE 0x0020
+
+#define rfcomm_pi(sk) ((struct rfcomm_pinfo *) sk)
+
+struct rfcomm_pinfo {
+ struct bt_sock bt;
+ struct rfcomm_dlc *dlc;
+ u8 channel;
+ u8 sec_level;
+ u8 role_switch;
+};
+
+int rfcomm_init_sockets(void);
+void rfcomm_cleanup_sockets(void);
+
+int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel,
+ struct rfcomm_dlc **d);
+
+/* ---- RFCOMM TTY ---- */
+#define RFCOMM_MAX_DEV 256
+
+#define RFCOMMCREATEDEV _IOW('R', 200, int)
+#define RFCOMMRELEASEDEV _IOW('R', 201, int)
+#define RFCOMMGETDEVLIST _IOR('R', 210, int)
+#define RFCOMMGETDEVINFO _IOR('R', 211, int)
+#define RFCOMMSTEALDLC _IOW('R', 220, int)
+
+#define RFCOMM_REUSE_DLC 0
+#define RFCOMM_RELEASE_ONHUP 1
+#define RFCOMM_HANGUP_NOW 2
+#define RFCOMM_TTY_ATTACHED 3
+#define RFCOMM_TTY_RELEASED 4
+
+struct rfcomm_dev_req {
+ s16 dev_id;
+ u32 flags;
+ bdaddr_t src;
+ bdaddr_t dst;
+ u8 channel;
+};
+
+struct rfcomm_dev_info {
+ s16 id;
+ u32 flags;
+ u16 state;
+ bdaddr_t src;
+ bdaddr_t dst;
+ u8 channel;
+};
+
+struct rfcomm_dev_list_req {
+ u16 dev_num;
+ struct rfcomm_dev_info dev_info[0];
+};
+
+int rfcomm_dev_ioctl(struct sock *sk, unsigned int cmd, void __user *arg);
+
+#ifdef CONFIG_BT_RFCOMM_TTY
+int rfcomm_init_ttys(void);
+void rfcomm_cleanup_ttys(void);
+#else
+static inline int rfcomm_init_ttys(void)
+{
+ return 0;
+}
+static inline void rfcomm_cleanup_ttys(void)
+{
+}
+#endif
+#endif /* __RFCOMM_H */
diff --git a/include/net/bluetooth/sco.h b/include/net/bluetooth/sco.h
new file mode 100644
index 00000000..6d1857ab
--- /dev/null
+++ b/include/net/bluetooth/sco.h
@@ -0,0 +1,81 @@
+/*
+ BlueZ - Bluetooth protocol stack for Linux
+ Copyright (C) 2000-2001 Qualcomm Incorporated
+
+ Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+ CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ SOFTWARE IS DISCLAIMED.
+*/
+
+#ifndef __SCO_H
+#define __SCO_H
+
+/* SCO defaults */
+#define SCO_DEFAULT_MTU 500
+#define SCO_DEFAULT_FLUSH_TO 0xFFFF
+
+#define SCO_CONN_TIMEOUT (HZ * 40)
+#define SCO_DISCONN_TIMEOUT (HZ * 2)
+#define SCO_CONN_IDLE_TIMEOUT (HZ * 60)
+
+/* SCO socket address */
+struct sockaddr_sco {
+ sa_family_t sco_family;
+ bdaddr_t sco_bdaddr;
+ __u16 sco_pkt_type;
+};
+
+/* SCO socket options */
+#define SCO_OPTIONS 0x01
+struct sco_options {
+ __u16 mtu;
+};
+
+#define SCO_CONNINFO 0x02
+struct sco_conninfo {
+ __u16 hci_handle;
+ __u8 dev_class[3];
+};
+
+/* ---- SCO connections ---- */
+struct sco_conn {
+ struct hci_conn *hcon;
+
+ bdaddr_t *dst;
+ bdaddr_t *src;
+
+ spinlock_t lock;
+ struct sock *sk;
+
+ unsigned int mtu;
+};
+
+#define sco_conn_lock(c) spin_lock(&c->lock);
+#define sco_conn_unlock(c) spin_unlock(&c->lock);
+
+/* ----- SCO socket info ----- */
+#define sco_pi(sk) ((struct sco_pinfo *) sk)
+
+struct sco_pinfo {
+ struct bt_sock bt;
+ __u16 pkt_type;
+
+ struct sco_conn *conn;
+};
+
+#endif /* __SCO_H */
diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
new file mode 100644
index 00000000..7b3acdd2
--- /dev/null
+++ b/include/net/bluetooth/smp.h
@@ -0,0 +1,146 @@
+/*
+ BlueZ - Bluetooth protocol stack for Linux
+ Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+ CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ SOFTWARE IS DISCLAIMED.
+*/
+
+#ifndef __SMP_H
+#define __SMP_H
+
+struct smp_command_hdr {
+ __u8 code;
+} __packed;
+
+#define SMP_CMD_PAIRING_REQ 0x01
+#define SMP_CMD_PAIRING_RSP 0x02
+struct smp_cmd_pairing {
+ __u8 io_capability;
+ __u8 oob_flag;
+ __u8 auth_req;
+ __u8 max_key_size;
+ __u8 init_key_dist;
+ __u8 resp_key_dist;
+} __packed;
+
+#define SMP_IO_DISPLAY_ONLY 0x00
+#define SMP_IO_DISPLAY_YESNO 0x01
+#define SMP_IO_KEYBOARD_ONLY 0x02
+#define SMP_IO_NO_INPUT_OUTPUT 0x03
+#define SMP_IO_KEYBOARD_DISPLAY 0x04
+
+#define SMP_OOB_NOT_PRESENT 0x00
+#define SMP_OOB_PRESENT 0x01
+
+#define SMP_DIST_ENC_KEY 0x01
+#define SMP_DIST_ID_KEY 0x02
+#define SMP_DIST_SIGN 0x04
+
+#define SMP_AUTH_NONE 0x00
+#define SMP_AUTH_BONDING 0x01
+#define SMP_AUTH_MITM 0x04
+
+#define SMP_CMD_PAIRING_CONFIRM 0x03
+struct smp_cmd_pairing_confirm {
+ __u8 confirm_val[16];
+} __packed;
+
+#define SMP_CMD_PAIRING_RANDOM 0x04
+struct smp_cmd_pairing_random {
+ __u8 rand_val[16];
+} __packed;
+
+#define SMP_CMD_PAIRING_FAIL 0x05
+struct smp_cmd_pairing_fail {
+ __u8 reason;
+} __packed;
+
+#define SMP_CMD_ENCRYPT_INFO 0x06
+struct smp_cmd_encrypt_info {
+ __u8 ltk[16];
+} __packed;
+
+#define SMP_CMD_MASTER_IDENT 0x07
+struct smp_cmd_master_ident {
+ __u16 ediv;
+ __u8 rand[8];
+} __packed;
+
+#define SMP_CMD_IDENT_INFO 0x08
+struct smp_cmd_ident_info {
+ __u8 irk[16];
+} __packed;
+
+#define SMP_CMD_IDENT_ADDR_INFO 0x09
+struct smp_cmd_ident_addr_info {
+ __u8 addr_type;
+ bdaddr_t bdaddr;
+} __packed;
+
+#define SMP_CMD_SIGN_INFO 0x0a
+struct smp_cmd_sign_info {
+ __u8 csrk[16];
+} __packed;
+
+#define SMP_CMD_SECURITY_REQ 0x0b
+struct smp_cmd_security_req {
+ __u8 auth_req;
+} __packed;
+
+#define SMP_PASSKEY_ENTRY_FAILED 0x01
+#define SMP_OOB_NOT_AVAIL 0x02
+#define SMP_AUTH_REQUIREMENTS 0x03
+#define SMP_CONFIRM_FAILED 0x04
+#define SMP_PAIRING_NOTSUPP 0x05
+#define SMP_ENC_KEY_SIZE 0x06
+#define SMP_CMD_NOTSUPP 0x07
+#define SMP_UNSPECIFIED 0x08
+#define SMP_REPEATED_ATTEMPTS 0x09
+
+#define SMP_MIN_ENC_KEY_SIZE 7
+#define SMP_MAX_ENC_KEY_SIZE 16
+
+#define SMP_FLAG_TK_VALID 1
+#define SMP_FLAG_CFM_PENDING 2
+#define SMP_FLAG_MITM_AUTH 3
+
+struct smp_chan {
+ struct l2cap_conn *conn;
+ u8 preq[7]; /* SMP Pairing Request */
+ u8 prsp[7]; /* SMP Pairing Response */
+ u8 prnd[16]; /* SMP Pairing Random (local) */
+ u8 rrnd[16]; /* SMP Pairing Random (remote) */
+ u8 pcnf[16]; /* SMP Pairing Confirm */
+ u8 tk[16]; /* SMP Temporary Key */
+ u8 enc_key_size;
+ unsigned long smp_flags;
+ struct crypto_blkcipher *tfm;
+ struct work_struct confirm;
+ struct work_struct random;
+
+};
+
+/* SMP Commands */
+int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level);
+int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
+int smp_distribute_keys(struct l2cap_conn *conn, __u8 force);
+int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey);
+
+void smp_chan_destroy(struct l2cap_conn *conn);
+
+#endif /* __SMP_H */
diff --git a/include/net/caif/caif_dev.h b/include/net/caif/caif_dev.h
new file mode 100644
index 00000000..ef2dd943
--- /dev/null
+++ b/include/net/caif/caif_dev.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Author: Sjur Brendeland/ sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef CAIF_DEV_H_
+#define CAIF_DEV_H_
+
+#include <net/caif/caif_layer.h>
+#include <net/caif/cfcnfg.h>
+#include <net/caif/caif_device.h>
+#include <linux/caif/caif_socket.h>
+#include <linux/if.h>
+#include <linux/net.h>
+
+/**
+ * struct caif_param - CAIF parameters.
+ * @size: Length of data
+ * @data: Binary Data Blob
+ */
+struct caif_param {
+ u16 size;
+ u8 data[256];
+};
+
+/**
+ * struct caif_connect_request - Request data for CAIF channel setup.
+ * @protocol: Type of CAIF protocol to use (at, datagram etc)
+ * @sockaddr: Socket address to connect.
+ * @priority: Priority of the connection.
+ * @link_selector: Link selector (high bandwidth or low latency)
+ * @ifindex: kernel index of the interface.
+ * @param: Connect Request parameters (CAIF_SO_REQ_PARAM).
+ *
+ * This struct is used when connecting a CAIF channel.
+ * It contains all CAIF channel configuration options.
+ */
+struct caif_connect_request {
+ enum caif_protocol_type protocol;
+ struct sockaddr_caif sockaddr;
+ enum caif_channel_priority priority;
+ enum caif_link_selector link_selector;
+ int ifindex;
+ struct caif_param param;
+};
+
+/**
+ * caif_connect_client - Connect a client to CAIF Core Stack.
+ * @config: Channel setup parameters, specifying what address
+ * to connect on the Modem.
+ * @client_layer: User implementation of client layer. This layer
+ * MUST have receive and control callback functions
+ * implemented.
+ * @ifindex: Link layer interface index used for this connection.
+ * @headroom: Head room needed by CAIF protocol.
+ * @tailroom: Tail room needed by CAIF protocol.
+ *
+ * This function connects a CAIF channel. The Client must implement
+ * the struct cflayer. This layer represents the Client layer and holds
+ * receive functions and control callback functions. Control callback
+ * function will receive information about connect/disconnect responses,
+ * flow control etc (see enum caif_control).
+ * E.g. CAIF Socket will call this function for each socket it connects
+ * and have one client_layer instance for each socket.
+ */
+int caif_connect_client(struct net *net,
+ struct caif_connect_request *conn_req,
+ struct cflayer *client_layer, int *ifindex,
+ int *headroom, int *tailroom);
+
+/**
+ * caif_disconnect_client - Disconnects a client from the CAIF stack.
+ *
+ * @client_layer: Client layer to be disconnected.
+ */
+int caif_disconnect_client(struct net *net, struct cflayer *client_layer);
+
+
+/**
+ * caif_client_register_refcnt - register ref-count functions provided by client.
+ *
+ * @adapt_layer: Client layer using CAIF Stack.
+ * @hold: Function provided by client layer increasing ref-count
+ * @put: Function provided by client layer decreasing ref-count
+ *
+ * Client of the CAIF Stack must register functions for reference counting.
+ * These functions are called by the CAIF Stack for every upstream packet,
+ * and must therefore be implemented efficiently.
+ *
+ * Client should call caif_free_client when reference count degrease to zero.
+ */
+
+void caif_client_register_refcnt(struct cflayer *adapt_layer,
+ void (*hold)(struct cflayer *lyr),
+ void (*put)(struct cflayer *lyr));
+/**
+ * caif_free_client - Free memory used to manage the client in the CAIF Stack.
+ *
+ * @client_layer: Client layer to be removed.
+ *
+ * This function must be called from client layer in order to free memory.
+ * Caller must guarantee that no packets are in flight upstream when calling
+ * this function.
+ */
+void caif_free_client(struct cflayer *adap_layer);
+
+/**
+ * struct caif_enroll_dev - Enroll a net-device as a CAIF Link layer
+ * @dev: Network device to enroll.
+ * @caifdev: Configuration information from CAIF Link Layer
+ * @link_support: Link layer support layer
+ * @head_room: Head room needed by link support layer
+ * @layer: Lowest layer in CAIF stack
+ * @rcv_fun: Receive function for CAIF stack.
+ *
+ * This function enroll a CAIF link layer into CAIF Stack and
+ * expects the interface to be able to handle CAIF payload.
+ * The link_support layer is used to add any Link Layer specific
+ * framing.
+ */
+void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev,
+ struct cflayer *link_support, int head_room,
+ struct cflayer **layer, int (**rcv_func)(
+ struct sk_buff *, struct net_device *,
+ struct packet_type *, struct net_device *));
+
+#endif /* CAIF_DEV_H_ */
diff --git a/include/net/caif/caif_device.h b/include/net/caif/caif_device.h
new file mode 100644
index 00000000..d02f044a
--- /dev/null
+++ b/include/net/caif/caif_device.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Author: Sjur Brendeland/ sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef CAIF_DEVICE_H_
+#define CAIF_DEVICE_H_
+#include <linux/kernel.h>
+#include <linux/net.h>
+#include <linux/netdevice.h>
+#include <linux/caif/caif_socket.h>
+#include <net/caif/caif_device.h>
+
+/**
+ * struct caif_dev_common - data shared between CAIF drivers and stack.
+ * @flowctrl: Flow Control callback function. This function is
+ * supplied by CAIF Core Stack and is used by CAIF
+ * Link Layer to send flow-stop to CAIF Core.
+ * The flow information will be distributed to all
+ * clients of CAIF.
+ *
+ * @link_select: Profile of device, either high-bandwidth or
+ * low-latency. This member is set by CAIF Link
+ * Layer Device in order to indicate if this device
+ * is a high bandwidth or low latency device.
+ *
+ * @use_frag: CAIF Frames may be fragmented.
+ * Is set by CAIF Link Layer in order to indicate if the
+ * interface receives fragmented frames that must be
+ * assembled by CAIF Core Layer.
+ *
+ * @use_fcs: Indicate if Frame CheckSum (fcs) is used.
+ * Is set if the physical interface is
+ * using Frame Checksum on the CAIF Frames.
+ *
+ * @use_stx: Indicate STart of frame eXtension (stx) in use.
+ * Is set if the CAIF Link Layer expects
+ * CAIF Frames to start with the STX byte.
+ *
+ * This structure is shared between the CAIF drivers and the CAIF stack.
+ * It is used by the device to register its behavior.
+ * CAIF Core layer must set the member flowctrl in order to supply
+ * CAIF Link Layer with the flow control function.
+ *
+ */
+ struct caif_dev_common {
+ void (*flowctrl)(struct net_device *net, int on);
+ enum caif_link_selector link_select;
+ int use_frag;
+ int use_fcs;
+ int use_stx;
+};
+
+#endif /* CAIF_DEVICE_H_ */
diff --git a/include/net/caif/caif_hsi.h b/include/net/caif/caif_hsi.h
new file mode 100644
index 00000000..6db8ecf5
--- /dev/null
+++ b/include/net/caif/caif_hsi.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Contact: Sjur Brendeland / sjur.brandeland@stericsson.com
+ * Author: Daniel Martensson / daniel.martensson@stericsson.com
+ * Dmitry.Tarnyagin / dmitry.tarnyagin@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef CAIF_HSI_H_
+#define CAIF_HSI_H_
+
+#include <net/caif/caif_layer.h>
+#include <net/caif/caif_device.h>
+#include <linux/atomic.h>
+
+/*
+ * Maximum number of CAIF frames that can reside in the same HSI frame.
+ */
+#define CFHSI_MAX_PKTS 15
+
+/*
+ * Maximum number of bytes used for the frame that can be embedded in the
+ * HSI descriptor.
+ */
+#define CFHSI_MAX_EMB_FRM_SZ 96
+
+/*
+ * Decides if HSI buffers should be prefilled with 0xFF pattern for easier
+ * debugging. Both TX and RX buffers will be filled before the transfer.
+ */
+#define CFHSI_DBG_PREFILL 0
+
+/* Structure describing a HSI packet descriptor. */
+#pragma pack(1) /* Byte alignment. */
+struct cfhsi_desc {
+ u8 header;
+ u8 offset;
+ u16 cffrm_len[CFHSI_MAX_PKTS];
+ u8 emb_frm[CFHSI_MAX_EMB_FRM_SZ];
+};
+#pragma pack() /* Default alignment. */
+
+/* Size of the complete HSI packet descriptor. */
+#define CFHSI_DESC_SZ (sizeof(struct cfhsi_desc))
+
+/*
+ * Size of the complete HSI packet descriptor excluding the optional embedded
+ * CAIF frame.
+ */
+#define CFHSI_DESC_SHORT_SZ (CFHSI_DESC_SZ - CFHSI_MAX_EMB_FRM_SZ)
+
+/*
+ * Maximum bytes transferred in one transfer.
+ */
+#define CFHSI_MAX_CAIF_FRAME_SZ 4096
+
+#define CFHSI_MAX_PAYLOAD_SZ (CFHSI_MAX_PKTS * CFHSI_MAX_CAIF_FRAME_SZ)
+
+/* Size of the complete HSI TX buffer. */
+#define CFHSI_BUF_SZ_TX (CFHSI_DESC_SZ + CFHSI_MAX_PAYLOAD_SZ)
+
+/* Size of the complete HSI RX buffer. */
+#define CFHSI_BUF_SZ_RX ((2 * CFHSI_DESC_SZ) + CFHSI_MAX_PAYLOAD_SZ)
+
+/* Bitmasks for the HSI descriptor. */
+#define CFHSI_PIGGY_DESC (0x01 << 7)
+
+#define CFHSI_TX_STATE_IDLE 0
+#define CFHSI_TX_STATE_XFER 1
+
+#define CFHSI_RX_STATE_DESC 0
+#define CFHSI_RX_STATE_PAYLOAD 1
+
+/* Bitmasks for power management. */
+#define CFHSI_WAKE_UP 0
+#define CFHSI_WAKE_UP_ACK 1
+#define CFHSI_WAKE_DOWN_ACK 2
+#define CFHSI_AWAKE 3
+#define CFHSI_WAKELOCK_HELD 4
+#define CFHSI_SHUTDOWN 5
+#define CFHSI_FLUSH_FIFO 6
+
+#ifndef CFHSI_INACTIVITY_TOUT
+#define CFHSI_INACTIVITY_TOUT (1 * HZ)
+#endif /* CFHSI_INACTIVITY_TOUT */
+
+#ifndef CFHSI_WAKE_TOUT
+#define CFHSI_WAKE_TOUT (3 * HZ)
+#endif /* CFHSI_WAKE_TOUT */
+
+#ifndef CFHSI_MAX_RX_RETRIES
+#define CFHSI_MAX_RX_RETRIES (10 * HZ)
+#endif
+
+/* Structure implemented by the CAIF HSI driver. */
+struct cfhsi_drv {
+ void (*tx_done_cb) (struct cfhsi_drv *drv);
+ void (*rx_done_cb) (struct cfhsi_drv *drv);
+ void (*wake_up_cb) (struct cfhsi_drv *drv);
+ void (*wake_down_cb) (struct cfhsi_drv *drv);
+};
+
+/* Structure implemented by HSI device. */
+struct cfhsi_dev {
+ int (*cfhsi_up) (struct cfhsi_dev *dev);
+ int (*cfhsi_down) (struct cfhsi_dev *dev);
+ int (*cfhsi_tx) (u8 *ptr, int len, struct cfhsi_dev *dev);
+ int (*cfhsi_rx) (u8 *ptr, int len, struct cfhsi_dev *dev);
+ int (*cfhsi_wake_up) (struct cfhsi_dev *dev);
+ int (*cfhsi_wake_down) (struct cfhsi_dev *dev);
+ int (*cfhsi_get_peer_wake) (struct cfhsi_dev *dev, bool *status);
+ int (*cfhsi_fifo_occupancy)(struct cfhsi_dev *dev, size_t *occupancy);
+ int (*cfhsi_rx_cancel)(struct cfhsi_dev *dev);
+ struct cfhsi_drv *drv;
+};
+
+/* Structure holds status of received CAIF frames processing */
+struct cfhsi_rx_state {
+ int state;
+ int nfrms;
+ int pld_len;
+ int retries;
+ bool piggy_desc;
+};
+
+/* Structure implemented by CAIF HSI drivers. */
+struct cfhsi {
+ struct caif_dev_common cfdev;
+ struct net_device *ndev;
+ struct platform_device *pdev;
+ struct sk_buff_head qhead;
+ struct cfhsi_drv drv;
+ struct cfhsi_dev *dev;
+ int tx_state;
+ struct cfhsi_rx_state rx_state;
+ unsigned long inactivity_timeout;
+ int rx_len;
+ u8 *rx_ptr;
+ u8 *tx_buf;
+ u8 *rx_buf;
+ u8 *rx_flip_buf;
+ spinlock_t lock;
+ int flow_off_sent;
+ u32 q_low_mark;
+ u32 q_high_mark;
+ struct list_head list;
+ struct work_struct wake_up_work;
+ struct work_struct wake_down_work;
+ struct work_struct out_of_sync_work;
+ struct workqueue_struct *wq;
+ wait_queue_head_t wake_up_wait;
+ wait_queue_head_t wake_down_wait;
+ wait_queue_head_t flush_fifo_wait;
+ struct timer_list timer;
+ struct timer_list rx_slowpath_timer;
+ unsigned long bits;
+};
+
+extern struct platform_driver cfhsi_driver;
+
+#endif /* CAIF_HSI_H_ */
diff --git a/include/net/caif/caif_layer.h b/include/net/caif/caif_layer.h
new file mode 100644
index 00000000..0f3a3912
--- /dev/null
+++ b/include/net/caif/caif_layer.h
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Author: Sjur Brendeland / sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef CAIF_LAYER_H_
+#define CAIF_LAYER_H_
+
+#include <linux/list.h>
+
+struct cflayer;
+struct cfpkt;
+struct cfpktq;
+struct caif_payload_info;
+struct caif_packet_funcs;
+
+#define CAIF_LAYER_NAME_SZ 16
+
+/**
+ * caif_assert() - Assert function for CAIF.
+ * @assert: expression to evaluate.
+ *
+ * This function will print a error message and a do WARN_ON if the
+ * assertion failes. Normally this will do a stack up at the current location.
+ */
+#define caif_assert(assert) \
+do { \
+ if (!(assert)) { \
+ pr_err("caif:Assert detected:'%s'\n", #assert); \
+ WARN_ON(!(assert)); \
+ } \
+} while (0)
+
+/**
+ * enum caif_ctrlcmd - CAIF Stack Control Signaling sent in layer.ctrlcmd().
+ *
+ * @CAIF_CTRLCMD_FLOW_OFF_IND: Flow Control is OFF, transmit function
+ * should stop sending data
+ *
+ * @CAIF_CTRLCMD_FLOW_ON_IND: Flow Control is ON, transmit function
+ * can start sending data
+ *
+ * @CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND: Remote end modem has decided to close
+ * down channel
+ *
+ * @CAIF_CTRLCMD_INIT_RSP: Called initially when the layer below
+ * has finished initialization
+ *
+ * @CAIF_CTRLCMD_DEINIT_RSP: Called when de-initialization is
+ * complete
+ *
+ * @CAIF_CTRLCMD_INIT_FAIL_RSP: Called if initialization fails
+ *
+ * @_CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND: CAIF Link layer temporarily cannot
+ * send more packets.
+ * @_CAIF_CTRLCMD_PHYIF_FLOW_ON_IND: Called if CAIF Link layer is able
+ * to send packets again.
+ * @_CAIF_CTRLCMD_PHYIF_DOWN_IND: Called if CAIF Link layer is going
+ * down.
+ *
+ * These commands are sent upwards in the CAIF stack to the CAIF Client.
+ * They are used for signaling originating from the modem or CAIF Link Layer.
+ * These are either responses (*_RSP) or events (*_IND).
+ */
+enum caif_ctrlcmd {
+ CAIF_CTRLCMD_FLOW_OFF_IND,
+ CAIF_CTRLCMD_FLOW_ON_IND,
+ CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND,
+ CAIF_CTRLCMD_INIT_RSP,
+ CAIF_CTRLCMD_DEINIT_RSP,
+ CAIF_CTRLCMD_INIT_FAIL_RSP,
+ _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND,
+ _CAIF_CTRLCMD_PHYIF_FLOW_ON_IND,
+ _CAIF_CTRLCMD_PHYIF_DOWN_IND,
+};
+
+/**
+ * enum caif_modemcmd - Modem Control Signaling, sent from CAIF Client
+ * to the CAIF Link Layer or modem.
+ *
+ * @CAIF_MODEMCMD_FLOW_ON_REQ: Flow Control is ON, transmit function
+ * can start sending data.
+ *
+ * @CAIF_MODEMCMD_FLOW_OFF_REQ: Flow Control is OFF, transmit function
+ * should stop sending data.
+ *
+ * @_CAIF_MODEMCMD_PHYIF_USEFULL: Notify physical layer that it is in use
+ *
+ * @_CAIF_MODEMCMD_PHYIF_USELESS: Notify physical layer that it is
+ * no longer in use.
+ *
+ * These are requests sent 'downwards' in the stack.
+ * Flow ON, OFF can be indicated to the modem.
+ */
+enum caif_modemcmd {
+ CAIF_MODEMCMD_FLOW_ON_REQ = 0,
+ CAIF_MODEMCMD_FLOW_OFF_REQ = 1,
+ _CAIF_MODEMCMD_PHYIF_USEFULL = 3,
+ _CAIF_MODEMCMD_PHYIF_USELESS = 4
+};
+
+/**
+ * enum caif_direction - CAIF Packet Direction.
+ * Indicate if a packet is to be sent out or to be received in.
+ * @CAIF_DIR_IN: Incoming packet received.
+ * @CAIF_DIR_OUT: Outgoing packet to be transmitted.
+ */
+enum caif_direction {
+ CAIF_DIR_IN = 0,
+ CAIF_DIR_OUT = 1
+};
+
+/**
+ * struct cflayer - CAIF Stack layer.
+ * Defines the framework for the CAIF Core Stack.
+ * @up: Pointer up to the layer above.
+ * @dn: Pointer down to the layer below.
+ * @node: List node used when layer participate in a list.
+ * @receive: Packet receive function.
+ * @transmit: Packet transmit funciton.
+ * @ctrlcmd: Used for control signalling upwards in the stack.
+ * @modemcmd: Used for control signaling downwards in the stack.
+ * @id: The identity of this layer
+ * @name: Name of the layer.
+ *
+ * This structure defines the layered structure in CAIF.
+ *
+ * It defines CAIF layering structure, used by all CAIF Layers and the
+ * layers interfacing CAIF.
+ *
+ * In order to integrate with CAIF an adaptation layer on top of the CAIF stack
+ * and PHY layer below the CAIF stack
+ * must be implemented. These layer must follow the design principles below.
+ *
+ * Principles for layering of protocol layers:
+ * - All layers must use this structure. If embedding it, then place this
+ * structure first in the layer specific structure.
+ *
+ * - Each layer should not depend on any others layer's private data.
+ *
+ * - In order to send data upwards do
+ * layer->up->receive(layer->up, packet);
+ *
+ * - In order to send data downwards do
+ * layer->dn->transmit(layer->dn, info, packet);
+ */
+struct cflayer {
+ struct cflayer *up;
+ struct cflayer *dn;
+ struct list_head node;
+
+ /*
+ * receive() - Receive Function (non-blocking).
+ * Contract: Each layer must implement a receive function passing the
+ * CAIF packets upwards in the stack.
+ * Packet handling rules:
+ * - The CAIF packet (cfpkt) ownership is passed to the
+ * called receive function. This means that the the
+ * packet cannot be accessed after passing it to the
+ * above layer using up->receive().
+ *
+ * - If parsing of the packet fails, the packet must be
+ * destroyed and negative error code returned
+ * from the function.
+ * EXCEPTION: If the framing layer (cffrml) returns
+ * -EILSEQ, the packet is not freed.
+ *
+ * - If parsing succeeds (and above layers return OK) then
+ * the function must return a value >= 0.
+ *
+ * Returns result < 0 indicates an error, 0 or positive value
+ * indicates success.
+ *
+ * @layr: Pointer to the current layer the receive function is
+ * implemented for (this pointer).
+ * @cfpkt: Pointer to CaifPacket to be handled.
+ */
+ int (*receive)(struct cflayer *layr, struct cfpkt *cfpkt);
+
+ /*
+ * transmit() - Transmit Function (non-blocking).
+ * Contract: Each layer must implement a transmit function passing the
+ * CAIF packet downwards in the stack.
+ * Packet handling rules:
+ * - The CAIF packet (cfpkt) ownership is passed to the
+ * transmit function. This means that the the packet
+ * cannot be accessed after passing it to the below
+ * layer using dn->transmit().
+ *
+ * - Upon error the packet ownership is still passed on,
+ * so the packet shall be freed where error is detected.
+ * Callers of the transmit function shall not free packets,
+ * but errors shall be returned.
+ *
+ * - Return value less than zero means error, zero or
+ * greater than zero means OK.
+ *
+ * Returns result < 0 indicates an error, 0 or positive value
+ * indicates success.
+ *
+ * @layr: Pointer to the current layer the receive function
+ * isimplemented for (this pointer).
+ * @cfpkt: Pointer to CaifPacket to be handled.
+ */
+ int (*transmit) (struct cflayer *layr, struct cfpkt *cfpkt);
+
+ /*
+ * cttrlcmd() - Control Function upwards in CAIF Stack (non-blocking).
+ * Used for signaling responses (CAIF_CTRLCMD_*_RSP)
+ * and asynchronous events from the modem (CAIF_CTRLCMD_*_IND)
+ *
+ * @layr: Pointer to the current layer the receive function
+ * is implemented for (this pointer).
+ * @ctrl: Control Command.
+ */
+ void (*ctrlcmd) (struct cflayer *layr, enum caif_ctrlcmd ctrl,
+ int phyid);
+
+ /*
+ * modemctrl() - Control Function used for controlling the modem.
+ * Used to signal down-wards in the CAIF stack.
+ * Returns 0 on success, < 0 upon failure.
+ *
+ * @layr: Pointer to the current layer the receive function
+ * is implemented for (this pointer).
+ * @ctrl: Control Command.
+ */
+ int (*modemcmd) (struct cflayer *layr, enum caif_modemcmd ctrl);
+
+ unsigned int id;
+ char name[CAIF_LAYER_NAME_SZ];
+};
+
+/**
+ * layer_set_up() - Set the up pointer for a specified layer.
+ * @layr: Layer where up pointer shall be set.
+ * @above: Layer above.
+ */
+#define layer_set_up(layr, above) ((layr)->up = (struct cflayer *)(above))
+
+/**
+ * layer_set_dn() - Set the down pointer for a specified layer.
+ * @layr: Layer where down pointer shall be set.
+ * @below: Layer below.
+ */
+#define layer_set_dn(layr, below) ((layr)->dn = (struct cflayer *)(below))
+
+/**
+ * struct dev_info - Physical Device info information about physical layer.
+ * @dev: Pointer to native physical device.
+ * @id: Physical ID of the physical connection used by the
+ * logical CAIF connection. Used by service layers to
+ * identify their physical id to Caif MUX (CFMUXL)so
+ * that the MUX can add the correct physical ID to the
+ * packet.
+ */
+struct dev_info {
+ void *dev;
+ unsigned int id;
+};
+
+/**
+ * struct caif_payload_info - Payload information embedded in packet (sk_buff).
+ *
+ * @dev_info: Information about the receiving device.
+ *
+ * @hdr_len: Header length, used to align pay load on 32bit boundary.
+ *
+ * @channel_id: Channel ID of the logical CAIF connection.
+ * Used by mux to insert channel id into the caif packet.
+ */
+struct caif_payload_info {
+ struct dev_info *dev_info;
+ unsigned short hdr_len;
+ unsigned short channel_id;
+};
+
+#endif /* CAIF_LAYER_H_ */
diff --git a/include/net/caif/caif_shm.h b/include/net/caif/caif_shm.h
new file mode 100644
index 00000000..5bcce554
--- /dev/null
+++ b/include/net/caif/caif_shm.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Contact: Sjur Brendeland / sjur.brandeland@stericsson.com
+ * Author: Amarnath Revanna / amarnath.bangalore.revanna@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef CAIF_SHM_H_
+#define CAIF_SHM_H_
+
+struct shmdev_layer {
+ u32 shm_base_addr;
+ u32 shm_total_sz;
+ u32 shm_id;
+ u32 shm_loopback;
+ void *hmbx;
+ int (*pshmdev_mbxsend) (u32 shm_id, u32 mbx_msg);
+ int (*pshmdev_mbxsetup) (void *pshmdrv_cb,
+ struct shmdev_layer *pshm_dev, void *pshm_drv);
+ struct net_device *pshm_netdev;
+};
+
+extern int caif_shmcore_probe(struct shmdev_layer *pshm_dev);
+extern void caif_shmcore_remove(struct net_device *pshm_netdev);
+
+#endif
diff --git a/include/net/caif/caif_spi.h b/include/net/caif/caif_spi.h
new file mode 100644
index 00000000..aa6a485b
--- /dev/null
+++ b/include/net/caif/caif_spi.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Author: Daniel Martensson / Daniel.Martensson@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef CAIF_SPI_H_
+#define CAIF_SPI_H_
+
+#include <net/caif/caif_device.h>
+
+#define SPI_CMD_WR 0x00
+#define SPI_CMD_RD 0x01
+#define SPI_CMD_EOT 0x02
+#define SPI_CMD_IND 0x04
+
+#define SPI_DMA_BUF_LEN 8192
+
+#define WL_SZ 2 /* 16 bits. */
+#define SPI_CMD_SZ 4 /* 32 bits. */
+#define SPI_IND_SZ 4 /* 32 bits. */
+
+#define SPI_XFER 0
+#define SPI_SS_ON 1
+#define SPI_SS_OFF 2
+#define SPI_TERMINATE 3
+
+/* Minimum time between different levels is 50 microseconds. */
+#define MIN_TRANSITION_TIME_USEC 50
+
+/* Defines for calculating duration of SPI transfers for a particular
+ * number of bytes.
+ */
+#define SPI_MASTER_CLK_MHZ 13
+#define SPI_XFER_TIME_USEC(bytes, clk) (((bytes) * 8) / clk)
+
+/* Normally this should be aligned on the modem in order to benefit from full
+ * duplex transfers. However a size of 8188 provokes errors when running with
+ * the modem. These errors occur when packet sizes approaches 4 kB of data.
+ */
+#define CAIF_MAX_SPI_FRAME 4092
+
+/* Maximum number of uplink CAIF frames that can reside in the same SPI frame.
+ * This number should correspond with the modem setting. The application side
+ * CAIF accepts any number of embedded downlink CAIF frames.
+ */
+#define CAIF_MAX_SPI_PKTS 9
+
+/* Decides if SPI buffers should be prefilled with 0xFF pattern for easier
+ * debugging. Both TX and RX buffers will be filled before the transfer.
+ */
+#define CFSPI_DBG_PREFILL 0
+
+/* Structure describing a SPI transfer. */
+struct cfspi_xfer {
+ u16 tx_dma_len;
+ u16 rx_dma_len;
+ void *va_tx[2];
+ dma_addr_t pa_tx[2];
+ void *va_rx;
+ dma_addr_t pa_rx;
+};
+
+/* Structure implemented by the SPI interface. */
+struct cfspi_ifc {
+ void (*ss_cb) (bool assert, struct cfspi_ifc *ifc);
+ void (*xfer_done_cb) (struct cfspi_ifc *ifc);
+ void *priv;
+};
+
+/* Structure implemented by SPI clients. */
+struct cfspi_dev {
+ int (*init_xfer) (struct cfspi_xfer *xfer, struct cfspi_dev *dev);
+ void (*sig_xfer) (bool xfer, struct cfspi_dev *dev);
+ struct cfspi_ifc *ifc;
+ char *name;
+ u32 clk_mhz;
+ void *priv;
+};
+
+/* Enumeration describing the CAIF SPI state. */
+enum cfspi_state {
+ CFSPI_STATE_WAITING = 0,
+ CFSPI_STATE_AWAKE,
+ CFSPI_STATE_FETCH_PKT,
+ CFSPI_STATE_GET_NEXT,
+ CFSPI_STATE_INIT_XFER,
+ CFSPI_STATE_WAIT_ACTIVE,
+ CFSPI_STATE_SIG_ACTIVE,
+ CFSPI_STATE_WAIT_XFER_DONE,
+ CFSPI_STATE_XFER_DONE,
+ CFSPI_STATE_WAIT_INACTIVE,
+ CFSPI_STATE_SIG_INACTIVE,
+ CFSPI_STATE_DELIVER_PKT,
+ CFSPI_STATE_MAX,
+};
+
+/* Structure implemented by SPI physical interfaces. */
+struct cfspi {
+ struct caif_dev_common cfdev;
+ struct net_device *ndev;
+ struct platform_device *pdev;
+ struct sk_buff_head qhead;
+ struct sk_buff_head chead;
+ u16 cmd;
+ u16 tx_cpck_len;
+ u16 tx_npck_len;
+ u16 rx_cpck_len;
+ u16 rx_npck_len;
+ struct cfspi_ifc ifc;
+ struct cfspi_xfer xfer;
+ struct cfspi_dev *dev;
+ unsigned long state;
+ struct work_struct work;
+ struct workqueue_struct *wq;
+ struct list_head list;
+ int flow_off_sent;
+ u32 qd_low_mark;
+ u32 qd_high_mark;
+ struct completion comp;
+ wait_queue_head_t wait;
+ spinlock_t lock;
+ bool flow_stop;
+ bool slave;
+ bool slave_talked;
+#ifdef CONFIG_DEBUG_FS
+ enum cfspi_state dbg_state;
+ u16 pcmd;
+ u16 tx_ppck_len;
+ u16 rx_ppck_len;
+ struct dentry *dbgfs_dir;
+ struct dentry *dbgfs_state;
+ struct dentry *dbgfs_frame;
+#endif /* CONFIG_DEBUG_FS */
+};
+
+extern int spi_frm_align;
+extern int spi_up_head_align;
+extern int spi_up_tail_align;
+extern int spi_down_head_align;
+extern int spi_down_tail_align;
+extern struct platform_driver cfspi_spi_driver;
+
+void cfspi_dbg_state(struct cfspi *cfspi, int state);
+int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len);
+int cfspi_xmitlen(struct cfspi *cfspi);
+int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len);
+int cfspi_spi_remove(struct platform_device *pdev);
+int cfspi_spi_probe(struct platform_device *pdev);
+int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len);
+int cfspi_xmitlen(struct cfspi *cfspi);
+int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len);
+void cfspi_xfer(struct work_struct *work);
+
+#endif /* CAIF_SPI_H_ */
diff --git a/include/net/caif/cfcnfg.h b/include/net/caif/cfcnfg.h
new file mode 100644
index 00000000..90b4ff8b
--- /dev/null
+++ b/include/net/caif/cfcnfg.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef CFCNFG_H_
+#define CFCNFG_H_
+#include <linux/spinlock.h>
+#include <linux/netdevice.h>
+#include <net/caif/caif_layer.h>
+#include <net/caif/cfctrl.h>
+
+struct cfcnfg;
+
+/**
+ * enum cfcnfg_phy_preference - Physical preference HW Abstraction
+ *
+ * @CFPHYPREF_UNSPECIFIED: Default physical interface
+ *
+ * @CFPHYPREF_LOW_LAT: Default physical interface for low-latency
+ * traffic
+ * @CFPHYPREF_HIGH_BW: Default physical interface for high-bandwidth
+ * traffic
+ * @CFPHYPREF_LOOP: TEST only Loopback interface simulating modem
+ * responses.
+ *
+ */
+enum cfcnfg_phy_preference {
+ CFPHYPREF_UNSPECIFIED,
+ CFPHYPREF_LOW_LAT,
+ CFPHYPREF_HIGH_BW,
+ CFPHYPREF_LOOP
+};
+
+/**
+ * cfcnfg_create() - Get the CAIF configuration object given network.
+ * @net: Network for the CAIF configuration object.
+ */
+struct cfcnfg *get_cfcnfg(struct net *net);
+
+/**
+ * cfcnfg_create() - Create the CAIF configuration object.
+ */
+struct cfcnfg *cfcnfg_create(void);
+
+/**
+ * cfcnfg_remove() - Remove the CFCNFG object
+ * @cfg: config object
+ */
+void cfcnfg_remove(struct cfcnfg *cfg);
+
+/**
+ * cfcnfg_add_phy_layer() - Adds a physical layer to the CAIF stack.
+ * @cnfg: Pointer to a CAIF configuration object, created by
+ * cfcnfg_create().
+ * @dev: Pointer to link layer device
+ * @phy_layer: Specify the physical layer. The transmit function
+ * MUST be set in the structure.
+ * @pref: The phy (link layer) preference.
+ * @link_support: Protocol implementation for link layer specific protocol.
+ * @fcs: Specify if checksum is used in CAIF Framing Layer.
+ * @head_room: Head space needed by link specific protocol.
+ */
+void
+cfcnfg_add_phy_layer(struct cfcnfg *cnfg,
+ struct net_device *dev, struct cflayer *phy_layer,
+ enum cfcnfg_phy_preference pref,
+ struct cflayer *link_support,
+ bool fcs, int head_room);
+
+/**
+ * cfcnfg_del_phy_layer - Deletes an phy layer from the CAIF stack.
+ *
+ * @cnfg: Pointer to a CAIF configuration object, created by
+ * cfcnfg_create().
+ * @phy_layer: Adaptation layer to be removed.
+ */
+int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer);
+
+/**
+ * cfcnfg_set_phy_state() - Set the state of the physical interface device.
+ * @cnfg: Configuration object
+ * @phy_layer: Physical Layer representation
+ * @up: State of device
+ */
+int cfcnfg_set_phy_state(struct cfcnfg *cnfg, struct cflayer *phy_layer,
+ bool up);
+
+#endif /* CFCNFG_H_ */
diff --git a/include/net/caif/cfctrl.h b/include/net/caif/cfctrl.h
new file mode 100644
index 00000000..9e5425b4
--- /dev/null
+++ b/include/net/caif/cfctrl.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef CFCTRL_H_
+#define CFCTRL_H_
+#include <net/caif/caif_layer.h>
+#include <net/caif/cfsrvl.h>
+
+/* CAIF Control packet commands */
+enum cfctrl_cmd {
+ CFCTRL_CMD_LINK_SETUP = 0,
+ CFCTRL_CMD_LINK_DESTROY = 1,
+ CFCTRL_CMD_LINK_ERR = 2,
+ CFCTRL_CMD_ENUM = 3,
+ CFCTRL_CMD_SLEEP = 4,
+ CFCTRL_CMD_WAKE = 5,
+ CFCTRL_CMD_LINK_RECONF = 6,
+ CFCTRL_CMD_START_REASON = 7,
+ CFCTRL_CMD_RADIO_SET = 8,
+ CFCTRL_CMD_MODEM_SET = 9,
+ CFCTRL_CMD_MASK = 0xf
+};
+
+/* Channel types */
+enum cfctrl_srv {
+ CFCTRL_SRV_DECM = 0,
+ CFCTRL_SRV_VEI = 1,
+ CFCTRL_SRV_VIDEO = 2,
+ CFCTRL_SRV_DBG = 3,
+ CFCTRL_SRV_DATAGRAM = 4,
+ CFCTRL_SRV_RFM = 5,
+ CFCTRL_SRV_UTIL = 6,
+ CFCTRL_SRV_MASK = 0xf
+};
+
+#define CFCTRL_RSP_BIT 0x20
+#define CFCTRL_ERR_BIT 0x10
+
+struct cfctrl_rsp {
+ void (*linksetup_rsp)(struct cflayer *layer, u8 linkid,
+ enum cfctrl_srv serv, u8 phyid,
+ struct cflayer *adapt_layer);
+ void (*linkdestroy_rsp)(struct cflayer *layer, u8 linkid);
+ void (*linkerror_ind)(void);
+ void (*enum_rsp)(void);
+ void (*sleep_rsp)(void);
+ void (*wake_rsp)(void);
+ void (*restart_rsp)(void);
+ void (*radioset_rsp)(void);
+ void (*reject_rsp)(struct cflayer *layer, u8 linkid,
+ struct cflayer *client_layer);
+};
+
+/* Link Setup Parameters for CAIF-Links. */
+struct cfctrl_link_param {
+ enum cfctrl_srv linktype;/* (T3,T0) Type of Channel */
+ u8 priority; /* (P4,P0) Priority of the channel */
+ u8 phyid; /* (U2-U0) Physical interface to connect */
+ u8 endpoint; /* (E1,E0) Endpoint for data channels */
+ u8 chtype; /* (H1,H0) Channel-Type, applies to
+ * VEI, DEBUG */
+ union {
+ struct {
+ u8 connid; /* (D7,D0) Video LinkId */
+ } video;
+
+ struct {
+ u32 connid; /* (N31,Ngit0) Connection ID used
+ * for Datagram */
+ } datagram;
+
+ struct {
+ u32 connid; /* Connection ID used for RFM */
+ char volume[20]; /* Volume to mount for RFM */
+ } rfm; /* Configuration for RFM */
+
+ struct {
+ u16 fifosize_kb; /* Psock FIFO size in KB */
+ u16 fifosize_bufs; /* Psock # signal buffers */
+ char name[16]; /* Name of the PSOCK service */
+ u8 params[255]; /* Link setup Parameters> */
+ u16 paramlen; /* Length of Link Setup
+ * Parameters */
+ } utility; /* Configuration for Utility Links (Psock) */
+ } u;
+};
+
+/* This structure is used internally in CFCTRL */
+struct cfctrl_request_info {
+ int sequence_no;
+ enum cfctrl_cmd cmd;
+ u8 channel_id;
+ struct cfctrl_link_param param;
+ struct cflayer *client_layer;
+ struct list_head list;
+};
+
+struct cfctrl {
+ struct cfsrvl serv;
+ struct cfctrl_rsp res;
+ atomic_t req_seq_no;
+ atomic_t rsp_seq_no;
+ struct list_head list;
+ /* Protects from simultaneous access to first_req list */
+ spinlock_t info_list_lock;
+#ifndef CAIF_NO_LOOP
+ u8 loop_linkid;
+ int loop_linkused[256];
+ /* Protects simultaneous access to loop_linkid and loop_linkused */
+ spinlock_t loop_linkid_lock;
+#endif
+
+};
+
+void cfctrl_enum_req(struct cflayer *cfctrl, u8 physlinkid);
+int cfctrl_linkup_request(struct cflayer *cfctrl,
+ struct cfctrl_link_param *param,
+ struct cflayer *user_layer);
+int cfctrl_linkdown_req(struct cflayer *cfctrl, u8 linkid,
+ struct cflayer *client);
+
+struct cflayer *cfctrl_create(void);
+struct cfctrl_rsp *cfctrl_get_respfuncs(struct cflayer *layer);
+int cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer);
+void cfctrl_remove(struct cflayer *layr);
+
+#endif /* CFCTRL_H_ */
diff --git a/include/net/caif/cffrml.h b/include/net/caif/cffrml.h
new file mode 100644
index 00000000..afac1a48
--- /dev/null
+++ b/include/net/caif/cffrml.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef CFFRML_H_
+#define CFFRML_H_
+#include <net/caif/caif_layer.h>
+#include <linux/netdevice.h>
+
+struct cffrml;
+struct cflayer *cffrml_create(u16 phyid, bool use_fcs);
+void cffrml_free(struct cflayer *layr);
+void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up);
+void cffrml_set_dnlayer(struct cflayer *this, struct cflayer *dn);
+void cffrml_put(struct cflayer *layr);
+void cffrml_hold(struct cflayer *layr);
+int cffrml_refcnt_read(struct cflayer *layr);
+
+#endif /* CFFRML_H_ */
diff --git a/include/net/caif/cfmuxl.h b/include/net/caif/cfmuxl.h
new file mode 100644
index 00000000..5847a196
--- /dev/null
+++ b/include/net/caif/cfmuxl.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef CFMUXL_H_
+#define CFMUXL_H_
+#include <net/caif/caif_layer.h>
+
+struct cfsrvl;
+struct cffrml;
+
+struct cflayer *cfmuxl_create(void);
+int cfmuxl_set_uplayer(struct cflayer *layr, struct cflayer *up, u8 linkid);
+struct cflayer *cfmuxl_remove_dnlayer(struct cflayer *layr, u8 phyid);
+int cfmuxl_set_dnlayer(struct cflayer *layr, struct cflayer *up, u8 phyid);
+struct cflayer *cfmuxl_remove_uplayer(struct cflayer *layr, u8 linkid);
+
+#endif /* CFMUXL_H_ */
diff --git a/include/net/caif/cfpkt.h b/include/net/caif/cfpkt.h
new file mode 100644
index 00000000..6bd200a4
--- /dev/null
+++ b/include/net/caif/cfpkt.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef CFPKT_H_
+#define CFPKT_H_
+#include <net/caif/caif_layer.h>
+#include <linux/types.h>
+struct cfpkt;
+
+/* Create a CAIF packet.
+ * len: Length of packet to be created
+ * @return New packet.
+ */
+struct cfpkt *cfpkt_create(u16 len);
+
+/*
+ * Destroy a CAIF Packet.
+ * pkt Packet to be destoyed.
+ */
+void cfpkt_destroy(struct cfpkt *pkt);
+
+/*
+ * Extract header from packet.
+ *
+ * pkt Packet to extract header data from.
+ * data Pointer to copy the header data into.
+ * len Length of head data to copy.
+ * @return zero on success and error code upon failure
+ */
+int cfpkt_extr_head(struct cfpkt *pkt, void *data, u16 len);
+
+/*
+ * Peek header from packet.
+ * Reads data from packet without changing packet.
+ *
+ * pkt Packet to extract header data from.
+ * data Pointer to copy the header data into.
+ * len Length of head data to copy.
+ * @return zero on success and error code upon failure
+ */
+int cfpkt_peek_head(struct cfpkt *pkt, void *data, u16 len);
+
+/*
+ * Extract header from trailer (end of packet).
+ *
+ * pkt Packet to extract header data from.
+ * data Pointer to copy the trailer data into.
+ * len Length of header data to copy.
+ * @return zero on success and error code upon failure
+ */
+int cfpkt_extr_trail(struct cfpkt *pkt, void *data, u16 len);
+
+/*
+ * Add header to packet.
+ *
+ *
+ * pkt Packet to add header data to.
+ * data Pointer to data to copy into the header.
+ * len Length of header data to copy.
+ * @return zero on success and error code upon failure
+ */
+int cfpkt_add_head(struct cfpkt *pkt, const void *data, u16 len);
+
+/*
+ * Add trailer to packet.
+ *
+ *
+ * pkt Packet to add trailer data to.
+ * data Pointer to data to copy into the trailer.
+ * len Length of trailer data to copy.
+ * @return zero on success and error code upon failure
+ */
+int cfpkt_add_trail(struct cfpkt *pkt, const void *data, u16 len);
+
+/*
+ * Pad trailer on packet.
+ * Moves data pointer in packet, no content copied.
+ *
+ * pkt Packet in which to pad trailer.
+ * len Length of padding to add.
+ * @return zero on success and error code upon failure
+ */
+int cfpkt_pad_trail(struct cfpkt *pkt, u16 len);
+
+/*
+ * Add a single byte to packet body (tail).
+ *
+ * pkt Packet in which to add byte.
+ * data Byte to add.
+ * @return zero on success and error code upon failure
+ */
+int cfpkt_addbdy(struct cfpkt *pkt, const u8 data);
+
+/*
+ * Add a data to packet body (tail).
+ *
+ * pkt Packet in which to add data.
+ * data Pointer to data to copy into the packet body.
+ * len Length of data to add.
+ * @return zero on success and error code upon failure
+ */
+int cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len);
+
+/*
+ * Checks whether there are more data to process in packet.
+ * pkt Packet to check.
+ * @return true if more data are available in packet false otherwise
+ */
+bool cfpkt_more(struct cfpkt *pkt);
+
+/*
+ * Checks whether the packet is erroneous,
+ * i.e. if it has been attempted to extract more data than available in packet
+ * or writing more data than has been allocated in cfpkt_create().
+ * pkt Packet to check.
+ * @return true on error false otherwise
+ */
+bool cfpkt_erroneous(struct cfpkt *pkt);
+
+/*
+ * Get the packet length.
+ * pkt Packet to get length from.
+ * @return Number of bytes in packet.
+ */
+u16 cfpkt_getlen(struct cfpkt *pkt);
+
+/*
+ * Set the packet length, by adjusting the trailer pointer according to length.
+ * pkt Packet to set length.
+ * len Packet length.
+ * @return Number of bytes in packet.
+ */
+int cfpkt_setlen(struct cfpkt *pkt, u16 len);
+
+/*
+ * cfpkt_append - Appends a packet's data to another packet.
+ * dstpkt: Packet to append data into, WILL BE FREED BY THIS FUNCTION
+ * addpkt: Packet to be appended and automatically released,
+ * WILL BE FREED BY THIS FUNCTION.
+ * expectlen: Packet's expected total length. This should be considered
+ * as a hint.
+ * NB: Input packets will be destroyed after appending and cannot be used
+ * after calling this function.
+ * @return The new appended packet.
+ */
+struct cfpkt *cfpkt_append(struct cfpkt *dstpkt, struct cfpkt *addpkt,
+ u16 expectlen);
+
+/*
+ * cfpkt_split - Split a packet into two packets at the specified split point.
+ * pkt: Packet to be split (will contain the first part of the data on exit)
+ * pos: Position to split packet in two parts.
+ * @return The new packet, containing the second part of the data.
+ */
+struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos);
+
+/*
+ * Iteration function, iterates the packet buffers from start to end.
+ *
+ * Checksum iteration function used to iterate buffers
+ * (we may have packets consisting of a chain of buffers)
+ * pkt: Packet to calculate checksum for
+ * iter_func: Function pointer to iteration function
+ * chks: Checksum calculated so far.
+ * buf: Pointer to the buffer to checksum
+ * len: Length of buf.
+ * data: Initial checksum value.
+ * @return Checksum of buffer.
+ */
+
+u16 cfpkt_iterate(struct cfpkt *pkt,
+ u16 (*iter_func)(u16 chks, void *buf, u16 len),
+ u16 data);
+
+/* Map from a "native" packet (e.g. Linux Socket Buffer) to a CAIF packet.
+ * dir - Direction indicating whether this packet is to be sent or received.
+ * nativepkt - The native packet to be transformed to a CAIF packet
+ * @return The mapped CAIF Packet CFPKT.
+ */
+struct cfpkt *cfpkt_fromnative(enum caif_direction dir, void *nativepkt);
+
+/* Map from a CAIF packet to a "native" packet (e.g. Linux Socket Buffer).
+ * pkt - The CAIF packet to be transformed into a "native" packet.
+ * @return The native packet transformed from a CAIF packet.
+ */
+void *cfpkt_tonative(struct cfpkt *pkt);
+
+
+/*
+ * Returns packet information for a packet.
+ * pkt Packet to get info from;
+ * @return Packet information
+ */
+struct caif_payload_info *cfpkt_info(struct cfpkt *pkt);
+#endif /* CFPKT_H_ */
diff --git a/include/net/caif/cfserl.h b/include/net/caif/cfserl.h
new file mode 100644
index 00000000..f121299a
--- /dev/null
+++ b/include/net/caif/cfserl.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef CFSERL_H_
+#define CFSERL_H_
+#include <net/caif/caif_layer.h>
+
+struct cflayer *cfserl_create(int instance, bool use_stx);
+#endif
diff --git a/include/net/caif/cfsrvl.h b/include/net/caif/cfsrvl.h
new file mode 100644
index 00000000..0f590524
--- /dev/null
+++ b/include/net/caif/cfsrvl.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef CFSRVL_H_
+#define CFSRVL_H_
+#include <linux/list.h>
+#include <linux/stddef.h>
+#include <linux/types.h>
+#include <linux/kref.h>
+#include <linux/rculist.h>
+
+struct cfsrvl {
+ struct cflayer layer;
+ bool open;
+ bool phy_flow_on;
+ bool modem_flow_on;
+ bool supports_flowctrl;
+ void (*release)(struct cflayer *layer);
+ struct dev_info dev_info;
+ void (*hold)(struct cflayer *lyr);
+ void (*put)(struct cflayer *lyr);
+ struct rcu_head rcu;
+};
+
+struct cflayer *cfvei_create(u8 linkid, struct dev_info *dev_info);
+struct cflayer *cfdgml_create(u8 linkid, struct dev_info *dev_info);
+struct cflayer *cfutill_create(u8 linkid, struct dev_info *dev_info);
+struct cflayer *cfvidl_create(u8 linkid, struct dev_info *dev_info);
+struct cflayer *cfrfml_create(u8 linkid, struct dev_info *dev_info,
+ int mtu_size);
+struct cflayer *cfdbgl_create(u8 linkid, struct dev_info *dev_info);
+
+void cfsrvl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
+ int phyid);
+
+bool cfsrvl_phyid_match(struct cflayer *layer, int phyid);
+
+void cfsrvl_init(struct cfsrvl *service,
+ u8 channel_id,
+ struct dev_info *dev_info,
+ bool supports_flowctrl);
+bool cfsrvl_ready(struct cfsrvl *service, int *err);
+u8 cfsrvl_getphyid(struct cflayer *layer);
+
+static inline void cfsrvl_get(struct cflayer *layr)
+{
+ struct cfsrvl *s = container_of(layr, struct cfsrvl, layer);
+ if (layr == NULL || layr->up == NULL || s->hold == NULL)
+ return;
+
+ s->hold(layr->up);
+}
+
+static inline void cfsrvl_put(struct cflayer *layr)
+{
+ struct cfsrvl *s = container_of(layr, struct cfsrvl, layer);
+ if (layr == NULL || layr->up == NULL || s->hold == NULL)
+ return;
+
+ s->put(layr->up);
+}
+#endif /* CFSRVL_H_ */
diff --git a/include/net/cfg80211-wext.h b/include/net/cfg80211-wext.h
new file mode 100644
index 00000000..25baddc4
--- /dev/null
+++ b/include/net/cfg80211-wext.h
@@ -0,0 +1,55 @@
+#ifndef __NET_CFG80211_WEXT_H
+#define __NET_CFG80211_WEXT_H
+/*
+ * 802.11 device and configuration interface -- wext handlers
+ *
+ * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+
+/*
+ * Temporary wext handlers & helper functions
+ *
+ * These are used only by drivers that aren't yet fully
+ * converted to cfg80211.
+ */
+int cfg80211_wext_giwname(struct net_device *dev,
+ struct iw_request_info *info,
+ char *name, char *extra);
+int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
+ u32 *mode, char *extra);
+int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info,
+ u32 *mode, char *extra);
+int cfg80211_wext_siwscan(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+int cfg80211_wext_giwscan(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra);
+int cfg80211_wext_giwrange(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra);
+int cfg80211_wext_siwrts(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rts, char *extra);
+int cfg80211_wext_giwrts(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rts, char *extra);
+int cfg80211_wext_siwfrag(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *frag, char *extra);
+int cfg80211_wext_giwfrag(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *frag, char *extra);
+int cfg80211_wext_giwretry(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *retry, char *extra);
+
+#endif /* __NET_CFG80211_WEXT_H */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
new file mode 100644
index 00000000..83d800c3
--- /dev/null
+++ b/include/net/cfg80211.h
@@ -0,0 +1,3399 @@
+#ifndef __NET_CFG80211_H
+#define __NET_CFG80211_H
+/*
+ * 802.11 device and configuration interface
+ *
+ * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/debugfs.h>
+#include <linux/list.h>
+#include <linux/bug.h>
+#include <linux/netlink.h>
+#include <linux/skbuff.h>
+#include <linux/nl80211.h>
+#include <linux/if_ether.h>
+#include <linux/ieee80211.h>
+#include <net/regulatory.h>
+
+/**
+ * DOC: Introduction
+ *
+ * cfg80211 is the configuration API for 802.11 devices in Linux. It bridges
+ * userspace and drivers, and offers some utility functionality associated
+ * with 802.11. cfg80211 must, directly or indirectly via mac80211, be used
+ * by all modern wireless drivers in Linux, so that they offer a consistent
+ * API through nl80211. For backward compatibility, cfg80211 also offers
+ * wireless extensions to userspace, but hides them from drivers completely.
+ *
+ * Additionally, cfg80211 contains code to help enforce regulatory spectrum
+ * use restrictions.
+ */
+
+
+/**
+ * DOC: Device registration
+ *
+ * In order for a driver to use cfg80211, it must register the hardware device
+ * with cfg80211. This happens through a number of hardware capability structs
+ * described below.
+ *
+ * The fundamental structure for each device is the 'wiphy', of which each
+ * instance describes a physical wireless device connected to the system. Each
+ * such wiphy can have zero, one, or many virtual interfaces associated with
+ * it, which need to be identified as such by pointing the network interface's
+ * @ieee80211_ptr pointer to a &struct wireless_dev which further describes
+ * the wireless part of the interface, normally this struct is embedded in the
+ * network interface's private data area. Drivers can optionally allow creating
+ * or destroying virtual interfaces on the fly, but without at least one or the
+ * ability to create some the wireless device isn't useful.
+ *
+ * Each wiphy structure contains device capability information, and also has
+ * a pointer to the various operations the driver offers. The definitions and
+ * structures here describe these capabilities in detail.
+ */
+
+/*
+ * wireless hardware capability structures
+ */
+
+/**
+ * enum ieee80211_band - supported frequency bands
+ *
+ * The bands are assigned this way because the supported
+ * bitrates differ in these bands.
+ *
+ * @IEEE80211_BAND_2GHZ: 2.4GHz ISM band
+ * @IEEE80211_BAND_5GHZ: around 5GHz band (4.9-5.7)
+ * @IEEE80211_NUM_BANDS: number of defined bands
+ */
+enum ieee80211_band {
+ IEEE80211_BAND_2GHZ = NL80211_BAND_2GHZ,
+ IEEE80211_BAND_5GHZ = NL80211_BAND_5GHZ,
+
+ /* keep last */
+ IEEE80211_NUM_BANDS
+};
+
+/**
+ * enum ieee80211_channel_flags - channel flags
+ *
+ * Channel flags set by the regulatory control code.
+ *
+ * @IEEE80211_CHAN_DISABLED: This channel is disabled.
+ * @IEEE80211_CHAN_PASSIVE_SCAN: Only passive scanning is permitted
+ * on this channel.
+ * @IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel.
+ * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel.
+ * @IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel
+ * is not permitted.
+ * @IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel
+ * is not permitted.
+ */
+enum ieee80211_channel_flags {
+ IEEE80211_CHAN_DISABLED = 1<<0,
+ IEEE80211_CHAN_PASSIVE_SCAN = 1<<1,
+ IEEE80211_CHAN_NO_IBSS = 1<<2,
+ IEEE80211_CHAN_RADAR = 1<<3,
+ IEEE80211_CHAN_NO_HT40PLUS = 1<<4,
+ IEEE80211_CHAN_NO_HT40MINUS = 1<<5,
+};
+
+#define IEEE80211_CHAN_NO_HT40 \
+ (IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
+
+/**
+ * struct ieee80211_channel - channel definition
+ *
+ * This structure describes a single channel for use
+ * with cfg80211.
+ *
+ * @center_freq: center frequency in MHz
+ * @hw_value: hardware-specific value for the channel
+ * @flags: channel flags from &enum ieee80211_channel_flags.
+ * @orig_flags: channel flags at registration time, used by regulatory
+ * code to support devices with additional restrictions
+ * @band: band this channel belongs to.
+ * @max_antenna_gain: maximum antenna gain in dBi
+ * @max_power: maximum transmission power (in dBm)
+ * @max_reg_power: maximum regulatory transmission power (in dBm)
+ * @beacon_found: helper to regulatory code to indicate when a beacon
+ * has been found on this channel. Use regulatory_hint_found_beacon()
+ * to enable this, this is useful only on 5 GHz band.
+ * @orig_mag: internal use
+ * @orig_mpwr: internal use
+ */
+struct ieee80211_channel {
+ enum ieee80211_band band;
+ u16 center_freq;
+ u16 hw_value;
+ u32 flags;
+ int max_antenna_gain;
+ int max_power;
+ int max_reg_power;
+ bool beacon_found;
+ u32 orig_flags;
+ int orig_mag, orig_mpwr;
+};
+
+/**
+ * enum ieee80211_rate_flags - rate flags
+ *
+ * Hardware/specification flags for rates. These are structured
+ * in a way that allows using the same bitrate structure for
+ * different bands/PHY modes.
+ *
+ * @IEEE80211_RATE_SHORT_PREAMBLE: Hardware can send with short
+ * preamble on this bitrate; only relevant in 2.4GHz band and
+ * with CCK rates.
+ * @IEEE80211_RATE_MANDATORY_A: This bitrate is a mandatory rate
+ * when used with 802.11a (on the 5 GHz band); filled by the
+ * core code when registering the wiphy.
+ * @IEEE80211_RATE_MANDATORY_B: This bitrate is a mandatory rate
+ * when used with 802.11b (on the 2.4 GHz band); filled by the
+ * core code when registering the wiphy.
+ * @IEEE80211_RATE_MANDATORY_G: This bitrate is a mandatory rate
+ * when used with 802.11g (on the 2.4 GHz band); filled by the
+ * core code when registering the wiphy.
+ * @IEEE80211_RATE_ERP_G: This is an ERP rate in 802.11g mode.
+ */
+enum ieee80211_rate_flags {
+ IEEE80211_RATE_SHORT_PREAMBLE = 1<<0,
+ IEEE80211_RATE_MANDATORY_A = 1<<1,
+ IEEE80211_RATE_MANDATORY_B = 1<<2,
+ IEEE80211_RATE_MANDATORY_G = 1<<3,
+ IEEE80211_RATE_ERP_G = 1<<4,
+};
+
+/**
+ * struct ieee80211_rate - bitrate definition
+ *
+ * This structure describes a bitrate that an 802.11 PHY can
+ * operate with. The two values @hw_value and @hw_value_short
+ * are only for driver use when pointers to this structure are
+ * passed around.
+ *
+ * @flags: rate-specific flags
+ * @bitrate: bitrate in units of 100 Kbps
+ * @hw_value: driver/hardware value for this rate
+ * @hw_value_short: driver/hardware value for this rate when
+ * short preamble is used
+ */
+struct ieee80211_rate {
+ u32 flags;
+ u16 bitrate;
+ u16 hw_value, hw_value_short;
+};
+
+/**
+ * struct ieee80211_sta_ht_cap - STA's HT capabilities
+ *
+ * This structure describes most essential parameters needed
+ * to describe 802.11n HT capabilities for an STA.
+ *
+ * @ht_supported: is HT supported by the STA
+ * @cap: HT capabilities map as described in 802.11n spec
+ * @ampdu_factor: Maximum A-MPDU length factor
+ * @ampdu_density: Minimum A-MPDU spacing
+ * @mcs: Supported MCS rates
+ */
+struct ieee80211_sta_ht_cap {
+ u16 cap; /* use IEEE80211_HT_CAP_ */
+ bool ht_supported;
+ u8 ampdu_factor;
+ u8 ampdu_density;
+ struct ieee80211_mcs_info mcs;
+};
+
+/**
+ * struct ieee80211_supported_band - frequency band definition
+ *
+ * This structure describes a frequency band a wiphy
+ * is able to operate in.
+ *
+ * @channels: Array of channels the hardware can operate in
+ * in this band.
+ * @band: the band this structure represents
+ * @n_channels: Number of channels in @channels
+ * @bitrates: Array of bitrates the hardware can operate with
+ * in this band. Must be sorted to give a valid "supported
+ * rates" IE, i.e. CCK rates first, then OFDM.
+ * @n_bitrates: Number of bitrates in @bitrates
+ * @ht_cap: HT capabilities in this band
+ */
+struct ieee80211_supported_band {
+ struct ieee80211_channel *channels;
+ struct ieee80211_rate *bitrates;
+ enum ieee80211_band band;
+ int n_channels;
+ int n_bitrates;
+ struct ieee80211_sta_ht_cap ht_cap;
+};
+
+/*
+ * Wireless hardware/device configuration structures and methods
+ */
+
+/**
+ * DOC: Actions and configuration
+ *
+ * Each wireless device and each virtual interface offer a set of configuration
+ * operations and other actions that are invoked by userspace. Each of these
+ * actions is described in the operations structure, and the parameters these
+ * operations use are described separately.
+ *
+ * Additionally, some operations are asynchronous and expect to get status
+ * information via some functions that drivers need to call.
+ *
+ * Scanning and BSS list handling with its associated functionality is described
+ * in a separate chapter.
+ */
+
+/**
+ * struct vif_params - describes virtual interface parameters
+ * @use_4addr: use 4-address frames
+ */
+struct vif_params {
+ int use_4addr;
+};
+
+/**
+ * struct key_params - key information
+ *
+ * Information about a key
+ *
+ * @key: key material
+ * @key_len: length of key material
+ * @cipher: cipher suite selector
+ * @seq: sequence counter (IV/PN) for TKIP and CCMP keys, only used
+ * with the get_key() callback, must be in little endian,
+ * length given by @seq_len.
+ * @seq_len: length of @seq.
+ */
+struct key_params {
+ u8 *key;
+ u8 *seq;
+ int key_len;
+ int seq_len;
+ u32 cipher;
+};
+
+/**
+ * enum survey_info_flags - survey information flags
+ *
+ * @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in
+ * @SURVEY_INFO_IN_USE: channel is currently being used
+ * @SURVEY_INFO_CHANNEL_TIME: channel active time (in ms) was filled in
+ * @SURVEY_INFO_CHANNEL_TIME_BUSY: channel busy time was filled in
+ * @SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: extension channel busy time was filled in
+ * @SURVEY_INFO_CHANNEL_TIME_RX: channel receive time was filled in
+ * @SURVEY_INFO_CHANNEL_TIME_TX: channel transmit time was filled in
+ *
+ * Used by the driver to indicate which info in &struct survey_info
+ * it has filled in during the get_survey().
+ */
+enum survey_info_flags {
+ SURVEY_INFO_NOISE_DBM = 1<<0,
+ SURVEY_INFO_IN_USE = 1<<1,
+ SURVEY_INFO_CHANNEL_TIME = 1<<2,
+ SURVEY_INFO_CHANNEL_TIME_BUSY = 1<<3,
+ SURVEY_INFO_CHANNEL_TIME_EXT_BUSY = 1<<4,
+ SURVEY_INFO_CHANNEL_TIME_RX = 1<<5,
+ SURVEY_INFO_CHANNEL_TIME_TX = 1<<6,
+};
+
+/**
+ * struct survey_info - channel survey response
+ *
+ * @channel: the channel this survey record reports, mandatory
+ * @filled: bitflag of flags from &enum survey_info_flags
+ * @noise: channel noise in dBm. This and all following fields are
+ * optional
+ * @channel_time: amount of time in ms the radio spent on the channel
+ * @channel_time_busy: amount of time the primary channel was sensed busy
+ * @channel_time_ext_busy: amount of time the extension channel was sensed busy
+ * @channel_time_rx: amount of time the radio spent receiving data
+ * @channel_time_tx: amount of time the radio spent transmitting data
+ *
+ * Used by dump_survey() to report back per-channel survey information.
+ *
+ * This structure can later be expanded with things like
+ * channel duty cycle etc.
+ */
+struct survey_info {
+ struct ieee80211_channel *channel;
+ u64 channel_time;
+ u64 channel_time_busy;
+ u64 channel_time_ext_busy;
+ u64 channel_time_rx;
+ u64 channel_time_tx;
+ u32 filled;
+ s8 noise;
+};
+
+/**
+ * struct cfg80211_crypto_settings - Crypto settings
+ * @wpa_versions: indicates which, if any, WPA versions are enabled
+ * (from enum nl80211_wpa_versions)
+ * @cipher_group: group key cipher suite (or 0 if unset)
+ * @n_ciphers_pairwise: number of AP supported unicast ciphers
+ * @ciphers_pairwise: unicast key cipher suites
+ * @n_akm_suites: number of AKM suites
+ * @akm_suites: AKM suites
+ * @control_port: Whether user space controls IEEE 802.1X port, i.e.,
+ * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is
+ * required to assume that the port is unauthorized until authorized by
+ * user space. Otherwise, port is marked authorized by default.
+ * @control_port_ethertype: the control port protocol that should be
+ * allowed through even on unauthorized ports
+ * @control_port_no_encrypt: TRUE to prevent encryption of control port
+ * protocol frames.
+ */
+struct cfg80211_crypto_settings {
+ u32 wpa_versions;
+ u32 cipher_group;
+ int n_ciphers_pairwise;
+ u32 ciphers_pairwise[NL80211_MAX_NR_CIPHER_SUITES];
+ int n_akm_suites;
+ u32 akm_suites[NL80211_MAX_NR_AKM_SUITES];
+ bool control_port;
+ __be16 control_port_ethertype;
+ bool control_port_no_encrypt;
+};
+
+/**
+ * struct cfg80211_beacon_data - beacon data
+ * @head: head portion of beacon (before TIM IE)
+ * or %NULL if not changed
+ * @tail: tail portion of beacon (after TIM IE)
+ * or %NULL if not changed
+ * @head_len: length of @head
+ * @tail_len: length of @tail
+ * @beacon_ies: extra information element(s) to add into Beacon frames or %NULL
+ * @beacon_ies_len: length of beacon_ies in octets
+ * @proberesp_ies: extra information element(s) to add into Probe Response
+ * frames or %NULL
+ * @proberesp_ies_len: length of proberesp_ies in octets
+ * @assocresp_ies: extra information element(s) to add into (Re)Association
+ * Response frames or %NULL
+ * @assocresp_ies_len: length of assocresp_ies in octets
+ * @probe_resp_len: length of probe response template (@probe_resp)
+ * @probe_resp: probe response template (AP mode only)
+ */
+struct cfg80211_beacon_data {
+ const u8 *head, *tail;
+ const u8 *beacon_ies;
+ const u8 *proberesp_ies;
+ const u8 *assocresp_ies;
+ const u8 *probe_resp;
+
+ size_t head_len, tail_len;
+ size_t beacon_ies_len;
+ size_t proberesp_ies_len;
+ size_t assocresp_ies_len;
+ size_t probe_resp_len;
+};
+
+/**
+ * struct cfg80211_ap_settings - AP configuration
+ *
+ * Used to configure an AP interface.
+ *
+ * @beacon: beacon data
+ * @beacon_interval: beacon interval
+ * @dtim_period: DTIM period
+ * @ssid: SSID to be used in the BSS (note: may be %NULL if not provided from
+ * user space)
+ * @ssid_len: length of @ssid
+ * @hidden_ssid: whether to hide the SSID in Beacon/Probe Response frames
+ * @crypto: crypto settings
+ * @privacy: the BSS uses privacy
+ * @auth_type: Authentication type (algorithm)
+ * @inactivity_timeout: time in seconds to determine station's inactivity.
+ */
+struct cfg80211_ap_settings {
+ struct cfg80211_beacon_data beacon;
+
+ int beacon_interval, dtim_period;
+ const u8 *ssid;
+ size_t ssid_len;
+ enum nl80211_hidden_ssid hidden_ssid;
+ struct cfg80211_crypto_settings crypto;
+ bool privacy;
+ enum nl80211_auth_type auth_type;
+ int inactivity_timeout;
+};
+
+/**
+ * enum plink_action - actions to perform in mesh peers
+ *
+ * @PLINK_ACTION_INVALID: action 0 is reserved
+ * @PLINK_ACTION_OPEN: start mesh peer link establishment
+ * @PLINK_ACTION_BLOCK: block traffic from this mesh peer
+ */
+enum plink_actions {
+ PLINK_ACTION_INVALID,
+ PLINK_ACTION_OPEN,
+ PLINK_ACTION_BLOCK,
+};
+
+/**
+ * enum station_parameters_apply_mask - station parameter values to apply
+ * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp)
+ *
+ * Not all station parameters have in-band "no change" signalling,
+ * for those that don't these flags will are used.
+ */
+enum station_parameters_apply_mask {
+ STATION_PARAM_APPLY_UAPSD = BIT(0),
+};
+
+/**
+ * struct station_parameters - station parameters
+ *
+ * Used to change and create a new station.
+ *
+ * @vlan: vlan interface station should belong to
+ * @supported_rates: supported rates in IEEE 802.11 format
+ * (or NULL for no change)
+ * @supported_rates_len: number of supported rates
+ * @sta_flags_mask: station flags that changed
+ * (bitmask of BIT(NL80211_STA_FLAG_...))
+ * @sta_flags_set: station flags values
+ * (bitmask of BIT(NL80211_STA_FLAG_...))
+ * @listen_interval: listen interval or -1 for no change
+ * @aid: AID or zero for no change
+ * @plink_action: plink action to take
+ * @plink_state: set the peer link state for a station
+ * @ht_capa: HT capabilities of station
+ * @uapsd_queues: bitmap of queues configured for uapsd. same format
+ * as the AC bitmap in the QoS info field
+ * @max_sp: max Service Period. same format as the MAX_SP in the
+ * QoS info field (but already shifted down)
+ * @sta_modify_mask: bitmap indicating which parameters changed
+ * (for those that don't have a natural "no change" value),
+ * see &enum station_parameters_apply_mask
+ */
+struct station_parameters {
+ u8 *supported_rates;
+ struct net_device *vlan;
+ u32 sta_flags_mask, sta_flags_set;
+ u32 sta_modify_mask;
+ int listen_interval;
+ u16 aid;
+ u8 supported_rates_len;
+ u8 plink_action;
+ u8 plink_state;
+ struct ieee80211_ht_cap *ht_capa;
+ u8 uapsd_queues;
+ u8 max_sp;
+};
+
+/**
+ * enum station_info_flags - station information flags
+ *
+ * Used by the driver to indicate which info in &struct station_info
+ * it has filled in during get_station() or dump_station().
+ *
+ * @STATION_INFO_INACTIVE_TIME: @inactive_time filled
+ * @STATION_INFO_RX_BYTES: @rx_bytes filled
+ * @STATION_INFO_TX_BYTES: @tx_bytes filled
+ * @STATION_INFO_LLID: @llid filled
+ * @STATION_INFO_PLID: @plid filled
+ * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_TX_BITRATE: @txrate fields are filled
+ * (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
+ * @STATION_INFO_RX_PACKETS: @rx_packets filled
+ * @STATION_INFO_TX_PACKETS: @tx_packets filled
+ * @STATION_INFO_TX_RETRIES: @tx_retries filled
+ * @STATION_INFO_TX_FAILED: @tx_failed filled
+ * @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled
+ * @STATION_INFO_SIGNAL_AVG: @signal_avg filled
+ * @STATION_INFO_RX_BITRATE: @rxrate fields are filled
+ * @STATION_INFO_BSS_PARAM: @bss_param filled
+ * @STATION_INFO_CONNECTED_TIME: @connected_time filled
+ * @STATION_INFO_ASSOC_REQ_IES: @assoc_req_ies filled
+ * @STATION_INFO_STA_FLAGS: @sta_flags filled
+ * @STATION_INFO_BEACON_LOSS_COUNT: @beacon_loss_count filled
+ */
+enum station_info_flags {
+ STATION_INFO_INACTIVE_TIME = 1<<0,
+ STATION_INFO_RX_BYTES = 1<<1,
+ STATION_INFO_TX_BYTES = 1<<2,
+ STATION_INFO_LLID = 1<<3,
+ STATION_INFO_PLID = 1<<4,
+ STATION_INFO_PLINK_STATE = 1<<5,
+ STATION_INFO_SIGNAL = 1<<6,
+ STATION_INFO_TX_BITRATE = 1<<7,
+ STATION_INFO_RX_PACKETS = 1<<8,
+ STATION_INFO_TX_PACKETS = 1<<9,
+ STATION_INFO_TX_RETRIES = 1<<10,
+ STATION_INFO_TX_FAILED = 1<<11,
+ STATION_INFO_RX_DROP_MISC = 1<<12,
+ STATION_INFO_SIGNAL_AVG = 1<<13,
+ STATION_INFO_RX_BITRATE = 1<<14,
+ STATION_INFO_BSS_PARAM = 1<<15,
+ STATION_INFO_CONNECTED_TIME = 1<<16,
+ STATION_INFO_ASSOC_REQ_IES = 1<<17,
+ STATION_INFO_STA_FLAGS = 1<<18,
+ STATION_INFO_BEACON_LOSS_COUNT = 1<<19
+};
+
+/**
+ * enum station_info_rate_flags - bitrate info flags
+ *
+ * Used by the driver to indicate the specific rate transmission
+ * type for 802.11n transmissions.
+ *
+ * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled
+ * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
+ */
+enum rate_info_flags {
+ RATE_INFO_FLAGS_MCS = 1<<0,
+ RATE_INFO_FLAGS_40_MHZ_WIDTH = 1<<1,
+ RATE_INFO_FLAGS_SHORT_GI = 1<<2,
+};
+
+/**
+ * struct rate_info - bitrate information
+ *
+ * Information about a receiving or transmitting bitrate
+ *
+ * @flags: bitflag of flags from &enum rate_info_flags
+ * @mcs: mcs index if struct describes a 802.11n bitrate
+ * @legacy: bitrate in 100kbit/s for 802.11abg
+ */
+struct rate_info {
+ u8 flags;
+ u8 mcs;
+ u16 legacy;
+};
+
+/**
+ * enum station_info_rate_flags - bitrate info flags
+ *
+ * Used by the driver to indicate the specific rate transmission
+ * type for 802.11n transmissions.
+ *
+ * @BSS_PARAM_FLAGS_CTS_PROT: whether CTS protection is enabled
+ * @BSS_PARAM_FLAGS_SHORT_PREAMBLE: whether short preamble is enabled
+ * @BSS_PARAM_FLAGS_SHORT_SLOT_TIME: whether short slot time is enabled
+ */
+enum bss_param_flags {
+ BSS_PARAM_FLAGS_CTS_PROT = 1<<0,
+ BSS_PARAM_FLAGS_SHORT_PREAMBLE = 1<<1,
+ BSS_PARAM_FLAGS_SHORT_SLOT_TIME = 1<<2,
+};
+
+/**
+ * struct sta_bss_parameters - BSS parameters for the attached station
+ *
+ * Information about the currently associated BSS
+ *
+ * @flags: bitflag of flags from &enum bss_param_flags
+ * @dtim_period: DTIM period for the BSS
+ * @beacon_interval: beacon interval
+ */
+struct sta_bss_parameters {
+ u8 flags;
+ u8 dtim_period;
+ u16 beacon_interval;
+};
+
+/**
+ * struct station_info - station information
+ *
+ * Station information filled by driver for get_station() and dump_station.
+ *
+ * @filled: bitflag of flags from &enum station_info_flags
+ * @connected_time: time(in secs) since a station is last connected
+ * @inactive_time: time since last station activity (tx/rx) in milliseconds
+ * @rx_bytes: bytes received from this station
+ * @tx_bytes: bytes transmitted to this station
+ * @llid: mesh local link id
+ * @plid: mesh peer link id
+ * @plink_state: mesh peer link state
+ * @signal: the signal strength, type depends on the wiphy's signal_type
+ NOTE: For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
+ * @signal_avg: avg signal strength, type depends on the wiphy's signal_type
+ NOTE: For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
+ * @txrate: current unicast bitrate from this station
+ * @rxrate: current unicast bitrate to this station
+ * @rx_packets: packets received from this station
+ * @tx_packets: packets transmitted to this station
+ * @tx_retries: cumulative retry counts
+ * @tx_failed: number of failed transmissions (retries exceeded, no ACK)
+ * @rx_dropped_misc: Dropped for un-specified reason.
+ * @bss_param: current BSS parameters
+ * @generation: generation number for nl80211 dumps.
+ * This number should increase every time the list of stations
+ * changes, i.e. when a station is added or removed, so that
+ * userspace can tell whether it got a consistent snapshot.
+ * @assoc_req_ies: IEs from (Re)Association Request.
+ * This is used only when in AP mode with drivers that do not use
+ * user space MLME/SME implementation. The information is provided for
+ * the cfg80211_new_sta() calls to notify user space of the IEs.
+ * @assoc_req_ies_len: Length of assoc_req_ies buffer in octets.
+ * @sta_flags: station flags mask & values
+ * @beacon_loss_count: Number of times beacon loss event has triggered.
+ */
+struct station_info {
+ u32 filled;
+ u32 connected_time;
+ u32 inactive_time;
+ u32 rx_bytes;
+ u32 tx_bytes;
+ u16 llid;
+ u16 plid;
+ u8 plink_state;
+ s8 signal;
+ s8 signal_avg;
+ struct rate_info txrate;
+ struct rate_info rxrate;
+ u32 rx_packets;
+ u32 tx_packets;
+ u32 tx_retries;
+ u32 tx_failed;
+ u32 rx_dropped_misc;
+ struct sta_bss_parameters bss_param;
+ struct nl80211_sta_flag_update sta_flags;
+
+ int generation;
+
+ const u8 *assoc_req_ies;
+ size_t assoc_req_ies_len;
+
+ u32 beacon_loss_count;
+
+ /*
+ * Note: Add a new enum station_info_flags value for each new field and
+ * use it to check which fields are initialized.
+ */
+};
+
+/**
+ * enum monitor_flags - monitor flags
+ *
+ * Monitor interface configuration flags. Note that these must be the bits
+ * according to the nl80211 flags.
+ *
+ * @MONITOR_FLAG_FCSFAIL: pass frames with bad FCS
+ * @MONITOR_FLAG_PLCPFAIL: pass frames with bad PLCP
+ * @MONITOR_FLAG_CONTROL: pass control frames
+ * @MONITOR_FLAG_OTHER_BSS: disable BSSID filtering
+ * @MONITOR_FLAG_COOK_FRAMES: report frames after processing
+ */
+enum monitor_flags {
+ MONITOR_FLAG_FCSFAIL = 1<<NL80211_MNTR_FLAG_FCSFAIL,
+ MONITOR_FLAG_PLCPFAIL = 1<<NL80211_MNTR_FLAG_PLCPFAIL,
+ MONITOR_FLAG_CONTROL = 1<<NL80211_MNTR_FLAG_CONTROL,
+ MONITOR_FLAG_OTHER_BSS = 1<<NL80211_MNTR_FLAG_OTHER_BSS,
+ MONITOR_FLAG_COOK_FRAMES = 1<<NL80211_MNTR_FLAG_COOK_FRAMES,
+};
+
+/**
+ * enum mpath_info_flags - mesh path information flags
+ *
+ * Used by the driver to indicate which info in &struct mpath_info it has filled
+ * in during get_station() or dump_station().
+ *
+ * @MPATH_INFO_FRAME_QLEN: @frame_qlen filled
+ * @MPATH_INFO_SN: @sn filled
+ * @MPATH_INFO_METRIC: @metric filled
+ * @MPATH_INFO_EXPTIME: @exptime filled
+ * @MPATH_INFO_DISCOVERY_TIMEOUT: @discovery_timeout filled
+ * @MPATH_INFO_DISCOVERY_RETRIES: @discovery_retries filled
+ * @MPATH_INFO_FLAGS: @flags filled
+ */
+enum mpath_info_flags {
+ MPATH_INFO_FRAME_QLEN = BIT(0),
+ MPATH_INFO_SN = BIT(1),
+ MPATH_INFO_METRIC = BIT(2),
+ MPATH_INFO_EXPTIME = BIT(3),
+ MPATH_INFO_DISCOVERY_TIMEOUT = BIT(4),
+ MPATH_INFO_DISCOVERY_RETRIES = BIT(5),
+ MPATH_INFO_FLAGS = BIT(6),
+};
+
+/**
+ * struct mpath_info - mesh path information
+ *
+ * Mesh path information filled by driver for get_mpath() and dump_mpath().
+ *
+ * @filled: bitfield of flags from &enum mpath_info_flags
+ * @frame_qlen: number of queued frames for this destination
+ * @sn: target sequence number
+ * @metric: metric (cost) of this mesh path
+ * @exptime: expiration time for the mesh path from now, in msecs
+ * @flags: mesh path flags
+ * @discovery_timeout: total mesh path discovery timeout, in msecs
+ * @discovery_retries: mesh path discovery retries
+ * @generation: generation number for nl80211 dumps.
+ * This number should increase every time the list of mesh paths
+ * changes, i.e. when a station is added or removed, so that
+ * userspace can tell whether it got a consistent snapshot.
+ */
+struct mpath_info {
+ u32 filled;
+ u32 frame_qlen;
+ u32 sn;
+ u32 metric;
+ u32 exptime;
+ u32 discovery_timeout;
+ u8 discovery_retries;
+ u8 flags;
+
+ int generation;
+};
+
+/**
+ * struct bss_parameters - BSS parameters
+ *
+ * Used to change BSS parameters (mainly for AP mode).
+ *
+ * @use_cts_prot: Whether to use CTS protection
+ * (0 = no, 1 = yes, -1 = do not change)
+ * @use_short_preamble: Whether the use of short preambles is allowed
+ * (0 = no, 1 = yes, -1 = do not change)
+ * @use_short_slot_time: Whether the use of short slot time is allowed
+ * (0 = no, 1 = yes, -1 = do not change)
+ * @basic_rates: basic rates in IEEE 802.11 format
+ * (or NULL for no change)
+ * @basic_rates_len: number of basic rates
+ * @ap_isolate: do not forward packets between connected stations
+ * @ht_opmode: HT Operation mode
+ * (u16 = opmode, -1 = do not change)
+ */
+struct bss_parameters {
+ int use_cts_prot;
+ int use_short_preamble;
+ int use_short_slot_time;
+ u8 *basic_rates;
+ u8 basic_rates_len;
+ int ap_isolate;
+ int ht_opmode;
+};
+
+/*
+ * struct mesh_config - 802.11s mesh configuration
+ *
+ * These parameters can be changed while the mesh is active.
+ */
+struct mesh_config {
+ /* Timeouts in ms */
+ /* Mesh plink management parameters */
+ u16 dot11MeshRetryTimeout;
+ u16 dot11MeshConfirmTimeout;
+ u16 dot11MeshHoldingTimeout;
+ u16 dot11MeshMaxPeerLinks;
+ u8 dot11MeshMaxRetries;
+ u8 dot11MeshTTL;
+ /* ttl used in path selection information elements */
+ u8 element_ttl;
+ bool auto_open_plinks;
+ /* HWMP parameters */
+ u8 dot11MeshHWMPmaxPREQretries;
+ u32 path_refresh_time;
+ u16 min_discovery_timeout;
+ u32 dot11MeshHWMPactivePathTimeout;
+ u16 dot11MeshHWMPpreqMinInterval;
+ u16 dot11MeshHWMPperrMinInterval;
+ u16 dot11MeshHWMPnetDiameterTraversalTime;
+ u8 dot11MeshHWMPRootMode;
+ u16 dot11MeshHWMPRannInterval;
+ /* This is missnamed in draft 12.0: dot11MeshGateAnnouncementProtocol
+ * set to true only means that the station will announce others it's a
+ * mesh gate, but not necessarily using the gate announcement protocol.
+ * Still keeping the same nomenclature to be in sync with the spec. */
+ bool dot11MeshGateAnnouncementProtocol;
+ bool dot11MeshForwarding;
+ s32 rssi_threshold;
+};
+
+/**
+ * struct mesh_setup - 802.11s mesh setup configuration
+ * @mesh_id: the mesh ID
+ * @mesh_id_len: length of the mesh ID, at least 1 and at most 32 bytes
+ * @path_sel_proto: which path selection protocol to use
+ * @path_metric: which metric to use
+ * @ie: vendor information elements (optional)
+ * @ie_len: length of vendor information elements
+ * @is_authenticated: this mesh requires authentication
+ * @is_secure: this mesh uses security
+ * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a]
+ *
+ * These parameters are fixed when the mesh is created.
+ */
+struct mesh_setup {
+ const u8 *mesh_id;
+ u8 mesh_id_len;
+ u8 path_sel_proto;
+ u8 path_metric;
+ const u8 *ie;
+ u8 ie_len;
+ bool is_authenticated;
+ bool is_secure;
+ int mcast_rate[IEEE80211_NUM_BANDS];
+};
+
+/**
+ * struct ieee80211_txq_params - TX queue parameters
+ * @queue: TX queue identifier (NL80211_TXQ_Q_*)
+ * @txop: Maximum burst time in units of 32 usecs, 0 meaning disabled
+ * @cwmin: Minimum contention window [a value of the form 2^n-1 in the range
+ * 1..32767]
+ * @cwmax: Maximum contention window [a value of the form 2^n-1 in the range
+ * 1..32767]
+ * @aifs: Arbitration interframe space [0..255]
+ */
+struct ieee80211_txq_params {
+ enum nl80211_txq_q queue;
+ u16 txop;
+ u16 cwmin;
+ u16 cwmax;
+ u8 aifs;
+};
+
+/* from net/wireless.h */
+struct wiphy;
+
+/**
+ * DOC: Scanning and BSS list handling
+ *
+ * The scanning process itself is fairly simple, but cfg80211 offers quite
+ * a bit of helper functionality. To start a scan, the scan operation will
+ * be invoked with a scan definition. This scan definition contains the
+ * channels to scan, and the SSIDs to send probe requests for (including the
+ * wildcard, if desired). A passive scan is indicated by having no SSIDs to
+ * probe. Additionally, a scan request may contain extra information elements
+ * that should be added to the probe request. The IEs are guaranteed to be
+ * well-formed, and will not exceed the maximum length the driver advertised
+ * in the wiphy structure.
+ *
+ * When scanning finds a BSS, cfg80211 needs to be notified of that, because
+ * it is responsible for maintaining the BSS list; the driver should not
+ * maintain a list itself. For this notification, various functions exist.
+ *
+ * Since drivers do not maintain a BSS list, there are also a number of
+ * functions to search for a BSS and obtain information about it from the
+ * BSS structure cfg80211 maintains. The BSS list is also made available
+ * to userspace.
+ */
+
+/**
+ * struct cfg80211_ssid - SSID description
+ * @ssid: the SSID
+ * @ssid_len: length of the ssid
+ */
+struct cfg80211_ssid {
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+ u8 ssid_len;
+};
+
+/**
+ * struct cfg80211_scan_request - scan request description
+ *
+ * @ssids: SSIDs to scan for (active scan only)
+ * @n_ssids: number of SSIDs
+ * @channels: channels to scan on.
+ * @n_channels: total number of channels to scan
+ * @ie: optional information element(s) to add into Probe Request or %NULL
+ * @ie_len: length of ie in octets
+ * @rates: bitmap of rates to advertise for each band
+ * @wiphy: the wiphy this was for
+ * @dev: the interface
+ * @aborted: (internal) scan request was notified as aborted
+ * @no_cck: used to send probe requests at non CCK rate in 2GHz band
+ */
+struct cfg80211_scan_request {
+ struct cfg80211_ssid *ssids;
+ int n_ssids;
+ u32 n_channels;
+ const u8 *ie;
+ size_t ie_len;
+
+ u32 rates[IEEE80211_NUM_BANDS];
+
+ /* internal */
+ struct wiphy *wiphy;
+ struct net_device *dev;
+ bool aborted;
+ bool no_cck;
+
+ /* keep last */
+ struct ieee80211_channel *channels[0];
+};
+
+/**
+ * struct cfg80211_match_set - sets of attributes to match
+ *
+ * @ssid: SSID to be matched
+ */
+struct cfg80211_match_set {
+ struct cfg80211_ssid ssid;
+};
+
+/**
+ * struct cfg80211_sched_scan_request - scheduled scan request description
+ *
+ * @ssids: SSIDs to scan for (passed in the probe_reqs in active scans)
+ * @n_ssids: number of SSIDs
+ * @n_channels: total number of channels to scan
+ * @interval: interval between each scheduled scan cycle
+ * @ie: optional information element(s) to add into Probe Request or %NULL
+ * @ie_len: length of ie in octets
+ * @match_sets: sets of parameters to be matched for a scan result
+ * entry to be considered valid and to be passed to the host
+ * (others are filtered out).
+ * If ommited, all results are passed.
+ * @n_match_sets: number of match sets
+ * @wiphy: the wiphy this was for
+ * @dev: the interface
+ * @channels: channels to scan
+ */
+struct cfg80211_sched_scan_request {
+ struct cfg80211_ssid *ssids;
+ int n_ssids;
+ u32 n_channels;
+ u32 interval;
+ const u8 *ie;
+ size_t ie_len;
+ struct cfg80211_match_set *match_sets;
+ int n_match_sets;
+
+ /* internal */
+ struct wiphy *wiphy;
+ struct net_device *dev;
+
+ /* keep last */
+ struct ieee80211_channel *channels[0];
+};
+
+/**
+ * enum cfg80211_signal_type - signal type
+ *
+ * @CFG80211_SIGNAL_TYPE_NONE: no signal strength information available
+ * @CFG80211_SIGNAL_TYPE_MBM: signal strength in mBm (100*dBm)
+ * @CFG80211_SIGNAL_TYPE_UNSPEC: signal strength, increasing from 0 through 100
+ */
+enum cfg80211_signal_type {
+ CFG80211_SIGNAL_TYPE_NONE,
+ CFG80211_SIGNAL_TYPE_MBM,
+ CFG80211_SIGNAL_TYPE_UNSPEC,
+};
+
+/**
+ * struct cfg80211_bss - BSS description
+ *
+ * This structure describes a BSS (which may also be a mesh network)
+ * for use in scan results and similar.
+ *
+ * @channel: channel this BSS is on
+ * @bssid: BSSID of the BSS
+ * @tsf: timestamp of last received update
+ * @beacon_interval: the beacon interval as from the frame
+ * @capability: the capability field in host byte order
+ * @information_elements: the information elements (Note that there
+ * is no guarantee that these are well-formed!); this is a pointer to
+ * either the beacon_ies or proberesp_ies depending on whether Probe
+ * Response frame has been received
+ * @len_information_elements: total length of the information elements
+ * @beacon_ies: the information elements from the last Beacon frame
+ * @len_beacon_ies: total length of the beacon_ies
+ * @proberesp_ies: the information elements from the last Probe Response frame
+ * @len_proberesp_ies: total length of the proberesp_ies
+ * @signal: signal strength value (type depends on the wiphy's signal_type)
+ * @free_priv: function pointer to free private data
+ * @priv: private area for driver use, has at least wiphy->bss_priv_size bytes
+ */
+struct cfg80211_bss {
+ struct ieee80211_channel *channel;
+
+ u8 bssid[ETH_ALEN];
+ u64 tsf;
+ u16 beacon_interval;
+ u16 capability;
+ u8 *information_elements;
+ size_t len_information_elements;
+ u8 *beacon_ies;
+ size_t len_beacon_ies;
+ u8 *proberesp_ies;
+ size_t len_proberesp_ies;
+
+ s32 signal;
+
+ void (*free_priv)(struct cfg80211_bss *bss);
+ u8 priv[0] __attribute__((__aligned__(sizeof(void *))));
+};
+
+/**
+ * ieee80211_bss_get_ie - find IE with given ID
+ * @bss: the bss to search
+ * @ie: the IE ID
+ * Returns %NULL if not found.
+ */
+const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
+
+
+/**
+ * struct cfg80211_auth_request - Authentication request data
+ *
+ * This structure provides information needed to complete IEEE 802.11
+ * authentication.
+ *
+ * @bss: The BSS to authenticate with.
+ * @auth_type: Authentication type (algorithm)
+ * @ie: Extra IEs to add to Authentication frame or %NULL
+ * @ie_len: Length of ie buffer in octets
+ * @key_len: length of WEP key for shared key authentication
+ * @key_idx: index of WEP key for shared key authentication
+ * @key: WEP key for shared key authentication
+ */
+struct cfg80211_auth_request {
+ struct cfg80211_bss *bss;
+ const u8 *ie;
+ size_t ie_len;
+ enum nl80211_auth_type auth_type;
+ const u8 *key;
+ u8 key_len, key_idx;
+};
+
+/**
+ * enum cfg80211_assoc_req_flags - Over-ride default behaviour in association.
+ *
+ * @ASSOC_REQ_DISABLE_HT: Disable HT (802.11n)
+ */
+enum cfg80211_assoc_req_flags {
+ ASSOC_REQ_DISABLE_HT = BIT(0),
+};
+
+/**
+ * struct cfg80211_assoc_request - (Re)Association request data
+ *
+ * This structure provides information needed to complete IEEE 802.11
+ * (re)association.
+ * @bss: The BSS to associate with. If the call is successful the driver
+ * is given a reference that it must release, normally via a call to
+ * cfg80211_send_rx_assoc(), or, if association timed out, with a
+ * call to cfg80211_put_bss() (in addition to calling
+ * cfg80211_send_assoc_timeout())
+ * @ie: Extra IEs to add to (Re)Association Request frame or %NULL
+ * @ie_len: Length of ie buffer in octets
+ * @use_mfp: Use management frame protection (IEEE 802.11w) in this association
+ * @crypto: crypto settings
+ * @prev_bssid: previous BSSID, if not %NULL use reassociate frame
+ * @flags: See &enum cfg80211_assoc_req_flags
+ * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask
+ * will be used in ht_capa. Un-supported values will be ignored.
+ * @ht_capa_mask: The bits of ht_capa which are to be used.
+ */
+struct cfg80211_assoc_request {
+ struct cfg80211_bss *bss;
+ const u8 *ie, *prev_bssid;
+ size_t ie_len;
+ struct cfg80211_crypto_settings crypto;
+ bool use_mfp;
+ u32 flags;
+ struct ieee80211_ht_cap ht_capa;
+ struct ieee80211_ht_cap ht_capa_mask;
+};
+
+/**
+ * struct cfg80211_deauth_request - Deauthentication request data
+ *
+ * This structure provides information needed to complete IEEE 802.11
+ * deauthentication.
+ *
+ * @bssid: the BSSID of the BSS to deauthenticate from
+ * @ie: Extra IEs to add to Deauthentication frame or %NULL
+ * @ie_len: Length of ie buffer in octets
+ * @reason_code: The reason code for the deauthentication
+ */
+struct cfg80211_deauth_request {
+ const u8 *bssid;
+ const u8 *ie;
+ size_t ie_len;
+ u16 reason_code;
+};
+
+/**
+ * struct cfg80211_disassoc_request - Disassociation request data
+ *
+ * This structure provides information needed to complete IEEE 802.11
+ * disassocation.
+ *
+ * @bss: the BSS to disassociate from
+ * @ie: Extra IEs to add to Disassociation frame or %NULL
+ * @ie_len: Length of ie buffer in octets
+ * @reason_code: The reason code for the disassociation
+ * @local_state_change: This is a request for a local state only, i.e., no
+ * Disassociation frame is to be transmitted.
+ */
+struct cfg80211_disassoc_request {
+ struct cfg80211_bss *bss;
+ const u8 *ie;
+ size_t ie_len;
+ u16 reason_code;
+ bool local_state_change;
+};
+
+/**
+ * struct cfg80211_ibss_params - IBSS parameters
+ *
+ * This structure defines the IBSS parameters for the join_ibss()
+ * method.
+ *
+ * @ssid: The SSID, will always be non-null.
+ * @ssid_len: The length of the SSID, will always be non-zero.
+ * @bssid: Fixed BSSID requested, maybe be %NULL, if set do not
+ * search for IBSSs with a different BSSID.
+ * @channel: The channel to use if no IBSS can be found to join.
+ * @channel_type: channel type (HT mode)
+ * @channel_fixed: The channel should be fixed -- do not search for
+ * IBSSs to join on other channels.
+ * @ie: information element(s) to include in the beacon
+ * @ie_len: length of that
+ * @beacon_interval: beacon interval to use
+ * @privacy: this is a protected network, keys will be configured
+ * after joining
+ * @control_port: whether user space controls IEEE 802.1X port, i.e.,
+ * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is
+ * required to assume that the port is unauthorized until authorized by
+ * user space. Otherwise, port is marked authorized by default.
+ * @basic_rates: bitmap of basic rates to use when creating the IBSS
+ * @mcast_rate: per-band multicast rate index + 1 (0: disabled)
+ */
+struct cfg80211_ibss_params {
+ u8 *ssid;
+ u8 *bssid;
+ struct ieee80211_channel *channel;
+ enum nl80211_channel_type channel_type;
+ u8 *ie;
+ u8 ssid_len, ie_len;
+ u16 beacon_interval;
+ u32 basic_rates;
+ bool channel_fixed;
+ bool privacy;
+ bool control_port;
+ int mcast_rate[IEEE80211_NUM_BANDS];
+};
+
+/**
+ * struct cfg80211_connect_params - Connection parameters
+ *
+ * This structure provides information needed to complete IEEE 802.11
+ * authentication and association.
+ *
+ * @channel: The channel to use or %NULL if not specified (auto-select based
+ * on scan results)
+ * @bssid: The AP BSSID or %NULL if not specified (auto-select based on scan
+ * results)
+ * @ssid: SSID
+ * @ssid_len: Length of ssid in octets
+ * @auth_type: Authentication type (algorithm)
+ * @ie: IEs for association request
+ * @ie_len: Length of assoc_ie in octets
+ * @privacy: indicates whether privacy-enabled APs should be used
+ * @crypto: crypto settings
+ * @key_len: length of WEP key for shared key authentication
+ * @key_idx: index of WEP key for shared key authentication
+ * @key: WEP key for shared key authentication
+ * @flags: See &enum cfg80211_assoc_req_flags
+ * @bg_scan_period: Background scan period in seconds
+ * or -1 to indicate that default value is to be used.
+ * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask
+ * will be used in ht_capa. Un-supported values will be ignored.
+ * @ht_capa_mask: The bits of ht_capa which are to be used.
+ */
+struct cfg80211_connect_params {
+ struct ieee80211_channel *channel;
+ u8 *bssid;
+ u8 *ssid;
+ size_t ssid_len;
+ enum nl80211_auth_type auth_type;
+ u8 *ie;
+ size_t ie_len;
+ bool privacy;
+ struct cfg80211_crypto_settings crypto;
+ const u8 *key;
+ u8 key_len, key_idx;
+ u32 flags;
+ int bg_scan_period;
+ struct ieee80211_ht_cap ht_capa;
+ struct ieee80211_ht_cap ht_capa_mask;
+};
+
+/**
+ * enum wiphy_params_flags - set_wiphy_params bitfield values
+ * @WIPHY_PARAM_RETRY_SHORT: wiphy->retry_short has changed
+ * @WIPHY_PARAM_RETRY_LONG: wiphy->retry_long has changed
+ * @WIPHY_PARAM_FRAG_THRESHOLD: wiphy->frag_threshold has changed
+ * @WIPHY_PARAM_RTS_THRESHOLD: wiphy->rts_threshold has changed
+ * @WIPHY_PARAM_COVERAGE_CLASS: coverage class changed
+ */
+enum wiphy_params_flags {
+ WIPHY_PARAM_RETRY_SHORT = 1 << 0,
+ WIPHY_PARAM_RETRY_LONG = 1 << 1,
+ WIPHY_PARAM_FRAG_THRESHOLD = 1 << 2,
+ WIPHY_PARAM_RTS_THRESHOLD = 1 << 3,
+ WIPHY_PARAM_COVERAGE_CLASS = 1 << 4,
+};
+
+/*
+ * cfg80211_bitrate_mask - masks for bitrate control
+ */
+struct cfg80211_bitrate_mask {
+ struct {
+ u32 legacy;
+ u8 mcs[IEEE80211_HT_MCS_MASK_LEN];
+ } control[IEEE80211_NUM_BANDS];
+};
+/**
+ * struct cfg80211_pmksa - PMK Security Association
+ *
+ * This structure is passed to the set/del_pmksa() method for PMKSA
+ * caching.
+ *
+ * @bssid: The AP's BSSID.
+ * @pmkid: The PMK material itself.
+ */
+struct cfg80211_pmksa {
+ u8 *bssid;
+ u8 *pmkid;
+};
+
+/**
+ * struct cfg80211_wowlan_trig_pkt_pattern - packet pattern
+ * @mask: bitmask where to match pattern and where to ignore bytes,
+ * one bit per byte, in same format as nl80211
+ * @pattern: bytes to match where bitmask is 1
+ * @pattern_len: length of pattern (in bytes)
+ *
+ * Internal note: @mask and @pattern are allocated in one chunk of
+ * memory, free @mask only!
+ */
+struct cfg80211_wowlan_trig_pkt_pattern {
+ u8 *mask, *pattern;
+ int pattern_len;
+};
+
+/**
+ * struct cfg80211_wowlan - Wake on Wireless-LAN support info
+ *
+ * This structure defines the enabled WoWLAN triggers for the device.
+ * @any: wake up on any activity -- special trigger if device continues
+ * operating as normal during suspend
+ * @disconnect: wake up if getting disconnected
+ * @magic_pkt: wake up on receiving magic packet
+ * @patterns: wake up on receiving packet matching a pattern
+ * @n_patterns: number of patterns
+ * @gtk_rekey_failure: wake up on GTK rekey failure
+ * @eap_identity_req: wake up on EAP identity request packet
+ * @four_way_handshake: wake up on 4-way handshake
+ * @rfkill_release: wake up when rfkill is released
+ */
+struct cfg80211_wowlan {
+ bool any, disconnect, magic_pkt, gtk_rekey_failure,
+ eap_identity_req, four_way_handshake,
+ rfkill_release;
+ struct cfg80211_wowlan_trig_pkt_pattern *patterns;
+ int n_patterns;
+};
+
+/**
+ * struct cfg80211_gtk_rekey_data - rekey data
+ * @kek: key encryption key
+ * @kck: key confirmation key
+ * @replay_ctr: replay counter
+ */
+struct cfg80211_gtk_rekey_data {
+ u8 kek[NL80211_KEK_LEN];
+ u8 kck[NL80211_KCK_LEN];
+ u8 replay_ctr[NL80211_REPLAY_CTR_LEN];
+};
+
+/**
+ * struct cfg80211_ops - backend description for wireless configuration
+ *
+ * This struct is registered by fullmac card drivers and/or wireless stacks
+ * in order to handle configuration requests on their interfaces.
+ *
+ * All callbacks except where otherwise noted should return 0
+ * on success or a negative error code.
+ *
+ * All operations are currently invoked under rtnl for consistency with the
+ * wireless extensions but this is subject to reevaluation as soon as this
+ * code is used more widely and we have a first user without wext.
+ *
+ * @suspend: wiphy device needs to be suspended. The variable @wow will
+ * be %NULL or contain the enabled Wake-on-Wireless triggers that are
+ * configured for the device.
+ * @resume: wiphy device needs to be resumed
+ *
+ * @add_virtual_intf: create a new virtual interface with the given name,
+ * must set the struct wireless_dev's iftype. Beware: You must create
+ * the new netdev in the wiphy's network namespace! Returns the netdev,
+ * or an ERR_PTR.
+ *
+ * @del_virtual_intf: remove the virtual interface determined by ifindex.
+ *
+ * @change_virtual_intf: change type/configuration of virtual interface,
+ * keep the struct wireless_dev's iftype updated.
+ *
+ * @add_key: add a key with the given parameters. @mac_addr will be %NULL
+ * when adding a group key.
+ *
+ * @get_key: get information about the key with the given parameters.
+ * @mac_addr will be %NULL when requesting information for a group
+ * key. All pointers given to the @callback function need not be valid
+ * after it returns. This function should return an error if it is
+ * not possible to retrieve the key, -ENOENT if it doesn't exist.
+ *
+ * @del_key: remove a key given the @mac_addr (%NULL for a group key)
+ * and @key_index, return -ENOENT if the key doesn't exist.
+ *
+ * @set_default_key: set the default key on an interface
+ *
+ * @set_default_mgmt_key: set the default management frame key on an interface
+ *
+ * @set_rekey_data: give the data necessary for GTK rekeying to the driver
+ *
+ * @start_ap: Start acting in AP mode defined by the parameters.
+ * @change_beacon: Change the beacon parameters for an access point mode
+ * interface. This should reject the call when AP mode wasn't started.
+ * @stop_ap: Stop being an AP, including stopping beaconing.
+ *
+ * @add_station: Add a new station.
+ * @del_station: Remove a station; @mac may be NULL to remove all stations.
+ * @change_station: Modify a given station. Note that flags changes are not much
+ * validated in cfg80211, in particular the auth/assoc/authorized flags
+ * might come to the driver in invalid combinations -- make sure to check
+ * them, also against the existing state! Also, supported_rates changes are
+ * not checked in station mode -- drivers need to reject (or ignore) them
+ * for anything but TDLS peers.
+ * @get_station: get station information for the station identified by @mac
+ * @dump_station: dump station callback -- resume dump at index @idx
+ *
+ * @add_mpath: add a fixed mesh path
+ * @del_mpath: delete a given mesh path
+ * @change_mpath: change a given mesh path
+ * @get_mpath: get a mesh path for the given parameters
+ * @dump_mpath: dump mesh path callback -- resume dump at index @idx
+ * @join_mesh: join the mesh network with the specified parameters
+ * @leave_mesh: leave the current mesh network
+ *
+ * @get_mesh_config: Get the current mesh configuration
+ *
+ * @update_mesh_config: Update mesh parameters on a running mesh.
+ * The mask is a bitfield which tells us which parameters to
+ * set, and which to leave alone.
+ *
+ * @change_bss: Modify parameters for a given BSS.
+ *
+ * @set_txq_params: Set TX queue parameters
+ *
+ * @set_channel: Set channel for a given wireless interface. Some devices
+ * may support multi-channel operation (by channel hopping) so cfg80211
+ * doesn't verify much. Note, however, that the passed netdev may be
+ * %NULL as well if the user requested changing the channel for the
+ * device itself, or for a monitor interface.
+ * @get_channel: Get the current operating channel, should return %NULL if
+ * there's no single defined operating channel if for example the
+ * device implements channel hopping for multi-channel virtual interfaces.
+ *
+ * @scan: Request to do a scan. If returning zero, the scan request is given
+ * the driver, and will be valid until passed to cfg80211_scan_done().
+ * For scan results, call cfg80211_inform_bss(); you can call this outside
+ * the scan/scan_done bracket too.
+ *
+ * @auth: Request to authenticate with the specified peer
+ * @assoc: Request to (re)associate with the specified peer
+ * @deauth: Request to deauthenticate from the specified peer
+ * @disassoc: Request to disassociate from the specified peer
+ *
+ * @connect: Connect to the ESS with the specified parameters. When connected,
+ * call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS.
+ * If the connection fails for some reason, call cfg80211_connect_result()
+ * with the status from the AP.
+ * @disconnect: Disconnect from the BSS/ESS.
+ *
+ * @join_ibss: Join the specified IBSS (or create if necessary). Once done, call
+ * cfg80211_ibss_joined(), also call that function when changing BSSID due
+ * to a merge.
+ * @leave_ibss: Leave the IBSS.
+ *
+ * @set_wiphy_params: Notify that wiphy parameters have changed;
+ * @changed bitfield (see &enum wiphy_params_flags) describes which values
+ * have changed. The actual parameter values are available in
+ * struct wiphy. If returning an error, no value should be changed.
+ *
+ * @set_tx_power: set the transmit power according to the parameters,
+ * the power passed is in mBm, to get dBm use MBM_TO_DBM().
+ * @get_tx_power: store the current TX power into the dbm variable;
+ * return 0 if successful
+ *
+ * @set_wds_peer: set the WDS peer for a WDS interface
+ *
+ * @rfkill_poll: polls the hw rfkill line, use cfg80211 reporting
+ * functions to adjust rfkill hw state
+ *
+ * @dump_survey: get site survey information.
+ *
+ * @remain_on_channel: Request the driver to remain awake on the specified
+ * channel for the specified duration to complete an off-channel
+ * operation (e.g., public action frame exchange). When the driver is
+ * ready on the requested channel, it must indicate this with an event
+ * notification by calling cfg80211_ready_on_channel().
+ * @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation.
+ * This allows the operation to be terminated prior to timeout based on
+ * the duration value.
+ * @mgmt_tx: Transmit a management frame.
+ * @mgmt_tx_cancel_wait: Cancel the wait time from transmitting a management
+ * frame on another channel
+ *
+ * @testmode_cmd: run a test mode command
+ * @testmode_dump: Implement a test mode dump. The cb->args[2] and up may be
+ * used by the function, but 0 and 1 must not be touched. Additionally,
+ * return error codes other than -ENOBUFS and -ENOENT will terminate the
+ * dump and return to userspace with an error, so be careful. If any data
+ * was passed in from userspace then the data/len arguments will be present
+ * and point to the data contained in %NL80211_ATTR_TESTDATA.
+ *
+ * @set_bitrate_mask: set the bitrate mask configuration
+ *
+ * @set_pmksa: Cache a PMKID for a BSSID. This is mostly useful for fullmac
+ * devices running firmwares capable of generating the (re) association
+ * RSN IE. It allows for faster roaming between WPA2 BSSIDs.
+ * @del_pmksa: Delete a cached PMKID.
+ * @flush_pmksa: Flush all cached PMKIDs.
+ * @set_power_mgmt: Configure WLAN power management. A timeout value of -1
+ * allows the driver to adjust the dynamic ps timeout value.
+ * @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold.
+ * @sched_scan_start: Tell the driver to start a scheduled scan.
+ * @sched_scan_stop: Tell the driver to stop an ongoing scheduled
+ * scan. The driver_initiated flag specifies whether the driver
+ * itself has informed that the scan has stopped.
+ *
+ * @mgmt_frame_register: Notify driver that a management frame type was
+ * registered. Note that this callback may not sleep, and cannot run
+ * concurrently with itself.
+ *
+ * @set_antenna: Set antenna configuration (tx_ant, rx_ant) on the device.
+ * Parameters are bitmaps of allowed antennas to use for TX/RX. Drivers may
+ * reject TX/RX mask combinations they cannot support by returning -EINVAL
+ * (also see nl80211.h @NL80211_ATTR_WIPHY_ANTENNA_TX).
+ *
+ * @get_antenna: Get current antenna configuration from device (tx_ant, rx_ant).
+ *
+ * @set_ringparam: Set tx and rx ring sizes.
+ *
+ * @get_ringparam: Get tx and rx ring current and maximum sizes.
+ *
+ * @tdls_mgmt: Transmit a TDLS management frame.
+ * @tdls_oper: Perform a high-level TDLS operation (e.g. TDLS link setup).
+ *
+ * @probe_client: probe an associated client, must return a cookie that it
+ * later passes to cfg80211_probe_status().
+ *
+ * @set_noack_map: Set the NoAck Map for the TIDs.
+ */
+struct cfg80211_ops {
+ int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
+ int (*resume)(struct wiphy *wiphy);
+
+ struct net_device * (*add_virtual_intf)(struct wiphy *wiphy,
+ char *name,
+ enum nl80211_iftype type,
+ u32 *flags,
+ struct vif_params *params);
+ int (*del_virtual_intf)(struct wiphy *wiphy, struct net_device *dev);
+ int (*change_virtual_intf)(struct wiphy *wiphy,
+ struct net_device *dev,
+ enum nl80211_iftype type, u32 *flags,
+ struct vif_params *params);
+
+ int (*add_key)(struct wiphy *wiphy, struct net_device *netdev,
+ u8 key_index, bool pairwise, const u8 *mac_addr,
+ struct key_params *params);
+ int (*get_key)(struct wiphy *wiphy, struct net_device *netdev,
+ u8 key_index, bool pairwise, const u8 *mac_addr,
+ void *cookie,
+ void (*callback)(void *cookie, struct key_params*));
+ int (*del_key)(struct wiphy *wiphy, struct net_device *netdev,
+ u8 key_index, bool pairwise, const u8 *mac_addr);
+ int (*set_default_key)(struct wiphy *wiphy,
+ struct net_device *netdev,
+ u8 key_index, bool unicast, bool multicast);
+ int (*set_default_mgmt_key)(struct wiphy *wiphy,
+ struct net_device *netdev,
+ u8 key_index);
+
+ int (*start_ap)(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_ap_settings *settings);
+ int (*change_beacon)(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_beacon_data *info);
+ int (*stop_ap)(struct wiphy *wiphy, struct net_device *dev);
+
+
+ int (*add_station)(struct wiphy *wiphy, struct net_device *dev,
+ u8 *mac, struct station_parameters *params);
+ int (*del_station)(struct wiphy *wiphy, struct net_device *dev,
+ u8 *mac);
+ int (*change_station)(struct wiphy *wiphy, struct net_device *dev,
+ u8 *mac, struct station_parameters *params);
+ int (*get_station)(struct wiphy *wiphy, struct net_device *dev,
+ u8 *mac, struct station_info *sinfo);
+ int (*dump_station)(struct wiphy *wiphy, struct net_device *dev,
+ int idx, u8 *mac, struct station_info *sinfo);
+
+ int (*add_mpath)(struct wiphy *wiphy, struct net_device *dev,
+ u8 *dst, u8 *next_hop);
+ int (*del_mpath)(struct wiphy *wiphy, struct net_device *dev,
+ u8 *dst);
+ int (*change_mpath)(struct wiphy *wiphy, struct net_device *dev,
+ u8 *dst, u8 *next_hop);
+ int (*get_mpath)(struct wiphy *wiphy, struct net_device *dev,
+ u8 *dst, u8 *next_hop,
+ struct mpath_info *pinfo);
+ int (*dump_mpath)(struct wiphy *wiphy, struct net_device *dev,
+ int idx, u8 *dst, u8 *next_hop,
+ struct mpath_info *pinfo);
+ int (*get_mesh_config)(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct mesh_config *conf);
+ int (*update_mesh_config)(struct wiphy *wiphy,
+ struct net_device *dev, u32 mask,
+ const struct mesh_config *nconf);
+ int (*join_mesh)(struct wiphy *wiphy, struct net_device *dev,
+ const struct mesh_config *conf,
+ const struct mesh_setup *setup);
+ int (*leave_mesh)(struct wiphy *wiphy, struct net_device *dev);
+
+ int (*change_bss)(struct wiphy *wiphy, struct net_device *dev,
+ struct bss_parameters *params);
+
+ int (*set_txq_params)(struct wiphy *wiphy, struct net_device *dev,
+ struct ieee80211_txq_params *params);
+
+ int (*set_channel)(struct wiphy *wiphy, struct net_device *dev,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type);
+
+ int (*scan)(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_scan_request *request);
+
+ int (*auth)(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_auth_request *req);
+ int (*assoc)(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_assoc_request *req);
+ int (*deauth)(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_deauth_request *req);
+ int (*disassoc)(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_disassoc_request *req);
+
+ int (*connect)(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_connect_params *sme);
+ int (*disconnect)(struct wiphy *wiphy, struct net_device *dev,
+ u16 reason_code);
+
+ int (*join_ibss)(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_ibss_params *params);
+ int (*leave_ibss)(struct wiphy *wiphy, struct net_device *dev);
+
+ int (*set_wiphy_params)(struct wiphy *wiphy, u32 changed);
+
+ int (*set_tx_power)(struct wiphy *wiphy,
+ enum nl80211_tx_power_setting type, int mbm);
+ int (*get_tx_power)(struct wiphy *wiphy, int *dbm);
+
+ int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *addr);
+
+ void (*rfkill_poll)(struct wiphy *wiphy);
+
+#ifdef CONFIG_NL80211_TESTMODE
+ int (*testmode_cmd)(struct wiphy *wiphy, void *data, int len);
+ int (*testmode_dump)(struct wiphy *wiphy, struct sk_buff *skb,
+ struct netlink_callback *cb,
+ void *data, int len);
+#endif
+
+ int (*set_bitrate_mask)(struct wiphy *wiphy,
+ struct net_device *dev,
+ const u8 *peer,
+ const struct cfg80211_bitrate_mask *mask);
+
+ int (*dump_survey)(struct wiphy *wiphy, struct net_device *netdev,
+ int idx, struct survey_info *info);
+
+ int (*set_pmksa)(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_pmksa *pmksa);
+ int (*del_pmksa)(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_pmksa *pmksa);
+ int (*flush_pmksa)(struct wiphy *wiphy, struct net_device *netdev);
+
+ int (*remain_on_channel)(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type,
+ unsigned int duration,
+ u64 *cookie);
+ int (*cancel_remain_on_channel)(struct wiphy *wiphy,
+ struct net_device *dev,
+ u64 cookie);
+
+ int (*mgmt_tx)(struct wiphy *wiphy, struct net_device *dev,
+ struct ieee80211_channel *chan, bool offchan,
+ enum nl80211_channel_type channel_type,
+ bool channel_type_valid, unsigned int wait,
+ const u8 *buf, size_t len, bool no_cck,
+ bool dont_wait_for_ack, u64 *cookie);
+ int (*mgmt_tx_cancel_wait)(struct wiphy *wiphy,
+ struct net_device *dev,
+ u64 cookie);
+
+ int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev,
+ bool enabled, int timeout);
+
+ int (*set_cqm_rssi_config)(struct wiphy *wiphy,
+ struct net_device *dev,
+ s32 rssi_thold, u32 rssi_hyst);
+
+ void (*mgmt_frame_register)(struct wiphy *wiphy,
+ struct net_device *dev,
+ u16 frame_type, bool reg);
+
+ int (*set_antenna)(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant);
+ int (*get_antenna)(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant);
+
+ int (*set_ringparam)(struct wiphy *wiphy, u32 tx, u32 rx);
+ void (*get_ringparam)(struct wiphy *wiphy,
+ u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
+
+ int (*sched_scan_start)(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct cfg80211_sched_scan_request *request);
+ int (*sched_scan_stop)(struct wiphy *wiphy, struct net_device *dev);
+
+ int (*set_rekey_data)(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_gtk_rekey_data *data);
+
+ int (*tdls_mgmt)(struct wiphy *wiphy, struct net_device *dev,
+ u8 *peer, u8 action_code, u8 dialog_token,
+ u16 status_code, const u8 *buf, size_t len);
+ int (*tdls_oper)(struct wiphy *wiphy, struct net_device *dev,
+ u8 *peer, enum nl80211_tdls_operation oper);
+
+ int (*probe_client)(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *peer, u64 *cookie);
+
+ int (*set_noack_map)(struct wiphy *wiphy,
+ struct net_device *dev,
+ u16 noack_map);
+
+ struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy);
+};
+
+/*
+ * wireless hardware and networking interfaces structures
+ * and registration/helper functions
+ */
+
+/**
+ * enum wiphy_flags - wiphy capability flags
+ *
+ * @WIPHY_FLAG_CUSTOM_REGULATORY: tells us the driver for this device
+ * has its own custom regulatory domain and cannot identify the
+ * ISO / IEC 3166 alpha2 it belongs to. When this is enabled
+ * we will disregard the first regulatory hint (when the
+ * initiator is %REGDOM_SET_BY_CORE).
+ * @WIPHY_FLAG_STRICT_REGULATORY: tells us the driver for this device will
+ * ignore regulatory domain settings until it gets its own regulatory
+ * domain via its regulatory_hint() unless the regulatory hint is
+ * from a country IE. After its gets its own regulatory domain it will
+ * only allow further regulatory domain settings to further enhance
+ * compliance. For example if channel 13 and 14 are disabled by this
+ * regulatory domain no user regulatory domain can enable these channels
+ * at a later time. This can be used for devices which do not have
+ * calibration information guaranteed for frequencies or settings
+ * outside of its regulatory domain. If used in combination with
+ * WIPHY_FLAG_CUSTOM_REGULATORY the inspected country IE power settings
+ * will be followed.
+ * @WIPHY_FLAG_DISABLE_BEACON_HINTS: enable this if your driver needs to ensure
+ * that passive scan flags and beaconing flags may not be lifted by
+ * cfg80211 due to regulatory beacon hints. For more information on beacon
+ * hints read the documenation for regulatory_hint_found_beacon()
+ * @WIPHY_FLAG_NETNS_OK: if not set, do not allow changing the netns of this
+ * wiphy at all
+ * @WIPHY_FLAG_ENFORCE_COMBINATIONS: Set this flag to enforce interface
+ * combinations for this device. This flag is used for backward
+ * compatibility only until all drivers advertise combinations and
+ * they will always be enforced.
+ * @WIPHY_FLAG_PS_ON_BY_DEFAULT: if set to true, powersave will be enabled
+ * by default -- this flag will be set depending on the kernel's default
+ * on wiphy_new(), but can be changed by the driver if it has a good
+ * reason to override the default
+ * @WIPHY_FLAG_4ADDR_AP: supports 4addr mode even on AP (with a single station
+ * on a VLAN interface)
+ * @WIPHY_FLAG_4ADDR_STATION: supports 4addr mode even as a station
+ * @WIPHY_FLAG_CONTROL_PORT_PROTOCOL: This device supports setting the
+ * control port protocol ethertype. The device also honours the
+ * control_port_no_encrypt flag.
+ * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN.
+ * @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing
+ * auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH.
+ * @WIPHY_FLAG_SUPPORTS_SCHED_SCAN: The device supports scheduled scans.
+ * @WIPHY_FLAG_SUPPORTS_FW_ROAM: The device supports roaming feature in the
+ * firmware.
+ * @WIPHY_FLAG_AP_UAPSD: The device supports uapsd on AP.
+ * @WIPHY_FLAG_SUPPORTS_TDLS: The device supports TDLS (802.11z) operation.
+ * @WIPHY_FLAG_TDLS_EXTERNAL_SETUP: The device does not handle TDLS (802.11z)
+ * link setup/discovery operations internally. Setup, discovery and
+ * teardown packets should be sent through the @NL80211_CMD_TDLS_MGMT
+ * command. When this flag is not set, @NL80211_CMD_TDLS_OPER should be
+ * used for asking the driver/firmware to perform a TDLS operation.
+ * @WIPHY_FLAG_HAVE_AP_SME: device integrates AP SME
+ * @WIPHY_FLAG_REPORTS_OBSS: the device will report beacons from other BSSes
+ * when there are virtual interfaces in AP mode by calling
+ * cfg80211_report_obss_beacon().
+ * @WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD: When operating as an AP, the device
+ * responds to probe-requests in hardware.
+ * @WIPHY_FLAG_OFFCHAN_TX: Device supports direct off-channel TX.
+ * @WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL: Device supports remain-on-channel call.
+ */
+enum wiphy_flags {
+ WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0),
+ WIPHY_FLAG_STRICT_REGULATORY = BIT(1),
+ WIPHY_FLAG_DISABLE_BEACON_HINTS = BIT(2),
+ WIPHY_FLAG_NETNS_OK = BIT(3),
+ WIPHY_FLAG_PS_ON_BY_DEFAULT = BIT(4),
+ WIPHY_FLAG_4ADDR_AP = BIT(5),
+ WIPHY_FLAG_4ADDR_STATION = BIT(6),
+ WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7),
+ WIPHY_FLAG_IBSS_RSN = BIT(8),
+ WIPHY_FLAG_MESH_AUTH = BIT(10),
+ WIPHY_FLAG_SUPPORTS_SCHED_SCAN = BIT(11),
+ WIPHY_FLAG_ENFORCE_COMBINATIONS = BIT(12),
+ WIPHY_FLAG_SUPPORTS_FW_ROAM = BIT(13),
+ WIPHY_FLAG_AP_UAPSD = BIT(14),
+ WIPHY_FLAG_SUPPORTS_TDLS = BIT(15),
+ WIPHY_FLAG_TDLS_EXTERNAL_SETUP = BIT(16),
+ WIPHY_FLAG_HAVE_AP_SME = BIT(17),
+ WIPHY_FLAG_REPORTS_OBSS = BIT(18),
+ WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD = BIT(19),
+ WIPHY_FLAG_OFFCHAN_TX = BIT(20),
+ WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL = BIT(21),
+};
+
+/**
+ * struct ieee80211_iface_limit - limit on certain interface types
+ * @max: maximum number of interfaces of these types
+ * @types: interface types (bits)
+ */
+struct ieee80211_iface_limit {
+ u16 max;
+ u16 types;
+};
+
+/**
+ * struct ieee80211_iface_combination - possible interface combination
+ * @limits: limits for the given interface types
+ * @n_limits: number of limitations
+ * @num_different_channels: can use up to this many different channels
+ * @max_interfaces: maximum number of interfaces in total allowed in this
+ * group
+ * @beacon_int_infra_match: In this combination, the beacon intervals
+ * between infrastructure and AP types must match. This is required
+ * only in special cases.
+ *
+ * These examples can be expressed as follows:
+ *
+ * Allow #STA <= 1, #AP <= 1, matching BI, channels = 1, 2 total:
+ *
+ * struct ieee80211_iface_limit limits1[] = {
+ * { .max = 1, .types = BIT(NL80211_IFTYPE_STATION), },
+ * { .max = 1, .types = BIT(NL80211_IFTYPE_AP}, },
+ * };
+ * struct ieee80211_iface_combination combination1 = {
+ * .limits = limits1,
+ * .n_limits = ARRAY_SIZE(limits1),
+ * .max_interfaces = 2,
+ * .beacon_int_infra_match = true,
+ * };
+ *
+ *
+ * Allow #{AP, P2P-GO} <= 8, channels = 1, 8 total:
+ *
+ * struct ieee80211_iface_limit limits2[] = {
+ * { .max = 8, .types = BIT(NL80211_IFTYPE_AP) |
+ * BIT(NL80211_IFTYPE_P2P_GO), },
+ * };
+ * struct ieee80211_iface_combination combination2 = {
+ * .limits = limits2,
+ * .n_limits = ARRAY_SIZE(limits2),
+ * .max_interfaces = 8,
+ * .num_different_channels = 1,
+ * };
+ *
+ *
+ * Allow #STA <= 1, #{P2P-client,P2P-GO} <= 3 on two channels, 4 total.
+ * This allows for an infrastructure connection and three P2P connections.
+ *
+ * struct ieee80211_iface_limit limits3[] = {
+ * { .max = 1, .types = BIT(NL80211_IFTYPE_STATION), },
+ * { .max = 3, .types = BIT(NL80211_IFTYPE_P2P_GO) |
+ * BIT(NL80211_IFTYPE_P2P_CLIENT), },
+ * };
+ * struct ieee80211_iface_combination combination3 = {
+ * .limits = limits3,
+ * .n_limits = ARRAY_SIZE(limits3),
+ * .max_interfaces = 4,
+ * .num_different_channels = 2,
+ * };
+ */
+struct ieee80211_iface_combination {
+ const struct ieee80211_iface_limit *limits;
+ u32 num_different_channels;
+ u16 max_interfaces;
+ u8 n_limits;
+ bool beacon_int_infra_match;
+};
+
+struct mac_address {
+ u8 addr[ETH_ALEN];
+};
+
+struct ieee80211_txrx_stypes {
+ u16 tx, rx;
+};
+
+/**
+ * enum wiphy_wowlan_support_flags - WoWLAN support flags
+ * @WIPHY_WOWLAN_ANY: supports wakeup for the special "any"
+ * trigger that keeps the device operating as-is and
+ * wakes up the host on any activity, for example a
+ * received packet that passed filtering; note that the
+ * packet should be preserved in that case
+ * @WIPHY_WOWLAN_MAGIC_PKT: supports wakeup on magic packet
+ * (see nl80211.h)
+ * @WIPHY_WOWLAN_DISCONNECT: supports wakeup on disconnect
+ * @WIPHY_WOWLAN_SUPPORTS_GTK_REKEY: supports GTK rekeying while asleep
+ * @WIPHY_WOWLAN_GTK_REKEY_FAILURE: supports wakeup on GTK rekey failure
+ * @WIPHY_WOWLAN_EAP_IDENTITY_REQ: supports wakeup on EAP identity request
+ * @WIPHY_WOWLAN_4WAY_HANDSHAKE: supports wakeup on 4-way handshake failure
+ * @WIPHY_WOWLAN_RFKILL_RELEASE: supports wakeup on RF-kill release
+ */
+enum wiphy_wowlan_support_flags {
+ WIPHY_WOWLAN_ANY = BIT(0),
+ WIPHY_WOWLAN_MAGIC_PKT = BIT(1),
+ WIPHY_WOWLAN_DISCONNECT = BIT(2),
+ WIPHY_WOWLAN_SUPPORTS_GTK_REKEY = BIT(3),
+ WIPHY_WOWLAN_GTK_REKEY_FAILURE = BIT(4),
+ WIPHY_WOWLAN_EAP_IDENTITY_REQ = BIT(5),
+ WIPHY_WOWLAN_4WAY_HANDSHAKE = BIT(6),
+ WIPHY_WOWLAN_RFKILL_RELEASE = BIT(7),
+};
+
+/**
+ * struct wiphy_wowlan_support - WoWLAN support data
+ * @flags: see &enum wiphy_wowlan_support_flags
+ * @n_patterns: number of supported wakeup patterns
+ * (see nl80211.h for the pattern definition)
+ * @pattern_max_len: maximum length of each pattern
+ * @pattern_min_len: minimum length of each pattern
+ */
+struct wiphy_wowlan_support {
+ u32 flags;
+ int n_patterns;
+ int pattern_max_len;
+ int pattern_min_len;
+};
+
+/**
+ * struct wiphy - wireless hardware description
+ * @reg_notifier: the driver's regulatory notification callback,
+ * note that if your driver uses wiphy_apply_custom_regulatory()
+ * the reg_notifier's request can be passed as NULL
+ * @regd: the driver's regulatory domain, if one was requested via
+ * the regulatory_hint() API. This can be used by the driver
+ * on the reg_notifier() if it chooses to ignore future
+ * regulatory domain changes caused by other drivers.
+ * @signal_type: signal type reported in &struct cfg80211_bss.
+ * @cipher_suites: supported cipher suites
+ * @n_cipher_suites: number of supported cipher suites
+ * @retry_short: Retry limit for short frames (dot11ShortRetryLimit)
+ * @retry_long: Retry limit for long frames (dot11LongRetryLimit)
+ * @frag_threshold: Fragmentation threshold (dot11FragmentationThreshold);
+ * -1 = fragmentation disabled, only odd values >= 256 used
+ * @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled
+ * @_net: the network namespace this wiphy currently lives in
+ * @perm_addr: permanent MAC address of this device
+ * @addr_mask: If the device supports multiple MAC addresses by masking,
+ * set this to a mask with variable bits set to 1, e.g. if the last
+ * four bits are variable then set it to 00:...:00:0f. The actual
+ * variable bits shall be determined by the interfaces added, with
+ * interfaces not matching the mask being rejected to be brought up.
+ * @n_addresses: number of addresses in @addresses.
+ * @addresses: If the device has more than one address, set this pointer
+ * to a list of addresses (6 bytes each). The first one will be used
+ * by default for perm_addr. In this case, the mask should be set to
+ * all-zeroes. In this case it is assumed that the device can handle
+ * the same number of arbitrary MAC addresses.
+ * @registered: protects ->resume and ->suspend sysfs callbacks against
+ * unregister hardware
+ * @debugfsdir: debugfs directory used for this wiphy, will be renamed
+ * automatically on wiphy renames
+ * @dev: (virtual) struct device for this wiphy
+ * @registered: helps synchronize suspend/resume with wiphy unregister
+ * @wext: wireless extension handlers
+ * @priv: driver private data (sized according to wiphy_new() parameter)
+ * @interface_modes: bitmask of interfaces types valid for this wiphy,
+ * must be set by driver
+ * @iface_combinations: Valid interface combinations array, should not
+ * list single interface types.
+ * @n_iface_combinations: number of entries in @iface_combinations array.
+ * @software_iftypes: bitmask of software interface types, these are not
+ * subject to any restrictions since they are purely managed in SW.
+ * @flags: wiphy flags, see &enum wiphy_flags
+ * @features: features advertised to nl80211, see &enum nl80211_feature_flags.
+ * @bss_priv_size: each BSS struct has private data allocated with it,
+ * this variable determines its size
+ * @max_scan_ssids: maximum number of SSIDs the device can scan for in
+ * any given scan
+ * @max_sched_scan_ssids: maximum number of SSIDs the device can scan
+ * for in any given scheduled scan
+ * @max_match_sets: maximum number of match sets the device can handle
+ * when performing a scheduled scan, 0 if filtering is not
+ * supported.
+ * @max_scan_ie_len: maximum length of user-controlled IEs device can
+ * add to probe request frames transmitted during a scan, must not
+ * include fixed IEs like supported rates
+ * @max_sched_scan_ie_len: same as max_scan_ie_len, but for scheduled
+ * scans
+ * @coverage_class: current coverage class
+ * @fw_version: firmware version for ethtool reporting
+ * @hw_version: hardware version for ethtool reporting
+ * @max_num_pmkids: maximum number of PMKIDs supported by device
+ * @privid: a pointer that drivers can use to identify if an arbitrary
+ * wiphy is theirs, e.g. in global notifiers
+ * @bands: information about bands/channels supported by this device
+ *
+ * @mgmt_stypes: bitmasks of frame subtypes that can be subscribed to or
+ * transmitted through nl80211, points to an array indexed by interface
+ * type
+ *
+ * @available_antennas_tx: bitmap of antennas which are available to be
+ * configured as TX antennas. Antenna configuration commands will be
+ * rejected unless this or @available_antennas_rx is set.
+ *
+ * @available_antennas_rx: bitmap of antennas which are available to be
+ * configured as RX antennas. Antenna configuration commands will be
+ * rejected unless this or @available_antennas_tx is set.
+ *
+ * @probe_resp_offload:
+ * Bitmap of supported protocols for probe response offloading.
+ * See &enum nl80211_probe_resp_offload_support_attr. Only valid
+ * when the wiphy flag @WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD is set.
+ *
+ * @max_remain_on_channel_duration: Maximum time a remain-on-channel operation
+ * may request, if implemented.
+ *
+ * @wowlan: WoWLAN support information
+ *
+ * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features.
+ * @ht_capa_mod_mask: Specify what ht_cap values can be over-ridden.
+ * If null, then none can be over-ridden.
+ */
+struct wiphy {
+ /* assign these fields before you register the wiphy */
+
+ /* permanent MAC address(es) */
+ u8 perm_addr[ETH_ALEN];
+ u8 addr_mask[ETH_ALEN];
+
+ struct mac_address *addresses;
+
+ const struct ieee80211_txrx_stypes *mgmt_stypes;
+
+ const struct ieee80211_iface_combination *iface_combinations;
+ int n_iface_combinations;
+ u16 software_iftypes;
+
+ u16 n_addresses;
+
+ /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */
+ u16 interface_modes;
+
+ u32 flags, features;
+
+ u32 ap_sme_capa;
+
+ enum cfg80211_signal_type signal_type;
+
+ int bss_priv_size;
+ u8 max_scan_ssids;
+ u8 max_sched_scan_ssids;
+ u8 max_match_sets;
+ u16 max_scan_ie_len;
+ u16 max_sched_scan_ie_len;
+
+ int n_cipher_suites;
+ const u32 *cipher_suites;
+
+ u8 retry_short;
+ u8 retry_long;
+ u32 frag_threshold;
+ u32 rts_threshold;
+ u8 coverage_class;
+
+ char fw_version[ETHTOOL_BUSINFO_LEN];
+ u32 hw_version;
+
+ struct wiphy_wowlan_support wowlan;
+
+ u16 max_remain_on_channel_duration;
+
+ u8 max_num_pmkids;
+
+ u32 available_antennas_tx;
+ u32 available_antennas_rx;
+
+ /*
+ * Bitmap of supported protocols for probe response offloading
+ * see &enum nl80211_probe_resp_offload_support_attr. Only valid
+ * when the wiphy flag @WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD is set.
+ */
+ u32 probe_resp_offload;
+
+ /* If multiple wiphys are registered and you're handed e.g.
+ * a regular netdev with assigned ieee80211_ptr, you won't
+ * know whether it points to a wiphy your driver has registered
+ * or not. Assign this to something global to your driver to
+ * help determine whether you own this wiphy or not. */
+ const void *privid;
+
+ struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS];
+
+ /* Lets us get back the wiphy on the callback */
+ int (*reg_notifier)(struct wiphy *wiphy,
+ struct regulatory_request *request);
+
+ /* fields below are read-only, assigned by cfg80211 */
+
+ const struct ieee80211_regdomain *regd;
+
+ /* the item in /sys/class/ieee80211/ points to this,
+ * you need use set_wiphy_dev() (see below) */
+ struct device dev;
+
+ /* protects ->resume, ->suspend sysfs callbacks against unregister hw */
+ bool registered;
+
+ /* dir in debugfs: ieee80211/<wiphyname> */
+ struct dentry *debugfsdir;
+
+ const struct ieee80211_ht_cap *ht_capa_mod_mask;
+
+#ifdef CONFIG_NET_NS
+ /* the network namespace this phy lives in currently */
+ struct net *_net;
+#endif
+
+#ifdef CONFIG_CFG80211_WEXT
+ const struct iw_handler_def *wext;
+#endif
+
+ char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
+};
+
+static inline struct net *wiphy_net(struct wiphy *wiphy)
+{
+ return read_pnet(&wiphy->_net);
+}
+
+static inline void wiphy_net_set(struct wiphy *wiphy, struct net *net)
+{
+ write_pnet(&wiphy->_net, net);
+}
+
+/**
+ * wiphy_priv - return priv from wiphy
+ *
+ * @wiphy: the wiphy whose priv pointer to return
+ */
+static inline void *wiphy_priv(struct wiphy *wiphy)
+{
+ BUG_ON(!wiphy);
+ return &wiphy->priv;
+}
+
+/**
+ * priv_to_wiphy - return the wiphy containing the priv
+ *
+ * @priv: a pointer previously returned by wiphy_priv
+ */
+static inline struct wiphy *priv_to_wiphy(void *priv)
+{
+ BUG_ON(!priv);
+ return container_of(priv, struct wiphy, priv);
+}
+
+/**
+ * set_wiphy_dev - set device pointer for wiphy
+ *
+ * @wiphy: The wiphy whose device to bind
+ * @dev: The device to parent it to
+ */
+static inline void set_wiphy_dev(struct wiphy *wiphy, struct device *dev)
+{
+ wiphy->dev.parent = dev;
+}
+
+/**
+ * wiphy_dev - get wiphy dev pointer
+ *
+ * @wiphy: The wiphy whose device struct to look up
+ */
+static inline struct device *wiphy_dev(struct wiphy *wiphy)
+{
+ return wiphy->dev.parent;
+}
+
+/**
+ * wiphy_name - get wiphy name
+ *
+ * @wiphy: The wiphy whose name to return
+ */
+static inline const char *wiphy_name(const struct wiphy *wiphy)
+{
+ return dev_name(&wiphy->dev);
+}
+
+/**
+ * wiphy_new - create a new wiphy for use with cfg80211
+ *
+ * @ops: The configuration operations for this device
+ * @sizeof_priv: The size of the private area to allocate
+ *
+ * Create a new wiphy and associate the given operations with it.
+ * @sizeof_priv bytes are allocated for private use.
+ *
+ * The returned pointer must be assigned to each netdev's
+ * ieee80211_ptr for proper operation.
+ */
+struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv);
+
+/**
+ * wiphy_register - register a wiphy with cfg80211
+ *
+ * @wiphy: The wiphy to register.
+ *
+ * Returns a non-negative wiphy index or a negative error code.
+ */
+extern int wiphy_register(struct wiphy *wiphy);
+
+/**
+ * wiphy_unregister - deregister a wiphy from cfg80211
+ *
+ * @wiphy: The wiphy to unregister.
+ *
+ * After this call, no more requests can be made with this priv
+ * pointer, but the call may sleep to wait for an outstanding
+ * request that is being handled.
+ */
+extern void wiphy_unregister(struct wiphy *wiphy);
+
+/**
+ * wiphy_free - free wiphy
+ *
+ * @wiphy: The wiphy to free
+ */
+extern void wiphy_free(struct wiphy *wiphy);
+
+/* internal structs */
+struct cfg80211_conn;
+struct cfg80211_internal_bss;
+struct cfg80211_cached_keys;
+
+/**
+ * struct wireless_dev - wireless per-netdev state
+ *
+ * This structure must be allocated by the driver/stack
+ * that uses the ieee80211_ptr field in struct net_device
+ * (this is intentional so it can be allocated along with
+ * the netdev.)
+ *
+ * @wiphy: pointer to hardware description
+ * @iftype: interface type
+ * @list: (private) Used to collect the interfaces
+ * @netdev: (private) Used to reference back to the netdev
+ * @current_bss: (private) Used by the internal configuration code
+ * @channel: (private) Used by the internal configuration code to track
+ * user-set AP, monitor and WDS channels for wireless extensions
+ * @bssid: (private) Used by the internal configuration code
+ * @ssid: (private) Used by the internal configuration code
+ * @ssid_len: (private) Used by the internal configuration code
+ * @mesh_id_len: (private) Used by the internal configuration code
+ * @mesh_id_up_len: (private) Used by the internal configuration code
+ * @wext: (private) Used by the internal wireless extensions compat code
+ * @use_4addr: indicates 4addr mode is used on this interface, must be
+ * set by driver (if supported) on add_interface BEFORE registering the
+ * netdev and may otherwise be used by driver read-only, will be update
+ * by cfg80211 on change_interface
+ * @mgmt_registrations: list of registrations for management frames
+ * @mgmt_registrations_lock: lock for the list
+ * @mtx: mutex used to lock data in this struct
+ * @cleanup_work: work struct used for cleanup that can't be done directly
+ * @beacon_interval: beacon interval used on this device for transmitting
+ * beacons, 0 when not valid
+ */
+struct wireless_dev {
+ struct wiphy *wiphy;
+ enum nl80211_iftype iftype;
+
+ /* the remainder of this struct should be private to cfg80211 */
+ struct list_head list;
+ struct net_device *netdev;
+
+ struct list_head mgmt_registrations;
+ spinlock_t mgmt_registrations_lock;
+
+ struct mutex mtx;
+
+ struct work_struct cleanup_work;
+
+ bool use_4addr;
+
+ /* currently used for IBSS and SME - might be rearranged later */
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+ u8 ssid_len, mesh_id_len, mesh_id_up_len;
+ enum {
+ CFG80211_SME_IDLE,
+ CFG80211_SME_CONNECTING,
+ CFG80211_SME_CONNECTED,
+ } sme_state;
+ struct cfg80211_conn *conn;
+ struct cfg80211_cached_keys *connect_keys;
+
+ struct list_head event_list;
+ spinlock_t event_lock;
+
+ struct cfg80211_internal_bss *current_bss; /* associated / joined */
+ struct ieee80211_channel *channel;
+
+ bool ps;
+ int ps_timeout;
+
+ int beacon_interval;
+
+ u32 ap_unexpected_nlpid;
+
+#ifdef CONFIG_CFG80211_WEXT
+ /* wext data */
+ struct {
+ struct cfg80211_ibss_params ibss;
+ struct cfg80211_connect_params connect;
+ struct cfg80211_cached_keys *keys;
+ u8 *ie;
+ size_t ie_len;
+ u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+ s8 default_key, default_mgmt_key;
+ bool prev_bssid_valid;
+ } wext;
+#endif
+};
+
+/**
+ * wdev_priv - return wiphy priv from wireless_dev
+ *
+ * @wdev: The wireless device whose wiphy's priv pointer to return
+ */
+static inline void *wdev_priv(struct wireless_dev *wdev)
+{
+ BUG_ON(!wdev);
+ return wiphy_priv(wdev->wiphy);
+}
+
+/**
+ * DOC: Utility functions
+ *
+ * cfg80211 offers a number of utility functions that can be useful.
+ */
+
+/**
+ * ieee80211_channel_to_frequency - convert channel number to frequency
+ * @chan: channel number
+ * @band: band, necessary due to channel number overlap
+ */
+extern int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band);
+
+/**
+ * ieee80211_frequency_to_channel - convert frequency to channel number
+ * @freq: center frequency
+ */
+extern int ieee80211_frequency_to_channel(int freq);
+
+/*
+ * Name indirection necessary because the ieee80211 code also has
+ * a function named "ieee80211_get_channel", so if you include
+ * cfg80211's header file you get cfg80211's version, if you try
+ * to include both header files you'll (rightfully!) get a symbol
+ * clash.
+ */
+extern struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy,
+ int freq);
+/**
+ * ieee80211_get_channel - get channel struct from wiphy for specified frequency
+ * @wiphy: the struct wiphy to get the channel for
+ * @freq: the center frequency of the channel
+ */
+static inline struct ieee80211_channel *
+ieee80211_get_channel(struct wiphy *wiphy, int freq)
+{
+ return __ieee80211_get_channel(wiphy, freq);
+}
+
+/**
+ * ieee80211_get_response_rate - get basic rate for a given rate
+ *
+ * @sband: the band to look for rates in
+ * @basic_rates: bitmap of basic rates
+ * @bitrate: the bitrate for which to find the basic rate
+ *
+ * This function returns the basic rate corresponding to a given
+ * bitrate, that is the next lower bitrate contained in the basic
+ * rate map, which is, for this function, given as a bitmap of
+ * indices of rates in the band's bitrate table.
+ */
+struct ieee80211_rate *
+ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
+ u32 basic_rates, int bitrate);
+
+/*
+ * Radiotap parsing functions -- for controlled injection support
+ *
+ * Implemented in net/wireless/radiotap.c
+ * Documentation in Documentation/networking/radiotap-headers.txt
+ */
+
+struct radiotap_align_size {
+ uint8_t align:4, size:4;
+};
+
+struct ieee80211_radiotap_namespace {
+ const struct radiotap_align_size *align_size;
+ int n_bits;
+ uint32_t oui;
+ uint8_t subns;
+};
+
+struct ieee80211_radiotap_vendor_namespaces {
+ const struct ieee80211_radiotap_namespace *ns;
+ int n_ns;
+};
+
+/**
+ * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args
+ * @this_arg_index: index of current arg, valid after each successful call
+ * to ieee80211_radiotap_iterator_next()
+ * @this_arg: pointer to current radiotap arg; it is valid after each
+ * call to ieee80211_radiotap_iterator_next() but also after
+ * ieee80211_radiotap_iterator_init() where it will point to
+ * the beginning of the actual data portion
+ * @this_arg_size: length of the current arg, for convenience
+ * @current_namespace: pointer to the current namespace definition
+ * (or internally %NULL if the current namespace is unknown)
+ * @is_radiotap_ns: indicates whether the current namespace is the default
+ * radiotap namespace or not
+ *
+ * @_rtheader: pointer to the radiotap header we are walking through
+ * @_max_length: length of radiotap header in cpu byte ordering
+ * @_arg_index: next argument index
+ * @_arg: next argument pointer
+ * @_next_bitmap: internal pointer to next present u32
+ * @_bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present
+ * @_vns: vendor namespace definitions
+ * @_next_ns_data: beginning of the next namespace's data
+ * @_reset_on_ext: internal; reset the arg index to 0 when going to the
+ * next bitmap word
+ *
+ * Describes the radiotap parser state. Fields prefixed with an underscore
+ * must not be used by users of the parser, only by the parser internally.
+ */
+
+struct ieee80211_radiotap_iterator {
+ struct ieee80211_radiotap_header *_rtheader;
+ const struct ieee80211_radiotap_vendor_namespaces *_vns;
+ const struct ieee80211_radiotap_namespace *current_namespace;
+
+ unsigned char *_arg, *_next_ns_data;
+ __le32 *_next_bitmap;
+
+ unsigned char *this_arg;
+ int this_arg_index;
+ int this_arg_size;
+
+ int is_radiotap_ns;
+
+ int _max_length;
+ int _arg_index;
+ uint32_t _bitmap_shifter;
+ int _reset_on_ext;
+};
+
+extern int ieee80211_radiotap_iterator_init(
+ struct ieee80211_radiotap_iterator *iterator,
+ struct ieee80211_radiotap_header *radiotap_header,
+ int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns);
+
+extern int ieee80211_radiotap_iterator_next(
+ struct ieee80211_radiotap_iterator *iterator);
+
+
+extern const unsigned char rfc1042_header[6];
+extern const unsigned char bridge_tunnel_header[6];
+
+/**
+ * ieee80211_get_hdrlen_from_skb - get header length from data
+ *
+ * Given an skb with a raw 802.11 header at the data pointer this function
+ * returns the 802.11 header length in bytes (not including encryption
+ * headers). If the data in the sk_buff is too short to contain a valid 802.11
+ * header the function returns 0.
+ *
+ * @skb: the frame
+ */
+unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);
+
+/**
+ * ieee80211_hdrlen - get header length in bytes from frame control
+ * @fc: frame control field in little-endian format
+ */
+unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc);
+
+/**
+ * DOC: Data path helpers
+ *
+ * In addition to generic utilities, cfg80211 also offers
+ * functions that help implement the data path for devices
+ * that do not do the 802.11/802.3 conversion on the device.
+ */
+
+/**
+ * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3
+ * @skb: the 802.11 data frame
+ * @addr: the device MAC address
+ * @iftype: the virtual interface type
+ */
+int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
+ enum nl80211_iftype iftype);
+
+/**
+ * ieee80211_data_from_8023 - convert an 802.3 frame to 802.11
+ * @skb: the 802.3 frame
+ * @addr: the device MAC address
+ * @iftype: the virtual interface type
+ * @bssid: the network bssid (used only for iftype STATION and ADHOC)
+ * @qos: build 802.11 QoS data frame
+ */
+int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
+ enum nl80211_iftype iftype, u8 *bssid, bool qos);
+
+/**
+ * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame
+ *
+ * Decode an IEEE 802.11n A-MSDU frame and convert it to a list of
+ * 802.3 frames. The @list will be empty if the decode fails. The
+ * @skb is consumed after the function returns.
+ *
+ * @skb: The input IEEE 802.11n A-MSDU frame.
+ * @list: The output list of 802.3 frames. It must be allocated and
+ * initialized by by the caller.
+ * @addr: The device MAC address.
+ * @iftype: The device interface type.
+ * @extra_headroom: The hardware extra headroom for SKBs in the @list.
+ * @has_80211_header: Set it true if SKB is with IEEE 802.11 header.
+ */
+void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
+ const u8 *addr, enum nl80211_iftype iftype,
+ const unsigned int extra_headroom,
+ bool has_80211_header);
+
+/**
+ * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame
+ * @skb: the data frame
+ */
+unsigned int cfg80211_classify8021d(struct sk_buff *skb);
+
+/**
+ * cfg80211_find_ie - find information element in data
+ *
+ * @eid: element ID
+ * @ies: data consisting of IEs
+ * @len: length of data
+ *
+ * This function will return %NULL if the element ID could
+ * not be found or if the element is invalid (claims to be
+ * longer than the given data), or a pointer to the first byte
+ * of the requested element, that is the byte containing the
+ * element ID. There are no checks on the element length
+ * other than having to fit into the given data.
+ */
+const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len);
+
+/**
+ * cfg80211_find_vendor_ie - find vendor specific information element in data
+ *
+ * @oui: vendor OUI
+ * @oui_type: vendor-specific OUI type
+ * @ies: data consisting of IEs
+ * @len: length of data
+ *
+ * This function will return %NULL if the vendor specific element ID
+ * could not be found or if the element is invalid (claims to be
+ * longer than the given data), or a pointer to the first byte
+ * of the requested element, that is the byte containing the
+ * element ID. There are no checks on the element length
+ * other than having to fit into the given data.
+ */
+const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type,
+ const u8 *ies, int len);
+
+/**
+ * DOC: Regulatory enforcement infrastructure
+ *
+ * TODO
+ */
+
+/**
+ * regulatory_hint - driver hint to the wireless core a regulatory domain
+ * @wiphy: the wireless device giving the hint (used only for reporting
+ * conflicts)
+ * @alpha2: the ISO/IEC 3166 alpha2 the driver claims its regulatory domain
+ * should be in. If @rd is set this should be NULL. Note that if you
+ * set this to NULL you should still set rd->alpha2 to some accepted
+ * alpha2.
+ *
+ * Wireless drivers can use this function to hint to the wireless core
+ * what it believes should be the current regulatory domain by
+ * giving it an ISO/IEC 3166 alpha2 country code it knows its regulatory
+ * domain should be in or by providing a completely build regulatory domain.
+ * If the driver provides an ISO/IEC 3166 alpha2 userspace will be queried
+ * for a regulatory domain structure for the respective country.
+ *
+ * The wiphy must have been registered to cfg80211 prior to this call.
+ * For cfg80211 drivers this means you must first use wiphy_register(),
+ * for mac80211 drivers you must first use ieee80211_register_hw().
+ *
+ * Drivers should check the return value, its possible you can get
+ * an -ENOMEM.
+ */
+extern int regulatory_hint(struct wiphy *wiphy, const char *alpha2);
+
+/**
+ * wiphy_apply_custom_regulatory - apply a custom driver regulatory domain
+ * @wiphy: the wireless device we want to process the regulatory domain on
+ * @regd: the custom regulatory domain to use for this wiphy
+ *
+ * Drivers can sometimes have custom regulatory domains which do not apply
+ * to a specific country. Drivers can use this to apply such custom regulatory
+ * domains. This routine must be called prior to wiphy registration. The
+ * custom regulatory domain will be trusted completely and as such previous
+ * default channel settings will be disregarded. If no rule is found for a
+ * channel on the regulatory domain the channel will be disabled.
+ */
+extern void wiphy_apply_custom_regulatory(
+ struct wiphy *wiphy,
+ const struct ieee80211_regdomain *regd);
+
+/**
+ * freq_reg_info - get regulatory information for the given frequency
+ * @wiphy: the wiphy for which we want to process this rule for
+ * @center_freq: Frequency in KHz for which we want regulatory information for
+ * @desired_bw_khz: the desired max bandwidth you want to use per
+ * channel. Note that this is still 20 MHz if you want to use HT40
+ * as HT40 makes use of two channels for its 40 MHz width bandwidth.
+ * If set to 0 we'll assume you want the standard 20 MHz.
+ * @reg_rule: the regulatory rule which we have for this frequency
+ *
+ * Use this function to get the regulatory rule for a specific frequency on
+ * a given wireless device. If the device has a specific regulatory domain
+ * it wants to follow we respect that unless a country IE has been received
+ * and processed already.
+ *
+ * Returns 0 if it was able to find a valid regulatory rule which does
+ * apply to the given center_freq otherwise it returns non-zero. It will
+ * also return -ERANGE if we determine the given center_freq does not even have
+ * a regulatory rule for a frequency range in the center_freq's band. See
+ * freq_in_rule_band() for our current definition of a band -- this is purely
+ * subjective and right now its 802.11 specific.
+ */
+extern int freq_reg_info(struct wiphy *wiphy,
+ u32 center_freq,
+ u32 desired_bw_khz,
+ const struct ieee80211_reg_rule **reg_rule);
+
+/*
+ * callbacks for asynchronous cfg80211 methods, notification
+ * functions and BSS handling helpers
+ */
+
+/**
+ * cfg80211_scan_done - notify that scan finished
+ *
+ * @request: the corresponding scan request
+ * @aborted: set to true if the scan was aborted for any reason,
+ * userspace will be notified of that
+ */
+void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted);
+
+/**
+ * cfg80211_sched_scan_results - notify that new scan results are available
+ *
+ * @wiphy: the wiphy which got scheduled scan results
+ */
+void cfg80211_sched_scan_results(struct wiphy *wiphy);
+
+/**
+ * cfg80211_sched_scan_stopped - notify that the scheduled scan has stopped
+ *
+ * @wiphy: the wiphy on which the scheduled scan stopped
+ *
+ * The driver can call this function to inform cfg80211 that the
+ * scheduled scan had to be stopped, for whatever reason. The driver
+ * is then called back via the sched_scan_stop operation when done.
+ */
+void cfg80211_sched_scan_stopped(struct wiphy *wiphy);
+
+/**
+ * cfg80211_inform_bss_frame - inform cfg80211 of a received BSS frame
+ *
+ * @wiphy: the wiphy reporting the BSS
+ * @channel: The channel the frame was received on
+ * @mgmt: the management frame (probe response or beacon)
+ * @len: length of the management frame
+ * @signal: the signal strength, type depends on the wiphy's signal_type
+ * @gfp: context flags
+ *
+ * This informs cfg80211 that BSS information was found and
+ * the BSS should be updated/added.
+ *
+ * NOTE: Returns a referenced struct, must be released with cfg80211_put_bss()!
+ */
+struct cfg80211_bss * __must_check
+cfg80211_inform_bss_frame(struct wiphy *wiphy,
+ struct ieee80211_channel *channel,
+ struct ieee80211_mgmt *mgmt, size_t len,
+ s32 signal, gfp_t gfp);
+
+/**
+ * cfg80211_inform_bss - inform cfg80211 of a new BSS
+ *
+ * @wiphy: the wiphy reporting the BSS
+ * @channel: The channel the frame was received on
+ * @bssid: the BSSID of the BSS
+ * @tsf: the TSF sent by the peer in the beacon/probe response (or 0)
+ * @capability: the capability field sent by the peer
+ * @beacon_interval: the beacon interval announced by the peer
+ * @ie: additional IEs sent by the peer
+ * @ielen: length of the additional IEs
+ * @signal: the signal strength, type depends on the wiphy's signal_type
+ * @gfp: context flags
+ *
+ * This informs cfg80211 that BSS information was found and
+ * the BSS should be updated/added.
+ *
+ * NOTE: Returns a referenced struct, must be released with cfg80211_put_bss()!
+ */
+struct cfg80211_bss * __must_check
+cfg80211_inform_bss(struct wiphy *wiphy,
+ struct ieee80211_channel *channel,
+ const u8 *bssid, u64 tsf, u16 capability,
+ u16 beacon_interval, const u8 *ie, size_t ielen,
+ s32 signal, gfp_t gfp);
+
+struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
+ struct ieee80211_channel *channel,
+ const u8 *bssid,
+ const u8 *ssid, size_t ssid_len,
+ u16 capa_mask, u16 capa_val);
+static inline struct cfg80211_bss *
+cfg80211_get_ibss(struct wiphy *wiphy,
+ struct ieee80211_channel *channel,
+ const u8 *ssid, size_t ssid_len)
+{
+ return cfg80211_get_bss(wiphy, channel, NULL, ssid, ssid_len,
+ WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
+}
+
+struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy,
+ struct ieee80211_channel *channel,
+ const u8 *meshid, size_t meshidlen,
+ const u8 *meshcfg);
+/**
+ * cfg80211_ref_bss - reference BSS struct
+ * @bss: the BSS struct to reference
+ *
+ * Increments the refcount of the given BSS struct.
+ */
+void cfg80211_ref_bss(struct cfg80211_bss *bss);
+
+/**
+ * cfg80211_put_bss - unref BSS struct
+ * @bss: the BSS struct
+ *
+ * Decrements the refcount of the given BSS struct.
+ */
+void cfg80211_put_bss(struct cfg80211_bss *bss);
+
+/**
+ * cfg80211_unlink_bss - unlink BSS from internal data structures
+ * @wiphy: the wiphy
+ * @bss: the bss to remove
+ *
+ * This function removes the given BSS from the internal data structures
+ * thereby making it no longer show up in scan results etc. Use this
+ * function when you detect a BSS is gone. Normally BSSes will also time
+ * out, so it is not necessary to use this function at all.
+ */
+void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss);
+
+/**
+ * cfg80211_send_rx_auth - notification of processed authentication
+ * @dev: network device
+ * @buf: authentication frame (header + body)
+ * @len: length of the frame data
+ *
+ * This function is called whenever an authentication has been processed in
+ * station mode. The driver is required to call either this function or
+ * cfg80211_send_auth_timeout() to indicate the result of cfg80211_ops::auth()
+ * call. This function may sleep.
+ */
+void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
+
+/**
+ * cfg80211_send_auth_timeout - notification of timed out authentication
+ * @dev: network device
+ * @addr: The MAC address of the device with which the authentication timed out
+ *
+ * This function may sleep.
+ */
+void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr);
+
+/**
+ * cfg80211_send_rx_assoc - notification of processed association
+ * @dev: network device
+ * @bss: the BSS struct association was requested for, the struct reference
+ * is owned by cfg80211 after this call
+ * @buf: (re)association response frame (header + body)
+ * @len: length of the frame data
+ *
+ * This function is called whenever a (re)association response has been
+ * processed in station mode. The driver is required to call either this
+ * function or cfg80211_send_assoc_timeout() to indicate the result of
+ * cfg80211_ops::assoc() call. This function may sleep.
+ */
+void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
+ const u8 *buf, size_t len);
+
+/**
+ * cfg80211_send_assoc_timeout - notification of timed out association
+ * @dev: network device
+ * @addr: The MAC address of the device with which the association timed out
+ *
+ * This function may sleep.
+ */
+void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr);
+
+/**
+ * cfg80211_send_deauth - notification of processed deauthentication
+ * @dev: network device
+ * @buf: deauthentication frame (header + body)
+ * @len: length of the frame data
+ *
+ * This function is called whenever deauthentication has been processed in
+ * station mode. This includes both received deauthentication frames and
+ * locally generated ones. This function may sleep.
+ */
+void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
+
+/**
+ * __cfg80211_send_deauth - notification of processed deauthentication
+ * @dev: network device
+ * @buf: deauthentication frame (header + body)
+ * @len: length of the frame data
+ *
+ * Like cfg80211_send_deauth(), but doesn't take the wdev lock.
+ */
+void __cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
+
+/**
+ * cfg80211_send_disassoc - notification of processed disassociation
+ * @dev: network device
+ * @buf: disassociation response frame (header + body)
+ * @len: length of the frame data
+ *
+ * This function is called whenever disassociation has been processed in
+ * station mode. This includes both received disassociation frames and locally
+ * generated ones. This function may sleep.
+ */
+void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len);
+
+/**
+ * __cfg80211_send_disassoc - notification of processed disassociation
+ * @dev: network device
+ * @buf: disassociation response frame (header + body)
+ * @len: length of the frame data
+ *
+ * Like cfg80211_send_disassoc(), but doesn't take the wdev lock.
+ */
+void __cfg80211_send_disassoc(struct net_device *dev, const u8 *buf,
+ size_t len);
+
+/**
+ * cfg80211_send_unprot_deauth - notification of unprotected deauthentication
+ * @dev: network device
+ * @buf: deauthentication frame (header + body)
+ * @len: length of the frame data
+ *
+ * This function is called whenever a received Deauthentication frame has been
+ * dropped in station mode because of MFP being used but the Deauthentication
+ * frame was not protected. This function may sleep.
+ */
+void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf,
+ size_t len);
+
+/**
+ * cfg80211_send_unprot_disassoc - notification of unprotected disassociation
+ * @dev: network device
+ * @buf: disassociation frame (header + body)
+ * @len: length of the frame data
+ *
+ * This function is called whenever a received Disassociation frame has been
+ * dropped in station mode because of MFP being used but the Disassociation
+ * frame was not protected. This function may sleep.
+ */
+void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf,
+ size_t len);
+
+/**
+ * cfg80211_michael_mic_failure - notification of Michael MIC failure (TKIP)
+ * @dev: network device
+ * @addr: The source MAC address of the frame
+ * @key_type: The key type that the received frame used
+ * @key_id: Key identifier (0..3). Can be -1 if missing.
+ * @tsc: The TSC value of the frame that generated the MIC failure (6 octets)
+ * @gfp: allocation flags
+ *
+ * This function is called whenever the local MAC detects a MIC failure in a
+ * received frame. This matches with MLME-MICHAELMICFAILURE.indication()
+ * primitive.
+ */
+void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
+ enum nl80211_key_type key_type, int key_id,
+ const u8 *tsc, gfp_t gfp);
+
+/**
+ * cfg80211_ibss_joined - notify cfg80211 that device joined an IBSS
+ *
+ * @dev: network device
+ * @bssid: the BSSID of the IBSS joined
+ * @gfp: allocation flags
+ *
+ * This function notifies cfg80211 that the device joined an IBSS or
+ * switched to a different BSSID. Before this function can be called,
+ * either a beacon has to have been received from the IBSS, or one of
+ * the cfg80211_inform_bss{,_frame} functions must have been called
+ * with the locally generated beacon -- this guarantees that there is
+ * always a scan result for this IBSS. cfg80211 will handle the rest.
+ */
+void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp);
+
+/**
+ * cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate
+ *
+ * @dev: network device
+ * @macaddr: the MAC address of the new candidate
+ * @ie: information elements advertised by the peer candidate
+ * @ie_len: lenght of the information elements buffer
+ * @gfp: allocation flags
+ *
+ * This function notifies cfg80211 that the mesh peer candidate has been
+ * detected, most likely via a beacon or, less likely, via a probe response.
+ * cfg80211 then sends a notification to userspace.
+ */
+void cfg80211_notify_new_peer_candidate(struct net_device *dev,
+ const u8 *macaddr, const u8 *ie, u8 ie_len, gfp_t gfp);
+
+/**
+ * DOC: RFkill integration
+ *
+ * RFkill integration in cfg80211 is almost invisible to drivers,
+ * as cfg80211 automatically registers an rfkill instance for each
+ * wireless device it knows about. Soft kill is also translated
+ * into disconnecting and turning all interfaces off, drivers are
+ * expected to turn off the device when all interfaces are down.
+ *
+ * However, devices may have a hard RFkill line, in which case they
+ * also need to interact with the rfkill subsystem, via cfg80211.
+ * They can do this with a few helper functions documented here.
+ */
+
+/**
+ * wiphy_rfkill_set_hw_state - notify cfg80211 about hw block state
+ * @wiphy: the wiphy
+ * @blocked: block status
+ */
+void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked);
+
+/**
+ * wiphy_rfkill_start_polling - start polling rfkill
+ * @wiphy: the wiphy
+ */
+void wiphy_rfkill_start_polling(struct wiphy *wiphy);
+
+/**
+ * wiphy_rfkill_stop_polling - stop polling rfkill
+ * @wiphy: the wiphy
+ */
+void wiphy_rfkill_stop_polling(struct wiphy *wiphy);
+
+#ifdef CONFIG_NL80211_TESTMODE
+/**
+ * DOC: Test mode
+ *
+ * Test mode is a set of utility functions to allow drivers to
+ * interact with driver-specific tools to aid, for instance,
+ * factory programming.
+ *
+ * This chapter describes how drivers interact with it, for more
+ * information see the nl80211 book's chapter on it.
+ */
+
+/**
+ * cfg80211_testmode_alloc_reply_skb - allocate testmode reply
+ * @wiphy: the wiphy
+ * @approxlen: an upper bound of the length of the data that will
+ * be put into the skb
+ *
+ * This function allocates and pre-fills an skb for a reply to
+ * the testmode command. Since it is intended for a reply, calling
+ * it outside of the @testmode_cmd operation is invalid.
+ *
+ * The returned skb (or %NULL if any errors happen) is pre-filled
+ * with the wiphy index and set up in a way that any data that is
+ * put into the skb (with skb_put(), nla_put() or similar) will end
+ * up being within the %NL80211_ATTR_TESTDATA attribute, so all that
+ * needs to be done with the skb is adding data for the corresponding
+ * userspace tool which can then read that data out of the testdata
+ * attribute. You must not modify the skb in any other way.
+ *
+ * When done, call cfg80211_testmode_reply() with the skb and return
+ * its error code as the result of the @testmode_cmd operation.
+ */
+struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy,
+ int approxlen);
+
+/**
+ * cfg80211_testmode_reply - send the reply skb
+ * @skb: The skb, must have been allocated with
+ * cfg80211_testmode_alloc_reply_skb()
+ *
+ * Returns an error code or 0 on success, since calling this
+ * function will usually be the last thing before returning
+ * from the @testmode_cmd you should return the error code.
+ * Note that this function consumes the skb regardless of the
+ * return value.
+ */
+int cfg80211_testmode_reply(struct sk_buff *skb);
+
+/**
+ * cfg80211_testmode_alloc_event_skb - allocate testmode event
+ * @wiphy: the wiphy
+ * @approxlen: an upper bound of the length of the data that will
+ * be put into the skb
+ * @gfp: allocation flags
+ *
+ * This function allocates and pre-fills an skb for an event on the
+ * testmode multicast group.
+ *
+ * The returned skb (or %NULL if any errors happen) is set up in the
+ * same way as with cfg80211_testmode_alloc_reply_skb() but prepared
+ * for an event. As there, you should simply add data to it that will
+ * then end up in the %NL80211_ATTR_TESTDATA attribute. Again, you must
+ * not modify the skb in any other way.
+ *
+ * When done filling the skb, call cfg80211_testmode_event() with the
+ * skb to send the event.
+ */
+struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy,
+ int approxlen, gfp_t gfp);
+
+/**
+ * cfg80211_testmode_event - send the event
+ * @skb: The skb, must have been allocated with
+ * cfg80211_testmode_alloc_event_skb()
+ * @gfp: allocation flags
+ *
+ * This function sends the given @skb, which must have been allocated
+ * by cfg80211_testmode_alloc_event_skb(), as an event. It always
+ * consumes it.
+ */
+void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp);
+
+#define CFG80211_TESTMODE_CMD(cmd) .testmode_cmd = (cmd),
+#define CFG80211_TESTMODE_DUMP(cmd) .testmode_dump = (cmd),
+#else
+#define CFG80211_TESTMODE_CMD(cmd)
+#define CFG80211_TESTMODE_DUMP(cmd)
+#endif
+
+/**
+ * cfg80211_connect_result - notify cfg80211 of connection result
+ *
+ * @dev: network device
+ * @bssid: the BSSID of the AP
+ * @req_ie: association request IEs (maybe be %NULL)
+ * @req_ie_len: association request IEs length
+ * @resp_ie: association response IEs (may be %NULL)
+ * @resp_ie_len: assoc response IEs length
+ * @status: status code, 0 for successful connection, use
+ * %WLAN_STATUS_UNSPECIFIED_FAILURE if your device cannot give you
+ * the real status code for failures.
+ * @gfp: allocation flags
+ *
+ * It should be called by the underlying driver whenever connect() has
+ * succeeded.
+ */
+void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len,
+ u16 status, gfp_t gfp);
+
+/**
+ * cfg80211_roamed - notify cfg80211 of roaming
+ *
+ * @dev: network device
+ * @channel: the channel of the new AP
+ * @bssid: the BSSID of the new AP
+ * @req_ie: association request IEs (maybe be %NULL)
+ * @req_ie_len: association request IEs length
+ * @resp_ie: association response IEs (may be %NULL)
+ * @resp_ie_len: assoc response IEs length
+ * @gfp: allocation flags
+ *
+ * It should be called by the underlying driver whenever it roamed
+ * from one AP to another while connected.
+ */
+void cfg80211_roamed(struct net_device *dev,
+ struct ieee80211_channel *channel,
+ const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp);
+
+/**
+ * cfg80211_roamed_bss - notify cfg80211 of roaming
+ *
+ * @dev: network device
+ * @bss: entry of bss to which STA got roamed
+ * @req_ie: association request IEs (maybe be %NULL)
+ * @req_ie_len: association request IEs length
+ * @resp_ie: association response IEs (may be %NULL)
+ * @resp_ie_len: assoc response IEs length
+ * @gfp: allocation flags
+ *
+ * This is just a wrapper to notify cfg80211 of roaming event with driver
+ * passing bss to avoid a race in timeout of the bss entry. It should be
+ * called by the underlying driver whenever it roamed from one AP to another
+ * while connected. Drivers which have roaming implemented in firmware
+ * may use this function to avoid a race in bss entry timeout where the bss
+ * entry of the new AP is seen in the driver, but gets timed out by the time
+ * it is accessed in __cfg80211_roamed() due to delay in scheduling
+ * rdev->event_work. In case of any failures, the reference is released
+ * either in cfg80211_roamed_bss() or in __cfg80211_romed(), Otherwise,
+ * it will be released while diconneting from the current bss.
+ */
+void cfg80211_roamed_bss(struct net_device *dev, struct cfg80211_bss *bss,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp);
+
+/**
+ * cfg80211_disconnected - notify cfg80211 that connection was dropped
+ *
+ * @dev: network device
+ * @ie: information elements of the deauth/disassoc frame (may be %NULL)
+ * @ie_len: length of IEs
+ * @reason: reason code for the disconnection, set it to 0 if unknown
+ * @gfp: allocation flags
+ *
+ * After it calls this function, the driver should enter an idle state
+ * and not try to connect to any AP any more.
+ */
+void cfg80211_disconnected(struct net_device *dev, u16 reason,
+ u8 *ie, size_t ie_len, gfp_t gfp);
+
+/**
+ * cfg80211_ready_on_channel - notification of remain_on_channel start
+ * @dev: network device
+ * @cookie: the request cookie
+ * @chan: The current channel (from remain_on_channel request)
+ * @channel_type: Channel type
+ * @duration: Duration in milliseconds that the driver intents to remain on the
+ * channel
+ * @gfp: allocation flags
+ */
+void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type,
+ unsigned int duration, gfp_t gfp);
+
+/**
+ * cfg80211_remain_on_channel_expired - remain_on_channel duration expired
+ * @dev: network device
+ * @cookie: the request cookie
+ * @chan: The current channel (from remain_on_channel request)
+ * @channel_type: Channel type
+ * @gfp: allocation flags
+ */
+void cfg80211_remain_on_channel_expired(struct net_device *dev,
+ u64 cookie,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type,
+ gfp_t gfp);
+
+
+/**
+ * cfg80211_new_sta - notify userspace about station
+ *
+ * @dev: the netdev
+ * @mac_addr: the station's address
+ * @sinfo: the station information
+ * @gfp: allocation flags
+ */
+void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
+ struct station_info *sinfo, gfp_t gfp);
+
+/**
+ * cfg80211_del_sta - notify userspace about deletion of a station
+ *
+ * @dev: the netdev
+ * @mac_addr: the station's address
+ * @gfp: allocation flags
+ */
+void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp);
+
+/**
+ * cfg80211_rx_mgmt - notification of received, unprocessed management frame
+ * @dev: network device
+ * @freq: Frequency on which the frame was received in MHz
+ * @sig_dbm: signal strength in mBm, or 0 if unknown
+ * @buf: Management frame (header + body)
+ * @len: length of the frame data
+ * @gfp: context flags
+ *
+ * Returns %true if a user space application has registered for this frame.
+ * For action frames, that makes it responsible for rejecting unrecognized
+ * action frames; %false otherwise, in which case for action frames the
+ * driver is responsible for rejecting the frame.
+ *
+ * This function is called whenever an Action frame is received for a station
+ * mode interface, but is not processed in kernel.
+ */
+bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_dbm,
+ const u8 *buf, size_t len, gfp_t gfp);
+
+/**
+ * cfg80211_mgmt_tx_status - notification of TX status for management frame
+ * @dev: network device
+ * @cookie: Cookie returned by cfg80211_ops::mgmt_tx()
+ * @buf: Management frame (header + body)
+ * @len: length of the frame data
+ * @ack: Whether frame was acknowledged
+ * @gfp: context flags
+ *
+ * This function is called whenever a management frame was requested to be
+ * transmitted with cfg80211_ops::mgmt_tx() to report the TX status of the
+ * transmission attempt.
+ */
+void cfg80211_mgmt_tx_status(struct net_device *dev, u64 cookie,
+ const u8 *buf, size_t len, bool ack, gfp_t gfp);
+
+
+/**
+ * cfg80211_cqm_rssi_notify - connection quality monitoring rssi event
+ * @dev: network device
+ * @rssi_event: the triggered RSSI event
+ * @gfp: context flags
+ *
+ * This function is called when a configured connection quality monitoring
+ * rssi threshold reached event occurs.
+ */
+void cfg80211_cqm_rssi_notify(struct net_device *dev,
+ enum nl80211_cqm_rssi_threshold_event rssi_event,
+ gfp_t gfp);
+
+/**
+ * cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer
+ * @dev: network device
+ * @peer: peer's MAC address
+ * @num_packets: how many packets were lost -- should be a fixed threshold
+ * but probably no less than maybe 50, or maybe a throughput dependent
+ * threshold (to account for temporary interference)
+ * @gfp: context flags
+ */
+void cfg80211_cqm_pktloss_notify(struct net_device *dev,
+ const u8 *peer, u32 num_packets, gfp_t gfp);
+
+/**
+ * cfg80211_gtk_rekey_notify - notify userspace about driver rekeying
+ * @dev: network device
+ * @bssid: BSSID of AP (to avoid races)
+ * @replay_ctr: new replay counter
+ * @gfp: allocation flags
+ */
+void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
+ const u8 *replay_ctr, gfp_t gfp);
+
+/**
+ * cfg80211_pmksa_candidate_notify - notify about PMKSA caching candidate
+ * @dev: network device
+ * @index: candidate index (the smaller the index, the higher the priority)
+ * @bssid: BSSID of AP
+ * @preauth: Whether AP advertises support for RSN pre-authentication
+ * @gfp: allocation flags
+ */
+void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
+ const u8 *bssid, bool preauth, gfp_t gfp);
+
+/**
+ * cfg80211_rx_spurious_frame - inform userspace about a spurious frame
+ * @dev: The device the frame matched to
+ * @addr: the transmitter address
+ * @gfp: context flags
+ *
+ * This function is used in AP mode (only!) to inform userspace that
+ * a spurious class 3 frame was received, to be able to deauth the
+ * sender.
+ * Returns %true if the frame was passed to userspace (or this failed
+ * for a reason other than not having a subscription.)
+ */
+bool cfg80211_rx_spurious_frame(struct net_device *dev,
+ const u8 *addr, gfp_t gfp);
+
+/**
+ * cfg80211_rx_unexpected_4addr_frame - inform about unexpected WDS frame
+ * @dev: The device the frame matched to
+ * @addr: the transmitter address
+ * @gfp: context flags
+ *
+ * This function is used in AP mode (only!) to inform userspace that
+ * an associated station sent a 4addr frame but that wasn't expected.
+ * It is allowed and desirable to send this event only once for each
+ * station to avoid event flooding.
+ * Returns %true if the frame was passed to userspace (or this failed
+ * for a reason other than not having a subscription.)
+ */
+bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
+ const u8 *addr, gfp_t gfp);
+
+/**
+ * cfg80211_probe_status - notify userspace about probe status
+ * @dev: the device the probe was sent on
+ * @addr: the address of the peer
+ * @cookie: the cookie filled in @probe_client previously
+ * @acked: indicates whether probe was acked or not
+ * @gfp: allocation flags
+ */
+void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
+ u64 cookie, bool acked, gfp_t gfp);
+
+/**
+ * cfg80211_report_obss_beacon - report beacon from other APs
+ * @wiphy: The wiphy that received the beacon
+ * @frame: the frame
+ * @len: length of the frame
+ * @freq: frequency the frame was received on
+ * @sig_dbm: signal strength in mBm, or 0 if unknown
+ * @gfp: allocation flags
+ *
+ * Use this function to report to userspace when a beacon was
+ * received. It is not useful to call this when there is no
+ * netdev that is in AP/GO mode.
+ */
+void cfg80211_report_obss_beacon(struct wiphy *wiphy,
+ const u8 *frame, size_t len,
+ int freq, int sig_dbm, gfp_t gfp);
+
+/*
+ * cfg80211_can_beacon_sec_chan - test if ht40 on extension channel can be used
+ * @wiphy: the wiphy
+ * @chan: main channel
+ * @channel_type: HT mode
+ */
+int cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type);
+
+/*
+ * cfg80211_calculate_bitrate - calculate actual bitrate (in 100Kbps units)
+ * @rate: given rate_info to calculate bitrate from
+ *
+ * return 0 if MCS index >= 32
+ */
+u16 cfg80211_calculate_bitrate(struct rate_info *rate);
+
+/* Logging, debugging and troubleshooting/diagnostic helpers. */
+
+/* wiphy_printk helpers, similar to dev_printk */
+
+#define wiphy_printk(level, wiphy, format, args...) \
+ dev_printk(level, &(wiphy)->dev, format, ##args)
+#define wiphy_emerg(wiphy, format, args...) \
+ dev_emerg(&(wiphy)->dev, format, ##args)
+#define wiphy_alert(wiphy, format, args...) \
+ dev_alert(&(wiphy)->dev, format, ##args)
+#define wiphy_crit(wiphy, format, args...) \
+ dev_crit(&(wiphy)->dev, format, ##args)
+#define wiphy_err(wiphy, format, args...) \
+ dev_err(&(wiphy)->dev, format, ##args)
+#define wiphy_warn(wiphy, format, args...) \
+ dev_warn(&(wiphy)->dev, format, ##args)
+#define wiphy_notice(wiphy, format, args...) \
+ dev_notice(&(wiphy)->dev, format, ##args)
+#define wiphy_info(wiphy, format, args...) \
+ dev_info(&(wiphy)->dev, format, ##args)
+
+#define wiphy_debug(wiphy, format, args...) \
+ wiphy_printk(KERN_DEBUG, wiphy, format, ##args)
+
+#define wiphy_dbg(wiphy, format, args...) \
+ dev_dbg(&(wiphy)->dev, format, ##args)
+
+#if defined(VERBOSE_DEBUG)
+#define wiphy_vdbg wiphy_dbg
+#else
+#define wiphy_vdbg(wiphy, format, args...) \
+({ \
+ if (0) \
+ wiphy_printk(KERN_DEBUG, wiphy, format, ##args); \
+ 0; \
+})
+#endif
+
+/*
+ * wiphy_WARN() acts like wiphy_printk(), but with the key difference
+ * of using a WARN/WARN_ON to get the message out, including the
+ * file/line information and a backtrace.
+ */
+#define wiphy_WARN(wiphy, format, args...) \
+ WARN(1, "wiphy: %s\n" format, wiphy_name(wiphy), ##args);
+
+#endif /* __NET_CFG80211_H */
diff --git a/include/net/checksum.h b/include/net/checksum.h
new file mode 100644
index 00000000..ba55d8b8
--- /dev/null
+++ b/include/net/checksum.h
@@ -0,0 +1,121 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Checksumming functions for IP, TCP, UDP and so on
+ *
+ * Authors: Jorge Cwik, <jorge@laser.satlink.net>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ * Borrows very liberally from tcp.c and ip.c, see those
+ * files for more names.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _CHECKSUM_H
+#define _CHECKSUM_H
+
+#include <linux/errno.h>
+#include <asm/types.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+#include <asm/checksum.h>
+
+#ifndef _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
+static inline
+__wsum csum_and_copy_from_user (const void __user *src, void *dst,
+ int len, __wsum sum, int *err_ptr)
+{
+ if (access_ok(VERIFY_READ, src, len))
+ return csum_partial_copy_from_user(src, dst, len, sum, err_ptr);
+
+ if (len)
+ *err_ptr = -EFAULT;
+
+ return sum;
+}
+#endif
+
+#ifndef HAVE_CSUM_COPY_USER
+static __inline__ __wsum csum_and_copy_to_user
+(const void *src, void __user *dst, int len, __wsum sum, int *err_ptr)
+{
+ sum = csum_partial(src, len, sum);
+
+ if (access_ok(VERIFY_WRITE, dst, len)) {
+ if (copy_to_user(dst, src, len) == 0)
+ return sum;
+ }
+ if (len)
+ *err_ptr = -EFAULT;
+
+ return (__force __wsum)-1; /* invalid checksum */
+}
+#endif
+
+static inline __wsum csum_add(__wsum csum, __wsum addend)
+{
+ u32 res = (__force u32)csum;
+ res += (__force u32)addend;
+ return (__force __wsum)(res + (res < (__force u32)addend));
+}
+
+static inline __wsum csum_sub(__wsum csum, __wsum addend)
+{
+ return csum_add(csum, ~addend);
+}
+
+static inline __wsum
+csum_block_add(__wsum csum, __wsum csum2, int offset)
+{
+ u32 sum = (__force u32)csum2;
+ if (offset&1)
+ sum = ((sum&0xFF00FF)<<8)+((sum>>8)&0xFF00FF);
+ return csum_add(csum, (__force __wsum)sum);
+}
+
+static inline __wsum
+csum_block_sub(__wsum csum, __wsum csum2, int offset)
+{
+ u32 sum = (__force u32)csum2;
+ if (offset&1)
+ sum = ((sum&0xFF00FF)<<8)+((sum>>8)&0xFF00FF);
+ return csum_sub(csum, (__force __wsum)sum);
+}
+
+static inline __wsum csum_unfold(__sum16 n)
+{
+ return (__force __wsum)n;
+}
+
+#define CSUM_MANGLED_0 ((__force __sum16)0xffff)
+
+static inline void csum_replace4(__sum16 *sum, __be32 from, __be32 to)
+{
+ __be32 diff[] = { ~from, to };
+
+ *sum = csum_fold(csum_partial(diff, sizeof(diff), ~csum_unfold(*sum)));
+}
+
+static inline void csum_replace2(__sum16 *sum, __be16 from, __be16 to)
+{
+ csum_replace4(sum, (__force __be32)from, (__force __be32)to);
+}
+
+struct sk_buff;
+extern void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
+ __be32 from, __be32 to, int pseudohdr);
+
+static inline void inet_proto_csum_replace2(__sum16 *sum, struct sk_buff *skb,
+ __be16 from, __be16 to,
+ int pseudohdr)
+{
+ inet_proto_csum_replace4(sum, skb, (__force __be32)from,
+ (__force __be32)to, pseudohdr);
+}
+
+#endif
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
new file mode 100644
index 00000000..a7a683e3
--- /dev/null
+++ b/include/net/cipso_ipv4.h
@@ -0,0 +1,319 @@
+/*
+ * CIPSO - Commercial IP Security Option
+ *
+ * This is an implementation of the CIPSO 2.2 protocol as specified in
+ * draft-ietf-cipso-ipsecurity-01.txt with additional tag types as found in
+ * FIPS-188, copies of both documents can be found in the Documentation
+ * directory. While CIPSO never became a full IETF RFC standard many vendors
+ * have chosen to adopt the protocol and over the years it has become a
+ * de-facto standard for labeled networking.
+ *
+ * Author: Paul Moore <paul@paul-moore.com>
+ *
+ */
+
+/*
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _CIPSO_IPV4_H
+#define _CIPSO_IPV4_H
+
+#include <linux/types.h>
+#include <linux/rcupdate.h>
+#include <linux/list.h>
+#include <linux/net.h>
+#include <linux/skbuff.h>
+#include <net/netlabel.h>
+#include <net/request_sock.h>
+#include <linux/atomic.h>
+#include <asm/unaligned.h>
+
+/* known doi values */
+#define CIPSO_V4_DOI_UNKNOWN 0x00000000
+
+/* standard tag types */
+#define CIPSO_V4_TAG_INVALID 0
+#define CIPSO_V4_TAG_RBITMAP 1
+#define CIPSO_V4_TAG_ENUM 2
+#define CIPSO_V4_TAG_RANGE 5
+#define CIPSO_V4_TAG_PBITMAP 6
+#define CIPSO_V4_TAG_FREEFORM 7
+
+/* non-standard tag types (tags > 127) */
+#define CIPSO_V4_TAG_LOCAL 128
+
+/* doi mapping types */
+#define CIPSO_V4_MAP_UNKNOWN 0
+#define CIPSO_V4_MAP_TRANS 1
+#define CIPSO_V4_MAP_PASS 2
+#define CIPSO_V4_MAP_LOCAL 3
+
+/* limits */
+#define CIPSO_V4_MAX_REM_LVLS 255
+#define CIPSO_V4_INV_LVL 0x80000000
+#define CIPSO_V4_MAX_LOC_LVLS (CIPSO_V4_INV_LVL - 1)
+#define CIPSO_V4_MAX_REM_CATS 65534
+#define CIPSO_V4_INV_CAT 0x80000000
+#define CIPSO_V4_MAX_LOC_CATS (CIPSO_V4_INV_CAT - 1)
+
+/*
+ * CIPSO DOI definitions
+ */
+
+/* DOI definition struct */
+#define CIPSO_V4_TAG_MAXCNT 5
+struct cipso_v4_doi {
+ u32 doi;
+ u32 type;
+ union {
+ struct cipso_v4_std_map_tbl *std;
+ } map;
+ u8 tags[CIPSO_V4_TAG_MAXCNT];
+
+ atomic_t refcount;
+ struct list_head list;
+ struct rcu_head rcu;
+};
+
+/* Standard CIPSO mapping table */
+/* NOTE: the highest order bit (i.e. 0x80000000) is an 'invalid' flag, if the
+ * bit is set then consider that value as unspecified, meaning the
+ * mapping for that particular level/category is invalid */
+struct cipso_v4_std_map_tbl {
+ struct {
+ u32 *cipso;
+ u32 *local;
+ u32 cipso_size;
+ u32 local_size;
+ } lvl;
+ struct {
+ u32 *cipso;
+ u32 *local;
+ u32 cipso_size;
+ u32 local_size;
+ } cat;
+};
+
+/*
+ * Sysctl Variables
+ */
+
+#ifdef CONFIG_NETLABEL
+extern int cipso_v4_cache_enabled;
+extern int cipso_v4_cache_bucketsize;
+extern int cipso_v4_rbm_optfmt;
+extern int cipso_v4_rbm_strictvalid;
+#endif
+
+/*
+ * Helper Functions
+ */
+
+#define CIPSO_V4_OPTEXIST(x) (IPCB(x)->opt.cipso != 0)
+#define CIPSO_V4_OPTPTR(x) (skb_network_header(x) + IPCB(x)->opt.cipso)
+
+/*
+ * DOI List Functions
+ */
+
+#ifdef CONFIG_NETLABEL
+int cipso_v4_doi_add(struct cipso_v4_doi *doi_def,
+ struct netlbl_audit *audit_info);
+void cipso_v4_doi_free(struct cipso_v4_doi *doi_def);
+int cipso_v4_doi_remove(u32 doi, struct netlbl_audit *audit_info);
+struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi);
+void cipso_v4_doi_putdef(struct cipso_v4_doi *doi_def);
+int cipso_v4_doi_walk(u32 *skip_cnt,
+ int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
+ void *cb_arg);
+#else
+static inline int cipso_v4_doi_add(struct cipso_v4_doi *doi_def,
+ struct netlbl_audit *audit_info)
+{
+ return -ENOSYS;
+}
+
+static inline void cipso_v4_doi_free(struct cipso_v4_doi *doi_def)
+{
+ return;
+}
+
+static inline int cipso_v4_doi_remove(u32 doi,
+ struct netlbl_audit *audit_info)
+{
+ return 0;
+}
+
+static inline struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
+{
+ return NULL;
+}
+
+static inline int cipso_v4_doi_walk(u32 *skip_cnt,
+ int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
+ void *cb_arg)
+{
+ return 0;
+}
+
+static inline int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def,
+ const char *domain)
+{
+ return -ENOSYS;
+}
+
+static inline int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
+ const char *domain)
+{
+ return 0;
+}
+#endif /* CONFIG_NETLABEL */
+
+/*
+ * Label Mapping Cache Functions
+ */
+
+#ifdef CONFIG_NETLABEL
+void cipso_v4_cache_invalidate(void);
+int cipso_v4_cache_add(const struct sk_buff *skb,
+ const struct netlbl_lsm_secattr *secattr);
+#else
+static inline void cipso_v4_cache_invalidate(void)
+{
+ return;
+}
+
+static inline int cipso_v4_cache_add(const struct sk_buff *skb,
+ const struct netlbl_lsm_secattr *secattr)
+{
+ return 0;
+}
+#endif /* CONFIG_NETLABEL */
+
+/*
+ * Protocol Handling Functions
+ */
+
+#ifdef CONFIG_NETLABEL
+void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway);
+int cipso_v4_sock_setattr(struct sock *sk,
+ const struct cipso_v4_doi *doi_def,
+ const struct netlbl_lsm_secattr *secattr);
+void cipso_v4_sock_delattr(struct sock *sk);
+int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr);
+int cipso_v4_req_setattr(struct request_sock *req,
+ const struct cipso_v4_doi *doi_def,
+ const struct netlbl_lsm_secattr *secattr);
+void cipso_v4_req_delattr(struct request_sock *req);
+int cipso_v4_skbuff_setattr(struct sk_buff *skb,
+ const struct cipso_v4_doi *doi_def,
+ const struct netlbl_lsm_secattr *secattr);
+int cipso_v4_skbuff_delattr(struct sk_buff *skb);
+int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
+ struct netlbl_lsm_secattr *secattr);
+int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option);
+#else
+static inline void cipso_v4_error(struct sk_buff *skb,
+ int error,
+ u32 gateway)
+{
+ return;
+}
+
+static inline int cipso_v4_sock_setattr(struct sock *sk,
+ const struct cipso_v4_doi *doi_def,
+ const struct netlbl_lsm_secattr *secattr)
+{
+ return -ENOSYS;
+}
+
+static inline void cipso_v4_sock_delattr(struct sock *sk)
+{
+}
+
+static inline int cipso_v4_sock_getattr(struct sock *sk,
+ struct netlbl_lsm_secattr *secattr)
+{
+ return -ENOSYS;
+}
+
+static inline int cipso_v4_req_setattr(struct request_sock *req,
+ const struct cipso_v4_doi *doi_def,
+ const struct netlbl_lsm_secattr *secattr)
+{
+ return -ENOSYS;
+}
+
+static inline void cipso_v4_req_delattr(struct request_sock *req)
+{
+ return;
+}
+
+static inline int cipso_v4_skbuff_setattr(struct sk_buff *skb,
+ const struct cipso_v4_doi *doi_def,
+ const struct netlbl_lsm_secattr *secattr)
+{
+ return -ENOSYS;
+}
+
+static inline int cipso_v4_skbuff_delattr(struct sk_buff *skb)
+{
+ return -ENOSYS;
+}
+
+static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
+ struct netlbl_lsm_secattr *secattr)
+{
+ return -ENOSYS;
+}
+
+static inline int cipso_v4_validate(const struct sk_buff *skb,
+ unsigned char **option)
+{
+ unsigned char *opt = *option;
+ unsigned char err_offset = 0;
+ u8 opt_len = opt[1];
+ u8 opt_iter;
+
+ if (opt_len < 8) {
+ err_offset = 1;
+ goto out;
+ }
+
+ if (get_unaligned_be32(&opt[2]) == 0) {
+ err_offset = 2;
+ goto out;
+ }
+
+ for (opt_iter = 6; opt_iter < opt_len;) {
+ if (opt[opt_iter + 1] > (opt_len - opt_iter)) {
+ err_offset = opt_iter + 1;
+ goto out;
+ }
+ opt_iter += opt[opt_iter + 1];
+ }
+
+out:
+ *option = opt + err_offset;
+ return err_offset;
+
+}
+#endif /* CONFIG_NETLABEL */
+
+#endif /* _CIPSO_IPV4_H */
diff --git a/include/net/cls_cgroup.h b/include/net/cls_cgroup.h
new file mode 100644
index 00000000..a4dc5b02
--- /dev/null
+++ b/include/net/cls_cgroup.h
@@ -0,0 +1,70 @@
+/*
+ * cls_cgroup.h Control Group Classifier
+ *
+ * Authors: Thomas Graf <tgraf@suug.ch>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#ifndef _NET_CLS_CGROUP_H
+#define _NET_CLS_CGROUP_H
+
+#include <linux/cgroup.h>
+#include <linux/hardirq.h>
+#include <linux/rcupdate.h>
+
+#ifdef CONFIG_CGROUPS
+struct cgroup_cls_state
+{
+ struct cgroup_subsys_state css;
+ u32 classid;
+};
+
+#ifdef CONFIG_NET_CLS_CGROUP
+static inline u32 task_cls_classid(struct task_struct *p)
+{
+ int classid;
+
+ if (in_interrupt())
+ return 0;
+
+ rcu_read_lock();
+ classid = container_of(task_subsys_state(p, net_cls_subsys_id),
+ struct cgroup_cls_state, css)->classid;
+ rcu_read_unlock();
+
+ return classid;
+}
+#else
+extern int net_cls_subsys_id;
+
+static inline u32 task_cls_classid(struct task_struct *p)
+{
+ int id;
+ u32 classid = 0;
+
+ if (in_interrupt())
+ return 0;
+
+ rcu_read_lock();
+ id = rcu_dereference_index_check(net_cls_subsys_id,
+ rcu_read_lock_held());
+ if (id >= 0)
+ classid = container_of(task_subsys_state(p, id),
+ struct cgroup_cls_state, css)->classid;
+ rcu_read_unlock();
+
+ return classid;
+}
+#endif
+#else
+static inline u32 task_cls_classid(struct task_struct *p)
+{
+ return 0;
+}
+#endif
+#endif /* _NET_CLS_CGROUP_H */
diff --git a/include/net/compat.h b/include/net/compat.h
new file mode 100644
index 00000000..a974ae92
--- /dev/null
+++ b/include/net/compat.h
@@ -0,0 +1,63 @@
+#ifndef NET_COMPAT_H
+#define NET_COMPAT_H
+
+
+struct sock;
+
+#if defined(CONFIG_COMPAT)
+
+#include <linux/compat.h>
+
+struct compat_msghdr {
+ compat_uptr_t msg_name; /* void * */
+ compat_int_t msg_namelen;
+ compat_uptr_t msg_iov; /* struct compat_iovec * */
+ compat_size_t msg_iovlen;
+ compat_uptr_t msg_control; /* void * */
+ compat_size_t msg_controllen;
+ compat_uint_t msg_flags;
+};
+
+struct compat_mmsghdr {
+ struct compat_msghdr msg_hdr;
+ compat_uint_t msg_len;
+};
+
+struct compat_cmsghdr {
+ compat_size_t cmsg_len;
+ compat_int_t cmsg_level;
+ compat_int_t cmsg_type;
+};
+
+extern int compat_sock_get_timestamp(struct sock *, struct timeval __user *);
+extern int compat_sock_get_timestampns(struct sock *, struct timespec __user *);
+
+#else /* defined(CONFIG_COMPAT) */
+/*
+ * To avoid compiler warnings:
+ */
+#define compat_msghdr msghdr
+#define compat_mmsghdr mmsghdr
+#endif /* defined(CONFIG_COMPAT) */
+
+extern int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *);
+extern int verify_compat_iovec(struct msghdr *, struct iovec *, struct sockaddr_storage *, int);
+extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr __user *,unsigned);
+extern asmlinkage long compat_sys_sendmmsg(int, struct compat_mmsghdr __user *,
+ unsigned, unsigned);
+extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned);
+extern asmlinkage long compat_sys_recvmmsg(int, struct compat_mmsghdr __user *,
+ unsigned, unsigned,
+ struct compat_timespec __user *);
+extern asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *);
+extern int put_cmsg_compat(struct msghdr*, int, int, int, void *);
+
+extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *, unsigned char *, int);
+
+extern int compat_mc_setsockopt(struct sock *, int, int, char __user *, unsigned int,
+ int (*)(struct sock *, int, int, char __user *, unsigned int));
+extern int compat_mc_getsockopt(struct sock *, int, int, char __user *,
+ int __user *, int (*)(struct sock *, int, int, char __user *,
+ int __user *));
+
+#endif /* NET_COMPAT_H */
diff --git a/include/net/datalink.h b/include/net/datalink.h
new file mode 100644
index 00000000..deb7ca75
--- /dev/null
+++ b/include/net/datalink.h
@@ -0,0 +1,18 @@
+#ifndef _NET_INET_DATALINK_H_
+#define _NET_INET_DATALINK_H_
+
+struct datalink_proto {
+ unsigned char type[8];
+
+ struct llc_sap *sap;
+
+ unsigned short header_length;
+
+ int (*rcvfunc)(struct sk_buff *, struct net_device *,
+ struct packet_type *, struct net_device *);
+ int (*request)(struct datalink_proto *, struct sk_buff *,
+ unsigned char *);
+ struct list_head node;
+};
+
+#endif
diff --git a/include/net/dcbevent.h b/include/net/dcbevent.h
new file mode 100644
index 00000000..443626ed
--- /dev/null
+++ b/include/net/dcbevent.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Author: John Fastabend <john.r.fastabend@intel.com>
+ */
+
+#ifndef _DCB_EVENT_H
+#define _DCB_EVENT_H
+
+enum dcbevent_notif_type {
+ DCB_APP_EVENT = 1,
+};
+
+#ifdef CONFIG_DCB
+extern int register_dcbevent_notifier(struct notifier_block *nb);
+extern int unregister_dcbevent_notifier(struct notifier_block *nb);
+extern int call_dcbevent_notifiers(unsigned long val, void *v);
+#else
+static inline int
+register_dcbevent_notifier(struct notifier_block *nb)
+{
+ return 0;
+}
+
+static inline int unregister_dcbevent_notifier(struct notifier_block *nb)
+{
+ return 0;
+}
+
+static inline int call_dcbevent_notifiers(unsigned long val, void *v)
+{
+ return 0;
+}
+#endif /* CONFIG_DCB */
+
+#endif
diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h
new file mode 100644
index 00000000..f55c980d
--- /dev/null
+++ b/include/net/dcbnl.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2008, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Author: Lucy Liu <lucy.liu@intel.com>
+ */
+
+#ifndef __NET_DCBNL_H__
+#define __NET_DCBNL_H__
+
+#include <linux/dcbnl.h>
+
+struct dcb_app_type {
+ int ifindex;
+ struct dcb_app app;
+ struct list_head list;
+ u8 dcbx;
+};
+
+int dcb_setapp(struct net_device *, struct dcb_app *);
+u8 dcb_getapp(struct net_device *, struct dcb_app *);
+int dcb_ieee_setapp(struct net_device *, struct dcb_app *);
+int dcb_ieee_delapp(struct net_device *, struct dcb_app *);
+u8 dcb_ieee_getapp_mask(struct net_device *, struct dcb_app *);
+
+int dcbnl_ieee_notify(struct net_device *dev, int event, int cmd,
+ u32 seq, u32 pid);
+int dcbnl_cee_notify(struct net_device *dev, int event, int cmd,
+ u32 seq, u32 pid);
+
+/*
+ * Ops struct for the netlink callbacks. Used by DCB-enabled drivers through
+ * the netdevice struct.
+ */
+struct dcbnl_rtnl_ops {
+ /* IEEE 802.1Qaz std */
+ int (*ieee_getets) (struct net_device *, struct ieee_ets *);
+ int (*ieee_setets) (struct net_device *, struct ieee_ets *);
+ int (*ieee_getpfc) (struct net_device *, struct ieee_pfc *);
+ int (*ieee_setpfc) (struct net_device *, struct ieee_pfc *);
+ int (*ieee_getapp) (struct net_device *, struct dcb_app *);
+ int (*ieee_setapp) (struct net_device *, struct dcb_app *);
+ int (*ieee_delapp) (struct net_device *, struct dcb_app *);
+ int (*ieee_peer_getets) (struct net_device *, struct ieee_ets *);
+ int (*ieee_peer_getpfc) (struct net_device *, struct ieee_pfc *);
+
+ /* CEE std */
+ u8 (*getstate)(struct net_device *);
+ u8 (*setstate)(struct net_device *, u8);
+ void (*getpermhwaddr)(struct net_device *, u8 *);
+ void (*setpgtccfgtx)(struct net_device *, int, u8, u8, u8, u8);
+ void (*setpgbwgcfgtx)(struct net_device *, int, u8);
+ void (*setpgtccfgrx)(struct net_device *, int, u8, u8, u8, u8);
+ void (*setpgbwgcfgrx)(struct net_device *, int, u8);
+ void (*getpgtccfgtx)(struct net_device *, int, u8 *, u8 *, u8 *, u8 *);
+ void (*getpgbwgcfgtx)(struct net_device *, int, u8 *);
+ void (*getpgtccfgrx)(struct net_device *, int, u8 *, u8 *, u8 *, u8 *);
+ void (*getpgbwgcfgrx)(struct net_device *, int, u8 *);
+ void (*setpfccfg)(struct net_device *, int, u8);
+ void (*getpfccfg)(struct net_device *, int, u8 *);
+ u8 (*setall)(struct net_device *);
+ u8 (*getcap)(struct net_device *, int, u8 *);
+ int (*getnumtcs)(struct net_device *, int, u8 *);
+ int (*setnumtcs)(struct net_device *, int, u8);
+ u8 (*getpfcstate)(struct net_device *);
+ void (*setpfcstate)(struct net_device *, u8);
+ void (*getbcncfg)(struct net_device *, int, u32 *);
+ void (*setbcncfg)(struct net_device *, int, u32);
+ void (*getbcnrp)(struct net_device *, int, u8 *);
+ void (*setbcnrp)(struct net_device *, int, u8);
+ u8 (*setapp)(struct net_device *, u8, u16, u8);
+ u8 (*getapp)(struct net_device *, u8, u16);
+ u8 (*getfeatcfg)(struct net_device *, int, u8 *);
+ u8 (*setfeatcfg)(struct net_device *, int, u8);
+
+ /* DCBX configuration */
+ u8 (*getdcbx)(struct net_device *);
+ u8 (*setdcbx)(struct net_device *, u8);
+
+ /* peer apps */
+ int (*peer_getappinfo)(struct net_device *, struct dcb_peer_app_info *,
+ u16 *);
+ int (*peer_getapptable)(struct net_device *, struct dcb_app *);
+
+ /* CEE peer */
+ int (*cee_peer_getpg) (struct net_device *, struct cee_pg *);
+ int (*cee_peer_getpfc) (struct net_device *, struct cee_pfc *);
+};
+
+#endif /* __NET_DCBNL_H__ */
diff --git a/include/net/dn.h b/include/net/dn.h
new file mode 100644
index 00000000..814af0b9
--- /dev/null
+++ b/include/net/dn.h
@@ -0,0 +1,233 @@
+#ifndef _NET_DN_H
+#define _NET_DN_H
+
+#include <linux/dn.h>
+#include <net/sock.h>
+#include <net/flow.h>
+#include <asm/byteorder.h>
+#include <asm/unaligned.h>
+
+struct dn_scp /* Session Control Port */
+{
+ unsigned char state;
+#define DN_O 1 /* Open */
+#define DN_CR 2 /* Connect Receive */
+#define DN_DR 3 /* Disconnect Reject */
+#define DN_DRC 4 /* Discon. Rej. Complete*/
+#define DN_CC 5 /* Connect Confirm */
+#define DN_CI 6 /* Connect Initiate */
+#define DN_NR 7 /* No resources */
+#define DN_NC 8 /* No communication */
+#define DN_CD 9 /* Connect Delivery */
+#define DN_RJ 10 /* Rejected */
+#define DN_RUN 11 /* Running */
+#define DN_DI 12 /* Disconnect Initiate */
+#define DN_DIC 13 /* Disconnect Complete */
+#define DN_DN 14 /* Disconnect Notificat */
+#define DN_CL 15 /* Closed */
+#define DN_CN 16 /* Closed Notification */
+
+ __le16 addrloc;
+ __le16 addrrem;
+ __u16 numdat;
+ __u16 numoth;
+ __u16 numoth_rcv;
+ __u16 numdat_rcv;
+ __u16 ackxmt_dat;
+ __u16 ackxmt_oth;
+ __u16 ackrcv_dat;
+ __u16 ackrcv_oth;
+ __u8 flowrem_sw;
+ __u8 flowloc_sw;
+#define DN_SEND 2
+#define DN_DONTSEND 1
+#define DN_NOCHANGE 0
+ __u16 flowrem_dat;
+ __u16 flowrem_oth;
+ __u16 flowloc_dat;
+ __u16 flowloc_oth;
+ __u8 services_rem;
+ __u8 services_loc;
+ __u8 info_rem;
+ __u8 info_loc;
+
+ __u16 segsize_rem;
+ __u16 segsize_loc;
+
+ __u8 nonagle;
+ __u8 multi_ireq;
+ __u8 accept_mode;
+ unsigned long seg_total; /* Running total of current segment */
+
+ struct optdata_dn conndata_in;
+ struct optdata_dn conndata_out;
+ struct optdata_dn discdata_in;
+ struct optdata_dn discdata_out;
+ struct accessdata_dn accessdata;
+
+ struct sockaddr_dn addr; /* Local address */
+ struct sockaddr_dn peer; /* Remote address */
+
+ /*
+ * In this case the RTT estimation is not specified in the
+ * docs, nor is any back off algorithm. Here we follow well
+ * known tcp algorithms with a few small variations.
+ *
+ * snd_window: Max number of packets we send before we wait for
+ * an ack to come back. This will become part of a
+ * more complicated scheme when we support flow
+ * control.
+ *
+ * nsp_srtt: Round-Trip-Time (x8) in jiffies. This is a rolling
+ * average.
+ * nsp_rttvar: Round-Trip-Time-Varience (x4) in jiffies. This is the
+ * varience of the smoothed average (but calculated in
+ * a simpler way than for normal statistical varience
+ * calculations).
+ *
+ * nsp_rxtshift: Backoff counter. Value is zero normally, each time
+ * a packet is lost is increases by one until an ack
+ * is received. Its used to index an array of backoff
+ * multipliers.
+ */
+#define NSP_MIN_WINDOW 1
+#define NSP_MAX_WINDOW (0x07fe)
+ unsigned long max_window;
+ unsigned long snd_window;
+#define NSP_INITIAL_SRTT (HZ)
+ unsigned long nsp_srtt;
+#define NSP_INITIAL_RTTVAR (HZ*3)
+ unsigned long nsp_rttvar;
+#define NSP_MAXRXTSHIFT 12
+ unsigned long nsp_rxtshift;
+
+ /*
+ * Output queues, one for data, one for otherdata/linkservice
+ */
+ struct sk_buff_head data_xmit_queue;
+ struct sk_buff_head other_xmit_queue;
+
+ /*
+ * Input queue for other data
+ */
+ struct sk_buff_head other_receive_queue;
+ int other_report;
+
+ /*
+ * Stuff to do with the slow timer
+ */
+ unsigned long stamp; /* time of last transmit */
+ unsigned long persist;
+ int (*persist_fxn)(struct sock *sk);
+ unsigned long keepalive;
+ void (*keepalive_fxn)(struct sock *sk);
+
+ /*
+ * This stuff is for the fast timer for delayed acks
+ */
+ struct timer_list delack_timer;
+ int delack_pending;
+ void (*delack_fxn)(struct sock *sk);
+
+};
+
+static inline struct dn_scp *DN_SK(struct sock *sk)
+{
+ return (struct dn_scp *)(sk + 1);
+}
+
+/*
+ * src,dst : Source and Destination DECnet addresses
+ * hops : Number of hops through the network
+ * dst_port, src_port : NSP port numbers
+ * services, info : Useful data extracted from conninit messages
+ * rt_flags : Routing flags byte
+ * nsp_flags : NSP layer flags byte
+ * segsize : Size of segment
+ * segnum : Number, for data, otherdata and linkservice
+ * xmit_count : Number of times we've transmitted this skb
+ * stamp : Time stamp of most recent transmission, used in RTT calculations
+ * iif: Input interface number
+ *
+ * As a general policy, this structure keeps all addresses in network
+ * byte order, and all else in host byte order. Thus dst, src, dst_port
+ * and src_port are in network order. All else is in host order.
+ *
+ */
+#define DN_SKB_CB(skb) ((struct dn_skb_cb *)(skb)->cb)
+struct dn_skb_cb {
+ __le16 dst;
+ __le16 src;
+ __u16 hops;
+ __le16 dst_port;
+ __le16 src_port;
+ __u8 services;
+ __u8 info;
+ __u8 rt_flags;
+ __u8 nsp_flags;
+ __u16 segsize;
+ __u16 segnum;
+ __u16 xmit_count;
+ unsigned long stamp;
+ int iif;
+};
+
+static inline __le16 dn_eth2dn(unsigned char *ethaddr)
+{
+ return get_unaligned((__le16 *)(ethaddr + 4));
+}
+
+static inline __le16 dn_saddr2dn(struct sockaddr_dn *saddr)
+{
+ return *(__le16 *)saddr->sdn_nodeaddr;
+}
+
+static inline void dn_dn2eth(unsigned char *ethaddr, __le16 addr)
+{
+ __u16 a = le16_to_cpu(addr);
+ ethaddr[0] = 0xAA;
+ ethaddr[1] = 0x00;
+ ethaddr[2] = 0x04;
+ ethaddr[3] = 0x00;
+ ethaddr[4] = (__u8)(a & 0xff);
+ ethaddr[5] = (__u8)(a >> 8);
+}
+
+static inline void dn_sk_ports_copy(struct flowidn *fld, struct dn_scp *scp)
+{
+ fld->fld_sport = scp->addrloc;
+ fld->fld_dport = scp->addrrem;
+}
+
+extern unsigned dn_mss_from_pmtu(struct net_device *dev, int mtu);
+
+#define DN_MENUVER_ACC 0x01
+#define DN_MENUVER_USR 0x02
+#define DN_MENUVER_PRX 0x04
+#define DN_MENUVER_UIC 0x08
+
+extern struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr);
+extern struct sock *dn_find_by_skb(struct sk_buff *skb);
+#define DN_ASCBUF_LEN 9
+extern char *dn_addr2asc(__u16, char *);
+extern int dn_destroy_timer(struct sock *sk);
+
+extern int dn_sockaddr2username(struct sockaddr_dn *addr, unsigned char *buf, unsigned char type);
+extern int dn_username2sockaddr(unsigned char *data, int len, struct sockaddr_dn *addr, unsigned char *type);
+
+extern void dn_start_slow_timer(struct sock *sk);
+extern void dn_stop_slow_timer(struct sock *sk);
+
+extern __le16 decnet_address;
+extern int decnet_debug_level;
+extern int decnet_time_wait;
+extern int decnet_dn_count;
+extern int decnet_di_count;
+extern int decnet_dr_count;
+extern int decnet_no_fc_max_cwnd;
+
+extern long sysctl_decnet_mem[3];
+extern int sysctl_decnet_wmem[3];
+extern int sysctl_decnet_rmem[3];
+
+#endif /* _NET_DN_H */
diff --git a/include/net/dn_dev.h b/include/net/dn_dev.h
new file mode 100644
index 00000000..b9e32db0
--- /dev/null
+++ b/include/net/dn_dev.h
@@ -0,0 +1,198 @@
+#ifndef _NET_DN_DEV_H
+#define _NET_DN_DEV_H
+
+
+struct dn_dev;
+
+struct dn_ifaddr {
+ struct dn_ifaddr __rcu *ifa_next;
+ struct dn_dev *ifa_dev;
+ __le16 ifa_local;
+ __le16 ifa_address;
+ __u8 ifa_flags;
+ __u8 ifa_scope;
+ char ifa_label[IFNAMSIZ];
+ struct rcu_head rcu;
+};
+
+#define DN_DEV_S_RU 0 /* Run - working normally */
+#define DN_DEV_S_CR 1 /* Circuit Rejected */
+#define DN_DEV_S_DS 2 /* Data Link Start */
+#define DN_DEV_S_RI 3 /* Routing Layer Initialize */
+#define DN_DEV_S_RV 4 /* Routing Layer Verify */
+#define DN_DEV_S_RC 5 /* Routing Layer Complete */
+#define DN_DEV_S_OF 6 /* Off */
+#define DN_DEV_S_HA 7 /* Halt */
+
+
+/*
+ * The dn_dev_parms structure contains the set of parameters
+ * for each device (hence inclusion in the dn_dev structure)
+ * and an array is used to store the default types of supported
+ * device (in dn_dev.c).
+ *
+ * The type field matches the ARPHRD_ constants and is used in
+ * searching the list for supported devices when new devices
+ * come up.
+ *
+ * The mode field is used to find out if a device is broadcast,
+ * multipoint, or pointopoint. Please note that DECnet thinks
+ * different ways about devices to the rest of the kernel
+ * so the normal IFF_xxx flags are invalid here. For devices
+ * which can be any combination of the previously mentioned
+ * attributes, you can set this on a per device basis by
+ * installing an up() routine.
+ *
+ * The device state field, defines the initial state in which the
+ * device will come up. In the dn_dev structure, it is the actual
+ * state.
+ *
+ * Things have changed here. I've killed timer1 since it's a user space
+ * issue for a user space routing deamon to sort out. The kernel does
+ * not need to be bothered with it.
+ *
+ * Timers:
+ * t2 - Rate limit timer, min time between routing and hello messages
+ * t3 - Hello timer, send hello messages when it expires
+ *
+ * Callbacks:
+ * up() - Called to initialize device, return value can veto use of
+ * device with DECnet.
+ * down() - Called to turn device off when it goes down
+ * timer3() - Called once for each ifaddr when timer 3 goes off
+ *
+ * sysctl - Hook for sysctl things
+ *
+ */
+struct dn_dev_parms {
+ int type; /* ARPHRD_xxx */
+ int mode; /* Broadcast, Unicast, Mulitpoint */
+#define DN_DEV_BCAST 1
+#define DN_DEV_UCAST 2
+#define DN_DEV_MPOINT 4
+ int state; /* Initial state */
+ int forwarding; /* 0=EndNode, 1=L1Router, 2=L2Router */
+ unsigned long t2; /* Default value of t2 */
+ unsigned long t3; /* Default value of t3 */
+ int priority; /* Priority to be a router */
+ char *name; /* Name for sysctl */
+ int (*up)(struct net_device *);
+ void (*down)(struct net_device *);
+ void (*timer3)(struct net_device *, struct dn_ifaddr *ifa);
+ void *sysctl;
+};
+
+
+struct dn_dev {
+ struct dn_ifaddr __rcu *ifa_list;
+ struct net_device *dev;
+ struct dn_dev_parms parms;
+ char use_long;
+ struct timer_list timer;
+ unsigned long t3;
+ struct neigh_parms *neigh_parms;
+ __u8 addr[ETH_ALEN];
+ struct neighbour *router; /* Default router on circuit */
+ struct neighbour *peer; /* Peer on pointopoint links */
+ unsigned long uptime; /* Time device went up in jiffies */
+};
+
+struct dn_short_packet {
+ __u8 msgflg;
+ __le16 dstnode;
+ __le16 srcnode;
+ __u8 forward;
+} __packed;
+
+struct dn_long_packet {
+ __u8 msgflg;
+ __u8 d_area;
+ __u8 d_subarea;
+ __u8 d_id[6];
+ __u8 s_area;
+ __u8 s_subarea;
+ __u8 s_id[6];
+ __u8 nl2;
+ __u8 visit_ct;
+ __u8 s_class;
+ __u8 pt;
+} __packed;
+
+/*------------------------- DRP - Routing messages ---------------------*/
+
+struct endnode_hello_message {
+ __u8 msgflg;
+ __u8 tiver[3];
+ __u8 id[6];
+ __u8 iinfo;
+ __le16 blksize;
+ __u8 area;
+ __u8 seed[8];
+ __u8 neighbor[6];
+ __le16 timer;
+ __u8 mpd;
+ __u8 datalen;
+ __u8 data[2];
+} __packed;
+
+struct rtnode_hello_message {
+ __u8 msgflg;
+ __u8 tiver[3];
+ __u8 id[6];
+ __u8 iinfo;
+ __le16 blksize;
+ __u8 priority;
+ __u8 area;
+ __le16 timer;
+ __u8 mpd;
+} __packed;
+
+
+extern void dn_dev_init(void);
+extern void dn_dev_cleanup(void);
+
+extern int dn_dev_ioctl(unsigned int cmd, void __user *arg);
+
+extern void dn_dev_devices_off(void);
+extern void dn_dev_devices_on(void);
+
+extern void dn_dev_init_pkt(struct sk_buff *skb);
+extern void dn_dev_veri_pkt(struct sk_buff *skb);
+extern void dn_dev_hello(struct sk_buff *skb);
+
+extern void dn_dev_up(struct net_device *);
+extern void dn_dev_down(struct net_device *);
+
+extern int dn_dev_set_default(struct net_device *dev, int force);
+extern struct net_device *dn_dev_get_default(void);
+extern int dn_dev_bind_default(__le16 *addr);
+
+extern int register_dnaddr_notifier(struct notifier_block *nb);
+extern int unregister_dnaddr_notifier(struct notifier_block *nb);
+
+static inline int dn_dev_islocal(struct net_device *dev, __le16 addr)
+{
+ struct dn_dev *dn_db;
+ struct dn_ifaddr *ifa;
+ int res = 0;
+
+ rcu_read_lock();
+ dn_db = rcu_dereference(dev->dn_ptr);
+ if (dn_db == NULL) {
+ printk(KERN_DEBUG "dn_dev_islocal: Called for non DECnet device\n");
+ goto out;
+ }
+
+ for (ifa = rcu_dereference(dn_db->ifa_list);
+ ifa != NULL;
+ ifa = rcu_dereference(ifa->ifa_next))
+ if ((addr ^ ifa->ifa_local) == 0) {
+ res = 1;
+ break;
+ }
+out:
+ rcu_read_unlock();
+ return res;
+}
+
+#endif /* _NET_DN_DEV_H */
diff --git a/include/net/dn_fib.h b/include/net/dn_fib.h
new file mode 100644
index 00000000..782ef7cb
--- /dev/null
+++ b/include/net/dn_fib.h
@@ -0,0 +1,184 @@
+#ifndef _NET_DN_FIB_H
+#define _NET_DN_FIB_H
+
+/* WARNING: The ordering of these elements must match ordering
+ * of RTA_* rtnetlink attribute numbers.
+ */
+struct dn_kern_rta {
+ void *rta_dst;
+ void *rta_src;
+ int *rta_iif;
+ int *rta_oif;
+ void *rta_gw;
+ u32 *rta_priority;
+ void *rta_prefsrc;
+ struct rtattr *rta_mx;
+ struct rtattr *rta_mp;
+ unsigned char *rta_protoinfo;
+ u32 *rta_flow;
+ struct rta_cacheinfo *rta_ci;
+ struct rta_session *rta_sess;
+};
+
+struct dn_fib_res {
+ struct fib_rule *r;
+ struct dn_fib_info *fi;
+ unsigned char prefixlen;
+ unsigned char nh_sel;
+ unsigned char type;
+ unsigned char scope;
+};
+
+struct dn_fib_nh {
+ struct net_device *nh_dev;
+ unsigned nh_flags;
+ unsigned char nh_scope;
+ int nh_weight;
+ int nh_power;
+ int nh_oif;
+ __le16 nh_gw;
+};
+
+struct dn_fib_info {
+ struct dn_fib_info *fib_next;
+ struct dn_fib_info *fib_prev;
+ int fib_treeref;
+ atomic_t fib_clntref;
+ int fib_dead;
+ unsigned fib_flags;
+ int fib_protocol;
+ __le16 fib_prefsrc;
+ __u32 fib_priority;
+ __u32 fib_metrics[RTAX_MAX];
+ int fib_nhs;
+ int fib_power;
+ struct dn_fib_nh fib_nh[0];
+#define dn_fib_dev fib_nh[0].nh_dev
+};
+
+
+#define DN_FIB_RES_RESET(res) ((res).nh_sel = 0)
+#define DN_FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel])
+
+#define DN_FIB_RES_PREFSRC(res) ((res).fi->fib_prefsrc ? : __dn_fib_res_prefsrc(&res))
+#define DN_FIB_RES_GW(res) (DN_FIB_RES_NH(res).nh_gw)
+#define DN_FIB_RES_DEV(res) (DN_FIB_RES_NH(res).nh_dev)
+#define DN_FIB_RES_OIF(res) (DN_FIB_RES_NH(res).nh_oif)
+
+typedef struct {
+ __le16 datum;
+} dn_fib_key_t;
+
+typedef struct {
+ __le16 datum;
+} dn_fib_hash_t;
+
+typedef struct {
+ __u16 datum;
+} dn_fib_idx_t;
+
+struct dn_fib_node {
+ struct dn_fib_node *fn_next;
+ struct dn_fib_info *fn_info;
+#define DN_FIB_INFO(f) ((f)->fn_info)
+ dn_fib_key_t fn_key;
+ u8 fn_type;
+ u8 fn_scope;
+ u8 fn_state;
+};
+
+
+struct dn_fib_table {
+ struct hlist_node hlist;
+ u32 n;
+
+ int (*insert)(struct dn_fib_table *t, struct rtmsg *r,
+ struct dn_kern_rta *rta, struct nlmsghdr *n,
+ struct netlink_skb_parms *req);
+ int (*delete)(struct dn_fib_table *t, struct rtmsg *r,
+ struct dn_kern_rta *rta, struct nlmsghdr *n,
+ struct netlink_skb_parms *req);
+ int (*lookup)(struct dn_fib_table *t, const struct flowidn *fld,
+ struct dn_fib_res *res);
+ int (*flush)(struct dn_fib_table *t);
+ int (*dump)(struct dn_fib_table *t, struct sk_buff *skb, struct netlink_callback *cb);
+
+ unsigned char data[0];
+};
+
+#ifdef CONFIG_DECNET_ROUTER
+/*
+ * dn_fib.c
+ */
+extern void dn_fib_init(void);
+extern void dn_fib_cleanup(void);
+
+extern int dn_fib_ioctl(struct socket *sock, unsigned int cmd,
+ unsigned long arg);
+extern struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r,
+ struct dn_kern_rta *rta,
+ const struct nlmsghdr *nlh, int *errp);
+extern int dn_fib_semantic_match(int type, struct dn_fib_info *fi,
+ const struct flowidn *fld,
+ struct dn_fib_res *res);
+extern void dn_fib_release_info(struct dn_fib_info *fi);
+extern __le16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type);
+extern void dn_fib_flush(void);
+extern void dn_fib_select_multipath(const struct flowidn *fld,
+ struct dn_fib_res *res);
+
+/*
+ * dn_tables.c
+ */
+extern struct dn_fib_table *dn_fib_get_table(u32 n, int creat);
+extern struct dn_fib_table *dn_fib_empty_table(void);
+extern void dn_fib_table_init(void);
+extern void dn_fib_table_cleanup(void);
+
+/*
+ * dn_rules.c
+ */
+extern void dn_fib_rules_init(void);
+extern void dn_fib_rules_cleanup(void);
+extern unsigned dnet_addr_type(__le16 addr);
+extern int dn_fib_lookup(struct flowidn *fld, struct dn_fib_res *res);
+
+extern int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb);
+
+extern void dn_fib_free_info(struct dn_fib_info *fi);
+
+static inline void dn_fib_info_put(struct dn_fib_info *fi)
+{
+ if (atomic_dec_and_test(&fi->fib_clntref))
+ dn_fib_free_info(fi);
+}
+
+static inline void dn_fib_res_put(struct dn_fib_res *res)
+{
+ if (res->fi)
+ dn_fib_info_put(res->fi);
+ if (res->r)
+ fib_rule_put(res->r);
+}
+
+#else /* Endnode */
+
+#define dn_fib_init() do { } while(0)
+#define dn_fib_cleanup() do { } while(0)
+
+#define dn_fib_lookup(fl, res) (-ESRCH)
+#define dn_fib_info_put(fi) do { } while(0)
+#define dn_fib_select_multipath(fl, res) do { } while(0)
+#define dn_fib_rules_policy(saddr,res,flags) (0)
+#define dn_fib_res_put(res) do { } while(0)
+
+#endif /* CONFIG_DECNET_ROUTER */
+
+static inline __le16 dnet_make_mask(int n)
+{
+ if (n)
+ return cpu_to_le16(~((1 << (16 - n)) - 1));
+ return cpu_to_le16(0);
+}
+
+#endif /* _NET_DN_FIB_H */
diff --git a/include/net/dn_neigh.h b/include/net/dn_neigh.h
new file mode 100644
index 00000000..4cb4ae7f
--- /dev/null
+++ b/include/net/dn_neigh.h
@@ -0,0 +1,28 @@
+#ifndef _NET_DN_NEIGH_H
+#define _NET_DN_NEIGH_H
+
+/*
+ * The position of the first two fields of
+ * this structure are critical - SJW
+ */
+struct dn_neigh {
+ struct neighbour n;
+ __le16 addr;
+ unsigned long flags;
+#define DN_NDFLAG_R1 0x0001 /* Router L1 */
+#define DN_NDFLAG_R2 0x0002 /* Router L2 */
+#define DN_NDFLAG_P3 0x0004 /* Phase III Node */
+ unsigned long blksize;
+ __u8 priority;
+};
+
+extern void dn_neigh_init(void);
+extern void dn_neigh_cleanup(void);
+extern int dn_neigh_router_hello(struct sk_buff *skb);
+extern int dn_neigh_endnode_hello(struct sk_buff *skb);
+extern void dn_neigh_pointopoint_hello(struct sk_buff *skb);
+extern int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n);
+
+extern struct neigh_table dn_neigh_table;
+
+#endif /* _NET_DN_NEIGH_H */
diff --git a/include/net/dn_nsp.h b/include/net/dn_nsp.h
new file mode 100644
index 00000000..e43a2893
--- /dev/null
+++ b/include/net/dn_nsp.h
@@ -0,0 +1,201 @@
+#ifndef _NET_DN_NSP_H
+#define _NET_DN_NSP_H
+/******************************************************************************
+ (c) 1995-1998 E.M. Serrat emserrat@geocities.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*******************************************************************************/
+/* dn_nsp.c functions prototyping */
+
+extern void dn_nsp_send_data_ack(struct sock *sk);
+extern void dn_nsp_send_oth_ack(struct sock *sk);
+extern void dn_nsp_delayed_ack(struct sock *sk);
+extern void dn_send_conn_ack(struct sock *sk);
+extern void dn_send_conn_conf(struct sock *sk, gfp_t gfp);
+extern void dn_nsp_send_disc(struct sock *sk, unsigned char type,
+ unsigned short reason, gfp_t gfp);
+extern void dn_nsp_return_disc(struct sk_buff *skb, unsigned char type,
+ unsigned short reason);
+extern void dn_nsp_send_link(struct sock *sk, unsigned char lsflags, char fcval);
+extern void dn_nsp_send_conninit(struct sock *sk, unsigned char flags);
+
+extern void dn_nsp_output(struct sock *sk);
+extern int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff_head *q, unsigned short acknum);
+extern void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, gfp_t gfp, int oob);
+extern unsigned long dn_nsp_persist(struct sock *sk);
+extern int dn_nsp_xmit_timeout(struct sock *sk);
+
+extern int dn_nsp_rx(struct sk_buff *);
+extern int dn_nsp_backlog_rcv(struct sock *sk, struct sk_buff *skb);
+
+extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri);
+extern struct sk_buff *dn_alloc_send_skb(struct sock *sk, size_t *size, int noblock, long timeo, int *err);
+
+#define NSP_REASON_OK 0 /* No error */
+#define NSP_REASON_NR 1 /* No resources */
+#define NSP_REASON_UN 2 /* Unrecognised node name */
+#define NSP_REASON_SD 3 /* Node shutting down */
+#define NSP_REASON_ID 4 /* Invalid destination end user */
+#define NSP_REASON_ER 5 /* End user lacks resources */
+#define NSP_REASON_OB 6 /* Object too busy */
+#define NSP_REASON_US 7 /* Unspecified error */
+#define NSP_REASON_TP 8 /* Third-Party abort */
+#define NSP_REASON_EA 9 /* End user has aborted the link */
+#define NSP_REASON_IF 10 /* Invalid node name format */
+#define NSP_REASON_LS 11 /* Local node shutdown */
+#define NSP_REASON_LL 32 /* Node lacks logical-link resources */
+#define NSP_REASON_LE 33 /* End user lacks logical-link resources */
+#define NSP_REASON_UR 34 /* Unacceptable RQSTRID or PASSWORD field */
+#define NSP_REASON_UA 36 /* Unacceptable ACCOUNT field */
+#define NSP_REASON_TM 38 /* End user timed out logical link */
+#define NSP_REASON_NU 39 /* Node unreachable */
+#define NSP_REASON_NL 41 /* No-link message */
+#define NSP_REASON_DC 42 /* Disconnect confirm */
+#define NSP_REASON_IO 43 /* Image data field overflow */
+
+#define NSP_DISCINIT 0x38
+#define NSP_DISCCONF 0x48
+
+/*------------------------- NSP - messages ------------------------------*/
+/* Data Messages */
+/*---------------*/
+
+/* Data Messages (data segment/interrupt/link service) */
+
+struct nsp_data_seg_msg {
+ __u8 msgflg;
+ __le16 dstaddr;
+ __le16 srcaddr;
+} __packed;
+
+struct nsp_data_opt_msg {
+ __le16 acknum;
+ __le16 segnum;
+ __le16 lsflgs;
+} __packed;
+
+struct nsp_data_opt_msg1 {
+ __le16 acknum;
+ __le16 segnum;
+} __packed;
+
+
+/* Acknowledgment Message (data/other data) */
+struct nsp_data_ack_msg {
+ __u8 msgflg;
+ __le16 dstaddr;
+ __le16 srcaddr;
+ __le16 acknum;
+} __packed;
+
+/* Connect Acknowledgment Message */
+struct nsp_conn_ack_msg {
+ __u8 msgflg;
+ __le16 dstaddr;
+} __packed;
+
+
+/* Connect Initiate/Retransmit Initiate/Connect Confirm */
+struct nsp_conn_init_msg {
+ __u8 msgflg;
+#define NSP_CI 0x18 /* Connect Initiate */
+#define NSP_RCI 0x68 /* Retrans. Conn Init */
+ __le16 dstaddr;
+ __le16 srcaddr;
+ __u8 services;
+#define NSP_FC_NONE 0x00 /* Flow Control None */
+#define NSP_FC_SRC 0x04 /* Seg Req. Count */
+#define NSP_FC_SCMC 0x08 /* Sess. Control Mess */
+#define NSP_FC_MASK 0x0c /* FC type mask */
+ __u8 info;
+ __le16 segsize;
+} __packed;
+
+/* Disconnect Initiate/Disconnect Confirm */
+struct nsp_disconn_init_msg {
+ __u8 msgflg;
+ __le16 dstaddr;
+ __le16 srcaddr;
+ __le16 reason;
+} __packed;
+
+
+
+struct srcobj_fmt {
+ __u8 format;
+ __u8 task;
+ __le16 grpcode;
+ __le16 usrcode;
+ __u8 dlen;
+} __packed;
+
+/*
+ * A collection of functions for manipulating the sequence
+ * numbers used in NSP. Similar in operation to the functions
+ * of the same name in TCP.
+ */
+static __inline__ int dn_before(__u16 seq1, __u16 seq2)
+{
+ seq1 &= 0x0fff;
+ seq2 &= 0x0fff;
+
+ return (int)((seq1 - seq2) & 0x0fff) > 2048;
+}
+
+
+static __inline__ int dn_after(__u16 seq1, __u16 seq2)
+{
+ seq1 &= 0x0fff;
+ seq2 &= 0x0fff;
+
+ return (int)((seq2 - seq1) & 0x0fff) > 2048;
+}
+
+static __inline__ int dn_equal(__u16 seq1, __u16 seq2)
+{
+ return ((seq1 ^ seq2) & 0x0fff) == 0;
+}
+
+static __inline__ int dn_before_or_equal(__u16 seq1, __u16 seq2)
+{
+ return (dn_before(seq1, seq2) || dn_equal(seq1, seq2));
+}
+
+static __inline__ void seq_add(__u16 *seq, __u16 off)
+{
+ (*seq) += off;
+ (*seq) &= 0x0fff;
+}
+
+static __inline__ int seq_next(__u16 seq1, __u16 seq2)
+{
+ return dn_equal(seq1 + 1, seq2);
+}
+
+/*
+ * Can we delay the ack ?
+ */
+static __inline__ int sendack(__u16 seq)
+{
+ return (int)((seq & 0x1000) ? 0 : 1);
+}
+
+/*
+ * Is socket congested ?
+ */
+static __inline__ int dn_congested(struct sock *sk)
+{
+ return atomic_read(&sk->sk_rmem_alloc) > (sk->sk_rcvbuf >> 1);
+}
+
+#define DN_MAX_NSP_DATA_HEADER (11)
+
+#endif /* _NET_DN_NSP_H */
diff --git a/include/net/dn_route.h b/include/net/dn_route.h
new file mode 100644
index 00000000..81712cfa
--- /dev/null
+++ b/include/net/dn_route.h
@@ -0,0 +1,117 @@
+#ifndef _NET_DN_ROUTE_H
+#define _NET_DN_ROUTE_H
+
+/******************************************************************************
+ (c) 1995-1998 E.M. Serrat emserrat@geocities.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*******************************************************************************/
+
+extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri);
+extern int dn_route_output_sock(struct dst_entry **pprt, struct flowidn *, struct sock *sk, int flags);
+extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
+extern void dn_rt_cache_flush(int delay);
+
+/* Masks for flags field */
+#define DN_RT_F_PID 0x07 /* Mask for packet type */
+#define DN_RT_F_PF 0x80 /* Padding Follows */
+#define DN_RT_F_VER 0x40 /* Version =0 discard packet if ==1 */
+#define DN_RT_F_IE 0x20 /* Intra Ethernet, Reserved in short pkt */
+#define DN_RT_F_RTS 0x10 /* Packet is being returned to sender */
+#define DN_RT_F_RQR 0x08 /* Return packet to sender upon non-delivery */
+
+/* Mask for types of routing packets */
+#define DN_RT_PKT_MSK 0x06
+/* Types of routing packets */
+#define DN_RT_PKT_SHORT 0x02 /* Short routing packet */
+#define DN_RT_PKT_LONG 0x06 /* Long routing packet */
+
+/* Mask for control/routing selection */
+#define DN_RT_PKT_CNTL 0x01 /* Set to 1 if a control packet */
+/* Types of control packets */
+#define DN_RT_CNTL_MSK 0x0f /* Mask for control packets */
+#define DN_RT_PKT_INIT 0x01 /* Initialisation packet */
+#define DN_RT_PKT_VERI 0x03 /* Verification Message */
+#define DN_RT_PKT_HELO 0x05 /* Hello and Test Message */
+#define DN_RT_PKT_L1RT 0x07 /* Level 1 Routing Message */
+#define DN_RT_PKT_L2RT 0x09 /* Level 2 Routing Message */
+#define DN_RT_PKT_ERTH 0x0b /* Ethernet Router Hello */
+#define DN_RT_PKT_EEDH 0x0d /* Ethernet EndNode Hello */
+
+/* Values for info field in hello message */
+#define DN_RT_INFO_TYPE 0x03 /* Type mask */
+#define DN_RT_INFO_L1RT 0x02 /* L1 Router */
+#define DN_RT_INFO_L2RT 0x01 /* L2 Router */
+#define DN_RT_INFO_ENDN 0x03 /* EndNode */
+#define DN_RT_INFO_VERI 0x04 /* Verification Reqd. */
+#define DN_RT_INFO_RJCT 0x08 /* Reject Flag, Reserved */
+#define DN_RT_INFO_VFLD 0x10 /* Verification Failed, Reserved */
+#define DN_RT_INFO_NOML 0x20 /* No Multicast traffic accepted */
+#define DN_RT_INFO_BLKR 0x40 /* Blocking Requested */
+
+/*
+ * The fl structure is what we used to look up the route.
+ * The rt_saddr & rt_daddr entries are the same as key.saddr & key.daddr
+ * except for local input routes, where the rt_saddr = fl.fld_dst and
+ * rt_daddr = fl.fld_src to allow the route to be used for returning
+ * packets to the originating host.
+ */
+struct dn_route {
+ struct dst_entry dst;
+
+ struct flowidn fld;
+
+ __le16 rt_saddr;
+ __le16 rt_daddr;
+ __le16 rt_gateway;
+ __le16 rt_local_src; /* Source used for forwarding packets */
+ __le16 rt_src_map;
+ __le16 rt_dst_map;
+
+ unsigned rt_flags;
+ unsigned rt_type;
+};
+
+static inline bool dn_is_input_route(struct dn_route *rt)
+{
+ return rt->fld.flowidn_iif != 0;
+}
+
+static inline bool dn_is_output_route(struct dn_route *rt)
+{
+ return rt->fld.flowidn_iif == 0;
+}
+
+extern void dn_route_init(void);
+extern void dn_route_cleanup(void);
+
+#include <net/sock.h>
+#include <linux/if_arp.h>
+
+static inline void dn_rt_send(struct sk_buff *skb)
+{
+ dev_queue_xmit(skb);
+}
+
+static inline void dn_rt_finish_output(struct sk_buff *skb, char *dst, char *src)
+{
+ struct net_device *dev = skb->dev;
+
+ if ((dev->type != ARPHRD_ETHER) && (dev->type != ARPHRD_LOOPBACK))
+ dst = NULL;
+
+ if (dev_hard_header(skb, dev, ETH_P_DNA_RT, dst, src, skb->len) >= 0)
+ dn_rt_send(skb);
+ else
+ kfree_skb(skb);
+}
+
+#endif /* _NET_DN_ROUTE_H */
diff --git a/include/net/dsa.h b/include/net/dsa.h
new file mode 100644
index 00000000..7828ebf9
--- /dev/null
+++ b/include/net/dsa.h
@@ -0,0 +1,201 @@
+/*
+ * include/net/dsa.h - Driver for Distributed Switch Architecture switch chips
+ * Copyright (c) 2008-2009 Marvell Semiconductor
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __LINUX_NET_DSA_H
+#define __LINUX_NET_DSA_H
+
+#include <linux/if_ether.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+
+#define DSA_MAX_SWITCHES 4
+#define DSA_MAX_PORTS 12
+
+struct dsa_chip_data {
+ /*
+ * How to access the switch configuration registers.
+ */
+ struct device *mii_bus;
+ int sw_addr;
+
+ /*
+ * The names of the switch's ports. Use "cpu" to
+ * designate the switch port that the cpu is connected to,
+ * "dsa" to indicate that this port is a DSA link to
+ * another switch, NULL to indicate the port is unused,
+ * or any other string to indicate this is a physical port.
+ */
+ char *port_names[DSA_MAX_PORTS];
+
+ /*
+ * An array (with nr_chips elements) of which element [a]
+ * indicates which port on this switch should be used to
+ * send packets to that are destined for switch a. Can be
+ * NULL if there is only one switch chip.
+ */
+ s8 *rtable;
+};
+
+struct dsa_platform_data {
+ /*
+ * Reference to a Linux network interface that connects
+ * to the root switch chip of the tree.
+ */
+ struct device *netdev;
+
+ /*
+ * Info structs describing each of the switch chips
+ * connected via this network interface.
+ */
+ int nr_chips;
+ struct dsa_chip_data *chip;
+};
+
+struct dsa_switch_tree {
+ /*
+ * Configuration data for the platform device that owns
+ * this dsa switch tree instance.
+ */
+ struct dsa_platform_data *pd;
+
+ /*
+ * Reference to network device to use, and which tagging
+ * protocol to use.
+ */
+ struct net_device *master_netdev;
+ __be16 tag_protocol;
+
+ /*
+ * The switch and port to which the CPU is attached.
+ */
+ s8 cpu_switch;
+ s8 cpu_port;
+
+ /*
+ * Link state polling.
+ */
+ int link_poll_needed;
+ struct work_struct link_poll_work;
+ struct timer_list link_poll_timer;
+
+ /*
+ * Data for the individual switch chips.
+ */
+ struct dsa_switch *ds[DSA_MAX_SWITCHES];
+};
+
+struct dsa_switch {
+ /*
+ * Parent switch tree, and switch index.
+ */
+ struct dsa_switch_tree *dst;
+ int index;
+
+ /*
+ * Configuration data for this switch.
+ */
+ struct dsa_chip_data *pd;
+
+ /*
+ * The used switch driver.
+ */
+ struct dsa_switch_driver *drv;
+
+ /*
+ * Reference to mii bus to use.
+ */
+ struct mii_bus *master_mii_bus;
+
+ /*
+ * Slave mii_bus and devices for the individual ports.
+ */
+ u32 dsa_port_mask;
+ u32 phys_port_mask;
+ struct mii_bus *slave_mii_bus;
+ struct net_device *ports[DSA_MAX_PORTS];
+};
+
+static inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p)
+{
+ return !!(ds->index == ds->dst->cpu_switch && p == ds->dst->cpu_port);
+}
+
+static inline u8 dsa_upstream_port(struct dsa_switch *ds)
+{
+ struct dsa_switch_tree *dst = ds->dst;
+
+ /*
+ * If this is the root switch (i.e. the switch that connects
+ * to the CPU), return the cpu port number on this switch.
+ * Else return the (DSA) port number that connects to the
+ * switch that is one hop closer to the cpu.
+ */
+ if (dst->cpu_switch == ds->index)
+ return dst->cpu_port;
+ else
+ return ds->pd->rtable[dst->cpu_switch];
+}
+
+struct dsa_switch_driver {
+ struct list_head list;
+
+ __be16 tag_protocol;
+ int priv_size;
+
+ /*
+ * Probing and setup.
+ */
+ char *(*probe)(struct mii_bus *bus, int sw_addr);
+ int (*setup)(struct dsa_switch *ds);
+ int (*set_addr)(struct dsa_switch *ds, u8 *addr);
+
+ /*
+ * Access to the switch's PHY registers.
+ */
+ int (*phy_read)(struct dsa_switch *ds, int port, int regnum);
+ int (*phy_write)(struct dsa_switch *ds, int port,
+ int regnum, u16 val);
+
+ /*
+ * Link state polling and IRQ handling.
+ */
+ void (*poll_link)(struct dsa_switch *ds);
+
+ /*
+ * ethtool hardware statistics.
+ */
+ void (*get_strings)(struct dsa_switch *ds, int port, uint8_t *data);
+ void (*get_ethtool_stats)(struct dsa_switch *ds,
+ int port, uint64_t *data);
+ int (*get_sset_count)(struct dsa_switch *ds);
+};
+
+void register_switch_driver(struct dsa_switch_driver *type);
+void unregister_switch_driver(struct dsa_switch_driver *type);
+
+/*
+ * The original DSA tag format and some other tag formats have no
+ * ethertype, which means that we need to add a little hack to the
+ * networking receive path to make sure that received frames get
+ * the right ->protocol assigned to them when one of those tag
+ * formats is in use.
+ */
+static inline bool dsa_uses_dsa_tags(struct dsa_switch_tree *dst)
+{
+ return !!(dst->tag_protocol == htons(ETH_P_DSA));
+}
+
+static inline bool dsa_uses_trailer_tags(struct dsa_switch_tree *dst)
+{
+ return !!(dst->tag_protocol == htons(ETH_P_TRAILER));
+}
+
+#endif
diff --git a/include/net/dsfield.h b/include/net/dsfield.h
new file mode 100644
index 00000000..8a8d4e06
--- /dev/null
+++ b/include/net/dsfield.h
@@ -0,0 +1,54 @@
+/* include/net/dsfield.h - Manipulation of the Differentiated Services field */
+
+/* Written 1998-2000 by Werner Almesberger, EPFL ICA */
+
+
+#ifndef __NET_DSFIELD_H
+#define __NET_DSFIELD_H
+
+#include <linux/types.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <asm/byteorder.h>
+
+
+static inline __u8 ipv4_get_dsfield(const struct iphdr *iph)
+{
+ return iph->tos;
+}
+
+
+static inline __u8 ipv6_get_dsfield(const struct ipv6hdr *ipv6h)
+{
+ return ntohs(*(const __be16 *)ipv6h) >> 4;
+}
+
+
+static inline void ipv4_change_dsfield(struct iphdr *iph,__u8 mask,
+ __u8 value)
+{
+ __u32 check = ntohs((__force __be16)iph->check);
+ __u8 dsfield;
+
+ dsfield = (iph->tos & mask) | value;
+ check += iph->tos;
+ if ((check+1) >> 16) check = (check+1) & 0xffff;
+ check -= dsfield;
+ check += check >> 16; /* adjust carry */
+ iph->check = (__force __sum16)htons(check);
+ iph->tos = dsfield;
+}
+
+
+static inline void ipv6_change_dsfield(struct ipv6hdr *ipv6h,__u8 mask,
+ __u8 value)
+{
+ __u16 tmp;
+
+ tmp = ntohs(*(__be16 *) ipv6h);
+ tmp = (tmp & ((mask << 4) | 0xf00f)) | (value << 4);
+ *(__be16 *) ipv6h = htons(tmp);
+}
+
+
+#endif
diff --git a/include/net/dst.h b/include/net/dst.h
new file mode 100644
index 00000000..8197eadc
--- /dev/null
+++ b/include/net/dst.h
@@ -0,0 +1,473 @@
+/*
+ * net/dst.h Protocol independent destination cache definitions.
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ */
+
+#ifndef _NET_DST_H
+#define _NET_DST_H
+
+#include <net/dst_ops.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/rcupdate.h>
+#include <linux/bug.h>
+#include <linux/jiffies.h>
+#include <net/neighbour.h>
+#include <asm/processor.h>
+
+#define DST_GC_MIN (HZ/10)
+#define DST_GC_INC (HZ/2)
+#define DST_GC_MAX (120*HZ)
+
+/* Each dst_entry has reference count and sits in some parent list(s).
+ * When it is removed from parent list, it is "freed" (dst_free).
+ * After this it enters dead state (dst->obsolete > 0) and if its refcnt
+ * is zero, it can be destroyed immediately, otherwise it is added
+ * to gc list and garbage collector periodically checks the refcnt.
+ */
+
+struct sk_buff;
+
+struct dst_entry {
+ struct rcu_head rcu_head;
+ struct dst_entry *child;
+ struct net_device *dev;
+ struct dst_ops *ops;
+ unsigned long _metrics;
+ union {
+ unsigned long expires;
+ /* point to where the dst_entry copied from */
+ struct dst_entry *from;
+ };
+ struct dst_entry *path;
+ struct neighbour __rcu *_neighbour;
+#ifdef CONFIG_XFRM
+ struct xfrm_state *xfrm;
+#else
+ void *__pad1;
+#endif
+ int (*input)(struct sk_buff*);
+ int (*output)(struct sk_buff*);
+
+ int flags;
+#define DST_HOST 0x0001
+#define DST_NOXFRM 0x0002
+#define DST_NOPOLICY 0x0004
+#define DST_NOHASH 0x0008
+#define DST_NOCACHE 0x0010
+#define DST_NOCOUNT 0x0020
+#define DST_NOPEER 0x0040
+#define DST_FAKE_RTABLE 0x0080
+#define DST_XFRM_TUNNEL 0x0100
+
+ short error;
+ short obsolete;
+ unsigned short header_len; /* more space at head required */
+ unsigned short trailer_len; /* space to reserve at tail */
+#ifdef CONFIG_IP_ROUTE_CLASSID
+ __u32 tclassid;
+#else
+ __u32 __pad2;
+#endif
+
+ /*
+ * Align __refcnt to a 64 bytes alignment
+ * (L1_CACHE_SIZE would be too much)
+ */
+#ifdef CONFIG_64BIT
+ long __pad_to_align_refcnt[2];
+#endif
+ /*
+ * __refcnt wants to be on a different cache line from
+ * input/output/ops or performance tanks badly
+ */
+ atomic_t __refcnt; /* client references */
+ int __use;
+ unsigned long lastuse;
+ union {
+ struct dst_entry *next;
+ struct rtable __rcu *rt_next;
+ struct rt6_info *rt6_next;
+ struct dn_route __rcu *dn_next;
+ };
+};
+
+static inline struct neighbour *dst_get_neighbour_noref(struct dst_entry *dst)
+{
+ return rcu_dereference(dst->_neighbour);
+}
+
+static inline struct neighbour *dst_get_neighbour_noref_raw(struct dst_entry *dst)
+{
+ return rcu_dereference_raw(dst->_neighbour);
+}
+
+static inline void dst_set_neighbour(struct dst_entry *dst, struct neighbour *neigh)
+{
+ rcu_assign_pointer(dst->_neighbour, neigh);
+}
+
+extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old);
+extern const u32 dst_default_metrics[RTAX_MAX];
+
+#define DST_METRICS_READ_ONLY 0x1UL
+#define __DST_METRICS_PTR(Y) \
+ ((u32 *)((Y) & ~DST_METRICS_READ_ONLY))
+#define DST_METRICS_PTR(X) __DST_METRICS_PTR((X)->_metrics)
+
+static inline bool dst_metrics_read_only(const struct dst_entry *dst)
+{
+ return dst->_metrics & DST_METRICS_READ_ONLY;
+}
+
+extern void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old);
+
+static inline void dst_destroy_metrics_generic(struct dst_entry *dst)
+{
+ unsigned long val = dst->_metrics;
+ if (!(val & DST_METRICS_READ_ONLY))
+ __dst_destroy_metrics_generic(dst, val);
+}
+
+static inline u32 *dst_metrics_write_ptr(struct dst_entry *dst)
+{
+ unsigned long p = dst->_metrics;
+
+ BUG_ON(!p);
+
+ if (p & DST_METRICS_READ_ONLY)
+ return dst->ops->cow_metrics(dst, p);
+ return __DST_METRICS_PTR(p);
+}
+
+/* This may only be invoked before the entry has reached global
+ * visibility.
+ */
+static inline void dst_init_metrics(struct dst_entry *dst,
+ const u32 *src_metrics,
+ bool read_only)
+{
+ dst->_metrics = ((unsigned long) src_metrics) |
+ (read_only ? DST_METRICS_READ_ONLY : 0);
+}
+
+static inline void dst_copy_metrics(struct dst_entry *dest, const struct dst_entry *src)
+{
+ u32 *dst_metrics = dst_metrics_write_ptr(dest);
+
+ if (dst_metrics) {
+ u32 *src_metrics = DST_METRICS_PTR(src);
+
+ memcpy(dst_metrics, src_metrics, RTAX_MAX * sizeof(u32));
+ }
+}
+
+static inline u32 *dst_metrics_ptr(struct dst_entry *dst)
+{
+ return DST_METRICS_PTR(dst);
+}
+
+static inline u32
+dst_metric_raw(const struct dst_entry *dst, const int metric)
+{
+ u32 *p = DST_METRICS_PTR(dst);
+
+ return p[metric-1];
+}
+
+static inline u32
+dst_metric(const struct dst_entry *dst, const int metric)
+{
+ WARN_ON_ONCE(metric == RTAX_HOPLIMIT ||
+ metric == RTAX_ADVMSS ||
+ metric == RTAX_MTU);
+ return dst_metric_raw(dst, metric);
+}
+
+static inline u32
+dst_metric_advmss(const struct dst_entry *dst)
+{
+ u32 advmss = dst_metric_raw(dst, RTAX_ADVMSS);
+
+ if (!advmss)
+ advmss = dst->ops->default_advmss(dst);
+
+ return advmss;
+}
+
+static inline void dst_metric_set(struct dst_entry *dst, int metric, u32 val)
+{
+ u32 *p = dst_metrics_write_ptr(dst);
+
+ if (p)
+ p[metric-1] = val;
+}
+
+static inline u32
+dst_feature(const struct dst_entry *dst, u32 feature)
+{
+ return dst_metric(dst, RTAX_FEATURES) & feature;
+}
+
+static inline u32 dst_mtu(const struct dst_entry *dst)
+{
+ return dst->ops->mtu(dst);
+}
+
+/* RTT metrics are stored in milliseconds for user ABI, but used as jiffies */
+static inline unsigned long dst_metric_rtt(const struct dst_entry *dst, int metric)
+{
+ return msecs_to_jiffies(dst_metric(dst, metric));
+}
+
+static inline void set_dst_metric_rtt(struct dst_entry *dst, int metric,
+ unsigned long rtt)
+{
+ dst_metric_set(dst, metric, jiffies_to_msecs(rtt));
+}
+
+static inline u32
+dst_allfrag(const struct dst_entry *dst)
+{
+ int ret = dst_feature(dst, RTAX_FEATURE_ALLFRAG);
+ return ret;
+}
+
+static inline int
+dst_metric_locked(const struct dst_entry *dst, int metric)
+{
+ return dst_metric(dst, RTAX_LOCK) & (1<<metric);
+}
+
+static inline void dst_hold(struct dst_entry * dst)
+{
+ /*
+ * If your kernel compilation stops here, please check
+ * __pad_to_align_refcnt declaration in struct dst_entry
+ */
+ BUILD_BUG_ON(offsetof(struct dst_entry, __refcnt) & 63);
+ atomic_inc(&dst->__refcnt);
+}
+
+static inline void dst_use(struct dst_entry *dst, unsigned long time)
+{
+ dst_hold(dst);
+ dst->__use++;
+ dst->lastuse = time;
+}
+
+static inline void dst_use_noref(struct dst_entry *dst, unsigned long time)
+{
+ dst->__use++;
+ dst->lastuse = time;
+}
+
+static inline
+struct dst_entry * dst_clone(struct dst_entry * dst)
+{
+ if (dst)
+ atomic_inc(&dst->__refcnt);
+ return dst;
+}
+
+extern void dst_release(struct dst_entry *dst);
+
+static inline void refdst_drop(unsigned long refdst)
+{
+ if (!(refdst & SKB_DST_NOREF))
+ dst_release((struct dst_entry *)(refdst & SKB_DST_PTRMASK));
+}
+
+/**
+ * skb_dst_drop - drops skb dst
+ * @skb: buffer
+ *
+ * Drops dst reference count if a reference was taken.
+ */
+static inline void skb_dst_drop(struct sk_buff *skb)
+{
+ if (skb->_skb_refdst) {
+ refdst_drop(skb->_skb_refdst);
+ skb->_skb_refdst = 0UL;
+ }
+}
+
+static inline void skb_dst_copy(struct sk_buff *nskb, const struct sk_buff *oskb)
+{
+ nskb->_skb_refdst = oskb->_skb_refdst;
+ if (!(nskb->_skb_refdst & SKB_DST_NOREF))
+ dst_clone(skb_dst(nskb));
+}
+
+/**
+ * skb_dst_force - makes sure skb dst is refcounted
+ * @skb: buffer
+ *
+ * If dst is not yet refcounted, let's do it
+ */
+static inline void skb_dst_force(struct sk_buff *skb)
+{
+ if (skb_dst_is_noref(skb)) {
+ WARN_ON(!rcu_read_lock_held());
+ skb->_skb_refdst &= ~SKB_DST_NOREF;
+ dst_clone(skb_dst(skb));
+ }
+}
+
+
+/**
+ * __skb_tunnel_rx - prepare skb for rx reinsert
+ * @skb: buffer
+ * @dev: tunnel device
+ *
+ * After decapsulation, packet is going to re-enter (netif_rx()) our stack,
+ * so make some cleanups. (no accounting done)
+ */
+static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev)
+{
+ skb->dev = dev;
+
+ /*
+ * Clear rxhash so that we can recalulate the hash for the
+ * encapsulated packet, unless we have already determine the hash
+ * over the L4 4-tuple.
+ */
+ if (!skb->l4_rxhash)
+ skb->rxhash = 0;
+ skb_set_queue_mapping(skb, 0);
+ skb_dst_drop(skb);
+ nf_reset(skb);
+}
+
+/**
+ * skb_tunnel_rx - prepare skb for rx reinsert
+ * @skb: buffer
+ * @dev: tunnel device
+ *
+ * After decapsulation, packet is going to re-enter (netif_rx()) our stack,
+ * so make some cleanups, and perform accounting.
+ * Note: this accounting is not SMP safe.
+ */
+static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev)
+{
+ /* TODO : stats should be SMP safe */
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += skb->len;
+ __skb_tunnel_rx(skb, dev);
+}
+
+/* Children define the path of the packet through the
+ * Linux networking. Thus, destinations are stackable.
+ */
+
+static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb)
+{
+ struct dst_entry *child = dst_clone(skb_dst(skb)->child);
+
+ skb_dst_drop(skb);
+ return child;
+}
+
+extern int dst_discard(struct sk_buff *skb);
+extern void *dst_alloc(struct dst_ops * ops, struct net_device *dev,
+ int initial_ref, int initial_obsolete, int flags);
+extern void __dst_free(struct dst_entry * dst);
+extern struct dst_entry *dst_destroy(struct dst_entry * dst);
+
+static inline void dst_free(struct dst_entry * dst)
+{
+ if (dst->obsolete > 1)
+ return;
+ if (!atomic_read(&dst->__refcnt)) {
+ dst = dst_destroy(dst);
+ if (!dst)
+ return;
+ }
+ __dst_free(dst);
+}
+
+static inline void dst_rcu_free(struct rcu_head *head)
+{
+ struct dst_entry *dst = container_of(head, struct dst_entry, rcu_head);
+ dst_free(dst);
+}
+
+static inline void dst_confirm(struct dst_entry *dst)
+{
+ if (dst) {
+ struct neighbour *n;
+
+ rcu_read_lock();
+ n = dst_get_neighbour_noref(dst);
+ neigh_confirm(n);
+ rcu_read_unlock();
+ }
+}
+
+static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
+{
+ return dst->ops->neigh_lookup(dst, daddr);
+}
+
+static inline void dst_link_failure(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb_dst(skb);
+ if (dst && dst->ops && dst->ops->link_failure)
+ dst->ops->link_failure(skb);
+}
+
+static inline void dst_set_expires(struct dst_entry *dst, int timeout)
+{
+ unsigned long expires = jiffies + timeout;
+
+ if (expires == 0)
+ expires = 1;
+
+ if (dst->expires == 0 || time_before(expires, dst->expires))
+ dst->expires = expires;
+}
+
+/* Output packet to network from transport. */
+static inline int dst_output(struct sk_buff *skb)
+{
+ return skb_dst(skb)->output(skb);
+}
+
+/* Input packet from network to transport. */
+static inline int dst_input(struct sk_buff *skb)
+{
+ return skb_dst(skb)->input(skb);
+}
+
+static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie)
+{
+ if (dst->obsolete)
+ dst = dst->ops->check(dst, cookie);
+ return dst;
+}
+
+extern void dst_init(void);
+
+/* Flags for xfrm_lookup flags argument. */
+enum {
+ XFRM_LOOKUP_ICMP = 1 << 0,
+};
+
+struct flowi;
+#ifndef CONFIG_XFRM
+static inline struct dst_entry *xfrm_lookup(struct net *net,
+ struct dst_entry *dst_orig,
+ const struct flowi *fl, struct sock *sk,
+ int flags)
+{
+ return dst_orig;
+}
+#else
+extern struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
+ const struct flowi *fl, struct sock *sk,
+ int flags);
+#endif
+
+#endif /* _NET_DST_H */
diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h
new file mode 100644
index 00000000..e1c2ee0e
--- /dev/null
+++ b/include/net/dst_ops.h
@@ -0,0 +1,68 @@
+#ifndef _NET_DST_OPS_H
+#define _NET_DST_OPS_H
+#include <linux/types.h>
+#include <linux/percpu_counter.h>
+#include <linux/cache.h>
+
+struct dst_entry;
+struct kmem_cachep;
+struct net_device;
+struct sk_buff;
+
+struct dst_ops {
+ unsigned short family;
+ __be16 protocol;
+ unsigned gc_thresh;
+
+ int (*gc)(struct dst_ops *ops);
+ struct dst_entry * (*check)(struct dst_entry *, __u32 cookie);
+ unsigned int (*default_advmss)(const struct dst_entry *);
+ unsigned int (*mtu)(const struct dst_entry *);
+ u32 * (*cow_metrics)(struct dst_entry *, unsigned long);
+ void (*destroy)(struct dst_entry *);
+ void (*ifdown)(struct dst_entry *,
+ struct net_device *dev, int how);
+ struct dst_entry * (*negative_advice)(struct dst_entry *);
+ void (*link_failure)(struct sk_buff *);
+ void (*update_pmtu)(struct dst_entry *dst, u32 mtu);
+ int (*local_out)(struct sk_buff *skb);
+ struct neighbour * (*neigh_lookup)(const struct dst_entry *dst, const void *daddr);
+
+ struct kmem_cache *kmem_cachep;
+
+ struct percpu_counter pcpuc_entries ____cacheline_aligned_in_smp;
+};
+
+static inline int dst_entries_get_fast(struct dst_ops *dst)
+{
+ return percpu_counter_read_positive(&dst->pcpuc_entries);
+}
+
+static inline int dst_entries_get_slow(struct dst_ops *dst)
+{
+ int res;
+
+ local_bh_disable();
+ res = percpu_counter_sum_positive(&dst->pcpuc_entries);
+ local_bh_enable();
+ return res;
+}
+
+static inline void dst_entries_add(struct dst_ops *dst, int val)
+{
+ local_bh_disable();
+ percpu_counter_add(&dst->pcpuc_entries, val);
+ local_bh_enable();
+}
+
+static inline int dst_entries_init(struct dst_ops *dst)
+{
+ return percpu_counter_init(&dst->pcpuc_entries, 0);
+}
+
+static inline void dst_entries_destroy(struct dst_ops *dst)
+{
+ percpu_counter_destroy(&dst->pcpuc_entries);
+}
+
+#endif
diff --git a/include/net/esp.h b/include/net/esp.h
new file mode 100644
index 00000000..d5845133
--- /dev/null
+++ b/include/net/esp.h
@@ -0,0 +1,25 @@
+#ifndef _NET_ESP_H
+#define _NET_ESP_H
+
+#include <linux/skbuff.h>
+
+struct crypto_aead;
+
+struct esp_data {
+ /* 0..255 */
+ int padlen;
+
+ /* Confidentiality & Integrity */
+ struct crypto_aead *aead;
+};
+
+extern void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len);
+
+struct ip_esp_hdr;
+
+static inline struct ip_esp_hdr *ip_esp_hdr(const struct sk_buff *skb)
+{
+ return (struct ip_esp_hdr *)skb_transport_header(skb);
+}
+
+#endif
diff --git a/include/net/ethoc.h b/include/net/ethoc.h
new file mode 100644
index 00000000..96f3789b
--- /dev/null
+++ b/include/net/ethoc.h
@@ -0,0 +1,22 @@
+/*
+ * linux/include/net/ethoc.h
+ *
+ * Copyright (C) 2008-2009 Avionic Design GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Written by Thierry Reding <thierry.reding@avionic-design.de>
+ */
+
+#ifndef LINUX_NET_ETHOC_H
+#define LINUX_NET_ETHOC_H 1
+
+struct ethoc_platform_data {
+ u8 hwaddr[IFHWADDRLEN];
+ s8 phy_id;
+};
+
+#endif /* !LINUX_NET_ETHOC_H */
+
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
new file mode 100644
index 00000000..075f1e3a
--- /dev/null
+++ b/include/net/fib_rules.h
@@ -0,0 +1,119 @@
+#ifndef __NET_FIB_RULES_H
+#define __NET_FIB_RULES_H
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/fib_rules.h>
+#include <net/flow.h>
+#include <net/rtnetlink.h>
+
+struct fib_rule {
+ struct list_head list;
+ atomic_t refcnt;
+ int iifindex;
+ int oifindex;
+ u32 mark;
+ u32 mark_mask;
+ u32 pref;
+ u32 flags;
+ u32 table;
+ u8 action;
+ u32 target;
+ struct fib_rule __rcu *ctarget;
+ char iifname[IFNAMSIZ];
+ char oifname[IFNAMSIZ];
+ struct rcu_head rcu;
+ struct net * fr_net;
+};
+
+struct fib_lookup_arg {
+ void *lookup_ptr;
+ void *result;
+ struct fib_rule *rule;
+ int flags;
+#define FIB_LOOKUP_NOREF 1
+};
+
+struct fib_rules_ops {
+ int family;
+ struct list_head list;
+ int rule_size;
+ int addr_size;
+ int unresolved_rules;
+ int nr_goto_rules;
+
+ int (*action)(struct fib_rule *,
+ struct flowi *, int,
+ struct fib_lookup_arg *);
+ int (*match)(struct fib_rule *,
+ struct flowi *, int);
+ int (*configure)(struct fib_rule *,
+ struct sk_buff *,
+ struct fib_rule_hdr *,
+ struct nlattr **);
+ int (*compare)(struct fib_rule *,
+ struct fib_rule_hdr *,
+ struct nlattr **);
+ int (*fill)(struct fib_rule *, struct sk_buff *,
+ struct fib_rule_hdr *);
+ u32 (*default_pref)(struct fib_rules_ops *ops);
+ size_t (*nlmsg_payload)(struct fib_rule *);
+
+ /* Called after modifications to the rules set, must flush
+ * the route cache if one exists. */
+ void (*flush_cache)(struct fib_rules_ops *ops);
+
+ int nlgroup;
+ const struct nla_policy *policy;
+ struct list_head rules_list;
+ struct module *owner;
+ struct net *fro_net;
+ struct rcu_head rcu;
+};
+
+#define FRA_GENERIC_POLICY \
+ [FRA_IIFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, \
+ [FRA_OIFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, \
+ [FRA_PRIORITY] = { .type = NLA_U32 }, \
+ [FRA_FWMARK] = { .type = NLA_U32 }, \
+ [FRA_FWMASK] = { .type = NLA_U32 }, \
+ [FRA_TABLE] = { .type = NLA_U32 }, \
+ [FRA_GOTO] = { .type = NLA_U32 }
+
+static inline void fib_rule_get(struct fib_rule *rule)
+{
+ atomic_inc(&rule->refcnt);
+}
+
+static inline void fib_rule_put_rcu(struct rcu_head *head)
+{
+ struct fib_rule *rule = container_of(head, struct fib_rule, rcu);
+ release_net(rule->fr_net);
+ kfree(rule);
+}
+
+static inline void fib_rule_put(struct fib_rule *rule)
+{
+ if (atomic_dec_and_test(&rule->refcnt))
+ call_rcu(&rule->rcu, fib_rule_put_rcu);
+}
+
+static inline u32 frh_get_table(struct fib_rule_hdr *frh, struct nlattr **nla)
+{
+ if (nla[FRA_TABLE])
+ return nla_get_u32(nla[FRA_TABLE]);
+ return frh->table;
+}
+
+extern struct fib_rules_ops *fib_rules_register(const struct fib_rules_ops *, struct net *);
+extern void fib_rules_unregister(struct fib_rules_ops *);
+
+extern int fib_rules_lookup(struct fib_rules_ops *,
+ struct flowi *, int flags,
+ struct fib_lookup_arg *);
+extern int fib_default_rule_add(struct fib_rules_ops *,
+ u32 pref, u32 table,
+ u32 flags);
+extern u32 fib_default_rule_pref(struct fib_rules_ops *ops);
+#endif
diff --git a/include/net/flow.h b/include/net/flow.h
new file mode 100644
index 00000000..6c469dbd
--- /dev/null
+++ b/include/net/flow.h
@@ -0,0 +1,226 @@
+/*
+ *
+ * Generic internet FLOW.
+ *
+ */
+
+#ifndef _NET_FLOW_H
+#define _NET_FLOW_H
+
+#include <linux/socket.h>
+#include <linux/in6.h>
+#include <linux/atomic.h>
+
+struct flowi_common {
+ int flowic_oif;
+ int flowic_iif;
+ __u32 flowic_mark;
+ __u8 flowic_tos;
+ __u8 flowic_scope;
+ __u8 flowic_proto;
+ __u8 flowic_flags;
+#define FLOWI_FLAG_ANYSRC 0x01
+#define FLOWI_FLAG_PRECOW_METRICS 0x02
+#define FLOWI_FLAG_CAN_SLEEP 0x04
+ __u32 flowic_secid;
+};
+
+union flowi_uli {
+ struct {
+ __be16 dport;
+ __be16 sport;
+ } ports;
+
+ struct {
+ __u8 type;
+ __u8 code;
+ } icmpt;
+
+ struct {
+ __le16 dport;
+ __le16 sport;
+ } dnports;
+
+ __be32 spi;
+ __be32 gre_key;
+
+ struct {
+ __u8 type;
+ } mht;
+};
+
+struct flowi4 {
+ struct flowi_common __fl_common;
+#define flowi4_oif __fl_common.flowic_oif
+#define flowi4_iif __fl_common.flowic_iif
+#define flowi4_mark __fl_common.flowic_mark
+#define flowi4_tos __fl_common.flowic_tos
+#define flowi4_scope __fl_common.flowic_scope
+#define flowi4_proto __fl_common.flowic_proto
+#define flowi4_flags __fl_common.flowic_flags
+#define flowi4_secid __fl_common.flowic_secid
+
+ /* (saddr,daddr) must be grouped, same order as in IP header */
+ __be32 saddr;
+ __be32 daddr;
+
+ union flowi_uli uli;
+#define fl4_sport uli.ports.sport
+#define fl4_dport uli.ports.dport
+#define fl4_icmp_type uli.icmpt.type
+#define fl4_icmp_code uli.icmpt.code
+#define fl4_ipsec_spi uli.spi
+#define fl4_mh_type uli.mht.type
+#define fl4_gre_key uli.gre_key
+} __attribute__((__aligned__(BITS_PER_LONG/8)));
+
+static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
+ __u32 mark, __u8 tos, __u8 scope,
+ __u8 proto, __u8 flags,
+ __be32 daddr, __be32 saddr,
+ __be16 dport, __be16 sport)
+{
+ fl4->flowi4_oif = oif;
+ fl4->flowi4_iif = 0;
+ fl4->flowi4_mark = mark;
+ fl4->flowi4_tos = tos;
+ fl4->flowi4_scope = scope;
+ fl4->flowi4_proto = proto;
+ fl4->flowi4_flags = flags;
+ fl4->flowi4_secid = 0;
+ fl4->daddr = daddr;
+ fl4->saddr = saddr;
+ fl4->fl4_dport = dport;
+ fl4->fl4_sport = sport;
+}
+
+/* Reset some input parameters after previous lookup */
+static inline void flowi4_update_output(struct flowi4 *fl4, int oif, __u8 tos,
+ __be32 daddr, __be32 saddr)
+{
+ fl4->flowi4_oif = oif;
+ fl4->flowi4_tos = tos;
+ fl4->daddr = daddr;
+ fl4->saddr = saddr;
+}
+
+
+struct flowi6 {
+ struct flowi_common __fl_common;
+#define flowi6_oif __fl_common.flowic_oif
+#define flowi6_iif __fl_common.flowic_iif
+#define flowi6_mark __fl_common.flowic_mark
+#define flowi6_tos __fl_common.flowic_tos
+#define flowi6_scope __fl_common.flowic_scope
+#define flowi6_proto __fl_common.flowic_proto
+#define flowi6_flags __fl_common.flowic_flags
+#define flowi6_secid __fl_common.flowic_secid
+ struct in6_addr daddr;
+ struct in6_addr saddr;
+ __be32 flowlabel;
+ union flowi_uli uli;
+#define fl6_sport uli.ports.sport
+#define fl6_dport uli.ports.dport
+#define fl6_icmp_type uli.icmpt.type
+#define fl6_icmp_code uli.icmpt.code
+#define fl6_ipsec_spi uli.spi
+#define fl6_mh_type uli.mht.type
+#define fl6_gre_key uli.gre_key
+} __attribute__((__aligned__(BITS_PER_LONG/8)));
+
+struct flowidn {
+ struct flowi_common __fl_common;
+#define flowidn_oif __fl_common.flowic_oif
+#define flowidn_iif __fl_common.flowic_iif
+#define flowidn_mark __fl_common.flowic_mark
+#define flowidn_scope __fl_common.flowic_scope
+#define flowidn_proto __fl_common.flowic_proto
+#define flowidn_flags __fl_common.flowic_flags
+ __le16 daddr;
+ __le16 saddr;
+ union flowi_uli uli;
+#define fld_sport uli.ports.sport
+#define fld_dport uli.ports.dport
+} __attribute__((__aligned__(BITS_PER_LONG/8)));
+
+struct flowi {
+ union {
+ struct flowi_common __fl_common;
+ struct flowi4 ip4;
+ struct flowi6 ip6;
+ struct flowidn dn;
+ } u;
+#define flowi_oif u.__fl_common.flowic_oif
+#define flowi_iif u.__fl_common.flowic_iif
+#define flowi_mark u.__fl_common.flowic_mark
+#define flowi_tos u.__fl_common.flowic_tos
+#define flowi_scope u.__fl_common.flowic_scope
+#define flowi_proto u.__fl_common.flowic_proto
+#define flowi_flags u.__fl_common.flowic_flags
+#define flowi_secid u.__fl_common.flowic_secid
+} __attribute__((__aligned__(BITS_PER_LONG/8)));
+
+static inline struct flowi *flowi4_to_flowi(struct flowi4 *fl4)
+{
+ return container_of(fl4, struct flowi, u.ip4);
+}
+
+static inline struct flowi *flowi6_to_flowi(struct flowi6 *fl6)
+{
+ return container_of(fl6, struct flowi, u.ip6);
+}
+
+static inline struct flowi *flowidn_to_flowi(struct flowidn *fldn)
+{
+ return container_of(fldn, struct flowi, u.dn);
+}
+
+typedef unsigned long flow_compare_t;
+
+static inline size_t flow_key_size(u16 family)
+{
+ switch (family) {
+ case AF_INET:
+ BUILD_BUG_ON(sizeof(struct flowi4) % sizeof(flow_compare_t));
+ return sizeof(struct flowi4) / sizeof(flow_compare_t);
+ case AF_INET6:
+ BUILD_BUG_ON(sizeof(struct flowi6) % sizeof(flow_compare_t));
+ return sizeof(struct flowi6) / sizeof(flow_compare_t);
+ case AF_DECnet:
+ BUILD_BUG_ON(sizeof(struct flowidn) % sizeof(flow_compare_t));
+ return sizeof(struct flowidn) / sizeof(flow_compare_t);
+ }
+ return 0;
+}
+
+#define FLOW_DIR_IN 0
+#define FLOW_DIR_OUT 1
+#define FLOW_DIR_FWD 2
+
+struct net;
+struct sock;
+struct flow_cache_ops;
+
+struct flow_cache_object {
+ const struct flow_cache_ops *ops;
+};
+
+struct flow_cache_ops {
+ struct flow_cache_object *(*get)(struct flow_cache_object *);
+ int (*check)(struct flow_cache_object *);
+ void (*delete)(struct flow_cache_object *);
+};
+
+typedef struct flow_cache_object *(*flow_resolve_t)(
+ struct net *net, const struct flowi *key, u16 family,
+ u8 dir, struct flow_cache_object *oldobj, void *ctx);
+
+extern struct flow_cache_object *flow_cache_lookup(
+ struct net *net, const struct flowi *key, u16 family,
+ u8 dir, flow_resolve_t resolver, void *ctx);
+
+extern void flow_cache_flush(void);
+extern void flow_cache_flush_deferred(void);
+extern atomic_t flow_cache_genid;
+
+#endif
diff --git a/include/net/flow_keys.h b/include/net/flow_keys.h
new file mode 100644
index 00000000..80461c1a
--- /dev/null
+++ b/include/net/flow_keys.h
@@ -0,0 +1,16 @@
+#ifndef _NET_FLOW_KEYS_H
+#define _NET_FLOW_KEYS_H
+
+struct flow_keys {
+ /* (src,dst) must be grouped, in the same way than in IP header */
+ __be32 src;
+ __be32 dst;
+ union {
+ __be32 ports;
+ __be16 port16[2];
+ };
+ u8 ip_proto;
+};
+
+extern bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow);
+#endif
diff --git a/include/net/garp.h b/include/net/garp.h
new file mode 100644
index 00000000..834d8add
--- /dev/null
+++ b/include/net/garp.h
@@ -0,0 +1,130 @@
+#ifndef _NET_GARP_H
+#define _NET_GARP_H
+
+#include <net/stp.h>
+
+#define GARP_PROTOCOL_ID 0x1
+#define GARP_END_MARK 0x0
+
+struct garp_pdu_hdr {
+ __be16 protocol;
+};
+
+struct garp_msg_hdr {
+ u8 attrtype;
+};
+
+enum garp_attr_event {
+ GARP_LEAVE_ALL,
+ GARP_JOIN_EMPTY,
+ GARP_JOIN_IN,
+ GARP_LEAVE_EMPTY,
+ GARP_LEAVE_IN,
+ GARP_EMPTY,
+};
+
+struct garp_attr_hdr {
+ u8 len;
+ u8 event;
+ u8 data[];
+};
+
+struct garp_skb_cb {
+ u8 cur_type;
+};
+
+static inline struct garp_skb_cb *garp_cb(struct sk_buff *skb)
+{
+ BUILD_BUG_ON(sizeof(struct garp_skb_cb) >
+ FIELD_SIZEOF(struct sk_buff, cb));
+ return (struct garp_skb_cb *)skb->cb;
+}
+
+enum garp_applicant_state {
+ GARP_APPLICANT_INVALID,
+ GARP_APPLICANT_VA,
+ GARP_APPLICANT_AA,
+ GARP_APPLICANT_QA,
+ GARP_APPLICANT_LA,
+ GARP_APPLICANT_VP,
+ GARP_APPLICANT_AP,
+ GARP_APPLICANT_QP,
+ GARP_APPLICANT_VO,
+ GARP_APPLICANT_AO,
+ GARP_APPLICANT_QO,
+ __GARP_APPLICANT_MAX
+};
+#define GARP_APPLICANT_MAX (__GARP_APPLICANT_MAX - 1)
+
+enum garp_event {
+ GARP_EVENT_REQ_JOIN,
+ GARP_EVENT_REQ_LEAVE,
+ GARP_EVENT_R_JOIN_IN,
+ GARP_EVENT_R_JOIN_EMPTY,
+ GARP_EVENT_R_EMPTY,
+ GARP_EVENT_R_LEAVE_IN,
+ GARP_EVENT_R_LEAVE_EMPTY,
+ GARP_EVENT_TRANSMIT_PDU,
+ __GARP_EVENT_MAX
+};
+#define GARP_EVENT_MAX (__GARP_EVENT_MAX - 1)
+
+enum garp_action {
+ GARP_ACTION_NONE,
+ GARP_ACTION_S_JOIN_IN,
+ GARP_ACTION_S_LEAVE_EMPTY,
+};
+
+struct garp_attr {
+ struct rb_node node;
+ enum garp_applicant_state state;
+ u8 type;
+ u8 dlen;
+ unsigned char data[];
+};
+
+enum garp_applications {
+ GARP_APPLICATION_GVRP,
+ __GARP_APPLICATION_MAX
+};
+#define GARP_APPLICATION_MAX (__GARP_APPLICATION_MAX - 1)
+
+struct garp_application {
+ enum garp_applications type;
+ unsigned int maxattr;
+ struct stp_proto proto;
+};
+
+struct garp_applicant {
+ struct garp_application *app;
+ struct net_device *dev;
+ struct timer_list join_timer;
+
+ spinlock_t lock;
+ struct sk_buff_head queue;
+ struct sk_buff *pdu;
+ struct rb_root gid;
+ struct rcu_head rcu;
+};
+
+struct garp_port {
+ struct garp_applicant __rcu *applicants[GARP_APPLICATION_MAX + 1];
+ struct rcu_head rcu;
+};
+
+extern int garp_register_application(struct garp_application *app);
+extern void garp_unregister_application(struct garp_application *app);
+
+extern int garp_init_applicant(struct net_device *dev,
+ struct garp_application *app);
+extern void garp_uninit_applicant(struct net_device *dev,
+ struct garp_application *app);
+
+extern int garp_request_join(const struct net_device *dev,
+ const struct garp_application *app,
+ const void *data, u8 len, u8 type);
+extern void garp_request_leave(const struct net_device *dev,
+ const struct garp_application *app,
+ const void *data, u8 len, u8 type);
+
+#endif /* _NET_GARP_H */
diff --git a/include/net/gen_stats.h b/include/net/gen_stats.h
new file mode 100644
index 00000000..a79b6cfb
--- /dev/null
+++ b/include/net/gen_stats.h
@@ -0,0 +1,50 @@
+#ifndef __NET_GEN_STATS_H
+#define __NET_GEN_STATS_H
+
+#include <linux/gen_stats.h>
+#include <linux/socket.h>
+#include <linux/rtnetlink.h>
+#include <linux/pkt_sched.h>
+
+struct gnet_dump {
+ spinlock_t * lock;
+ struct sk_buff * skb;
+ struct nlattr * tail;
+
+ /* Backward compatibility */
+ int compat_tc_stats;
+ int compat_xstats;
+ void * xstats;
+ int xstats_len;
+ struct tc_stats tc_stats;
+};
+
+extern int gnet_stats_start_copy(struct sk_buff *skb, int type,
+ spinlock_t *lock, struct gnet_dump *d);
+
+extern int gnet_stats_start_copy_compat(struct sk_buff *skb, int type,
+ int tc_stats_type,int xstats_type,
+ spinlock_t *lock, struct gnet_dump *d);
+
+extern int gnet_stats_copy_basic(struct gnet_dump *d,
+ struct gnet_stats_basic_packed *b);
+extern int gnet_stats_copy_rate_est(struct gnet_dump *d,
+ const struct gnet_stats_basic_packed *b,
+ struct gnet_stats_rate_est *r);
+extern int gnet_stats_copy_queue(struct gnet_dump *d,
+ struct gnet_stats_queue *q);
+extern int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len);
+
+extern int gnet_stats_finish_copy(struct gnet_dump *d);
+
+extern int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
+ struct gnet_stats_rate_est *rate_est,
+ spinlock_t *stats_lock, struct nlattr *opt);
+extern void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
+ struct gnet_stats_rate_est *rate_est);
+extern int gen_replace_estimator(struct gnet_stats_basic_packed *bstats,
+ struct gnet_stats_rate_est *rate_est,
+ spinlock_t *stats_lock, struct nlattr *opt);
+extern bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats,
+ const struct gnet_stats_rate_est *rate_est);
+#endif
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
new file mode 100644
index 00000000..ccb68880
--- /dev/null
+++ b/include/net/genetlink.h
@@ -0,0 +1,317 @@
+#ifndef __NET_GENERIC_NETLINK_H
+#define __NET_GENERIC_NETLINK_H
+
+#include <linux/genetlink.h>
+#include <net/netlink.h>
+#include <net/net_namespace.h>
+
+/**
+ * struct genl_multicast_group - generic netlink multicast group
+ * @name: name of the multicast group, names are per-family
+ * @id: multicast group ID, assigned by the core, to use with
+ * genlmsg_multicast().
+ * @list: list entry for linking
+ * @family: pointer to family, need not be set before registering
+ */
+struct genl_multicast_group {
+ struct genl_family *family; /* private */
+ struct list_head list; /* private */
+ char name[GENL_NAMSIZ];
+ u32 id;
+};
+
+struct genl_ops;
+struct genl_info;
+
+/**
+ * struct genl_family - generic netlink family
+ * @id: protocol family idenfitier
+ * @hdrsize: length of user specific header in bytes
+ * @name: name of family
+ * @version: protocol version
+ * @maxattr: maximum number of attributes supported
+ * @netnsok: set to true if the family can handle network
+ * namespaces and should be presented in all of them
+ * @pre_doit: called before an operation's doit callback, it may
+ * do additional, common, filtering and return an error
+ * @post_doit: called after an operation's doit callback, it may
+ * undo operations done by pre_doit, for example release locks
+ * @attrbuf: buffer to store parsed attributes
+ * @ops_list: list of all assigned operations
+ * @family_list: family list
+ * @mcast_groups: multicast groups list
+ */
+struct genl_family {
+ unsigned int id;
+ unsigned int hdrsize;
+ char name[GENL_NAMSIZ];
+ unsigned int version;
+ unsigned int maxattr;
+ bool netnsok;
+ int (*pre_doit)(struct genl_ops *ops,
+ struct sk_buff *skb,
+ struct genl_info *info);
+ void (*post_doit)(struct genl_ops *ops,
+ struct sk_buff *skb,
+ struct genl_info *info);
+ struct nlattr ** attrbuf; /* private */
+ struct list_head ops_list; /* private */
+ struct list_head family_list; /* private */
+ struct list_head mcast_groups; /* private */
+};
+
+/**
+ * struct genl_info - receiving information
+ * @snd_seq: sending sequence number
+ * @snd_pid: netlink pid of sender
+ * @nlhdr: netlink message header
+ * @genlhdr: generic netlink message header
+ * @userhdr: user specific header
+ * @attrs: netlink attributes
+ * @_net: network namespace
+ * @user_ptr: user pointers
+ */
+struct genl_info {
+ u32 snd_seq;
+ u32 snd_pid;
+ struct nlmsghdr * nlhdr;
+ struct genlmsghdr * genlhdr;
+ void * userhdr;
+ struct nlattr ** attrs;
+#ifdef CONFIG_NET_NS
+ struct net * _net;
+#endif
+ void * user_ptr[2];
+};
+
+static inline struct net *genl_info_net(struct genl_info *info)
+{
+ return read_pnet(&info->_net);
+}
+
+static inline void genl_info_net_set(struct genl_info *info, struct net *net)
+{
+ write_pnet(&info->_net, net);
+}
+
+/**
+ * struct genl_ops - generic netlink operations
+ * @cmd: command identifier
+ * @internal_flags: flags used by the family
+ * @flags: flags
+ * @policy: attribute validation policy
+ * @doit: standard command callback
+ * @dumpit: callback for dumpers
+ * @done: completion callback for dumps
+ * @ops_list: operations list
+ */
+struct genl_ops {
+ u8 cmd;
+ u8 internal_flags;
+ unsigned int flags;
+ const struct nla_policy *policy;
+ int (*doit)(struct sk_buff *skb,
+ struct genl_info *info);
+ int (*dumpit)(struct sk_buff *skb,
+ struct netlink_callback *cb);
+ int (*done)(struct netlink_callback *cb);
+ struct list_head ops_list;
+};
+
+extern int genl_register_family(struct genl_family *family);
+extern int genl_register_family_with_ops(struct genl_family *family,
+ struct genl_ops *ops, size_t n_ops);
+extern int genl_unregister_family(struct genl_family *family);
+extern int genl_register_ops(struct genl_family *, struct genl_ops *ops);
+extern int genl_unregister_ops(struct genl_family *, struct genl_ops *ops);
+extern int genl_register_mc_group(struct genl_family *family,
+ struct genl_multicast_group *grp);
+extern void genl_unregister_mc_group(struct genl_family *family,
+ struct genl_multicast_group *grp);
+extern void genl_notify(struct sk_buff *skb, struct net *net, u32 pid,
+ u32 group, struct nlmsghdr *nlh, gfp_t flags);
+
+void *genlmsg_put(struct sk_buff *skb, u32 pid, u32 seq,
+ struct genl_family *family, int flags, u8 cmd);
+
+/**
+ * genlmsg_nlhdr - Obtain netlink header from user specified header
+ * @user_hdr: user header as returned from genlmsg_put()
+ * @family: generic netlink family
+ *
+ * Returns pointer to netlink header.
+ */
+static inline struct nlmsghdr *genlmsg_nlhdr(void *user_hdr,
+ struct genl_family *family)
+{
+ return (struct nlmsghdr *)((char *)user_hdr -
+ family->hdrsize -
+ GENL_HDRLEN -
+ NLMSG_HDRLEN);
+}
+
+/**
+ * genl_dump_check_consistent - check if sequence is consistent and advertise if not
+ * @cb: netlink callback structure that stores the sequence number
+ * @user_hdr: user header as returned from genlmsg_put()
+ * @family: generic netlink family
+ *
+ * Cf. nl_dump_check_consistent(), this just provides a wrapper to make it
+ * simpler to use with generic netlink.
+ */
+static inline void genl_dump_check_consistent(struct netlink_callback *cb,
+ void *user_hdr,
+ struct genl_family *family)
+{
+ nl_dump_check_consistent(cb, genlmsg_nlhdr(user_hdr, family));
+}
+
+/**
+ * genlmsg_put_reply - Add generic netlink header to a reply message
+ * @skb: socket buffer holding the message
+ * @info: receiver info
+ * @family: generic netlink family
+ * @flags: netlink message flags
+ * @cmd: generic netlink command
+ *
+ * Returns pointer to user specific header
+ */
+static inline void *genlmsg_put_reply(struct sk_buff *skb,
+ struct genl_info *info,
+ struct genl_family *family,
+ int flags, u8 cmd)
+{
+ return genlmsg_put(skb, info->snd_pid, info->snd_seq, family,
+ flags, cmd);
+}
+
+/**
+ * genlmsg_end - Finalize a generic netlink message
+ * @skb: socket buffer the message is stored in
+ * @hdr: user specific header
+ */
+static inline int genlmsg_end(struct sk_buff *skb, void *hdr)
+{
+ return nlmsg_end(skb, hdr - GENL_HDRLEN - NLMSG_HDRLEN);
+}
+
+/**
+ * genlmsg_cancel - Cancel construction of a generic netlink message
+ * @skb: socket buffer the message is stored in
+ * @hdr: generic netlink message header
+ */
+static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr)
+{
+ if (hdr)
+ nlmsg_cancel(skb, hdr - GENL_HDRLEN - NLMSG_HDRLEN);
+}
+
+/**
+ * genlmsg_multicast_netns - multicast a netlink message to a specific netns
+ * @net: the net namespace
+ * @skb: netlink message as socket buffer
+ * @pid: own netlink pid to avoid sending to yourself
+ * @group: multicast group id
+ * @flags: allocation flags
+ */
+static inline int genlmsg_multicast_netns(struct net *net, struct sk_buff *skb,
+ u32 pid, unsigned int group, gfp_t flags)
+{
+ return nlmsg_multicast(net->genl_sock, skb, pid, group, flags);
+}
+
+/**
+ * genlmsg_multicast - multicast a netlink message to the default netns
+ * @skb: netlink message as socket buffer
+ * @pid: own netlink pid to avoid sending to yourself
+ * @group: multicast group id
+ * @flags: allocation flags
+ */
+static inline int genlmsg_multicast(struct sk_buff *skb, u32 pid,
+ unsigned int group, gfp_t flags)
+{
+ return genlmsg_multicast_netns(&init_net, skb, pid, group, flags);
+}
+
+/**
+ * genlmsg_multicast_allns - multicast a netlink message to all net namespaces
+ * @skb: netlink message as socket buffer
+ * @pid: own netlink pid to avoid sending to yourself
+ * @group: multicast group id
+ * @flags: allocation flags
+ *
+ * This function must hold the RTNL or rcu_read_lock().
+ */
+int genlmsg_multicast_allns(struct sk_buff *skb, u32 pid,
+ unsigned int group, gfp_t flags);
+
+/**
+ * genlmsg_unicast - unicast a netlink message
+ * @skb: netlink message as socket buffer
+ * @pid: netlink pid of the destination socket
+ */
+static inline int genlmsg_unicast(struct net *net, struct sk_buff *skb, u32 pid)
+{
+ return nlmsg_unicast(net->genl_sock, skb, pid);
+}
+
+/**
+ * genlmsg_reply - reply to a request
+ * @skb: netlink message to be sent back
+ * @info: receiver information
+ */
+static inline int genlmsg_reply(struct sk_buff *skb, struct genl_info *info)
+{
+ return genlmsg_unicast(genl_info_net(info), skb, info->snd_pid);
+}
+
+/**
+ * gennlmsg_data - head of message payload
+ * @gnlh: genetlink message header
+ */
+static inline void *genlmsg_data(const struct genlmsghdr *gnlh)
+{
+ return ((unsigned char *) gnlh + GENL_HDRLEN);
+}
+
+/**
+ * genlmsg_len - length of message payload
+ * @gnlh: genetlink message header
+ */
+static inline int genlmsg_len(const struct genlmsghdr *gnlh)
+{
+ struct nlmsghdr *nlh = (struct nlmsghdr *)((unsigned char *)gnlh -
+ NLMSG_HDRLEN);
+ return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN);
+}
+
+/**
+ * genlmsg_msg_size - length of genetlink message not including padding
+ * @payload: length of message payload
+ */
+static inline int genlmsg_msg_size(int payload)
+{
+ return GENL_HDRLEN + payload;
+}
+
+/**
+ * genlmsg_total_size - length of genetlink message including padding
+ * @payload: length of message payload
+ */
+static inline int genlmsg_total_size(int payload)
+{
+ return NLMSG_ALIGN(genlmsg_msg_size(payload));
+}
+
+/**
+ * genlmsg_new - Allocate a new generic netlink message
+ * @payload: size of the message payload
+ * @flags: the type of memory to allocate.
+ */
+static inline struct sk_buff *genlmsg_new(size_t payload, gfp_t flags)
+{
+ return nlmsg_new(genlmsg_total_size(payload), flags);
+}
+
+
+#endif /* __NET_GENERIC_NETLINK_H */
diff --git a/include/net/gre.h b/include/net/gre.h
new file mode 100644
index 00000000..82665474
--- /dev/null
+++ b/include/net/gre.h
@@ -0,0 +1,18 @@
+#ifndef __LINUX_GRE_H
+#define __LINUX_GRE_H
+
+#include <linux/skbuff.h>
+
+#define GREPROTO_CISCO 0
+#define GREPROTO_PPTP 1
+#define GREPROTO_MAX 2
+
+struct gre_protocol {
+ int (*handler)(struct sk_buff *skb);
+ void (*err_handler)(struct sk_buff *skb, u32 info);
+};
+
+int gre_add_protocol(const struct gre_protocol *proto, u8 version);
+int gre_del_protocol(const struct gre_protocol *proto, u8 version);
+
+#endif
diff --git a/include/net/icmp.h b/include/net/icmp.h
new file mode 100644
index 00000000..75d61564
--- /dev/null
+++ b/include/net/icmp.h
@@ -0,0 +1,48 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the ICMP module.
+ *
+ * Version: @(#)icmp.h 1.0.4 05/13/93
+ *
+ * Authors: Ross Biro
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _ICMP_H
+#define _ICMP_H
+
+#include <linux/icmp.h>
+
+#include <net/inet_sock.h>
+#include <net/snmp.h>
+
+struct icmp_err {
+ int errno;
+ unsigned fatal:1;
+};
+
+extern const struct icmp_err icmp_err_convert[];
+#define ICMP_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.icmp_statistics, field)
+#define ICMP_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.icmp_statistics, field)
+#define ICMPMSGOUT_INC_STATS(net, field) SNMP_INC_STATS_ATOMIC_LONG((net)->mib.icmpmsg_statistics, field+256)
+#define ICMPMSGIN_INC_STATS_BH(net, field) SNMP_INC_STATS_ATOMIC_LONG((net)->mib.icmpmsg_statistics, field)
+
+struct dst_entry;
+struct net_proto_family;
+struct sk_buff;
+struct net;
+
+extern void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info);
+extern int icmp_rcv(struct sk_buff *skb);
+extern int icmp_ioctl(struct sock *sk, int cmd, unsigned long arg);
+extern int icmp_init(void);
+extern void icmp_out_count(struct net *net, unsigned char type);
+
+#endif /* _ICMP_H */
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
new file mode 100644
index 00000000..71392545
--- /dev/null
+++ b/include/net/ieee80211_radiotap.h
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2003, 2004 David Young. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of David Young may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID
+ * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+/*
+ * Modifications to fit into the linux IEEE 802.11 stack,
+ * Mike Kershaw (dragorn@kismetwireless.net)
+ */
+
+#ifndef IEEE80211RADIOTAP_H
+#define IEEE80211RADIOTAP_H
+
+#include <linux/if_ether.h>
+#include <linux/kernel.h>
+#include <asm/unaligned.h>
+
+/* Base version of the radiotap packet header data */
+#define PKTHDR_RADIOTAP_VERSION 0
+
+/* A generic radio capture format is desirable. There is one for
+ * Linux, but it is neither rigidly defined (there were not even
+ * units given for some fields) nor easily extensible.
+ *
+ * I suggest the following extensible radio capture format. It is
+ * based on a bitmap indicating which fields are present.
+ *
+ * I am trying to describe precisely what the application programmer
+ * should expect in the following, and for that reason I tell the
+ * units and origin of each measurement (where it applies), or else I
+ * use sufficiently weaselly language ("is a monotonically nondecreasing
+ * function of...") that I cannot set false expectations for lawyerly
+ * readers.
+ */
+
+/*
+ * The radio capture header precedes the 802.11 header.
+ * All data in the header is little endian on all platforms.
+ */
+struct ieee80211_radiotap_header {
+ u8 it_version; /* Version 0. Only increases
+ * for drastic changes,
+ * introduction of compatible
+ * new fields does not count.
+ */
+ u8 it_pad;
+ __le16 it_len; /* length of the whole
+ * header in bytes, including
+ * it_version, it_pad,
+ * it_len, and data fields.
+ */
+ __le32 it_present; /* A bitmap telling which
+ * fields are present. Set bit 31
+ * (0x80000000) to extend the
+ * bitmap by another 32 bits.
+ * Additional extensions are made
+ * by setting bit 31.
+ */
+} __packed;
+
+/* Name Data type Units
+ * ---- --------- -----
+ *
+ * IEEE80211_RADIOTAP_TSFT __le64 microseconds
+ *
+ * Value in microseconds of the MAC's 64-bit 802.11 Time
+ * Synchronization Function timer when the first bit of the
+ * MPDU arrived at the MAC. For received frames, only.
+ *
+ * IEEE80211_RADIOTAP_CHANNEL 2 x __le16 MHz, bitmap
+ *
+ * Tx/Rx frequency in MHz, followed by flags (see below).
+ *
+ * IEEE80211_RADIOTAP_FHSS __le16 see below
+ *
+ * For frequency-hopping radios, the hop set (first byte)
+ * and pattern (second byte).
+ *
+ * IEEE80211_RADIOTAP_RATE u8 500kb/s
+ *
+ * Tx/Rx data rate
+ *
+ * IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from
+ * one milliwatt (dBm)
+ *
+ * RF signal power at the antenna, decibel difference from
+ * one milliwatt.
+ *
+ * IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from
+ * one milliwatt (dBm)
+ *
+ * RF noise power at the antenna, decibel difference from one
+ * milliwatt.
+ *
+ * IEEE80211_RADIOTAP_DB_ANTSIGNAL u8 decibel (dB)
+ *
+ * RF signal power at the antenna, decibel difference from an
+ * arbitrary, fixed reference.
+ *
+ * IEEE80211_RADIOTAP_DB_ANTNOISE u8 decibel (dB)
+ *
+ * RF noise power at the antenna, decibel difference from an
+ * arbitrary, fixed reference point.
+ *
+ * IEEE80211_RADIOTAP_LOCK_QUALITY __le16 unitless
+ *
+ * Quality of Barker code lock. Unitless. Monotonically
+ * nondecreasing with "better" lock strength. Called "Signal
+ * Quality" in datasheets. (Is there a standard way to measure
+ * this?)
+ *
+ * IEEE80211_RADIOTAP_TX_ATTENUATION __le16 unitless
+ *
+ * Transmit power expressed as unitless distance from max
+ * power set at factory calibration. 0 is max power.
+ * Monotonically nondecreasing with lower power levels.
+ *
+ * IEEE80211_RADIOTAP_DB_TX_ATTENUATION __le16 decibels (dB)
+ *
+ * Transmit power expressed as decibel distance from max power
+ * set at factory calibration. 0 is max power. Monotonically
+ * nondecreasing with lower power levels.
+ *
+ * IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from
+ * one milliwatt (dBm)
+ *
+ * Transmit power expressed as dBm (decibels from a 1 milliwatt
+ * reference). This is the absolute power level measured at
+ * the antenna port.
+ *
+ * IEEE80211_RADIOTAP_FLAGS u8 bitmap
+ *
+ * Properties of transmitted and received frames. See flags
+ * defined below.
+ *
+ * IEEE80211_RADIOTAP_ANTENNA u8 antenna index
+ *
+ * Unitless indication of the Rx/Tx antenna for this packet.
+ * The first antenna is antenna 0.
+ *
+ * IEEE80211_RADIOTAP_RX_FLAGS __le16 bitmap
+ *
+ * Properties of received frames. See flags defined below.
+ *
+ * IEEE80211_RADIOTAP_TX_FLAGS __le16 bitmap
+ *
+ * Properties of transmitted frames. See flags defined below.
+ *
+ * IEEE80211_RADIOTAP_RTS_RETRIES u8 data
+ *
+ * Number of rts retries a transmitted frame used.
+ *
+ * IEEE80211_RADIOTAP_DATA_RETRIES u8 data
+ *
+ * Number of unicast retries a transmitted frame used.
+ *
+ * IEEE80211_RADIOTAP_MCS u8, u8, u8 unitless
+ *
+ * Contains a bitmap of known fields/flags, the flags, and
+ * the MCS index.
+ *
+ */
+enum ieee80211_radiotap_type {
+ IEEE80211_RADIOTAP_TSFT = 0,
+ IEEE80211_RADIOTAP_FLAGS = 1,
+ IEEE80211_RADIOTAP_RATE = 2,
+ IEEE80211_RADIOTAP_CHANNEL = 3,
+ IEEE80211_RADIOTAP_FHSS = 4,
+ IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
+ IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
+ IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
+ IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
+ IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
+ IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
+ IEEE80211_RADIOTAP_ANTENNA = 11,
+ IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
+ IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
+ IEEE80211_RADIOTAP_RX_FLAGS = 14,
+ IEEE80211_RADIOTAP_TX_FLAGS = 15,
+ IEEE80211_RADIOTAP_RTS_RETRIES = 16,
+ IEEE80211_RADIOTAP_DATA_RETRIES = 17,
+
+ IEEE80211_RADIOTAP_MCS = 19,
+
+ /* valid in every it_present bitmap, even vendor namespaces */
+ IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
+ IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
+ IEEE80211_RADIOTAP_EXT = 31
+};
+
+/* Channel flags. */
+#define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */
+#define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */
+#define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */
+#define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */
+#define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */
+#define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */
+#define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */
+#define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */
+
+/* For IEEE80211_RADIOTAP_FLAGS */
+#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received
+ * during CFP
+ */
+#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received
+ * with short
+ * preamble
+ */
+#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received
+ * with WEP encryption
+ */
+#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received
+ * with fragmentation
+ */
+#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */
+#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between
+ * 802.11 header and payload
+ * (to 32-bit boundary)
+ */
+#define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* bad FCS */
+
+/* For IEEE80211_RADIOTAP_RX_FLAGS */
+#define IEEE80211_RADIOTAP_F_RX_BADPLCP 0x0002 /* frame has bad PLCP */
+
+/* For IEEE80211_RADIOTAP_TX_FLAGS */
+#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive
+ * retries */
+#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */
+#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
+#define IEEE80211_RADIOTAP_F_TX_NOACK 0x0008 /* don't expect an ack */
+
+
+/* For IEEE80211_RADIOTAP_MCS */
+#define IEEE80211_RADIOTAP_MCS_HAVE_BW 0x01
+#define IEEE80211_RADIOTAP_MCS_HAVE_MCS 0x02
+#define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04
+#define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08
+#define IEEE80211_RADIOTAP_MCS_HAVE_FEC 0x10
+
+#define IEEE80211_RADIOTAP_MCS_BW_MASK 0x03
+#define IEEE80211_RADIOTAP_MCS_BW_20 0
+#define IEEE80211_RADIOTAP_MCS_BW_40 1
+#define IEEE80211_RADIOTAP_MCS_BW_20L 2
+#define IEEE80211_RADIOTAP_MCS_BW_20U 3
+#define IEEE80211_RADIOTAP_MCS_SGI 0x04
+#define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08
+#define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10
+
+
+/* helpers */
+static inline int ieee80211_get_radiotap_len(unsigned char *data)
+{
+ struct ieee80211_radiotap_header *hdr =
+ (struct ieee80211_radiotap_header *)data;
+
+ return get_unaligned_le16(&hdr->it_len);
+}
+
+#endif /* IEEE80211_RADIOTAP_H */
diff --git a/include/net/ieee802154.h b/include/net/ieee802154.h
new file mode 100644
index 00000000..ee59f8b1
--- /dev/null
+++ b/include/net/ieee802154.h
@@ -0,0 +1,166 @@
+/*
+ * IEEE802.15.4-2003 specification
+ *
+ * Copyright (C) 2007, 2008 Siemens AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by:
+ * Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
+ * Maxim Osipov <maxim.osipov@siemens.com>
+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
+ * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
+ */
+
+#ifndef NET_IEEE802154_H
+#define NET_IEEE802154_H
+
+#define IEEE802154_MTU 127
+
+#define IEEE802154_FC_TYPE_BEACON 0x0 /* Frame is beacon */
+#define IEEE802154_FC_TYPE_DATA 0x1 /* Frame is data */
+#define IEEE802154_FC_TYPE_ACK 0x2 /* Frame is acknowledgment */
+#define IEEE802154_FC_TYPE_MAC_CMD 0x3 /* Frame is MAC command */
+
+#define IEEE802154_FC_TYPE_SHIFT 0
+#define IEEE802154_FC_TYPE_MASK ((1 << 3) - 1)
+#define IEEE802154_FC_TYPE(x) ((x & IEEE802154_FC_TYPE_MASK) >> IEEE802154_FC_TYPE_SHIFT)
+#define IEEE802154_FC_SET_TYPE(v, x) do { \
+ v = (((v) & ~IEEE802154_FC_TYPE_MASK) | \
+ (((x) << IEEE802154_FC_TYPE_SHIFT) & IEEE802154_FC_TYPE_MASK)); \
+ } while (0)
+
+#define IEEE802154_FC_SECEN (1 << 3)
+#define IEEE802154_FC_FRPEND (1 << 4)
+#define IEEE802154_FC_ACK_REQ (1 << 5)
+#define IEEE802154_FC_INTRA_PAN (1 << 6)
+
+#define IEEE802154_FC_SAMODE_SHIFT 14
+#define IEEE802154_FC_SAMODE_MASK (3 << IEEE802154_FC_SAMODE_SHIFT)
+#define IEEE802154_FC_DAMODE_SHIFT 10
+#define IEEE802154_FC_DAMODE_MASK (3 << IEEE802154_FC_DAMODE_SHIFT)
+
+#define IEEE802154_FC_SAMODE(x) \
+ (((x) & IEEE802154_FC_SAMODE_MASK) >> IEEE802154_FC_SAMODE_SHIFT)
+
+#define IEEE802154_FC_DAMODE(x) \
+ (((x) & IEEE802154_FC_DAMODE_MASK) >> IEEE802154_FC_DAMODE_SHIFT)
+
+
+/* MAC footer size */
+#define IEEE802154_MFR_SIZE 2 /* 2 octets */
+
+/* MAC's Command Frames Identifiers */
+#define IEEE802154_CMD_ASSOCIATION_REQ 0x01
+#define IEEE802154_CMD_ASSOCIATION_RESP 0x02
+#define IEEE802154_CMD_DISASSOCIATION_NOTIFY 0x03
+#define IEEE802154_CMD_DATA_REQ 0x04
+#define IEEE802154_CMD_PANID_CONFLICT_NOTIFY 0x05
+#define IEEE802154_CMD_ORPHAN_NOTIFY 0x06
+#define IEEE802154_CMD_BEACON_REQ 0x07
+#define IEEE802154_CMD_COORD_REALIGN_NOTIFY 0x08
+#define IEEE802154_CMD_GTS_REQ 0x09
+
+/*
+ * The return values of MAC operations
+ */
+enum {
+ /*
+ * The requested operation was completed successfully.
+ * For a transmission request, this value indicates
+ * a successful transmission.
+ */
+ IEEE802154_SUCCESS = 0x0,
+
+ /* The beacon was lost following a synchronization request. */
+ IEEE802154_BEACON_LOSS = 0xe0,
+ /*
+ * A transmission could not take place due to activity on the
+ * channel, i.e., the CSMA-CA mechanism has failed.
+ */
+ IEEE802154_CHNL_ACCESS_FAIL = 0xe1,
+ /* The GTS request has been denied by the PAN coordinator. */
+ IEEE802154_DENINED = 0xe2,
+ /* The attempt to disable the transceiver has failed. */
+ IEEE802154_DISABLE_TRX_FAIL = 0xe3,
+ /*
+ * The received frame induces a failed security check according to
+ * the security suite.
+ */
+ IEEE802154_FAILED_SECURITY_CHECK = 0xe4,
+ /*
+ * The frame resulting from secure processing has a length that is
+ * greater than aMACMaxFrameSize.
+ */
+ IEEE802154_FRAME_TOO_LONG = 0xe5,
+ /*
+ * The requested GTS transmission failed because the specified GTS
+ * either did not have a transmit GTS direction or was not defined.
+ */
+ IEEE802154_INVALID_GTS = 0xe6,
+ /*
+ * A request to purge an MSDU from the transaction queue was made using
+ * an MSDU handle that was not found in the transaction table.
+ */
+ IEEE802154_INVALID_HANDLE = 0xe7,
+ /* A parameter in the primitive is out of the valid range.*/
+ IEEE802154_INVALID_PARAMETER = 0xe8,
+ /* No acknowledgment was received after aMaxFrameRetries. */
+ IEEE802154_NO_ACK = 0xe9,
+ /* A scan operation failed to find any network beacons.*/
+ IEEE802154_NO_BEACON = 0xea,
+ /* No response data were available following a request. */
+ IEEE802154_NO_DATA = 0xeb,
+ /* The operation failed because a short address was not allocated. */
+ IEEE802154_NO_SHORT_ADDRESS = 0xec,
+ /*
+ * A receiver enable request was unsuccessful because it could not be
+ * completed within the CAP.
+ */
+ IEEE802154_OUT_OF_CAP = 0xed,
+ /*
+ * A PAN identifier conflict has been detected and communicated to the
+ * PAN coordinator.
+ */
+ IEEE802154_PANID_CONFLICT = 0xee,
+ /* A coordinator realignment command has been received. */
+ IEEE802154_REALIGMENT = 0xef,
+ /* The transaction has expired and its information discarded. */
+ IEEE802154_TRANSACTION_EXPIRED = 0xf0,
+ /* There is no capacity to store the transaction. */
+ IEEE802154_TRANSACTION_OVERFLOW = 0xf1,
+ /*
+ * The transceiver was in the transmitter enabled state when the
+ * receiver was requested to be enabled.
+ */
+ IEEE802154_TX_ACTIVE = 0xf2,
+ /* The appropriate key is not available in the ACL. */
+ IEEE802154_UNAVAILABLE_KEY = 0xf3,
+ /*
+ * A SET/GET request was issued with the identifier of a PIB attribute
+ * that is not supported.
+ */
+ IEEE802154_UNSUPPORTED_ATTR = 0xf4,
+ /*
+ * A request to perform a scan operation failed because the MLME was
+ * in the process of performing a previously initiated scan operation.
+ */
+ IEEE802154_SCAN_IN_PROGRESS = 0xfc,
+};
+
+
+#endif
+
+
diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
new file mode 100644
index 00000000..57430555
--- /dev/null
+++ b/include/net/ieee802154_netdev.h
@@ -0,0 +1,121 @@
+/*
+ * An interface between IEEE802.15.4 device and rest of the kernel.
+ *
+ * Copyright (C) 2007, 2008, 2009 Siemens AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by:
+ * Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
+ * Maxim Osipov <maxim.osipov@siemens.com>
+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
+ */
+
+#ifndef IEEE802154_NETDEVICE_H
+#define IEEE802154_NETDEVICE_H
+
+/*
+ * A control block of skb passed between the ARPHRD_IEEE802154 device
+ * and other stack parts.
+ */
+struct ieee802154_mac_cb {
+ u8 lqi;
+ struct ieee802154_addr sa;
+ struct ieee802154_addr da;
+ u8 flags;
+ u8 seq;
+};
+
+static inline struct ieee802154_mac_cb *mac_cb(struct sk_buff *skb)
+{
+ return (struct ieee802154_mac_cb *)skb->cb;
+}
+
+#define MAC_CB_FLAG_TYPEMASK ((1 << 3) - 1)
+
+#define MAC_CB_FLAG_ACKREQ (1 << 3)
+#define MAC_CB_FLAG_SECEN (1 << 4)
+#define MAC_CB_FLAG_INTRAPAN (1 << 5)
+
+static inline int mac_cb_is_ackreq(struct sk_buff *skb)
+{
+ return mac_cb(skb)->flags & MAC_CB_FLAG_ACKREQ;
+}
+
+static inline int mac_cb_is_secen(struct sk_buff *skb)
+{
+ return mac_cb(skb)->flags & MAC_CB_FLAG_SECEN;
+}
+
+static inline int mac_cb_is_intrapan(struct sk_buff *skb)
+{
+ return mac_cb(skb)->flags & MAC_CB_FLAG_INTRAPAN;
+}
+
+static inline int mac_cb_type(struct sk_buff *skb)
+{
+ return mac_cb(skb)->flags & MAC_CB_FLAG_TYPEMASK;
+}
+
+#define IEEE802154_MAC_SCAN_ED 0
+#define IEEE802154_MAC_SCAN_ACTIVE 1
+#define IEEE802154_MAC_SCAN_PASSIVE 2
+#define IEEE802154_MAC_SCAN_ORPHAN 3
+
+struct wpan_phy;
+/*
+ * This should be located at net_device->ml_priv
+ *
+ * get_phy should increment the reference counting on returned phy.
+ * Use wpan_wpy_put to put that reference.
+ */
+struct ieee802154_mlme_ops {
+ int (*assoc_req)(struct net_device *dev,
+ struct ieee802154_addr *addr,
+ u8 channel, u8 page, u8 cap);
+ int (*assoc_resp)(struct net_device *dev,
+ struct ieee802154_addr *addr,
+ u16 short_addr, u8 status);
+ int (*disassoc_req)(struct net_device *dev,
+ struct ieee802154_addr *addr,
+ u8 reason);
+ int (*start_req)(struct net_device *dev,
+ struct ieee802154_addr *addr,
+ u8 channel, u8 page, u8 bcn_ord, u8 sf_ord,
+ u8 pan_coord, u8 blx, u8 coord_realign);
+ int (*scan_req)(struct net_device *dev,
+ u8 type, u32 channels, u8 page, u8 duration);
+
+ struct wpan_phy *(*get_phy)(const struct net_device *dev);
+
+ /*
+ * FIXME: these should become the part of PIB/MIB interface.
+ * However we still don't have IB interface of any kind
+ */
+ u16 (*get_pan_id)(const struct net_device *dev);
+ u16 (*get_short_addr)(const struct net_device *dev);
+ u8 (*get_dsn)(const struct net_device *dev);
+ u8 (*get_bsn)(const struct net_device *dev);
+};
+
+static inline struct ieee802154_mlme_ops *ieee802154_mlme_ops(
+ const struct net_device *dev)
+{
+ return dev->ml_priv;
+}
+
+#endif
+
+
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
new file mode 100644
index 00000000..51a7031b
--- /dev/null
+++ b/include/net/if_inet6.h
@@ -0,0 +1,304 @@
+/*
+ * inet6 interface/address list definitions
+ * Linux INET6 implementation
+ *
+ * Authors:
+ * Pedro Roque <roque@di.fc.ul.pt>
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _NET_IF_INET6_H
+#define _NET_IF_INET6_H
+
+#include <net/snmp.h>
+#include <linux/ipv6.h>
+
+/* inet6_dev.if_flags */
+
+#define IF_RA_OTHERCONF 0x80
+#define IF_RA_MANAGED 0x40
+#define IF_RA_RCVD 0x20
+#define IF_RS_SENT 0x10
+#define IF_READY 0x80000000
+
+/* prefix flags */
+#define IF_PREFIX_ONLINK 0x01
+#define IF_PREFIX_AUTOCONF 0x02
+
+enum {
+ INET6_IFADDR_STATE_DAD,
+ INET6_IFADDR_STATE_POSTDAD,
+ INET6_IFADDR_STATE_UP,
+ INET6_IFADDR_STATE_DEAD,
+};
+
+struct inet6_ifaddr {
+ struct in6_addr addr;
+ __u32 prefix_len;
+
+ /* In seconds, relative to tstamp. Expiry is at tstamp + HZ * lft. */
+ __u32 valid_lft;
+ __u32 prefered_lft;
+ atomic_t refcnt;
+ spinlock_t lock;
+ spinlock_t state_lock;
+
+ int state;
+
+ __u8 probes;
+ __u8 flags;
+
+ __u16 scope;
+
+ unsigned long cstamp; /* created timestamp */
+ unsigned long tstamp; /* updated timestamp */
+
+ struct timer_list timer;
+
+ struct inet6_dev *idev;
+ struct rt6_info *rt;
+
+ struct hlist_node addr_lst;
+ struct list_head if_list;
+
+#ifdef CONFIG_IPV6_PRIVACY
+ struct list_head tmp_list;
+ struct inet6_ifaddr *ifpub;
+ int regen_count;
+#endif
+ struct rcu_head rcu;
+};
+
+struct ip6_sf_socklist {
+ unsigned int sl_max;
+ unsigned int sl_count;
+ struct in6_addr sl_addr[0];
+};
+
+#define IP6_SFLSIZE(count) (sizeof(struct ip6_sf_socklist) + \
+ (count) * sizeof(struct in6_addr))
+
+#define IP6_SFBLOCK 10 /* allocate this many at once */
+
+struct ipv6_mc_socklist {
+ struct in6_addr addr;
+ int ifindex;
+ struct ipv6_mc_socklist __rcu *next;
+ rwlock_t sflock;
+ unsigned int sfmode; /* MCAST_{INCLUDE,EXCLUDE} */
+ struct ip6_sf_socklist *sflist;
+ struct rcu_head rcu;
+};
+
+struct ip6_sf_list {
+ struct ip6_sf_list *sf_next;
+ struct in6_addr sf_addr;
+ unsigned long sf_count[2]; /* include/exclude counts */
+ unsigned char sf_gsresp; /* include in g & s response? */
+ unsigned char sf_oldin; /* change state */
+ unsigned char sf_crcount; /* retrans. left to send */
+};
+
+#define MAF_TIMER_RUNNING 0x01
+#define MAF_LAST_REPORTER 0x02
+#define MAF_LOADED 0x04
+#define MAF_NOREPORT 0x08
+#define MAF_GSQUERY 0x10
+
+struct ifmcaddr6 {
+ struct in6_addr mca_addr;
+ struct inet6_dev *idev;
+ struct ifmcaddr6 *next;
+ struct ip6_sf_list *mca_sources;
+ struct ip6_sf_list *mca_tomb;
+ unsigned int mca_sfmode;
+ unsigned char mca_crcount;
+ unsigned long mca_sfcount[2];
+ struct timer_list mca_timer;
+ unsigned mca_flags;
+ int mca_users;
+ atomic_t mca_refcnt;
+ spinlock_t mca_lock;
+ unsigned long mca_cstamp;
+ unsigned long mca_tstamp;
+};
+
+/* Anycast stuff */
+
+struct ipv6_ac_socklist {
+ struct in6_addr acl_addr;
+ int acl_ifindex;
+ struct ipv6_ac_socklist *acl_next;
+};
+
+struct ifacaddr6 {
+ struct in6_addr aca_addr;
+ struct inet6_dev *aca_idev;
+ struct rt6_info *aca_rt;
+ struct ifacaddr6 *aca_next;
+ int aca_users;
+ atomic_t aca_refcnt;
+ spinlock_t aca_lock;
+ unsigned long aca_cstamp;
+ unsigned long aca_tstamp;
+};
+
+#define IFA_HOST IPV6_ADDR_LOOPBACK
+#define IFA_LINK IPV6_ADDR_LINKLOCAL
+#define IFA_SITE IPV6_ADDR_SITELOCAL
+
+struct ipv6_devstat {
+ struct proc_dir_entry *proc_dir_entry;
+ DEFINE_SNMP_STAT(struct ipstats_mib, ipv6);
+ DEFINE_SNMP_STAT_ATOMIC(struct icmpv6_mib_device, icmpv6dev);
+ DEFINE_SNMP_STAT_ATOMIC(struct icmpv6msg_mib_device, icmpv6msgdev);
+};
+
+struct inet6_dev {
+ struct net_device *dev;
+
+ struct list_head addr_list;
+
+ struct ifmcaddr6 *mc_list;
+ struct ifmcaddr6 *mc_tomb;
+ spinlock_t mc_lock;
+ unsigned char mc_qrv;
+ unsigned char mc_gq_running;
+ unsigned char mc_ifc_count;
+ unsigned long mc_v1_seen;
+ unsigned long mc_maxdelay;
+ struct timer_list mc_gq_timer; /* general query timer */
+ struct timer_list mc_ifc_timer; /* interface change timer */
+
+ struct ifacaddr6 *ac_list;
+ rwlock_t lock;
+ atomic_t refcnt;
+ __u32 if_flags;
+ int dead;
+
+#ifdef CONFIG_IPV6_PRIVACY
+ u8 rndid[8];
+ struct timer_list regen_timer;
+ struct list_head tempaddr_list;
+#endif
+
+ struct neigh_parms *nd_parms;
+ struct inet6_dev *next;
+ struct ipv6_devconf cnf;
+ struct ipv6_devstat stats;
+ unsigned long tstamp; /* ipv6InterfaceTable update timestamp */
+ struct rcu_head rcu;
+};
+
+static inline void ipv6_eth_mc_map(const struct in6_addr *addr, char *buf)
+{
+ /*
+ * +-------+-------+-------+-------+-------+-------+
+ * | 33 | 33 | DST13 | DST14 | DST15 | DST16 |
+ * +-------+-------+-------+-------+-------+-------+
+ */
+
+ buf[0]= 0x33;
+ buf[1]= 0x33;
+
+ memcpy(buf + 2, &addr->s6_addr32[3], sizeof(__u32));
+}
+
+static inline void ipv6_tr_mc_map(const struct in6_addr *addr, char *buf)
+{
+ /* All nodes FF01::1, FF02::1, FF02::1:FFxx:xxxx */
+
+ if (((addr->s6_addr[0] == 0xFF) &&
+ ((addr->s6_addr[1] == 0x01) || (addr->s6_addr[1] == 0x02)) &&
+ (addr->s6_addr16[1] == 0) &&
+ (addr->s6_addr32[1] == 0) &&
+ (addr->s6_addr32[2] == 0) &&
+ (addr->s6_addr16[6] == 0) &&
+ (addr->s6_addr[15] == 1)) ||
+ ((addr->s6_addr[0] == 0xFF) &&
+ (addr->s6_addr[1] == 0x02) &&
+ (addr->s6_addr16[1] == 0) &&
+ (addr->s6_addr32[1] == 0) &&
+ (addr->s6_addr16[4] == 0) &&
+ (addr->s6_addr[10] == 0) &&
+ (addr->s6_addr[11] == 1) &&
+ (addr->s6_addr[12] == 0xff)))
+ {
+ buf[0]=0xC0;
+ buf[1]=0x00;
+ buf[2]=0x01;
+ buf[3]=0x00;
+ buf[4]=0x00;
+ buf[5]=0x00;
+ /* All routers FF0x::2 */
+ } else if ((addr->s6_addr[0] ==0xff) &&
+ ((addr->s6_addr[1] & 0xF0) == 0) &&
+ (addr->s6_addr16[1] == 0) &&
+ (addr->s6_addr32[1] == 0) &&
+ (addr->s6_addr32[2] == 0) &&
+ (addr->s6_addr16[6] == 0) &&
+ (addr->s6_addr[15] == 2))
+ {
+ buf[0]=0xC0;
+ buf[1]=0x00;
+ buf[2]=0x02;
+ buf[3]=0x00;
+ buf[4]=0x00;
+ buf[5]=0x00;
+ } else {
+ unsigned char i ;
+
+ i = addr->s6_addr[15] & 7 ;
+ buf[0]=0xC0;
+ buf[1]=0x00;
+ buf[2]=0x00;
+ buf[3]=0x01 << i ;
+ buf[4]=0x00;
+ buf[5]=0x00;
+ }
+}
+
+static inline void ipv6_arcnet_mc_map(const struct in6_addr *addr, char *buf)
+{
+ buf[0] = 0x00;
+}
+
+static inline void ipv6_ib_mc_map(const struct in6_addr *addr,
+ const unsigned char *broadcast, char *buf)
+{
+ unsigned char scope = broadcast[5] & 0xF;
+
+ buf[0] = 0; /* Reserved */
+ buf[1] = 0xff; /* Multicast QPN */
+ buf[2] = 0xff;
+ buf[3] = 0xff;
+ buf[4] = 0xff;
+ buf[5] = 0x10 | scope; /* scope from broadcast address */
+ buf[6] = 0x60; /* IPv6 signature */
+ buf[7] = 0x1b;
+ buf[8] = broadcast[8]; /* P_Key */
+ buf[9] = broadcast[9];
+ memcpy(buf + 10, addr->s6_addr + 6, 10);
+}
+
+static inline int ipv6_ipgre_mc_map(const struct in6_addr *addr,
+ const unsigned char *broadcast, char *buf)
+{
+ if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0) {
+ memcpy(buf, broadcast, 4);
+ } else {
+ /* v4mapped? */
+ if ((addr->s6_addr32[0] | addr->s6_addr32[1] |
+ (addr->s6_addr32[2] ^ htonl(0x0000ffff))) != 0)
+ return -EINVAL;
+ memcpy(buf, &addr->s6_addr32[3], 4);
+ }
+ return 0;
+}
+
+#endif
diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h
new file mode 100644
index 00000000..3207e58e
--- /dev/null
+++ b/include/net/inet6_connection_sock.h
@@ -0,0 +1,45 @@
+/*
+ * NET Generic infrastructure for INET6 connection oriented protocols.
+ *
+ * Authors: Many people, see the TCPv6 sources
+ *
+ * From code originally in TCPv6
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _INET6_CONNECTION_SOCK_H
+#define _INET6_CONNECTION_SOCK_H
+
+#include <linux/types.h>
+
+struct in6_addr;
+struct inet_bind_bucket;
+struct request_sock;
+struct sk_buff;
+struct sock;
+struct sockaddr;
+
+extern int inet6_csk_bind_conflict(const struct sock *sk,
+ const struct inet_bind_bucket *tb);
+
+extern struct dst_entry* inet6_csk_route_req(struct sock *sk,
+ const struct request_sock *req);
+
+extern struct request_sock *inet6_csk_search_req(const struct sock *sk,
+ struct request_sock ***prevp,
+ const __be16 rport,
+ const struct in6_addr *raddr,
+ const struct in6_addr *laddr,
+ const int iif);
+
+extern void inet6_csk_reqsk_queue_hash_add(struct sock *sk,
+ struct request_sock *req,
+ const unsigned long timeout);
+
+extern void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
+
+extern int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl);
+#endif /* _INET6_CONNECTION_SOCK_H */
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
new file mode 100644
index 00000000..00cbb438
--- /dev/null
+++ b/include/net/inet6_hashtables.h
@@ -0,0 +1,114 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Authors: Lotsa people, from code originally in tcp
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _INET6_HASHTABLES_H
+#define _INET6_HASHTABLES_H
+
+
+#if IS_ENABLED(CONFIG_IPV6)
+#include <linux/in6.h>
+#include <linux/ipv6.h>
+#include <linux/types.h>
+#include <linux/jhash.h>
+
+#include <net/inet_sock.h>
+
+#include <net/ipv6.h>
+#include <net/netns/hash.h>
+
+struct inet_hashinfo;
+
+/* I have no idea if this is a good hash for v6 or not. -DaveM */
+static inline unsigned int inet6_ehashfn(struct net *net,
+ const struct in6_addr *laddr, const u16 lport,
+ const struct in6_addr *faddr, const __be16 fport)
+{
+ u32 ports = (lport ^ (__force u16)fport);
+
+ return jhash_3words((__force u32)laddr->s6_addr32[3],
+ (__force u32)faddr->s6_addr32[3],
+ ports, inet_ehash_secret + net_hash_mix(net));
+}
+
+static inline int inet6_sk_ehashfn(const struct sock *sk)
+{
+ const struct inet_sock *inet = inet_sk(sk);
+ const struct ipv6_pinfo *np = inet6_sk(sk);
+ const struct in6_addr *laddr = &np->rcv_saddr;
+ const struct in6_addr *faddr = &np->daddr;
+ const __u16 lport = inet->inet_num;
+ const __be16 fport = inet->inet_dport;
+ struct net *net = sock_net(sk);
+
+ return inet6_ehashfn(net, laddr, lport, faddr, fport);
+}
+
+extern int __inet6_hash(struct sock *sk, struct inet_timewait_sock *twp);
+
+/*
+ * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
+ * we need not check it for TCP lookups anymore, thanks Alexey. -DaveM
+ *
+ * The sockhash lock must be held as a reader here.
+ */
+extern struct sock *__inet6_lookup_established(struct net *net,
+ struct inet_hashinfo *hashinfo,
+ const struct in6_addr *saddr,
+ const __be16 sport,
+ const struct in6_addr *daddr,
+ const u16 hnum,
+ const int dif);
+
+extern struct sock *inet6_lookup_listener(struct net *net,
+ struct inet_hashinfo *hashinfo,
+ const struct in6_addr *daddr,
+ const unsigned short hnum,
+ const int dif);
+
+static inline struct sock *__inet6_lookup(struct net *net,
+ struct inet_hashinfo *hashinfo,
+ const struct in6_addr *saddr,
+ const __be16 sport,
+ const struct in6_addr *daddr,
+ const u16 hnum,
+ const int dif)
+{
+ struct sock *sk = __inet6_lookup_established(net, hashinfo, saddr,
+ sport, daddr, hnum, dif);
+ if (sk)
+ return sk;
+
+ return inet6_lookup_listener(net, hashinfo, daddr, hnum, dif);
+}
+
+static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo,
+ struct sk_buff *skb,
+ const __be16 sport,
+ const __be16 dport)
+{
+ struct sock *sk;
+
+ if (unlikely(sk = skb_steal_sock(skb)))
+ return sk;
+ else return __inet6_lookup(dev_net(skb_dst(skb)->dev), hashinfo,
+ &ipv6_hdr(skb)->saddr, sport,
+ &ipv6_hdr(skb)->daddr, ntohs(dport),
+ inet6_iif(skb));
+}
+
+extern struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo,
+ const struct in6_addr *saddr, const __be16 sport,
+ const struct in6_addr *daddr, const __be16 dport,
+ const int dif);
+#endif /* IS_ENABLED(CONFIG_IPV6) */
+#endif /* _INET6_HASHTABLES_H */
diff --git a/include/net/inet_common.h b/include/net/inet_common.h
new file mode 100644
index 00000000..22fac989
--- /dev/null
+++ b/include/net/inet_common.h
@@ -0,0 +1,44 @@
+#ifndef _INET_COMMON_H
+#define _INET_COMMON_H
+
+extern const struct proto_ops inet_stream_ops;
+extern const struct proto_ops inet_dgram_ops;
+
+/*
+ * INET4 prototypes used by INET6
+ */
+
+struct msghdr;
+struct sock;
+struct sockaddr;
+struct socket;
+
+extern int inet_release(struct socket *sock);
+extern int inet_stream_connect(struct socket *sock, struct sockaddr * uaddr,
+ int addr_len, int flags);
+extern int inet_dgram_connect(struct socket *sock, struct sockaddr * uaddr,
+ int addr_len, int flags);
+extern int inet_accept(struct socket *sock, struct socket *newsock, int flags);
+extern int inet_sendmsg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *msg, size_t size);
+extern ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset,
+ size_t size, int flags);
+extern int inet_recvmsg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *msg, size_t size, int flags);
+extern int inet_shutdown(struct socket *sock, int how);
+extern int inet_listen(struct socket *sock, int backlog);
+extern void inet_sock_destruct(struct sock *sk);
+extern int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len);
+extern int inet_getname(struct socket *sock, struct sockaddr *uaddr,
+ int *uaddr_len, int peer);
+extern int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
+extern int inet_ctl_sock_create(struct sock **sk, unsigned short family,
+ unsigned short type, unsigned char protocol,
+ struct net *net);
+
+static inline void inet_ctl_sock_destroy(struct sock *sk)
+{
+ sk_release_kernel(sk);
+}
+
+#endif
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
new file mode 100644
index 00000000..dbf9aab3
--- /dev/null
+++ b/include/net/inet_connection_sock.h
@@ -0,0 +1,339 @@
+/*
+ * NET Generic infrastructure for INET connection oriented protocols.
+ *
+ * Definitions for inet_connection_sock
+ *
+ * Authors: Many people, see the TCP sources
+ *
+ * From code originally in TCP
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _INET_CONNECTION_SOCK_H
+#define _INET_CONNECTION_SOCK_H
+
+#include <linux/compiler.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/poll.h>
+
+#include <net/inet_sock.h>
+#include <net/request_sock.h>
+
+#define INET_CSK_DEBUG 1
+
+/* Cancel timers, when they are not required. */
+#undef INET_CSK_CLEAR_TIMERS
+
+struct inet_bind_bucket;
+struct tcp_congestion_ops;
+
+/*
+ * Pointers to address related TCP functions
+ * (i.e. things that depend on the address family)
+ */
+struct inet_connection_sock_af_ops {
+ int (*queue_xmit)(struct sk_buff *skb, struct flowi *fl);
+ void (*send_check)(struct sock *sk, struct sk_buff *skb);
+ int (*rebuild_header)(struct sock *sk);
+ int (*conn_request)(struct sock *sk, struct sk_buff *skb);
+ struct sock *(*syn_recv_sock)(struct sock *sk, struct sk_buff *skb,
+ struct request_sock *req,
+ struct dst_entry *dst);
+ struct inet_peer *(*get_peer)(struct sock *sk, bool *release_it);
+ u16 net_header_len;
+ u16 sockaddr_len;
+ int (*setsockopt)(struct sock *sk, int level, int optname,
+ char __user *optval, unsigned int optlen);
+ int (*getsockopt)(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+#ifdef CONFIG_COMPAT
+ int (*compat_setsockopt)(struct sock *sk,
+ int level, int optname,
+ char __user *optval, unsigned int optlen);
+ int (*compat_getsockopt)(struct sock *sk,
+ int level, int optname,
+ char __user *optval, int __user *optlen);
+#endif
+ void (*addr2sockaddr)(struct sock *sk, struct sockaddr *);
+ int (*bind_conflict)(const struct sock *sk,
+ const struct inet_bind_bucket *tb);
+};
+
+/** inet_connection_sock - INET connection oriented sock
+ *
+ * @icsk_accept_queue: FIFO of established children
+ * @icsk_bind_hash: Bind node
+ * @icsk_timeout: Timeout
+ * @icsk_retransmit_timer: Resend (no ack)
+ * @icsk_rto: Retransmit timeout
+ * @icsk_pmtu_cookie Last pmtu seen by socket
+ * @icsk_ca_ops Pluggable congestion control hook
+ * @icsk_af_ops Operations which are AF_INET{4,6} specific
+ * @icsk_ca_state: Congestion control state
+ * @icsk_retransmits: Number of unrecovered [RTO] timeouts
+ * @icsk_pending: Scheduled timer event
+ * @icsk_backoff: Backoff
+ * @icsk_syn_retries: Number of allowed SYN (or equivalent) retries
+ * @icsk_probes_out: unanswered 0 window probes
+ * @icsk_ext_hdr_len: Network protocol overhead (IP/IPv6 options)
+ * @icsk_ack: Delayed ACK control data
+ * @icsk_mtup; MTU probing control data
+ */
+struct inet_connection_sock {
+ /* inet_sock has to be the first member! */
+ struct inet_sock icsk_inet;
+ struct request_sock_queue icsk_accept_queue;
+ struct inet_bind_bucket *icsk_bind_hash;
+ unsigned long icsk_timeout;
+ struct timer_list icsk_retransmit_timer;
+ struct timer_list icsk_delack_timer;
+ __u32 icsk_rto;
+ __u32 icsk_pmtu_cookie;
+ const struct tcp_congestion_ops *icsk_ca_ops;
+ const struct inet_connection_sock_af_ops *icsk_af_ops;
+ unsigned int (*icsk_sync_mss)(struct sock *sk, u32 pmtu);
+ __u8 icsk_ca_state;
+ __u8 icsk_retransmits;
+ __u8 icsk_pending;
+ __u8 icsk_backoff;
+ __u8 icsk_syn_retries;
+ __u8 icsk_probes_out;
+ __u16 icsk_ext_hdr_len;
+ struct {
+ __u8 pending; /* ACK is pending */
+ __u8 quick; /* Scheduled number of quick acks */
+ __u8 pingpong; /* The session is interactive */
+ __u8 blocked; /* Delayed ACK was blocked by socket lock */
+ __u32 ato; /* Predicted tick of soft clock */
+ unsigned long timeout; /* Currently scheduled timeout */
+ __u32 lrcvtime; /* timestamp of last received data packet */
+ __u16 last_seg_size; /* Size of last incoming segment */
+ __u16 rcv_mss; /* MSS used for delayed ACK decisions */
+ } icsk_ack;
+ struct {
+ int enabled;
+
+ /* Range of MTUs to search */
+ int search_high;
+ int search_low;
+
+ /* Information on the current probe. */
+ int probe_size;
+ } icsk_mtup;
+ u32 icsk_ca_priv[16];
+ u32 icsk_user_timeout;
+#define ICSK_CA_PRIV_SIZE (16 * sizeof(u32))
+};
+
+#define ICSK_TIME_RETRANS 1 /* Retransmit timer */
+#define ICSK_TIME_DACK 2 /* Delayed ack timer */
+#define ICSK_TIME_PROBE0 3 /* Zero window probe timer */
+
+static inline struct inet_connection_sock *inet_csk(const struct sock *sk)
+{
+ return (struct inet_connection_sock *)sk;
+}
+
+static inline void *inet_csk_ca(const struct sock *sk)
+{
+ return (void *)inet_csk(sk)->icsk_ca_priv;
+}
+
+extern struct sock *inet_csk_clone_lock(const struct sock *sk,
+ const struct request_sock *req,
+ const gfp_t priority);
+
+enum inet_csk_ack_state_t {
+ ICSK_ACK_SCHED = 1,
+ ICSK_ACK_TIMER = 2,
+ ICSK_ACK_PUSHED = 4,
+ ICSK_ACK_PUSHED2 = 8
+};
+
+extern void inet_csk_init_xmit_timers(struct sock *sk,
+ void (*retransmit_handler)(unsigned long),
+ void (*delack_handler)(unsigned long),
+ void (*keepalive_handler)(unsigned long));
+extern void inet_csk_clear_xmit_timers(struct sock *sk);
+
+static inline void inet_csk_schedule_ack(struct sock *sk)
+{
+ inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_SCHED;
+}
+
+static inline int inet_csk_ack_scheduled(const struct sock *sk)
+{
+ return inet_csk(sk)->icsk_ack.pending & ICSK_ACK_SCHED;
+}
+
+static inline void inet_csk_delack_init(struct sock *sk)
+{
+ memset(&inet_csk(sk)->icsk_ack, 0, sizeof(inet_csk(sk)->icsk_ack));
+}
+
+extern void inet_csk_delete_keepalive_timer(struct sock *sk);
+extern void inet_csk_reset_keepalive_timer(struct sock *sk, unsigned long timeout);
+
+#ifdef INET_CSK_DEBUG
+extern const char inet_csk_timer_bug_msg[];
+#endif
+
+static inline void inet_csk_clear_xmit_timer(struct sock *sk, const int what)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+
+ if (what == ICSK_TIME_RETRANS || what == ICSK_TIME_PROBE0) {
+ icsk->icsk_pending = 0;
+#ifdef INET_CSK_CLEAR_TIMERS
+ sk_stop_timer(sk, &icsk->icsk_retransmit_timer);
+#endif
+ } else if (what == ICSK_TIME_DACK) {
+ icsk->icsk_ack.blocked = icsk->icsk_ack.pending = 0;
+#ifdef INET_CSK_CLEAR_TIMERS
+ sk_stop_timer(sk, &icsk->icsk_delack_timer);
+#endif
+ }
+#ifdef INET_CSK_DEBUG
+ else {
+ pr_debug("%s", inet_csk_timer_bug_msg);
+ }
+#endif
+}
+
+/*
+ * Reset the retransmission timer
+ */
+static inline void inet_csk_reset_xmit_timer(struct sock *sk, const int what,
+ unsigned long when,
+ const unsigned long max_when)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+
+ if (when > max_when) {
+#ifdef INET_CSK_DEBUG
+ pr_debug("reset_xmit_timer: sk=%p %d when=0x%lx, caller=%p\n",
+ sk, what, when, current_text_addr());
+#endif
+ when = max_when;
+ }
+
+ if (what == ICSK_TIME_RETRANS || what == ICSK_TIME_PROBE0) {
+ icsk->icsk_pending = what;
+ icsk->icsk_timeout = jiffies + when;
+ sk_reset_timer(sk, &icsk->icsk_retransmit_timer, icsk->icsk_timeout);
+ } else if (what == ICSK_TIME_DACK) {
+ icsk->icsk_ack.pending |= ICSK_ACK_TIMER;
+ icsk->icsk_ack.timeout = jiffies + when;
+ sk_reset_timer(sk, &icsk->icsk_delack_timer, icsk->icsk_ack.timeout);
+ }
+#ifdef INET_CSK_DEBUG
+ else {
+ pr_debug("%s", inet_csk_timer_bug_msg);
+ }
+#endif
+}
+
+extern struct sock *inet_csk_accept(struct sock *sk, int flags, int *err);
+
+extern struct request_sock *inet_csk_search_req(const struct sock *sk,
+ struct request_sock ***prevp,
+ const __be16 rport,
+ const __be32 raddr,
+ const __be32 laddr);
+extern int inet_csk_bind_conflict(const struct sock *sk,
+ const struct inet_bind_bucket *tb);
+extern int inet_csk_get_port(struct sock *sk, unsigned short snum);
+
+extern struct dst_entry* inet_csk_route_req(struct sock *sk,
+ struct flowi4 *fl4,
+ const struct request_sock *req);
+extern struct dst_entry* inet_csk_route_child_sock(struct sock *sk,
+ struct sock *newsk,
+ const struct request_sock *req);
+
+static inline void inet_csk_reqsk_queue_add(struct sock *sk,
+ struct request_sock *req,
+ struct sock *child)
+{
+ reqsk_queue_add(&inet_csk(sk)->icsk_accept_queue, req, sk, child);
+}
+
+extern void inet_csk_reqsk_queue_hash_add(struct sock *sk,
+ struct request_sock *req,
+ unsigned long timeout);
+
+static inline void inet_csk_reqsk_queue_removed(struct sock *sk,
+ struct request_sock *req)
+{
+ if (reqsk_queue_removed(&inet_csk(sk)->icsk_accept_queue, req) == 0)
+ inet_csk_delete_keepalive_timer(sk);
+}
+
+static inline void inet_csk_reqsk_queue_added(struct sock *sk,
+ const unsigned long timeout)
+{
+ if (reqsk_queue_added(&inet_csk(sk)->icsk_accept_queue) == 0)
+ inet_csk_reset_keepalive_timer(sk, timeout);
+}
+
+static inline int inet_csk_reqsk_queue_len(const struct sock *sk)
+{
+ return reqsk_queue_len(&inet_csk(sk)->icsk_accept_queue);
+}
+
+static inline int inet_csk_reqsk_queue_young(const struct sock *sk)
+{
+ return reqsk_queue_len_young(&inet_csk(sk)->icsk_accept_queue);
+}
+
+static inline int inet_csk_reqsk_queue_is_full(const struct sock *sk)
+{
+ return reqsk_queue_is_full(&inet_csk(sk)->icsk_accept_queue);
+}
+
+static inline void inet_csk_reqsk_queue_unlink(struct sock *sk,
+ struct request_sock *req,
+ struct request_sock **prev)
+{
+ reqsk_queue_unlink(&inet_csk(sk)->icsk_accept_queue, req, prev);
+}
+
+static inline void inet_csk_reqsk_queue_drop(struct sock *sk,
+ struct request_sock *req,
+ struct request_sock **prev)
+{
+ inet_csk_reqsk_queue_unlink(sk, req, prev);
+ inet_csk_reqsk_queue_removed(sk, req);
+ reqsk_free(req);
+}
+
+extern void inet_csk_reqsk_queue_prune(struct sock *parent,
+ const unsigned long interval,
+ const unsigned long timeout,
+ const unsigned long max_rto);
+
+extern void inet_csk_destroy_sock(struct sock *sk);
+
+/*
+ * LISTEN is a special case for poll..
+ */
+static inline unsigned int inet_csk_listen_poll(const struct sock *sk)
+{
+ return !reqsk_queue_empty(&inet_csk(sk)->icsk_accept_queue) ?
+ (POLLIN | POLLRDNORM) : 0;
+}
+
+extern int inet_csk_listen_start(struct sock *sk, const int nr_table_entries);
+extern void inet_csk_listen_stop(struct sock *sk);
+
+extern void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
+
+extern int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+extern int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, unsigned int optlen);
+#endif /* _INET_CONNECTION_SOCK_H */
diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h
new file mode 100644
index 00000000..2fa14691
--- /dev/null
+++ b/include/net/inet_ecn.h
@@ -0,0 +1,148 @@
+#ifndef _INET_ECN_H_
+#define _INET_ECN_H_
+
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+
+#include <net/inet_sock.h>
+#include <net/dsfield.h>
+
+enum {
+ INET_ECN_NOT_ECT = 0,
+ INET_ECN_ECT_1 = 1,
+ INET_ECN_ECT_0 = 2,
+ INET_ECN_CE = 3,
+ INET_ECN_MASK = 3,
+};
+
+static inline int INET_ECN_is_ce(__u8 dsfield)
+{
+ return (dsfield & INET_ECN_MASK) == INET_ECN_CE;
+}
+
+static inline int INET_ECN_is_not_ect(__u8 dsfield)
+{
+ return (dsfield & INET_ECN_MASK) == INET_ECN_NOT_ECT;
+}
+
+static inline int INET_ECN_is_capable(__u8 dsfield)
+{
+ return dsfield & INET_ECN_ECT_0;
+}
+
+/*
+ * RFC 3168 9.1.1
+ * The full-functionality option for ECN encapsulation is to copy the
+ * ECN codepoint of the inside header to the outside header on
+ * encapsulation if the inside header is not-ECT or ECT, and to set the
+ * ECN codepoint of the outside header to ECT(0) if the ECN codepoint of
+ * the inside header is CE.
+ */
+static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner)
+{
+ outer &= ~INET_ECN_MASK;
+ outer |= !INET_ECN_is_ce(inner) ? (inner & INET_ECN_MASK) :
+ INET_ECN_ECT_0;
+ return outer;
+}
+
+static inline void INET_ECN_xmit(struct sock *sk)
+{
+ inet_sk(sk)->tos |= INET_ECN_ECT_0;
+ if (inet6_sk(sk) != NULL)
+ inet6_sk(sk)->tclass |= INET_ECN_ECT_0;
+}
+
+static inline void INET_ECN_dontxmit(struct sock *sk)
+{
+ inet_sk(sk)->tos &= ~INET_ECN_MASK;
+ if (inet6_sk(sk) != NULL)
+ inet6_sk(sk)->tclass &= ~INET_ECN_MASK;
+}
+
+#define IP6_ECN_flow_init(label) do { \
+ (label) &= ~htonl(INET_ECN_MASK << 20); \
+ } while (0)
+
+#define IP6_ECN_flow_xmit(sk, label) do { \
+ if (INET_ECN_is_capable(inet6_sk(sk)->tclass)) \
+ (label) |= htonl(INET_ECN_ECT_0 << 20); \
+ } while (0)
+
+static inline int IP_ECN_set_ce(struct iphdr *iph)
+{
+ u32 check = (__force u32)iph->check;
+ u32 ecn = (iph->tos + 1) & INET_ECN_MASK;
+
+ /*
+ * After the last operation we have (in binary):
+ * INET_ECN_NOT_ECT => 01
+ * INET_ECN_ECT_1 => 10
+ * INET_ECN_ECT_0 => 11
+ * INET_ECN_CE => 00
+ */
+ if (!(ecn & 2))
+ return !ecn;
+
+ /*
+ * The following gives us:
+ * INET_ECN_ECT_1 => check += htons(0xFFFD)
+ * INET_ECN_ECT_0 => check += htons(0xFFFE)
+ */
+ check += (__force u16)htons(0xFFFB) + (__force u16)htons(ecn);
+
+ iph->check = (__force __sum16)(check + (check>=0xFFFF));
+ iph->tos |= INET_ECN_CE;
+ return 1;
+}
+
+static inline void IP_ECN_clear(struct iphdr *iph)
+{
+ iph->tos &= ~INET_ECN_MASK;
+}
+
+static inline void ipv4_copy_dscp(unsigned int dscp, struct iphdr *inner)
+{
+ dscp &= ~INET_ECN_MASK;
+ ipv4_change_dsfield(inner, INET_ECN_MASK, dscp);
+}
+
+struct ipv6hdr;
+
+static inline int IP6_ECN_set_ce(struct ipv6hdr *iph)
+{
+ if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph)))
+ return 0;
+ *(__be32*)iph |= htonl(INET_ECN_CE << 20);
+ return 1;
+}
+
+static inline void IP6_ECN_clear(struct ipv6hdr *iph)
+{
+ *(__be32*)iph &= ~htonl(INET_ECN_MASK << 20);
+}
+
+static inline void ipv6_copy_dscp(unsigned int dscp, struct ipv6hdr *inner)
+{
+ dscp &= ~INET_ECN_MASK;
+ ipv6_change_dsfield(inner, INET_ECN_MASK, dscp);
+}
+
+static inline int INET_ECN_set_ce(struct sk_buff *skb)
+{
+ switch (skb->protocol) {
+ case cpu_to_be16(ETH_P_IP):
+ if (skb->network_header + sizeof(struct iphdr) <= skb->tail)
+ return IP_ECN_set_ce(ip_hdr(skb));
+ break;
+
+ case cpu_to_be16(ETH_P_IPV6):
+ if (skb->network_header + sizeof(struct ipv6hdr) <= skb->tail)
+ return IP6_ECN_set_ce(ipv6_hdr(skb));
+ break;
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
new file mode 100644
index 00000000..16ff29a7
--- /dev/null
+++ b/include/net/inet_frag.h
@@ -0,0 +1,74 @@
+#ifndef __NET_FRAG_H__
+#define __NET_FRAG_H__
+
+struct netns_frags {
+ int nqueues;
+ atomic_t mem;
+ struct list_head lru_list;
+
+ /* sysctls */
+ int timeout;
+ int high_thresh;
+ int low_thresh;
+};
+
+struct inet_frag_queue {
+ struct hlist_node list;
+ struct netns_frags *net;
+ struct list_head lru_list; /* lru list member */
+ spinlock_t lock;
+ atomic_t refcnt;
+ struct timer_list timer; /* when will this queue expire? */
+ struct sk_buff *fragments; /* list of received fragments */
+ struct sk_buff *fragments_tail;
+ ktime_t stamp;
+ int len; /* total length of orig datagram */
+ int meat;
+ __u8 last_in; /* first/last segment arrived? */
+
+#define INET_FRAG_COMPLETE 4
+#define INET_FRAG_FIRST_IN 2
+#define INET_FRAG_LAST_IN 1
+};
+
+#define INETFRAGS_HASHSZ 64
+
+struct inet_frags {
+ struct hlist_head hash[INETFRAGS_HASHSZ];
+ rwlock_t lock;
+ u32 rnd;
+ int qsize;
+ int secret_interval;
+ struct timer_list secret_timer;
+
+ unsigned int (*hashfn)(struct inet_frag_queue *);
+ void (*constructor)(struct inet_frag_queue *q,
+ void *arg);
+ void (*destructor)(struct inet_frag_queue *);
+ void (*skb_free)(struct sk_buff *);
+ int (*match)(struct inet_frag_queue *q,
+ void *arg);
+ void (*frag_expire)(unsigned long data);
+};
+
+void inet_frags_init(struct inet_frags *);
+void inet_frags_fini(struct inet_frags *);
+
+void inet_frags_init_net(struct netns_frags *nf);
+void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f);
+
+void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f);
+void inet_frag_destroy(struct inet_frag_queue *q,
+ struct inet_frags *f, int *work);
+int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f);
+struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
+ struct inet_frags *f, void *key, unsigned int hash)
+ __releases(&f->lock);
+
+static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f)
+{
+ if (atomic_dec_and_test(&q->refcnt))
+ inet_frag_destroy(q, f, NULL);
+}
+
+#endif
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
new file mode 100644
index 00000000..808fc5f7
--- /dev/null
+++ b/include/net/inet_hashtables.h
@@ -0,0 +1,402 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Authors: Lotsa people, from code originally in tcp
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _INET_HASHTABLES_H
+#define _INET_HASHTABLES_H
+
+
+#include <linux/interrupt.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/socket.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/vmalloc.h>
+
+#include <net/inet_connection_sock.h>
+#include <net/inet_sock.h>
+#include <net/sock.h>
+#include <net/route.h>
+#include <net/tcp_states.h>
+#include <net/netns/hash.h>
+
+#include <linux/atomic.h>
+#include <asm/byteorder.h>
+
+/* This is for all connections with a full identity, no wildcards.
+ * One chain is dedicated to TIME_WAIT sockets.
+ * I'll experiment with dynamic table growth later.
+ */
+struct inet_ehash_bucket {
+ struct hlist_nulls_head chain;
+ struct hlist_nulls_head twchain;
+};
+
+/* There are a few simple rules, which allow for local port reuse by
+ * an application. In essence:
+ *
+ * 1) Sockets bound to different interfaces may share a local port.
+ * Failing that, goto test 2.
+ * 2) If all sockets have sk->sk_reuse set, and none of them are in
+ * TCP_LISTEN state, the port may be shared.
+ * Failing that, goto test 3.
+ * 3) If all sockets are bound to a specific inet_sk(sk)->rcv_saddr local
+ * address, and none of them are the same, the port may be
+ * shared.
+ * Failing this, the port cannot be shared.
+ *
+ * The interesting point, is test #2. This is what an FTP server does
+ * all day. To optimize this case we use a specific flag bit defined
+ * below. As we add sockets to a bind bucket list, we perform a
+ * check of: (newsk->sk_reuse && (newsk->sk_state != TCP_LISTEN))
+ * As long as all sockets added to a bind bucket pass this test,
+ * the flag bit will be set.
+ * The resulting situation is that tcp_v[46]_verify_bind() can just check
+ * for this flag bit, if it is set and the socket trying to bind has
+ * sk->sk_reuse set, we don't even have to walk the owners list at all,
+ * we return that it is ok to bind this socket to the requested local port.
+ *
+ * Sounds like a lot of work, but it is worth it. In a more naive
+ * implementation (ie. current FreeBSD etc.) the entire list of ports
+ * must be walked for each data port opened by an ftp server. Needless
+ * to say, this does not scale at all. With a couple thousand FTP
+ * users logged onto your box, isn't it nice to know that new data
+ * ports are created in O(1) time? I thought so. ;-) -DaveM
+ */
+struct inet_bind_bucket {
+#ifdef CONFIG_NET_NS
+ struct net *ib_net;
+#endif
+ unsigned short port;
+ signed short fastreuse;
+ int num_owners;
+ struct hlist_node node;
+ struct hlist_head owners;
+};
+
+static inline struct net *ib_net(struct inet_bind_bucket *ib)
+{
+ return read_pnet(&ib->ib_net);
+}
+
+#define inet_bind_bucket_for_each(tb, pos, head) \
+ hlist_for_each_entry(tb, pos, head, node)
+
+struct inet_bind_hashbucket {
+ spinlock_t lock;
+ struct hlist_head chain;
+};
+
+/*
+ * Sockets can be hashed in established or listening table
+ * We must use different 'nulls' end-of-chain value for listening
+ * hash table, or we might find a socket that was closed and
+ * reallocated/inserted into established hash table
+ */
+#define LISTENING_NULLS_BASE (1U << 29)
+struct inet_listen_hashbucket {
+ spinlock_t lock;
+ struct hlist_nulls_head head;
+};
+
+/* This is for listening sockets, thus all sockets which possess wildcards. */
+#define INET_LHTABLE_SIZE 32 /* Yes, really, this is all you need. */
+
+struct inet_hashinfo {
+ /* This is for sockets with full identity only. Sockets here will
+ * always be without wildcards and will have the following invariant:
+ *
+ * TCP_ESTABLISHED <= sk->sk_state < TCP_CLOSE
+ *
+ * TIME_WAIT sockets use a separate chain (twchain).
+ */
+ struct inet_ehash_bucket *ehash;
+ spinlock_t *ehash_locks;
+ unsigned int ehash_mask;
+ unsigned int ehash_locks_mask;
+
+ /* Ok, let's try this, I give up, we do need a local binding
+ * TCP hash as well as the others for fast bind/connect.
+ */
+ struct inet_bind_hashbucket *bhash;
+
+ unsigned int bhash_size;
+ /* 4 bytes hole on 64 bit */
+
+ struct kmem_cache *bind_bucket_cachep;
+
+ /* All the above members are written once at bootup and
+ * never written again _or_ are predominantly read-access.
+ *
+ * Now align to a new cache line as all the following members
+ * might be often dirty.
+ */
+ /* All sockets in TCP_LISTEN state will be in here. This is the only
+ * table where wildcard'd TCP sockets can exist. Hash function here
+ * is just local port number.
+ */
+ struct inet_listen_hashbucket listening_hash[INET_LHTABLE_SIZE]
+ ____cacheline_aligned_in_smp;
+
+ atomic_t bsockets;
+};
+
+static inline struct inet_ehash_bucket *inet_ehash_bucket(
+ struct inet_hashinfo *hashinfo,
+ unsigned int hash)
+{
+ return &hashinfo->ehash[hash & hashinfo->ehash_mask];
+}
+
+static inline spinlock_t *inet_ehash_lockp(
+ struct inet_hashinfo *hashinfo,
+ unsigned int hash)
+{
+ return &hashinfo->ehash_locks[hash & hashinfo->ehash_locks_mask];
+}
+
+static inline int inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo)
+{
+ unsigned int i, size = 256;
+#if defined(CONFIG_PROVE_LOCKING)
+ unsigned int nr_pcpus = 2;
+#else
+ unsigned int nr_pcpus = num_possible_cpus();
+#endif
+ if (nr_pcpus >= 4)
+ size = 512;
+ if (nr_pcpus >= 8)
+ size = 1024;
+ if (nr_pcpus >= 16)
+ size = 2048;
+ if (nr_pcpus >= 32)
+ size = 4096;
+ if (sizeof(spinlock_t) != 0) {
+#ifdef CONFIG_NUMA
+ if (size * sizeof(spinlock_t) > PAGE_SIZE)
+ hashinfo->ehash_locks = vmalloc(size * sizeof(spinlock_t));
+ else
+#endif
+ hashinfo->ehash_locks = kmalloc(size * sizeof(spinlock_t),
+ GFP_KERNEL);
+ if (!hashinfo->ehash_locks)
+ return ENOMEM;
+ for (i = 0; i < size; i++)
+ spin_lock_init(&hashinfo->ehash_locks[i]);
+ }
+ hashinfo->ehash_locks_mask = size - 1;
+ return 0;
+}
+
+static inline void inet_ehash_locks_free(struct inet_hashinfo *hashinfo)
+{
+ if (hashinfo->ehash_locks) {
+#ifdef CONFIG_NUMA
+ unsigned int size = (hashinfo->ehash_locks_mask + 1) *
+ sizeof(spinlock_t);
+ if (size > PAGE_SIZE)
+ vfree(hashinfo->ehash_locks);
+ else
+#endif
+ kfree(hashinfo->ehash_locks);
+ hashinfo->ehash_locks = NULL;
+ }
+}
+
+extern struct inet_bind_bucket *
+ inet_bind_bucket_create(struct kmem_cache *cachep,
+ struct net *net,
+ struct inet_bind_hashbucket *head,
+ const unsigned short snum);
+extern void inet_bind_bucket_destroy(struct kmem_cache *cachep,
+ struct inet_bind_bucket *tb);
+
+static inline int inet_bhashfn(struct net *net,
+ const __u16 lport, const int bhash_size)
+{
+ return (lport + net_hash_mix(net)) & (bhash_size - 1);
+}
+
+extern void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
+ const unsigned short snum);
+
+/* These can have wildcards, don't try too hard. */
+static inline int inet_lhashfn(struct net *net, const unsigned short num)
+{
+ return (num + net_hash_mix(net)) & (INET_LHTABLE_SIZE - 1);
+}
+
+static inline int inet_sk_listen_hashfn(const struct sock *sk)
+{
+ return inet_lhashfn(sock_net(sk), inet_sk(sk)->inet_num);
+}
+
+/* Caller must disable local BH processing. */
+extern int __inet_inherit_port(struct sock *sk, struct sock *child);
+
+extern void inet_put_port(struct sock *sk);
+
+void inet_hashinfo_init(struct inet_hashinfo *h);
+
+extern int __inet_hash_nolisten(struct sock *sk, struct inet_timewait_sock *tw);
+extern void inet_hash(struct sock *sk);
+extern void inet_unhash(struct sock *sk);
+
+extern struct sock *__inet_lookup_listener(struct net *net,
+ struct inet_hashinfo *hashinfo,
+ const __be32 daddr,
+ const unsigned short hnum,
+ const int dif);
+
+static inline struct sock *inet_lookup_listener(struct net *net,
+ struct inet_hashinfo *hashinfo,
+ __be32 daddr, __be16 dport, int dif)
+{
+ return __inet_lookup_listener(net, hashinfo, daddr, ntohs(dport), dif);
+}
+
+/* Socket demux engine toys. */
+/* What happens here is ugly; there's a pair of adjacent fields in
+ struct inet_sock; __be16 dport followed by __u16 num. We want to
+ search by pair, so we combine the keys into a single 32bit value
+ and compare with 32bit value read from &...->dport. Let's at least
+ make sure that it's not mixed with anything else...
+ On 64bit targets we combine comparisons with pair of adjacent __be32
+ fields in the same way.
+*/
+typedef __u32 __bitwise __portpair;
+#ifdef __BIG_ENDIAN
+#define INET_COMBINED_PORTS(__sport, __dport) \
+ ((__force __portpair)(((__force __u32)(__be16)(__sport) << 16) | (__u32)(__dport)))
+#else /* __LITTLE_ENDIAN */
+#define INET_COMBINED_PORTS(__sport, __dport) \
+ ((__force __portpair)(((__u32)(__dport) << 16) | (__force __u32)(__be16)(__sport)))
+#endif
+
+#if (BITS_PER_LONG == 64)
+typedef __u64 __bitwise __addrpair;
+#ifdef __BIG_ENDIAN
+#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
+ const __addrpair __name = (__force __addrpair) ( \
+ (((__force __u64)(__be32)(__saddr)) << 32) | \
+ ((__force __u64)(__be32)(__daddr)));
+#else /* __LITTLE_ENDIAN */
+#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
+ const __addrpair __name = (__force __addrpair) ( \
+ (((__force __u64)(__be32)(__daddr)) << 32) | \
+ ((__force __u64)(__be32)(__saddr)));
+#endif /* __BIG_ENDIAN */
+#define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
+ (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \
+ ((*((__addrpair *)&(inet_sk(__sk)->inet_daddr))) == (__cookie)) && \
+ ((*((__portpair *)&(inet_sk(__sk)->inet_dport))) == (__ports)) && \
+ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+#define INET_TW_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
+ (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \
+ ((*((__addrpair *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) && \
+ ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \
+ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+#else /* 32-bit arch */
+#define INET_ADDR_COOKIE(__name, __saddr, __daddr)
+#define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif) \
+ (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \
+ (inet_sk(__sk)->inet_daddr == (__saddr)) && \
+ (inet_sk(__sk)->inet_rcv_saddr == (__daddr)) && \
+ ((*((__portpair *)&(inet_sk(__sk)->inet_dport))) == (__ports)) && \
+ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+#define INET_TW_MATCH(__sk, __net, __hash,__cookie, __saddr, __daddr, __ports, __dif) \
+ (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \
+ (inet_twsk(__sk)->tw_daddr == (__saddr)) && \
+ (inet_twsk(__sk)->tw_rcv_saddr == (__daddr)) && \
+ ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \
+ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+#endif /* 64-bit arch */
+
+/*
+ * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so we need
+ * not check it for lookups anymore, thanks Alexey. -DaveM
+ *
+ * Local BH must be disabled here.
+ */
+extern struct sock * __inet_lookup_established(struct net *net,
+ struct inet_hashinfo *hashinfo,
+ const __be32 saddr, const __be16 sport,
+ const __be32 daddr, const u16 hnum, const int dif);
+
+static inline struct sock *
+ inet_lookup_established(struct net *net, struct inet_hashinfo *hashinfo,
+ const __be32 saddr, const __be16 sport,
+ const __be32 daddr, const __be16 dport,
+ const int dif)
+{
+ return __inet_lookup_established(net, hashinfo, saddr, sport, daddr,
+ ntohs(dport), dif);
+}
+
+static inline struct sock *__inet_lookup(struct net *net,
+ struct inet_hashinfo *hashinfo,
+ const __be32 saddr, const __be16 sport,
+ const __be32 daddr, const __be16 dport,
+ const int dif)
+{
+ u16 hnum = ntohs(dport);
+ struct sock *sk = __inet_lookup_established(net, hashinfo,
+ saddr, sport, daddr, hnum, dif);
+
+ return sk ? : __inet_lookup_listener(net, hashinfo, daddr, hnum, dif);
+}
+
+static inline struct sock *inet_lookup(struct net *net,
+ struct inet_hashinfo *hashinfo,
+ const __be32 saddr, const __be16 sport,
+ const __be32 daddr, const __be16 dport,
+ const int dif)
+{
+ struct sock *sk;
+
+ local_bh_disable();
+ sk = __inet_lookup(net, hashinfo, saddr, sport, daddr, dport, dif);
+ local_bh_enable();
+
+ return sk;
+}
+
+static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo,
+ struct sk_buff *skb,
+ const __be16 sport,
+ const __be16 dport)
+{
+ struct sock *sk;
+ const struct iphdr *iph = ip_hdr(skb);
+
+ if (unlikely(sk = skb_steal_sock(skb)))
+ return sk;
+ else
+ return __inet_lookup(dev_net(skb_dst(skb)->dev), hashinfo,
+ iph->saddr, sport,
+ iph->daddr, dport, inet_iif(skb));
+}
+
+extern int __inet_hash_connect(struct inet_timewait_death_row *death_row,
+ struct sock *sk,
+ u32 port_offset,
+ int (*check_established)(struct inet_timewait_death_row *,
+ struct sock *, __u16, struct inet_timewait_sock **),
+ int (*hash)(struct sock *sk, struct inet_timewait_sock *twp));
+
+extern int inet_hash_connect(struct inet_timewait_death_row *death_row,
+ struct sock *sk);
+#endif /* _INET_HASHTABLES_H */
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
new file mode 100644
index 00000000..ae17e135
--- /dev/null
+++ b/include/net/inet_sock.h
@@ -0,0 +1,253 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for inet_sock
+ *
+ * Authors: Many, reorganised here by
+ * Arnaldo Carvalho de Melo <acme@mandriva.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _INET_SOCK_H
+#define _INET_SOCK_H
+
+
+#include <linux/kmemcheck.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/jhash.h>
+#include <linux/netdevice.h>
+
+#include <net/flow.h>
+#include <net/sock.h>
+#include <net/request_sock.h>
+#include <net/netns/hash.h>
+
+/** struct ip_options - IP Options
+ *
+ * @faddr - Saved first hop address
+ * @nexthop - Saved nexthop address in LSRR and SSRR
+ * @is_data - Options in __data, rather than skb
+ * @is_strictroute - Strict source route
+ * @srr_is_hit - Packet destination addr was our one
+ * @is_changed - IP checksum more not valid
+ * @rr_needaddr - Need to record addr of outgoing dev
+ * @ts_needtime - Need to record timestamp
+ * @ts_needaddr - Need to record addr of outgoing dev
+ */
+struct ip_options {
+ __be32 faddr;
+ __be32 nexthop;
+ unsigned char optlen;
+ unsigned char srr;
+ unsigned char rr;
+ unsigned char ts;
+ unsigned char is_strictroute:1,
+ srr_is_hit:1,
+ is_changed:1,
+ rr_needaddr:1,
+ ts_needtime:1,
+ ts_needaddr:1;
+ unsigned char router_alert;
+ unsigned char cipso;
+ unsigned char __pad2;
+ unsigned char __data[0];
+};
+
+struct ip_options_rcu {
+ struct rcu_head rcu;
+ struct ip_options opt;
+};
+
+struct ip_options_data {
+ struct ip_options_rcu opt;
+ char data[40];
+};
+
+struct inet_request_sock {
+ struct request_sock req;
+#if IS_ENABLED(CONFIG_IPV6)
+ u16 inet6_rsk_offset;
+#endif
+ __be16 loc_port;
+ __be32 loc_addr;
+ __be32 rmt_addr;
+ __be16 rmt_port;
+ kmemcheck_bitfield_begin(flags);
+ u16 snd_wscale : 4,
+ rcv_wscale : 4,
+ tstamp_ok : 1,
+ sack_ok : 1,
+ wscale_ok : 1,
+ ecn_ok : 1,
+ acked : 1,
+ no_srccheck: 1;
+ kmemcheck_bitfield_end(flags);
+ struct ip_options_rcu *opt;
+};
+
+static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk)
+{
+ return (struct inet_request_sock *)sk;
+}
+
+struct inet_cork {
+ unsigned int flags;
+ __be32 addr;
+ struct ip_options *opt;
+ unsigned int fragsize;
+ struct dst_entry *dst;
+ int length; /* Total length of all frames */
+ struct page *page;
+ u32 off;
+ u8 tx_flags;
+};
+
+struct inet_cork_full {
+ struct inet_cork base;
+ struct flowi fl;
+};
+
+struct ip_mc_socklist;
+struct ipv6_pinfo;
+struct rtable;
+
+/** struct inet_sock - representation of INET sockets
+ *
+ * @sk - ancestor class
+ * @pinet6 - pointer to IPv6 control block
+ * @inet_daddr - Foreign IPv4 addr
+ * @inet_rcv_saddr - Bound local IPv4 addr
+ * @inet_dport - Destination port
+ * @inet_num - Local port
+ * @inet_saddr - Sending source
+ * @uc_ttl - Unicast TTL
+ * @inet_sport - Source port
+ * @inet_id - ID counter for DF pkts
+ * @tos - TOS
+ * @mc_ttl - Multicasting TTL
+ * @is_icsk - is this an inet_connection_sock?
+ * @uc_index - Unicast outgoing device index
+ * @mc_index - Multicast device index
+ * @mc_list - Group array
+ * @cork - info to build ip hdr on each ip frag while socket is corked
+ */
+struct inet_sock {
+ /* sk and pinet6 has to be the first two members of inet_sock */
+ struct sock sk;
+#if IS_ENABLED(CONFIG_IPV6)
+ struct ipv6_pinfo *pinet6;
+#endif
+ /* Socket demultiplex comparisons on incoming packets. */
+#define inet_daddr sk.__sk_common.skc_daddr
+#define inet_rcv_saddr sk.__sk_common.skc_rcv_saddr
+
+ __be16 inet_dport;
+ __u16 inet_num;
+ __be32 inet_saddr;
+ __s16 uc_ttl;
+ __u16 cmsg_flags;
+ __be16 inet_sport;
+ __u16 inet_id;
+
+ struct ip_options_rcu __rcu *inet_opt;
+ __u8 tos;
+ __u8 min_ttl;
+ __u8 mc_ttl;
+ __u8 pmtudisc;
+ __u8 recverr:1,
+ is_icsk:1,
+ freebind:1,
+ hdrincl:1,
+ mc_loop:1,
+ transparent:1,
+ mc_all:1,
+ nodefrag:1;
+ __u8 rcv_tos;
+ int uc_index;
+ int mc_index;
+ __be32 mc_addr;
+ struct ip_mc_socklist __rcu *mc_list;
+ struct inet_cork_full cork;
+};
+
+#define IPCORK_OPT 1 /* ip-options has been held in ipcork.opt */
+#define IPCORK_ALLFRAG 2 /* always fragment (for ipv6 for now) */
+
+static inline struct inet_sock *inet_sk(const struct sock *sk)
+{
+ return (struct inet_sock *)sk;
+}
+
+static inline void __inet_sk_copy_descendant(struct sock *sk_to,
+ const struct sock *sk_from,
+ const int ancestor_size)
+{
+ memcpy(inet_sk(sk_to) + 1, inet_sk(sk_from) + 1,
+ sk_from->sk_prot->obj_size - ancestor_size);
+}
+#if !(IS_ENABLED(CONFIG_IPV6))
+static inline void inet_sk_copy_descendant(struct sock *sk_to,
+ const struct sock *sk_from)
+{
+ __inet_sk_copy_descendant(sk_to, sk_from, sizeof(struct inet_sock));
+}
+#endif
+
+extern int inet_sk_rebuild_header(struct sock *sk);
+
+extern u32 inet_ehash_secret;
+extern void build_ehash_secret(void);
+
+static inline unsigned int inet_ehashfn(struct net *net,
+ const __be32 laddr, const __u16 lport,
+ const __be32 faddr, const __be16 fport)
+{
+ return jhash_3words((__force __u32) laddr,
+ (__force __u32) faddr,
+ ((__u32) lport) << 16 | (__force __u32)fport,
+ inet_ehash_secret + net_hash_mix(net));
+}
+
+static inline int inet_sk_ehashfn(const struct sock *sk)
+{
+ const struct inet_sock *inet = inet_sk(sk);
+ const __be32 laddr = inet->inet_rcv_saddr;
+ const __u16 lport = inet->inet_num;
+ const __be32 faddr = inet->inet_daddr;
+ const __be16 fport = inet->inet_dport;
+ struct net *net = sock_net(sk);
+
+ return inet_ehashfn(net, laddr, lport, faddr, fport);
+}
+
+static inline struct request_sock *inet_reqsk_alloc(struct request_sock_ops *ops)
+{
+ struct request_sock *req = reqsk_alloc(ops);
+ struct inet_request_sock *ireq = inet_rsk(req);
+
+ if (req != NULL) {
+ kmemcheck_annotate_bitfield(ireq, flags);
+ ireq->opt = NULL;
+ }
+
+ return req;
+}
+
+static inline __u8 inet_sk_flowi_flags(const struct sock *sk)
+{
+ __u8 flags = 0;
+
+ if (inet_sk(sk)->transparent || inet_sk(sk)->hdrincl)
+ flags |= FLOWI_FLAG_ANYSRC;
+ if (sk->sk_protocol == IPPROTO_TCP)
+ flags |= FLOWI_FLAG_PRECOW_METRICS;
+ return flags;
+}
+
+#endif /* _INET_SOCK_H */
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
new file mode 100644
index 00000000..ba52c830
--- /dev/null
+++ b/include/net/inet_timewait_sock.h
@@ -0,0 +1,229 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for a generic INET TIMEWAIT sock
+ *
+ * From code originally in net/tcp.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _INET_TIMEWAIT_SOCK_
+#define _INET_TIMEWAIT_SOCK_
+
+
+#include <linux/kmemcheck.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+#include <net/inet_sock.h>
+#include <net/sock.h>
+#include <net/tcp_states.h>
+#include <net/timewait_sock.h>
+
+#include <linux/atomic.h>
+
+struct inet_hashinfo;
+
+#define INET_TWDR_RECYCLE_SLOTS_LOG 5
+#define INET_TWDR_RECYCLE_SLOTS (1 << INET_TWDR_RECYCLE_SLOTS_LOG)
+
+/*
+ * If time > 4sec, it is "slow" path, no recycling is required,
+ * so that we select tick to get range about 4 seconds.
+ */
+#if HZ <= 16 || HZ > 4096
+# error Unsupported: HZ <= 16 or HZ > 4096
+#elif HZ <= 32
+# define INET_TWDR_RECYCLE_TICK (5 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
+#elif HZ <= 64
+# define INET_TWDR_RECYCLE_TICK (6 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
+#elif HZ <= 128
+# define INET_TWDR_RECYCLE_TICK (7 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
+#elif HZ <= 256
+# define INET_TWDR_RECYCLE_TICK (8 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
+#elif HZ <= 512
+# define INET_TWDR_RECYCLE_TICK (9 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
+#elif HZ <= 1024
+# define INET_TWDR_RECYCLE_TICK (10 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
+#elif HZ <= 2048
+# define INET_TWDR_RECYCLE_TICK (11 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
+#else
+# define INET_TWDR_RECYCLE_TICK (12 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
+#endif
+
+/* TIME_WAIT reaping mechanism. */
+#define INET_TWDR_TWKILL_SLOTS 8 /* Please keep this a power of 2. */
+
+#define INET_TWDR_TWKILL_QUOTA 100
+
+struct inet_timewait_death_row {
+ /* Short-time timewait calendar */
+ int twcal_hand;
+ unsigned long twcal_jiffie;
+ struct timer_list twcal_timer;
+ struct hlist_head twcal_row[INET_TWDR_RECYCLE_SLOTS];
+
+ spinlock_t death_lock;
+ int tw_count;
+ int period;
+ u32 thread_slots;
+ struct work_struct twkill_work;
+ struct timer_list tw_timer;
+ int slot;
+ struct hlist_head cells[INET_TWDR_TWKILL_SLOTS];
+ struct inet_hashinfo *hashinfo;
+ int sysctl_tw_recycle;
+ int sysctl_max_tw_buckets;
+};
+
+extern void inet_twdr_hangman(unsigned long data);
+extern void inet_twdr_twkill_work(struct work_struct *work);
+extern void inet_twdr_twcal_tick(unsigned long data);
+
+struct inet_bind_bucket;
+
+/*
+ * This is a TIME_WAIT sock. It works around the memory consumption
+ * problems of sockets in such a state on heavily loaded servers, but
+ * without violating the protocol specification.
+ */
+struct inet_timewait_sock {
+ /*
+ * Now struct sock also uses sock_common, so please just
+ * don't add nothing before this first member (__tw_common) --acme
+ */
+ struct sock_common __tw_common;
+#define tw_family __tw_common.skc_family
+#define tw_state __tw_common.skc_state
+#define tw_reuse __tw_common.skc_reuse
+#define tw_bound_dev_if __tw_common.skc_bound_dev_if
+#define tw_node __tw_common.skc_nulls_node
+#define tw_bind_node __tw_common.skc_bind_node
+#define tw_refcnt __tw_common.skc_refcnt
+#define tw_hash __tw_common.skc_hash
+#define tw_prot __tw_common.skc_prot
+#define tw_net __tw_common.skc_net
+#define tw_daddr __tw_common.skc_daddr
+#define tw_rcv_saddr __tw_common.skc_rcv_saddr
+ int tw_timeout;
+ volatile unsigned char tw_substate;
+ unsigned char tw_rcv_wscale;
+
+ /* Socket demultiplex comparisons on incoming packets. */
+ /* these three are in inet_sock */
+ __be16 tw_sport;
+ __be16 tw_dport;
+ __u16 tw_num;
+ kmemcheck_bitfield_begin(flags);
+ /* And these are ours. */
+ unsigned int tw_ipv6only : 1,
+ tw_transparent : 1,
+ tw_pad : 6, /* 6 bits hole */
+ tw_tos : 8,
+ tw_ipv6_offset : 16;
+ kmemcheck_bitfield_end(flags);
+ unsigned long tw_ttd;
+ struct inet_bind_bucket *tw_tb;
+ struct hlist_node tw_death_node;
+};
+#define tw_tclass tw_tos
+
+static inline void inet_twsk_add_node_rcu(struct inet_timewait_sock *tw,
+ struct hlist_nulls_head *list)
+{
+ hlist_nulls_add_head_rcu(&tw->tw_node, list);
+}
+
+static inline void inet_twsk_add_bind_node(struct inet_timewait_sock *tw,
+ struct hlist_head *list)
+{
+ hlist_add_head(&tw->tw_bind_node, list);
+}
+
+static inline int inet_twsk_dead_hashed(const struct inet_timewait_sock *tw)
+{
+ return !hlist_unhashed(&tw->tw_death_node);
+}
+
+static inline void inet_twsk_dead_node_init(struct inet_timewait_sock *tw)
+{
+ tw->tw_death_node.pprev = NULL;
+}
+
+static inline void __inet_twsk_del_dead_node(struct inet_timewait_sock *tw)
+{
+ __hlist_del(&tw->tw_death_node);
+ inet_twsk_dead_node_init(tw);
+}
+
+static inline int inet_twsk_del_dead_node(struct inet_timewait_sock *tw)
+{
+ if (inet_twsk_dead_hashed(tw)) {
+ __inet_twsk_del_dead_node(tw);
+ return 1;
+ }
+ return 0;
+}
+
+#define inet_twsk_for_each(tw, node, head) \
+ hlist_nulls_for_each_entry(tw, node, head, tw_node)
+
+#define inet_twsk_for_each_inmate(tw, node, jail) \
+ hlist_for_each_entry(tw, node, jail, tw_death_node)
+
+#define inet_twsk_for_each_inmate_safe(tw, node, safe, jail) \
+ hlist_for_each_entry_safe(tw, node, safe, jail, tw_death_node)
+
+static inline struct inet_timewait_sock *inet_twsk(const struct sock *sk)
+{
+ return (struct inet_timewait_sock *)sk;
+}
+
+static inline __be32 sk_rcv_saddr(const struct sock *sk)
+{
+/* both inet_sk() and inet_twsk() store rcv_saddr in skc_rcv_saddr */
+ return sk->__sk_common.skc_rcv_saddr;
+}
+
+extern void inet_twsk_put(struct inet_timewait_sock *tw);
+
+extern int inet_twsk_unhash(struct inet_timewait_sock *tw);
+
+extern int inet_twsk_bind_unhash(struct inet_timewait_sock *tw,
+ struct inet_hashinfo *hashinfo);
+
+extern struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk,
+ const int state);
+
+extern void __inet_twsk_hashdance(struct inet_timewait_sock *tw,
+ struct sock *sk,
+ struct inet_hashinfo *hashinfo);
+
+extern void inet_twsk_schedule(struct inet_timewait_sock *tw,
+ struct inet_timewait_death_row *twdr,
+ const int timeo, const int timewait_len);
+extern void inet_twsk_deschedule(struct inet_timewait_sock *tw,
+ struct inet_timewait_death_row *twdr);
+
+extern void inet_twsk_purge(struct inet_hashinfo *hashinfo,
+ struct inet_timewait_death_row *twdr, int family);
+
+static inline
+struct net *twsk_net(const struct inet_timewait_sock *twsk)
+{
+ return read_pnet(&twsk->tw_net);
+}
+
+static inline
+void twsk_net_set(struct inet_timewait_sock *twsk, struct net *net)
+{
+ write_pnet(&twsk->tw_net, net);
+}
+#endif /* _INET_TIMEWAIT_SOCK_ */
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
new file mode 100644
index 00000000..2040bff9
--- /dev/null
+++ b/include/net/inetpeer.h
@@ -0,0 +1,129 @@
+/*
+ * INETPEER - A storage for permanent information about peers
+ *
+ * Authors: Andrey V. Savochkin <saw@msu.ru>
+ */
+
+#ifndef _NET_INETPEER_H
+#define _NET_INETPEER_H
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/spinlock.h>
+#include <linux/rtnetlink.h>
+#include <net/ipv6.h>
+#include <linux/atomic.h>
+
+struct inetpeer_addr_base {
+ union {
+ __be32 a4;
+ __be32 a6[4];
+ };
+};
+
+struct inetpeer_addr {
+ struct inetpeer_addr_base addr;
+ __u16 family;
+};
+
+struct inet_peer {
+ /* group together avl_left,avl_right,v4daddr to speedup lookups */
+ struct inet_peer __rcu *avl_left, *avl_right;
+ struct inetpeer_addr daddr;
+ __u32 avl_height;
+
+ u32 metrics[RTAX_MAX];
+ u32 rate_tokens; /* rate limiting for ICMP */
+ unsigned long rate_last;
+ unsigned long pmtu_expires;
+ u32 pmtu_orig;
+ u32 pmtu_learned;
+ struct inetpeer_addr_base redirect_learned;
+ union {
+ struct list_head gc_list;
+ struct rcu_head gc_rcu;
+ };
+ /*
+ * Once inet_peer is queued for deletion (refcnt == -1), following fields
+ * are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp
+ * We can share memory with rcu_head to help keep inet_peer small.
+ */
+ union {
+ struct {
+ atomic_t rid; /* Frag reception counter */
+ atomic_t ip_id_count; /* IP ID for the next packet */
+ __u32 tcp_ts;
+ __u32 tcp_ts_stamp;
+ };
+ struct rcu_head rcu;
+ struct inet_peer *gc_next;
+ };
+
+ /* following fields might be frequently dirtied */
+ __u32 dtime; /* the time of last use of not referenced entries */
+ atomic_t refcnt;
+};
+
+void inet_initpeers(void) __init;
+
+#define INETPEER_METRICS_NEW (~(u32) 0)
+
+static inline bool inet_metrics_new(const struct inet_peer *p)
+{
+ return p->metrics[RTAX_LOCK-1] == INETPEER_METRICS_NEW;
+}
+
+/* can be called with or without local BH being disabled */
+struct inet_peer *inet_getpeer(const struct inetpeer_addr *daddr, int create);
+
+static inline struct inet_peer *inet_getpeer_v4(__be32 v4daddr, int create)
+{
+ struct inetpeer_addr daddr;
+
+ daddr.addr.a4 = v4daddr;
+ daddr.family = AF_INET;
+ return inet_getpeer(&daddr, create);
+}
+
+static inline struct inet_peer *inet_getpeer_v6(const struct in6_addr *v6daddr, int create)
+{
+ struct inetpeer_addr daddr;
+
+ *(struct in6_addr *)daddr.addr.a6 = *v6daddr;
+ daddr.family = AF_INET6;
+ return inet_getpeer(&daddr, create);
+}
+
+/* can be called from BH context or outside */
+extern void inet_putpeer(struct inet_peer *p);
+extern bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout);
+
+extern void inetpeer_invalidate_tree(int family);
+
+/*
+ * temporary check to make sure we dont access rid, ip_id_count, tcp_ts,
+ * tcp_ts_stamp if no refcount is taken on inet_peer
+ */
+static inline void inet_peer_refcheck(const struct inet_peer *p)
+{
+ WARN_ON_ONCE(atomic_read(&p->refcnt) <= 0);
+}
+
+
+/* can be called with or without local BH being disabled */
+static inline int inet_getid(struct inet_peer *p, int more)
+{
+ int old, new;
+ more++;
+ inet_peer_refcheck(p);
+ do {
+ old = atomic_read(&p->ip_id_count);
+ new = old + more;
+ if (!new)
+ new = 1;
+ } while (atomic_cmpxchg(&p->ip_id_count, old, new) != old);
+ return new;
+}
+
+#endif /* _NET_INETPEER_H */
diff --git a/include/net/ip.h b/include/net/ip.h
new file mode 100644
index 00000000..b53d65f2
--- /dev/null
+++ b/include/net/ip.h
@@ -0,0 +1,475 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the IP module.
+ *
+ * Version: @(#)ip.h 1.0.2 05/07/93
+ *
+ * Authors: Ross Biro
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Alan Cox, <gw4pts@gw4pts.ampr.org>
+ *
+ * Changes:
+ * Mike McLagan : Routing by source
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _IP_H
+#define _IP_H
+
+#include <linux/types.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/skbuff.h>
+
+#include <net/inet_sock.h>
+#include <net/snmp.h>
+#include <net/flow.h>
+
+struct sock;
+
+struct inet_skb_parm {
+ struct ip_options opt; /* Compiled IP options */
+ unsigned char flags;
+
+#define IPSKB_FORWARDED 1
+#define IPSKB_XFRM_TUNNEL_SIZE 2
+#define IPSKB_XFRM_TRANSFORMED 4
+#define IPSKB_FRAG_COMPLETE 8
+#define IPSKB_REROUTED 16
+};
+
+static inline unsigned int ip_hdrlen(const struct sk_buff *skb)
+{
+ return ip_hdr(skb)->ihl * 4;
+}
+
+struct ipcm_cookie {
+ __be32 addr;
+ int oif;
+ struct ip_options_rcu *opt;
+ __u8 tx_flags;
+};
+
+#define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
+
+struct ip_ra_chain {
+ struct ip_ra_chain __rcu *next;
+ struct sock *sk;
+ union {
+ void (*destructor)(struct sock *);
+ struct sock *saved_sk;
+ };
+ struct rcu_head rcu;
+};
+
+extern struct ip_ra_chain __rcu *ip_ra_chain;
+
+/* IP flags. */
+#define IP_CE 0x8000 /* Flag: "Congestion" */
+#define IP_DF 0x4000 /* Flag: "Don't Fragment" */
+#define IP_MF 0x2000 /* Flag: "More Fragments" */
+#define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
+
+#define IP_FRAG_TIME (30 * HZ) /* fragment lifetime */
+
+struct msghdr;
+struct net_device;
+struct packet_type;
+struct rtable;
+struct sockaddr;
+
+extern int igmp_mc_proc_init(void);
+
+/*
+ * Functions provided by ip.c
+ */
+
+extern int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
+ __be32 saddr, __be32 daddr,
+ struct ip_options_rcu *opt);
+extern int ip_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt, struct net_device *orig_dev);
+extern int ip_local_deliver(struct sk_buff *skb);
+extern int ip_mr_input(struct sk_buff *skb);
+extern int ip_output(struct sk_buff *skb);
+extern int ip_mc_output(struct sk_buff *skb);
+extern int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
+extern int ip_do_nat(struct sk_buff *skb);
+extern void ip_send_check(struct iphdr *ip);
+extern int __ip_local_out(struct sk_buff *skb);
+extern int ip_local_out(struct sk_buff *skb);
+extern int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl);
+extern void ip_init(void);
+extern int ip_append_data(struct sock *sk, struct flowi4 *fl4,
+ int getfrag(void *from, char *to, int offset, int len,
+ int odd, struct sk_buff *skb),
+ void *from, int len, int protolen,
+ struct ipcm_cookie *ipc,
+ struct rtable **rt,
+ unsigned int flags);
+extern int ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb);
+extern ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
+ int offset, size_t size, int flags);
+extern struct sk_buff *__ip_make_skb(struct sock *sk,
+ struct flowi4 *fl4,
+ struct sk_buff_head *queue,
+ struct inet_cork *cork);
+extern int ip_send_skb(struct sk_buff *skb);
+extern int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4);
+extern void ip_flush_pending_frames(struct sock *sk);
+extern struct sk_buff *ip_make_skb(struct sock *sk,
+ struct flowi4 *fl4,
+ int getfrag(void *from, char *to, int offset, int len,
+ int odd, struct sk_buff *skb),
+ void *from, int length, int transhdrlen,
+ struct ipcm_cookie *ipc,
+ struct rtable **rtp,
+ unsigned int flags);
+
+static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4)
+{
+ return __ip_make_skb(sk, fl4, &sk->sk_write_queue, &inet_sk(sk)->cork.base);
+}
+
+/* datagram.c */
+extern int ip4_datagram_connect(struct sock *sk,
+ struct sockaddr *uaddr, int addr_len);
+
+/*
+ * Map a multicast IP onto multicast MAC for type Token Ring.
+ * This conforms to RFC1469 Option 2 Multicasting i.e.
+ * using a functional address to transmit / receive
+ * multicast packets.
+ */
+
+static inline void ip_tr_mc_map(__be32 addr, char *buf)
+{
+ buf[0]=0xC0;
+ buf[1]=0x00;
+ buf[2]=0x00;
+ buf[3]=0x04;
+ buf[4]=0x00;
+ buf[5]=0x00;
+}
+
+struct ip_reply_arg {
+ struct kvec iov[1];
+ int flags;
+ __wsum csum;
+ int csumoffset; /* u16 offset of csum in iov[0].iov_base */
+ /* -1 if not needed */
+ int bound_dev_if;
+ u8 tos;
+};
+
+#define IP_REPLY_ARG_NOSRCCHECK 1
+
+static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg)
+{
+ return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0;
+}
+
+void ip_send_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr,
+ const struct ip_reply_arg *arg, unsigned int len);
+
+struct ipv4_config {
+ int log_martians;
+ int no_pmtu_disc;
+};
+
+extern struct ipv4_config ipv4_config;
+#define IP_INC_STATS(net, field) SNMP_INC_STATS64((net)->mib.ip_statistics, field)
+#define IP_INC_STATS_BH(net, field) SNMP_INC_STATS64_BH((net)->mib.ip_statistics, field)
+#define IP_ADD_STATS(net, field, val) SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val)
+#define IP_ADD_STATS_BH(net, field, val) SNMP_ADD_STATS64_BH((net)->mib.ip_statistics, field, val)
+#define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val)
+#define IP_UPD_PO_STATS_BH(net, field, val) SNMP_UPD_PO_STATS64_BH((net)->mib.ip_statistics, field, val)
+#define NET_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.net_statistics, field)
+#define NET_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.net_statistics, field)
+#define NET_INC_STATS_USER(net, field) SNMP_INC_STATS_USER((net)->mib.net_statistics, field)
+#define NET_ADD_STATS_BH(net, field, adnd) SNMP_ADD_STATS_BH((net)->mib.net_statistics, field, adnd)
+#define NET_ADD_STATS_USER(net, field, adnd) SNMP_ADD_STATS_USER((net)->mib.net_statistics, field, adnd)
+
+extern unsigned long snmp_fold_field(void __percpu *mib[], int offt);
+#if BITS_PER_LONG==32
+extern u64 snmp_fold_field64(void __percpu *mib[], int offt, size_t sync_off);
+#else
+static inline u64 snmp_fold_field64(void __percpu *mib[], int offt, size_t syncp_off)
+{
+ return snmp_fold_field(mib, offt);
+}
+#endif
+extern int snmp_mib_init(void __percpu *ptr[2], size_t mibsize, size_t align);
+extern void snmp_mib_free(void __percpu *ptr[2]);
+
+extern struct local_ports {
+ seqlock_t lock;
+ int range[2];
+} sysctl_local_ports;
+extern void inet_get_local_port_range(int *low, int *high);
+
+extern unsigned long *sysctl_local_reserved_ports;
+static inline int inet_is_reserved_local_port(int port)
+{
+ return test_bit(port, sysctl_local_reserved_ports);
+}
+
+extern int sysctl_ip_nonlocal_bind;
+
+extern struct ctl_path net_core_path[];
+extern struct ctl_path net_ipv4_ctl_path[];
+
+/* From inetpeer.c */
+extern int inet_peer_threshold;
+extern int inet_peer_minttl;
+extern int inet_peer_maxttl;
+
+/* From ip_output.c */
+extern int sysctl_ip_dynaddr;
+
+extern void ipfrag_init(void);
+
+extern void ip_static_sysctl_init(void);
+
+static inline bool ip_is_fragment(const struct iphdr *iph)
+{
+ return (iph->frag_off & htons(IP_MF | IP_OFFSET)) != 0;
+}
+
+#ifdef CONFIG_INET
+#include <net/dst.h>
+
+/* The function in 2.2 was invalid, producing wrong result for
+ * check=0xFEFF. It was noticed by Arthur Skawina _year_ ago. --ANK(000625) */
+static inline
+int ip_decrease_ttl(struct iphdr *iph)
+{
+ u32 check = (__force u32)iph->check;
+ check += (__force u32)htons(0x0100);
+ iph->check = (__force __sum16)(check + (check>=0xFFFF));
+ return --iph->ttl;
+}
+
+static inline
+int ip_dont_fragment(struct sock *sk, struct dst_entry *dst)
+{
+ return inet_sk(sk)->pmtudisc == IP_PMTUDISC_DO ||
+ (inet_sk(sk)->pmtudisc == IP_PMTUDISC_WANT &&
+ !(dst_metric_locked(dst, RTAX_MTU)));
+}
+
+extern void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more);
+
+static inline void ip_select_ident(struct iphdr *iph, struct dst_entry *dst, struct sock *sk)
+{
+ if (iph->frag_off & htons(IP_DF)) {
+ /* This is only to work around buggy Windows95/2000
+ * VJ compression implementations. If the ID field
+ * does not change, they drop every other packet in
+ * a TCP stream using header compression.
+ */
+ iph->id = (sk && inet_sk(sk)->inet_daddr) ?
+ htons(inet_sk(sk)->inet_id++) : 0;
+ } else
+ __ip_select_ident(iph, dst, 0);
+}
+
+static inline void ip_select_ident_more(struct iphdr *iph, struct dst_entry *dst, struct sock *sk, int more)
+{
+ if (iph->frag_off & htons(IP_DF)) {
+ if (sk && inet_sk(sk)->inet_daddr) {
+ iph->id = htons(inet_sk(sk)->inet_id);
+ inet_sk(sk)->inet_id += 1 + more;
+ } else
+ iph->id = 0;
+ } else
+ __ip_select_ident(iph, dst, more);
+}
+
+/*
+ * Map a multicast IP onto multicast MAC for type ethernet.
+ */
+
+static inline void ip_eth_mc_map(__be32 naddr, char *buf)
+{
+ __u32 addr=ntohl(naddr);
+ buf[0]=0x01;
+ buf[1]=0x00;
+ buf[2]=0x5e;
+ buf[5]=addr&0xFF;
+ addr>>=8;
+ buf[4]=addr&0xFF;
+ addr>>=8;
+ buf[3]=addr&0x7F;
+}
+
+/*
+ * Map a multicast IP onto multicast MAC for type IP-over-InfiniBand.
+ * Leave P_Key as 0 to be filled in by driver.
+ */
+
+static inline void ip_ib_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf)
+{
+ __u32 addr;
+ unsigned char scope = broadcast[5] & 0xF;
+
+ buf[0] = 0; /* Reserved */
+ buf[1] = 0xff; /* Multicast QPN */
+ buf[2] = 0xff;
+ buf[3] = 0xff;
+ addr = ntohl(naddr);
+ buf[4] = 0xff;
+ buf[5] = 0x10 | scope; /* scope from broadcast address */
+ buf[6] = 0x40; /* IPv4 signature */
+ buf[7] = 0x1b;
+ buf[8] = broadcast[8]; /* P_Key */
+ buf[9] = broadcast[9];
+ buf[10] = 0;
+ buf[11] = 0;
+ buf[12] = 0;
+ buf[13] = 0;
+ buf[14] = 0;
+ buf[15] = 0;
+ buf[19] = addr & 0xff;
+ addr >>= 8;
+ buf[18] = addr & 0xff;
+ addr >>= 8;
+ buf[17] = addr & 0xff;
+ addr >>= 8;
+ buf[16] = addr & 0x0f;
+}
+
+static inline void ip_ipgre_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf)
+{
+ if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0)
+ memcpy(buf, broadcast, 4);
+ else
+ memcpy(buf, &naddr, sizeof(naddr));
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+#include <linux/ipv6.h>
+#endif
+
+static __inline__ void inet_reset_saddr(struct sock *sk)
+{
+ inet_sk(sk)->inet_rcv_saddr = inet_sk(sk)->inet_saddr = 0;
+#if IS_ENABLED(CONFIG_IPV6)
+ if (sk->sk_family == PF_INET6) {
+ struct ipv6_pinfo *np = inet6_sk(sk);
+
+ memset(&np->saddr, 0, sizeof(np->saddr));
+ memset(&np->rcv_saddr, 0, sizeof(np->rcv_saddr));
+ }
+#endif
+}
+
+#endif
+
+static inline int sk_mc_loop(struct sock *sk)
+{
+ if (!sk)
+ return 1;
+ switch (sk->sk_family) {
+ case AF_INET:
+ return inet_sk(sk)->mc_loop;
+#if IS_ENABLED(CONFIG_IPV6)
+ case AF_INET6:
+ return inet6_sk(sk)->mc_loop;
+#endif
+ }
+ WARN_ON(1);
+ return 1;
+}
+
+extern bool ip_call_ra_chain(struct sk_buff *skb);
+
+/*
+ * Functions provided by ip_fragment.c
+ */
+
+enum ip_defrag_users {
+ IP_DEFRAG_LOCAL_DELIVER,
+ IP_DEFRAG_CALL_RA_CHAIN,
+ IP_DEFRAG_CONNTRACK_IN,
+ __IP_DEFRAG_CONNTRACK_IN_END = IP_DEFRAG_CONNTRACK_IN + USHRT_MAX,
+ IP_DEFRAG_CONNTRACK_OUT,
+ __IP_DEFRAG_CONNTRACK_OUT_END = IP_DEFRAG_CONNTRACK_OUT + USHRT_MAX,
+ IP_DEFRAG_CONNTRACK_BRIDGE_IN,
+ __IP_DEFRAG_CONNTRACK_BRIDGE_IN = IP_DEFRAG_CONNTRACK_BRIDGE_IN + USHRT_MAX,
+ IP_DEFRAG_VS_IN,
+ IP_DEFRAG_VS_OUT,
+ IP_DEFRAG_VS_FWD,
+ IP_DEFRAG_AF_PACKET,
+ IP_DEFRAG_MACVLAN,
+};
+
+int ip_defrag(struct sk_buff *skb, u32 user);
+#ifdef CONFIG_INET
+struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user);
+#else
+static inline struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user)
+{
+ return skb;
+}
+#endif
+int ip_frag_mem(struct net *net);
+int ip_frag_nqueues(struct net *net);
+
+/*
+ * Functions provided by ip_forward.c
+ */
+
+extern int ip_forward(struct sk_buff *skb);
+
+/*
+ * Functions provided by ip_options.c
+ */
+
+extern void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
+ __be32 daddr, struct rtable *rt, int is_frag);
+extern int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb);
+extern void ip_options_fragment(struct sk_buff *skb);
+extern int ip_options_compile(struct net *net,
+ struct ip_options *opt, struct sk_buff *skb);
+extern int ip_options_get(struct net *net, struct ip_options_rcu **optp,
+ unsigned char *data, int optlen);
+extern int ip_options_get_from_user(struct net *net, struct ip_options_rcu **optp,
+ unsigned char __user *data, int optlen);
+extern void ip_options_undo(struct ip_options * opt);
+extern void ip_forward_options(struct sk_buff *skb);
+extern int ip_options_rcv_srr(struct sk_buff *skb);
+
+/*
+ * Functions provided by ip_sockglue.c
+ */
+
+extern void ipv4_pktinfo_prepare(struct sk_buff *skb);
+extern void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb);
+extern int ip_cmsg_send(struct net *net,
+ struct msghdr *msg, struct ipcm_cookie *ipc);
+extern int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, unsigned int optlen);
+extern int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen);
+extern int compat_ip_setsockopt(struct sock *sk, int level,
+ int optname, char __user *optval, unsigned int optlen);
+extern int compat_ip_getsockopt(struct sock *sk, int level,
+ int optname, char __user *optval, int __user *optlen);
+extern int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *));
+
+extern int ip_recv_error(struct sock *sk, struct msghdr *msg, int len);
+extern void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
+ __be16 port, u32 info, u8 *payload);
+extern void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
+ u32 info);
+
+#ifdef CONFIG_PROC_FS
+extern int ip_misc_proc_init(void);
+#endif
+
+#endif /* _IP_H */
diff --git a/include/net/ip6_checksum.h b/include/net/ip6_checksum.h
new file mode 100644
index 00000000..bc1b0fda
--- /dev/null
+++ b/include/net/ip6_checksum.h
@@ -0,0 +1,94 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Checksumming functions for IPv6
+ *
+ * Authors: Jorge Cwik, <jorge@laser.satlink.net>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ * Borrows very liberally from tcp.c and ip.c, see those
+ * files for more names.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/*
+ * Fixes:
+ *
+ * Ralf Baechle : generic ipv6 checksum
+ * <ralf@waldorf-gmbh.de>
+ */
+
+#ifndef _CHECKSUM_IPV6_H
+#define _CHECKSUM_IPV6_H
+
+#include <asm/types.h>
+#include <asm/byteorder.h>
+#include <net/ip.h>
+#include <asm/checksum.h>
+#include <linux/in6.h>
+
+#ifndef _HAVE_ARCH_IPV6_CSUM
+
+static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, unsigned short proto,
+ __wsum csum)
+{
+
+ int carry;
+ __u32 ulen;
+ __u32 uproto;
+ __u32 sum = (__force u32)csum;
+
+ sum += (__force u32)saddr->s6_addr32[0];
+ carry = (sum < (__force u32)saddr->s6_addr32[0]);
+ sum += carry;
+
+ sum += (__force u32)saddr->s6_addr32[1];
+ carry = (sum < (__force u32)saddr->s6_addr32[1]);
+ sum += carry;
+
+ sum += (__force u32)saddr->s6_addr32[2];
+ carry = (sum < (__force u32)saddr->s6_addr32[2]);
+ sum += carry;
+
+ sum += (__force u32)saddr->s6_addr32[3];
+ carry = (sum < (__force u32)saddr->s6_addr32[3]);
+ sum += carry;
+
+ sum += (__force u32)daddr->s6_addr32[0];
+ carry = (sum < (__force u32)daddr->s6_addr32[0]);
+ sum += carry;
+
+ sum += (__force u32)daddr->s6_addr32[1];
+ carry = (sum < (__force u32)daddr->s6_addr32[1]);
+ sum += carry;
+
+ sum += (__force u32)daddr->s6_addr32[2];
+ carry = (sum < (__force u32)daddr->s6_addr32[2]);
+ sum += carry;
+
+ sum += (__force u32)daddr->s6_addr32[3];
+ carry = (sum < (__force u32)daddr->s6_addr32[3]);
+ sum += carry;
+
+ ulen = (__force u32)htonl((__u32) len);
+ sum += ulen;
+ carry = (sum < ulen);
+ sum += carry;
+
+ uproto = (__force u32)htonl(proto);
+ sum += uproto;
+ carry = (sum < uproto);
+ sum += carry;
+
+ return csum_fold((__force __wsum)sum);
+}
+
+#endif
+#endif
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
new file mode 100644
index 00000000..0ae759a6
--- /dev/null
+++ b/include/net/ip6_fib.h
@@ -0,0 +1,288 @@
+/*
+ * Linux INET6 implementation
+ *
+ * Authors:
+ * Pedro Roque <roque@di.fc.ul.pt>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _IP6_FIB_H
+#define _IP6_FIB_H
+
+#include <linux/ipv6_route.h>
+#include <linux/rtnetlink.h>
+#include <linux/spinlock.h>
+#include <net/dst.h>
+#include <net/flow.h>
+#include <net/netlink.h>
+#include <net/inetpeer.h>
+
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+#define FIB6_TABLE_HASHSZ 256
+#else
+#define FIB6_TABLE_HASHSZ 1
+#endif
+
+struct rt6_info;
+
+struct fib6_config {
+ u32 fc_table;
+ u32 fc_metric;
+ int fc_dst_len;
+ int fc_src_len;
+ int fc_ifindex;
+ u32 fc_flags;
+ u32 fc_protocol;
+
+ struct in6_addr fc_dst;
+ struct in6_addr fc_src;
+ struct in6_addr fc_prefsrc;
+ struct in6_addr fc_gateway;
+
+ unsigned long fc_expires;
+ struct nlattr *fc_mx;
+ int fc_mx_len;
+
+ struct nl_info fc_nlinfo;
+};
+
+struct fib6_node {
+ struct fib6_node *parent;
+ struct fib6_node *left;
+ struct fib6_node *right;
+#ifdef CONFIG_IPV6_SUBTREES
+ struct fib6_node *subtree;
+#endif
+ struct rt6_info *leaf;
+
+ __u16 fn_bit; /* bit key */
+ __u16 fn_flags;
+ __u32 fn_sernum;
+ struct rt6_info *rr_ptr;
+};
+
+#ifndef CONFIG_IPV6_SUBTREES
+#define FIB6_SUBTREE(fn) NULL
+#else
+#define FIB6_SUBTREE(fn) ((fn)->subtree)
+#endif
+
+/*
+ * routing information
+ *
+ */
+
+struct rt6key {
+ struct in6_addr addr;
+ int plen;
+};
+
+struct fib6_table;
+
+struct rt6_info {
+ struct dst_entry dst;
+
+ /*
+ * Tail elements of dst_entry (__refcnt etc.)
+ * and these elements (rarely used in hot path) are in
+ * the same cache line.
+ */
+ struct fib6_table *rt6i_table;
+ struct fib6_node *rt6i_node;
+
+ struct in6_addr rt6i_gateway;
+
+ atomic_t rt6i_ref;
+
+ /* These are in a separate cache line. */
+ struct rt6key rt6i_dst ____cacheline_aligned_in_smp;
+ u32 rt6i_flags;
+ struct rt6key rt6i_src;
+ struct rt6key rt6i_prefsrc;
+ u32 rt6i_metric;
+ u32 rt6i_peer_genid;
+
+ struct inet6_dev *rt6i_idev;
+ struct inet_peer *rt6i_peer;
+
+#ifdef CONFIG_XFRM
+ u32 rt6i_flow_cache_genid;
+#endif
+ /* more non-fragment space at head required */
+ unsigned short rt6i_nfheader_len;
+
+ u8 rt6i_protocol;
+};
+
+static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst)
+{
+ return ((struct rt6_info *)dst)->rt6i_idev;
+}
+
+static inline void rt6_clean_expires(struct rt6_info *rt)
+{
+ if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from)
+ dst_release(rt->dst.from);
+
+ rt->rt6i_flags &= ~RTF_EXPIRES;
+ rt->dst.from = NULL;
+}
+
+static inline void rt6_set_expires(struct rt6_info *rt, unsigned long expires)
+{
+ if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from)
+ dst_release(rt->dst.from);
+
+ rt->rt6i_flags |= RTF_EXPIRES;
+ rt->dst.expires = expires;
+}
+
+static inline void rt6_update_expires(struct rt6_info *rt, int timeout)
+{
+ if (!(rt->rt6i_flags & RTF_EXPIRES)) {
+ if (rt->dst.from)
+ dst_release(rt->dst.from);
+ /* dst_set_expires relies on expires == 0
+ * if it has not been set previously.
+ */
+ rt->dst.expires = 0;
+ }
+
+ dst_set_expires(&rt->dst, timeout);
+ rt->rt6i_flags |= RTF_EXPIRES;
+}
+
+static inline void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
+{
+ struct dst_entry *new = (struct dst_entry *) from;
+
+ if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) {
+ if (new == rt->dst.from)
+ return;
+ dst_release(rt->dst.from);
+ }
+
+ rt->rt6i_flags &= ~RTF_EXPIRES;
+ rt->dst.from = new;
+ dst_hold(new);
+}
+
+struct fib6_walker_t {
+ struct list_head lh;
+ struct fib6_node *root, *node;
+ struct rt6_info *leaf;
+ unsigned char state;
+ unsigned char prune;
+ unsigned int skip;
+ unsigned int count;
+ int (*func)(struct fib6_walker_t *);
+ void *args;
+};
+
+struct rt6_statistics {
+ __u32 fib_nodes;
+ __u32 fib_route_nodes;
+ __u32 fib_rt_alloc; /* permanent routes */
+ __u32 fib_rt_entries; /* rt entries in table */
+ __u32 fib_rt_cache; /* cache routes */
+ __u32 fib_discarded_routes;
+};
+
+#define RTN_TL_ROOT 0x0001
+#define RTN_ROOT 0x0002 /* tree root node */
+#define RTN_RTINFO 0x0004 /* node with valid routing info */
+
+/*
+ * priority levels (or metrics)
+ *
+ */
+
+
+struct fib6_table {
+ struct hlist_node tb6_hlist;
+ u32 tb6_id;
+ rwlock_t tb6_lock;
+ struct fib6_node tb6_root;
+};
+
+#define RT6_TABLE_UNSPEC RT_TABLE_UNSPEC
+#define RT6_TABLE_MAIN RT_TABLE_MAIN
+#define RT6_TABLE_DFLT RT6_TABLE_MAIN
+#define RT6_TABLE_INFO RT6_TABLE_MAIN
+#define RT6_TABLE_PREFIX RT6_TABLE_MAIN
+
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+#define FIB6_TABLE_MIN 1
+#define FIB6_TABLE_MAX RT_TABLE_MAX
+#define RT6_TABLE_LOCAL RT_TABLE_LOCAL
+#else
+#define FIB6_TABLE_MIN RT_TABLE_MAIN
+#define FIB6_TABLE_MAX FIB6_TABLE_MIN
+#define RT6_TABLE_LOCAL RT6_TABLE_MAIN
+#endif
+
+typedef struct rt6_info *(*pol_lookup_t)(struct net *,
+ struct fib6_table *,
+ struct flowi6 *, int);
+
+/*
+ * exported functions
+ */
+
+extern struct fib6_table *fib6_get_table(struct net *net, u32 id);
+extern struct fib6_table *fib6_new_table(struct net *net, u32 id);
+extern struct dst_entry *fib6_rule_lookup(struct net *net,
+ struct flowi6 *fl6, int flags,
+ pol_lookup_t lookup);
+
+extern struct fib6_node *fib6_lookup(struct fib6_node *root,
+ const struct in6_addr *daddr,
+ const struct in6_addr *saddr);
+
+struct fib6_node *fib6_locate(struct fib6_node *root,
+ const struct in6_addr *daddr, int dst_len,
+ const struct in6_addr *saddr, int src_len);
+
+extern void fib6_clean_all_ro(struct net *net,
+ int (*func)(struct rt6_info *, void *arg),
+ int prune, void *arg);
+
+extern void fib6_clean_all(struct net *net,
+ int (*func)(struct rt6_info *, void *arg),
+ int prune, void *arg);
+
+extern int fib6_add(struct fib6_node *root,
+ struct rt6_info *rt,
+ struct nl_info *info);
+
+extern int fib6_del(struct rt6_info *rt,
+ struct nl_info *info);
+
+extern void inet6_rt_notify(int event, struct rt6_info *rt,
+ struct nl_info *info);
+
+extern void fib6_run_gc(unsigned long expires,
+ struct net *net);
+
+extern void fib6_gc_cleanup(void);
+
+extern int fib6_init(void);
+
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+extern int fib6_rules_init(void);
+extern void fib6_rules_cleanup(void);
+#else
+static inline int fib6_rules_init(void)
+{
+ return 0;
+}
+static inline void fib6_rules_cleanup(void)
+{
+ return ;
+}
+#endif
+#endif
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
new file mode 100644
index 00000000..2ad92ca4
--- /dev/null
+++ b/include/net/ip6_route.h
@@ -0,0 +1,195 @@
+#ifndef _NET_IP6_ROUTE_H
+#define _NET_IP6_ROUTE_H
+
+#define IP6_RT_PRIO_USER 1024
+#define IP6_RT_PRIO_ADDRCONF 256
+
+struct route_info {
+ __u8 type;
+ __u8 length;
+ __u8 prefix_len;
+#if defined(__BIG_ENDIAN_BITFIELD)
+ __u8 reserved_h:3,
+ route_pref:2,
+ reserved_l:3;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 reserved_l:3,
+ route_pref:2,
+ reserved_h:3;
+#endif
+ __be32 lifetime;
+ __u8 prefix[0]; /* 0,8 or 16 */
+};
+
+#include <net/flow.h>
+#include <net/ip6_fib.h>
+#include <net/sock.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+
+#define RT6_LOOKUP_F_IFACE 0x00000001
+#define RT6_LOOKUP_F_REACHABLE 0x00000002
+#define RT6_LOOKUP_F_HAS_SADDR 0x00000004
+#define RT6_LOOKUP_F_SRCPREF_TMP 0x00000008
+#define RT6_LOOKUP_F_SRCPREF_PUBLIC 0x00000010
+#define RT6_LOOKUP_F_SRCPREF_COA 0x00000020
+
+/*
+ * rt6_srcprefs2flags() and rt6_flags2srcprefs() translate
+ * between IPV6_ADDR_PREFERENCES socket option values
+ * IPV6_PREFER_SRC_TMP = 0x1
+ * IPV6_PREFER_SRC_PUBLIC = 0x2
+ * IPV6_PREFER_SRC_COA = 0x4
+ * and above RT6_LOOKUP_F_SRCPREF_xxx flags.
+ */
+static inline int rt6_srcprefs2flags(unsigned int srcprefs)
+{
+ /* No need to bitmask because srcprefs have only 3 bits. */
+ return srcprefs << 3;
+}
+
+static inline unsigned int rt6_flags2srcprefs(int flags)
+{
+ return (flags >> 3) & 7;
+}
+
+extern void rt6_bind_peer(struct rt6_info *rt,
+ int create);
+
+static inline struct inet_peer *rt6_get_peer(struct rt6_info *rt)
+{
+ if (rt->rt6i_peer)
+ return rt->rt6i_peer;
+
+ rt6_bind_peer(rt, 0);
+ return rt->rt6i_peer;
+}
+
+extern void ip6_route_input(struct sk_buff *skb);
+
+extern struct dst_entry * ip6_route_output(struct net *net,
+ const struct sock *sk,
+ struct flowi6 *fl6);
+extern struct dst_entry * ip6_route_lookup(struct net *net,
+ struct flowi6 *fl6, int flags);
+
+extern int ip6_route_init(void);
+extern void ip6_route_cleanup(void);
+
+extern int ipv6_route_ioctl(struct net *net,
+ unsigned int cmd,
+ void __user *arg);
+
+extern int ip6_route_add(struct fib6_config *cfg);
+extern int ip6_ins_rt(struct rt6_info *);
+extern int ip6_del_rt(struct rt6_info *);
+
+extern int ip6_route_get_saddr(struct net *net,
+ struct rt6_info *rt,
+ const struct in6_addr *daddr,
+ unsigned int prefs,
+ struct in6_addr *saddr);
+
+extern struct rt6_info *rt6_lookup(struct net *net,
+ const struct in6_addr *daddr,
+ const struct in6_addr *saddr,
+ int oif, int flags);
+
+extern struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
+ struct neighbour *neigh,
+ struct flowi6 *fl6);
+extern int icmp6_dst_gc(void);
+
+extern void fib6_force_start_gc(struct net *net);
+
+extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
+ const struct in6_addr *addr,
+ bool anycast);
+
+extern int ip6_dst_hoplimit(struct dst_entry *dst);
+
+/*
+ * support functions for ND
+ *
+ */
+extern struct rt6_info * rt6_get_dflt_router(const struct in6_addr *addr,
+ struct net_device *dev);
+extern struct rt6_info * rt6_add_dflt_router(const struct in6_addr *gwaddr,
+ struct net_device *dev,
+ unsigned int pref);
+
+extern void rt6_purge_dflt_routers(struct net *net);
+
+extern int rt6_route_rcv(struct net_device *dev,
+ u8 *opt, int len,
+ const struct in6_addr *gwaddr);
+
+extern void rt6_redirect(const struct in6_addr *dest,
+ const struct in6_addr *src,
+ const struct in6_addr *saddr,
+ struct neighbour *neigh,
+ u8 *lladdr,
+ int on_link);
+
+extern void rt6_pmtu_discovery(const struct in6_addr *daddr,
+ const struct in6_addr *saddr,
+ struct net_device *dev,
+ u32 pmtu);
+
+struct netlink_callback;
+
+struct rt6_rtnl_dump_arg {
+ struct sk_buff *skb;
+ struct netlink_callback *cb;
+ struct net *net;
+};
+
+extern int rt6_dump_route(struct rt6_info *rt, void *p_arg);
+extern void rt6_ifdown(struct net *net, struct net_device *dev);
+extern void rt6_mtu_change(struct net_device *dev, unsigned mtu);
+extern void rt6_remove_prefsrc(struct inet6_ifaddr *ifp);
+
+
+/*
+ * Store a destination cache entry in a socket
+ */
+static inline void __ip6_dst_store(struct sock *sk, struct dst_entry *dst,
+ struct in6_addr *daddr, struct in6_addr *saddr)
+{
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct rt6_info *rt = (struct rt6_info *) dst;
+
+ sk_setup_caps(sk, dst);
+ np->daddr_cache = daddr;
+#ifdef CONFIG_IPV6_SUBTREES
+ np->saddr_cache = saddr;
+#endif
+ np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0;
+}
+
+static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst,
+ struct in6_addr *daddr, struct in6_addr *saddr)
+{
+ spin_lock(&sk->sk_dst_lock);
+ __ip6_dst_store(sk, dst, daddr, saddr);
+ spin_unlock(&sk->sk_dst_lock);
+}
+
+static inline int ipv6_unicast_destination(struct sk_buff *skb)
+{
+ struct rt6_info *rt = (struct rt6_info *) skb_dst(skb);
+
+ return rt->rt6i_flags & RTF_LOCAL;
+}
+
+int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
+
+static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
+{
+ struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL;
+
+ return (np && np->pmtudisc == IPV6_PMTUDISC_PROBE) ?
+ skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb));
+}
+
+#endif
diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h
new file mode 100644
index 00000000..fc73e667
--- /dev/null
+++ b/include/net/ip6_tunnel.h
@@ -0,0 +1,32 @@
+#ifndef _NET_IP6_TUNNEL_H
+#define _NET_IP6_TUNNEL_H
+
+#include <linux/ipv6.h>
+#include <linux/netdevice.h>
+#include <linux/ip6_tunnel.h>
+
+/* capable of sending packets */
+#define IP6_TNL_F_CAP_XMIT 0x10000
+/* capable of receiving packets */
+#define IP6_TNL_F_CAP_RCV 0x20000
+
+/* IPv6 tunnel */
+
+struct ip6_tnl {
+ struct ip6_tnl __rcu *next; /* next tunnel in list */
+ struct net_device *dev; /* virtual device associated with tunnel */
+ struct ip6_tnl_parm parms; /* tunnel configuration parameters */
+ struct flowi fl; /* flowi template for xmit */
+ struct dst_entry *dst_cache; /* cached dst */
+ u32 dst_cookie;
+};
+
+/* Tunnel encapsulation limit destination sub-option */
+
+struct ipv6_tlv_tnl_enc_lim {
+ __u8 type; /* type-code for option */
+ __u8 length; /* option length */
+ __u8 encap_limit; /* tunnel encapsulation limit */
+} __packed;
+
+#endif
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
new file mode 100644
index 00000000..10422ef1
--- /dev/null
+++ b/include/net/ip_fib.h
@@ -0,0 +1,285 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the Forwarding Information Base.
+ *
+ * Authors: A.N.Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _NET_IP_FIB_H
+#define _NET_IP_FIB_H
+
+#include <net/flow.h>
+#include <linux/seq_file.h>
+#include <net/fib_rules.h>
+
+struct fib_config {
+ u8 fc_dst_len;
+ u8 fc_tos;
+ u8 fc_protocol;
+ u8 fc_scope;
+ u8 fc_type;
+ /* 3 bytes unused */
+ u32 fc_table;
+ __be32 fc_dst;
+ __be32 fc_gw;
+ int fc_oif;
+ u32 fc_flags;
+ u32 fc_priority;
+ __be32 fc_prefsrc;
+ struct nlattr *fc_mx;
+ struct rtnexthop *fc_mp;
+ int fc_mx_len;
+ int fc_mp_len;
+ u32 fc_flow;
+ u32 fc_nlflags;
+ struct nl_info fc_nlinfo;
+ };
+
+struct fib_info;
+
+struct fib_nh {
+ struct net_device *nh_dev;
+ struct hlist_node nh_hash;
+ struct fib_info *nh_parent;
+ unsigned nh_flags;
+ unsigned char nh_scope;
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ int nh_weight;
+ int nh_power;
+#endif
+#ifdef CONFIG_IP_ROUTE_CLASSID
+ __u32 nh_tclassid;
+#endif
+ int nh_oif;
+ __be32 nh_gw;
+ __be32 nh_saddr;
+ int nh_saddr_genid;
+};
+
+/*
+ * This structure contains data shared by many of routes.
+ */
+
+struct fib_info {
+ struct hlist_node fib_hash;
+ struct hlist_node fib_lhash;
+ struct net *fib_net;
+ int fib_treeref;
+ atomic_t fib_clntref;
+ unsigned fib_flags;
+ unsigned char fib_dead;
+ unsigned char fib_protocol;
+ unsigned char fib_scope;
+ __be32 fib_prefsrc;
+ u32 fib_priority;
+ u32 *fib_metrics;
+#define fib_mtu fib_metrics[RTAX_MTU-1]
+#define fib_window fib_metrics[RTAX_WINDOW-1]
+#define fib_rtt fib_metrics[RTAX_RTT-1]
+#define fib_advmss fib_metrics[RTAX_ADVMSS-1]
+ int fib_nhs;
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ int fib_power;
+#endif
+ struct rcu_head rcu;
+ struct fib_nh fib_nh[0];
+#define fib_dev fib_nh[0].nh_dev
+};
+
+
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+struct fib_rule;
+#endif
+
+struct fib_table;
+struct fib_result {
+ unsigned char prefixlen;
+ unsigned char nh_sel;
+ unsigned char type;
+ unsigned char scope;
+ struct fib_info *fi;
+ struct fib_table *table;
+ struct list_head *fa_head;
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+ struct fib_rule *r;
+#endif
+};
+
+struct fib_result_nl {
+ __be32 fl_addr; /* To be looked up*/
+ u32 fl_mark;
+ unsigned char fl_tos;
+ unsigned char fl_scope;
+ unsigned char tb_id_in;
+
+ unsigned char tb_id; /* Results */
+ unsigned char prefixlen;
+ unsigned char nh_sel;
+ unsigned char type;
+ unsigned char scope;
+ int err;
+};
+
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+
+#define FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel])
+
+#define FIB_TABLE_HASHSZ 2
+
+#else /* CONFIG_IP_ROUTE_MULTIPATH */
+
+#define FIB_RES_NH(res) ((res).fi->fib_nh[0])
+
+#define FIB_TABLE_HASHSZ 256
+
+#endif /* CONFIG_IP_ROUTE_MULTIPATH */
+
+extern __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
+
+#define FIB_RES_SADDR(net, res) \
+ ((FIB_RES_NH(res).nh_saddr_genid == \
+ atomic_read(&(net)->ipv4.dev_addr_genid)) ? \
+ FIB_RES_NH(res).nh_saddr : \
+ fib_info_update_nh_saddr((net), &FIB_RES_NH(res)))
+#define FIB_RES_GW(res) (FIB_RES_NH(res).nh_gw)
+#define FIB_RES_DEV(res) (FIB_RES_NH(res).nh_dev)
+#define FIB_RES_OIF(res) (FIB_RES_NH(res).nh_oif)
+
+#define FIB_RES_PREFSRC(net, res) ((res).fi->fib_prefsrc ? : \
+ FIB_RES_SADDR(net, res))
+
+struct fib_table {
+ struct hlist_node tb_hlist;
+ u32 tb_id;
+ int tb_default;
+ int tb_num_default;
+ unsigned long tb_data[0];
+};
+
+extern int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
+ struct fib_result *res, int fib_flags);
+extern int fib_table_insert(struct fib_table *, struct fib_config *);
+extern int fib_table_delete(struct fib_table *, struct fib_config *);
+extern int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
+ struct netlink_callback *cb);
+extern int fib_table_flush(struct fib_table *table);
+extern void fib_free_table(struct fib_table *tb);
+
+
+
+#ifndef CONFIG_IP_MULTIPLE_TABLES
+
+#define TABLE_LOCAL_INDEX 0
+#define TABLE_MAIN_INDEX 1
+
+static inline struct fib_table *fib_get_table(struct net *net, u32 id)
+{
+ struct hlist_head *ptr;
+
+ ptr = id == RT_TABLE_LOCAL ?
+ &net->ipv4.fib_table_hash[TABLE_LOCAL_INDEX] :
+ &net->ipv4.fib_table_hash[TABLE_MAIN_INDEX];
+ return hlist_entry(ptr->first, struct fib_table, tb_hlist);
+}
+
+static inline struct fib_table *fib_new_table(struct net *net, u32 id)
+{
+ return fib_get_table(net, id);
+}
+
+static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
+ struct fib_result *res)
+{
+ struct fib_table *table;
+
+ table = fib_get_table(net, RT_TABLE_LOCAL);
+ if (!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF))
+ return 0;
+
+ table = fib_get_table(net, RT_TABLE_MAIN);
+ if (!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF))
+ return 0;
+ return -ENETUNREACH;
+}
+
+#else /* CONFIG_IP_MULTIPLE_TABLES */
+extern int __net_init fib4_rules_init(struct net *net);
+extern void __net_exit fib4_rules_exit(struct net *net);
+
+#ifdef CONFIG_IP_ROUTE_CLASSID
+extern u32 fib_rules_tclass(const struct fib_result *res);
+#endif
+
+extern int fib_lookup(struct net *n, struct flowi4 *flp, struct fib_result *res);
+
+extern struct fib_table *fib_new_table(struct net *net, u32 id);
+extern struct fib_table *fib_get_table(struct net *net, u32 id);
+
+#endif /* CONFIG_IP_MULTIPLE_TABLES */
+
+/* Exported by fib_frontend.c */
+extern const struct nla_policy rtm_ipv4_policy[];
+extern void ip_fib_init(void);
+extern int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
+ u8 tos, int oif, struct net_device *dev,
+ __be32 *spec_dst, u32 *itag);
+extern void fib_select_default(struct fib_result *res);
+
+/* Exported by fib_semantics.c */
+extern int ip_fib_check_default(__be32 gw, struct net_device *dev);
+extern int fib_sync_down_dev(struct net_device *dev, int force);
+extern int fib_sync_down_addr(struct net *net, __be32 local);
+extern void fib_update_nh_saddrs(struct net_device *dev);
+extern int fib_sync_up(struct net_device *dev);
+extern void fib_select_multipath(struct fib_result *res);
+
+/* Exported by fib_trie.c */
+extern void fib_trie_init(void);
+extern struct fib_table *fib_trie_table(u32 id);
+
+static inline void fib_combine_itag(u32 *itag, const struct fib_result *res)
+{
+#ifdef CONFIG_IP_ROUTE_CLASSID
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+ u32 rtag;
+#endif
+ *itag = FIB_RES_NH(*res).nh_tclassid<<16;
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+ rtag = fib_rules_tclass(res);
+ if (*itag == 0)
+ *itag = (rtag<<16);
+ *itag |= (rtag>>16);
+#endif
+#endif
+}
+
+extern void free_fib_info(struct fib_info *fi);
+
+static inline void fib_info_put(struct fib_info *fi)
+{
+ if (atomic_dec_and_test(&fi->fib_clntref))
+ free_fib_info(fi);
+}
+
+#ifdef CONFIG_PROC_FS
+extern int __net_init fib_proc_init(struct net *net);
+extern void __net_exit fib_proc_exit(struct net *net);
+#else
+static inline int fib_proc_init(struct net *net)
+{
+ return 0;
+}
+static inline void fib_proc_exit(struct net *net)
+{
+}
+#endif
+
+#endif /* _NET_FIB_H */
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
new file mode 100644
index 00000000..72522f08
--- /dev/null
+++ b/include/net/ip_vs.h
@@ -0,0 +1,1426 @@
+/*
+ * IP Virtual Server
+ * data structure and functionality definitions
+ */
+
+#ifndef _NET_IP_VS_H
+#define _NET_IP_VS_H
+
+#include <linux/ip_vs.h> /* definitions shared with userland */
+
+#include <asm/types.h> /* for __uXX types */
+
+#include <linux/sysctl.h> /* for ctl_path */
+#include <linux/list.h> /* for struct list_head */
+#include <linux/spinlock.h> /* for struct rwlock_t */
+#include <linux/atomic.h> /* for struct atomic_t */
+#include <linux/compiler.h>
+#include <linux/timer.h>
+#include <linux/bug.h>
+
+#include <net/checksum.h>
+#include <linux/netfilter.h> /* for union nf_inet_addr */
+#include <linux/ip.h>
+#include <linux/ipv6.h> /* for struct ipv6hdr */
+#include <net/ipv6.h>
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#include <net/netfilter/nf_conntrack.h>
+#endif
+#include <net/net_namespace.h> /* Netw namespace */
+
+/*
+ * Generic access of ipvs struct
+ */
+static inline struct netns_ipvs *net_ipvs(struct net* net)
+{
+ return net->ipvs;
+}
+/*
+ * Get net ptr from skb in traffic cases
+ * use skb_sknet when call is from userland (ioctl or netlink)
+ */
+static inline struct net *skb_net(const struct sk_buff *skb)
+{
+#ifdef CONFIG_NET_NS
+#ifdef CONFIG_IP_VS_DEBUG
+ /*
+ * This is used for debug only.
+ * Start with the most likely hit
+ * End with BUG
+ */
+ if (likely(skb->dev && skb->dev->nd_net))
+ return dev_net(skb->dev);
+ if (skb_dst(skb) && skb_dst(skb)->dev)
+ return dev_net(skb_dst(skb)->dev);
+ WARN(skb->sk, "Maybe skb_sknet should be used in %s() at line:%d\n",
+ __func__, __LINE__);
+ if (likely(skb->sk && skb->sk->sk_net))
+ return sock_net(skb->sk);
+ pr_err("There is no net ptr to find in the skb in %s() line:%d\n",
+ __func__, __LINE__);
+ BUG();
+#else
+ return dev_net(skb->dev ? : skb_dst(skb)->dev);
+#endif
+#else
+ return &init_net;
+#endif
+}
+
+static inline struct net *skb_sknet(const struct sk_buff *skb)
+{
+#ifdef CONFIG_NET_NS
+#ifdef CONFIG_IP_VS_DEBUG
+ /* Start with the most likely hit */
+ if (likely(skb->sk && skb->sk->sk_net))
+ return sock_net(skb->sk);
+ WARN(skb->dev, "Maybe skb_net should be used instead in %s() line:%d\n",
+ __func__, __LINE__);
+ if (likely(skb->dev && skb->dev->nd_net))
+ return dev_net(skb->dev);
+ pr_err("There is no net ptr to find in the skb in %s() line:%d\n",
+ __func__, __LINE__);
+ BUG();
+#else
+ return sock_net(skb->sk);
+#endif
+#else
+ return &init_net;
+#endif
+}
+/*
+ * This one needed for single_open_net since net is stored directly in
+ * private not as a struct i.e. seq_file_net can't be used.
+ */
+static inline struct net *seq_file_single_net(struct seq_file *seq)
+{
+#ifdef CONFIG_NET_NS
+ return (struct net *)seq->private;
+#else
+ return &init_net;
+#endif
+}
+
+/* Connections' size value needed by ip_vs_ctl.c */
+extern int ip_vs_conn_tab_size;
+
+
+struct ip_vs_iphdr {
+ int len;
+ __u8 protocol;
+ union nf_inet_addr saddr;
+ union nf_inet_addr daddr;
+};
+
+static inline void
+ip_vs_fill_iphdr(int af, const void *nh, struct ip_vs_iphdr *iphdr)
+{
+#ifdef CONFIG_IP_VS_IPV6
+ if (af == AF_INET6) {
+ const struct ipv6hdr *iph = nh;
+ iphdr->len = sizeof(struct ipv6hdr);
+ iphdr->protocol = iph->nexthdr;
+ iphdr->saddr.in6 = iph->saddr;
+ iphdr->daddr.in6 = iph->daddr;
+ } else
+#endif
+ {
+ const struct iphdr *iph = nh;
+ iphdr->len = iph->ihl * 4;
+ iphdr->protocol = iph->protocol;
+ iphdr->saddr.ip = iph->saddr;
+ iphdr->daddr.ip = iph->daddr;
+ }
+}
+
+static inline void ip_vs_addr_copy(int af, union nf_inet_addr *dst,
+ const union nf_inet_addr *src)
+{
+#ifdef CONFIG_IP_VS_IPV6
+ if (af == AF_INET6)
+ dst->in6 = src->in6;
+ else
+#endif
+ dst->ip = src->ip;
+}
+
+static inline int ip_vs_addr_equal(int af, const union nf_inet_addr *a,
+ const union nf_inet_addr *b)
+{
+#ifdef CONFIG_IP_VS_IPV6
+ if (af == AF_INET6)
+ return ipv6_addr_equal(&a->in6, &b->in6);
+#endif
+ return a->ip == b->ip;
+}
+
+#ifdef CONFIG_IP_VS_DEBUG
+#include <linux/net.h>
+
+extern int ip_vs_get_debug_level(void);
+
+static inline const char *ip_vs_dbg_addr(int af, char *buf, size_t buf_len,
+ const union nf_inet_addr *addr,
+ int *idx)
+{
+ int len;
+#ifdef CONFIG_IP_VS_IPV6
+ if (af == AF_INET6)
+ len = snprintf(&buf[*idx], buf_len - *idx, "[%pI6]",
+ &addr->in6) + 1;
+ else
+#endif
+ len = snprintf(&buf[*idx], buf_len - *idx, "%pI4",
+ &addr->ip) + 1;
+
+ *idx += len;
+ BUG_ON(*idx > buf_len + 1);
+ return &buf[*idx - len];
+}
+
+#define IP_VS_DBG_BUF(level, msg, ...) \
+ do { \
+ char ip_vs_dbg_buf[160]; \
+ int ip_vs_dbg_idx = 0; \
+ if (level <= ip_vs_get_debug_level()) \
+ printk(KERN_DEBUG pr_fmt(msg), ##__VA_ARGS__); \
+ } while (0)
+#define IP_VS_ERR_BUF(msg...) \
+ do { \
+ char ip_vs_dbg_buf[160]; \
+ int ip_vs_dbg_idx = 0; \
+ pr_err(msg); \
+ } while (0)
+
+/* Only use from within IP_VS_DBG_BUF() or IP_VS_ERR_BUF macros */
+#define IP_VS_DBG_ADDR(af, addr) \
+ ip_vs_dbg_addr(af, ip_vs_dbg_buf, \
+ sizeof(ip_vs_dbg_buf), addr, \
+ &ip_vs_dbg_idx)
+
+#define IP_VS_DBG(level, msg, ...) \
+ do { \
+ if (level <= ip_vs_get_debug_level()) \
+ printk(KERN_DEBUG pr_fmt(msg), ##__VA_ARGS__); \
+ } while (0)
+#define IP_VS_DBG_RL(msg, ...) \
+ do { \
+ if (net_ratelimit()) \
+ printk(KERN_DEBUG pr_fmt(msg), ##__VA_ARGS__); \
+ } while (0)
+#define IP_VS_DBG_PKT(level, af, pp, skb, ofs, msg) \
+ do { \
+ if (level <= ip_vs_get_debug_level()) \
+ pp->debug_packet(af, pp, skb, ofs, msg); \
+ } while (0)
+#define IP_VS_DBG_RL_PKT(level, af, pp, skb, ofs, msg) \
+ do { \
+ if (level <= ip_vs_get_debug_level() && \
+ net_ratelimit()) \
+ pp->debug_packet(af, pp, skb, ofs, msg); \
+ } while (0)
+#else /* NO DEBUGGING at ALL */
+#define IP_VS_DBG_BUF(level, msg...) do {} while (0)
+#define IP_VS_ERR_BUF(msg...) do {} while (0)
+#define IP_VS_DBG(level, msg...) do {} while (0)
+#define IP_VS_DBG_RL(msg...) do {} while (0)
+#define IP_VS_DBG_PKT(level, af, pp, skb, ofs, msg) do {} while (0)
+#define IP_VS_DBG_RL_PKT(level, af, pp, skb, ofs, msg) do {} while (0)
+#endif
+
+#define IP_VS_BUG() BUG()
+#define IP_VS_ERR_RL(msg, ...) \
+ do { \
+ if (net_ratelimit()) \
+ pr_err(msg, ##__VA_ARGS__); \
+ } while (0)
+
+#ifdef CONFIG_IP_VS_DEBUG
+#define EnterFunction(level) \
+ do { \
+ if (level <= ip_vs_get_debug_level()) \
+ printk(KERN_DEBUG \
+ pr_fmt("Enter: %s, %s line %i\n"), \
+ __func__, __FILE__, __LINE__); \
+ } while (0)
+#define LeaveFunction(level) \
+ do { \
+ if (level <= ip_vs_get_debug_level()) \
+ printk(KERN_DEBUG \
+ pr_fmt("Leave: %s, %s line %i\n"), \
+ __func__, __FILE__, __LINE__); \
+ } while (0)
+#else
+#define EnterFunction(level) do {} while (0)
+#define LeaveFunction(level) do {} while (0)
+#endif
+
+#define IP_VS_WAIT_WHILE(expr) while (expr) { cpu_relax(); }
+
+
+/*
+ * The port number of FTP service (in network order).
+ */
+#define FTPPORT cpu_to_be16(21)
+#define FTPDATA cpu_to_be16(20)
+
+/*
+ * TCP State Values
+ */
+enum {
+ IP_VS_TCP_S_NONE = 0,
+ IP_VS_TCP_S_ESTABLISHED,
+ IP_VS_TCP_S_SYN_SENT,
+ IP_VS_TCP_S_SYN_RECV,
+ IP_VS_TCP_S_FIN_WAIT,
+ IP_VS_TCP_S_TIME_WAIT,
+ IP_VS_TCP_S_CLOSE,
+ IP_VS_TCP_S_CLOSE_WAIT,
+ IP_VS_TCP_S_LAST_ACK,
+ IP_VS_TCP_S_LISTEN,
+ IP_VS_TCP_S_SYNACK,
+ IP_VS_TCP_S_LAST
+};
+
+/*
+ * UDP State Values
+ */
+enum {
+ IP_VS_UDP_S_NORMAL,
+ IP_VS_UDP_S_LAST,
+};
+
+/*
+ * ICMP State Values
+ */
+enum {
+ IP_VS_ICMP_S_NORMAL,
+ IP_VS_ICMP_S_LAST,
+};
+
+/*
+ * SCTP State Values
+ */
+enum ip_vs_sctp_states {
+ IP_VS_SCTP_S_NONE,
+ IP_VS_SCTP_S_INIT_CLI,
+ IP_VS_SCTP_S_INIT_SER,
+ IP_VS_SCTP_S_INIT_ACK_CLI,
+ IP_VS_SCTP_S_INIT_ACK_SER,
+ IP_VS_SCTP_S_ECHO_CLI,
+ IP_VS_SCTP_S_ECHO_SER,
+ IP_VS_SCTP_S_ESTABLISHED,
+ IP_VS_SCTP_S_SHUT_CLI,
+ IP_VS_SCTP_S_SHUT_SER,
+ IP_VS_SCTP_S_SHUT_ACK_CLI,
+ IP_VS_SCTP_S_SHUT_ACK_SER,
+ IP_VS_SCTP_S_CLOSED,
+ IP_VS_SCTP_S_LAST
+};
+
+/*
+ * Delta sequence info structure
+ * Each ip_vs_conn has 2 (output AND input seq. changes).
+ * Only used in the VS/NAT.
+ */
+struct ip_vs_seq {
+ __u32 init_seq; /* Add delta from this seq */
+ __u32 delta; /* Delta in sequence numbers */
+ __u32 previous_delta; /* Delta in sequence numbers
+ before last resized pkt */
+};
+
+/*
+ * counters per cpu
+ */
+struct ip_vs_counters {
+ __u32 conns; /* connections scheduled */
+ __u32 inpkts; /* incoming packets */
+ __u32 outpkts; /* outgoing packets */
+ __u64 inbytes; /* incoming bytes */
+ __u64 outbytes; /* outgoing bytes */
+};
+/*
+ * Stats per cpu
+ */
+struct ip_vs_cpu_stats {
+ struct ip_vs_counters ustats;
+ struct u64_stats_sync syncp;
+};
+
+/*
+ * IPVS statistics objects
+ */
+struct ip_vs_estimator {
+ struct list_head list;
+
+ u64 last_inbytes;
+ u64 last_outbytes;
+ u32 last_conns;
+ u32 last_inpkts;
+ u32 last_outpkts;
+
+ u32 cps;
+ u32 inpps;
+ u32 outpps;
+ u32 inbps;
+ u32 outbps;
+};
+
+struct ip_vs_stats {
+ struct ip_vs_stats_user ustats; /* statistics */
+ struct ip_vs_estimator est; /* estimator */
+ struct ip_vs_cpu_stats *cpustats; /* per cpu counters */
+ spinlock_t lock; /* spin lock */
+ struct ip_vs_stats_user ustats0; /* reset values */
+};
+
+struct dst_entry;
+struct iphdr;
+struct ip_vs_conn;
+struct ip_vs_app;
+struct sk_buff;
+struct ip_vs_proto_data;
+
+struct ip_vs_protocol {
+ struct ip_vs_protocol *next;
+ char *name;
+ u16 protocol;
+ u16 num_states;
+ int dont_defrag;
+
+ void (*init)(struct ip_vs_protocol *pp);
+
+ void (*exit)(struct ip_vs_protocol *pp);
+
+ int (*init_netns)(struct net *net, struct ip_vs_proto_data *pd);
+
+ void (*exit_netns)(struct net *net, struct ip_vs_proto_data *pd);
+
+ int (*conn_schedule)(int af, struct sk_buff *skb,
+ struct ip_vs_proto_data *pd,
+ int *verdict, struct ip_vs_conn **cpp);
+
+ struct ip_vs_conn *
+ (*conn_in_get)(int af,
+ const struct sk_buff *skb,
+ const struct ip_vs_iphdr *iph,
+ unsigned int proto_off,
+ int inverse);
+
+ struct ip_vs_conn *
+ (*conn_out_get)(int af,
+ const struct sk_buff *skb,
+ const struct ip_vs_iphdr *iph,
+ unsigned int proto_off,
+ int inverse);
+
+ int (*snat_handler)(struct sk_buff *skb,
+ struct ip_vs_protocol *pp, struct ip_vs_conn *cp);
+
+ int (*dnat_handler)(struct sk_buff *skb,
+ struct ip_vs_protocol *pp, struct ip_vs_conn *cp);
+
+ int (*csum_check)(int af, struct sk_buff *skb,
+ struct ip_vs_protocol *pp);
+
+ const char *(*state_name)(int state);
+
+ void (*state_transition)(struct ip_vs_conn *cp, int direction,
+ const struct sk_buff *skb,
+ struct ip_vs_proto_data *pd);
+
+ int (*register_app)(struct net *net, struct ip_vs_app *inc);
+
+ void (*unregister_app)(struct net *net, struct ip_vs_app *inc);
+
+ int (*app_conn_bind)(struct ip_vs_conn *cp);
+
+ void (*debug_packet)(int af, struct ip_vs_protocol *pp,
+ const struct sk_buff *skb,
+ int offset,
+ const char *msg);
+
+ void (*timeout_change)(struct ip_vs_proto_data *pd, int flags);
+};
+
+/*
+ * protocol data per netns
+ */
+struct ip_vs_proto_data {
+ struct ip_vs_proto_data *next;
+ struct ip_vs_protocol *pp;
+ int *timeout_table; /* protocol timeout table */
+ atomic_t appcnt; /* counter of proto app incs. */
+ struct tcp_states_t *tcp_state_table;
+};
+
+extern struct ip_vs_protocol *ip_vs_proto_get(unsigned short proto);
+extern struct ip_vs_proto_data *ip_vs_proto_data_get(struct net *net,
+ unsigned short proto);
+
+struct ip_vs_conn_param {
+ struct net *net;
+ const union nf_inet_addr *caddr;
+ const union nf_inet_addr *vaddr;
+ __be16 cport;
+ __be16 vport;
+ __u16 protocol;
+ u16 af;
+
+ const struct ip_vs_pe *pe;
+ char *pe_data;
+ __u8 pe_data_len;
+};
+
+/*
+ * IP_VS structure allocated for each dynamically scheduled connection
+ */
+struct ip_vs_conn {
+ struct hlist_node c_list; /* hashed list heads */
+#ifdef CONFIG_NET_NS
+ struct net *net; /* Name space */
+#endif
+ /* Protocol, addresses and port numbers */
+ u16 af; /* address family */
+ __be16 cport;
+ __be16 vport;
+ __be16 dport;
+ __u32 fwmark; /* Fire wall mark from skb */
+ union nf_inet_addr caddr; /* client address */
+ union nf_inet_addr vaddr; /* virtual address */
+ union nf_inet_addr daddr; /* destination address */
+ volatile __u32 flags; /* status flags */
+ __u16 protocol; /* Which protocol (TCP/UDP) */
+
+ /* counter and timer */
+ atomic_t refcnt; /* reference count */
+ struct timer_list timer; /* Expiration timer */
+ volatile unsigned long timeout; /* timeout */
+
+ /* Flags and state transition */
+ spinlock_t lock; /* lock for state transition */
+ volatile __u16 state; /* state info */
+ volatile __u16 old_state; /* old state, to be used for
+ * state transition triggerd
+ * synchronization
+ */
+
+ /* Control members */
+ struct ip_vs_conn *control; /* Master control connection */
+ atomic_t n_control; /* Number of controlled ones */
+ struct ip_vs_dest *dest; /* real server */
+ atomic_t in_pkts; /* incoming packet counter */
+
+ /* packet transmitter for different forwarding methods. If it
+ mangles the packet, it must return NF_DROP or better NF_STOLEN,
+ otherwise this must be changed to a sk_buff **.
+ NF_ACCEPT can be returned when destination is local.
+ */
+ int (*packet_xmit)(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp);
+
+ /* Note: we can group the following members into a structure,
+ in order to save more space, and the following members are
+ only used in VS/NAT anyway */
+ struct ip_vs_app *app; /* bound ip_vs_app object */
+ void *app_data; /* Application private data */
+ struct ip_vs_seq in_seq; /* incoming seq. struct */
+ struct ip_vs_seq out_seq; /* outgoing seq. struct */
+
+ const struct ip_vs_pe *pe;
+ char *pe_data;
+ __u8 pe_data_len;
+};
+
+/*
+ * To save some memory in conn table when name space is disabled.
+ */
+static inline struct net *ip_vs_conn_net(const struct ip_vs_conn *cp)
+{
+#ifdef CONFIG_NET_NS
+ return cp->net;
+#else
+ return &init_net;
+#endif
+}
+static inline void ip_vs_conn_net_set(struct ip_vs_conn *cp, struct net *net)
+{
+#ifdef CONFIG_NET_NS
+ cp->net = net;
+#endif
+}
+
+static inline int ip_vs_conn_net_eq(const struct ip_vs_conn *cp,
+ struct net *net)
+{
+#ifdef CONFIG_NET_NS
+ return cp->net == net;
+#else
+ return 1;
+#endif
+}
+
+/*
+ * Extended internal versions of struct ip_vs_service_user and
+ * ip_vs_dest_user for IPv6 support.
+ *
+ * We need these to conveniently pass around service and destination
+ * options, but unfortunately, we also need to keep the old definitions to
+ * maintain userspace backwards compatibility for the setsockopt interface.
+ */
+struct ip_vs_service_user_kern {
+ /* virtual service addresses */
+ u16 af;
+ u16 protocol;
+ union nf_inet_addr addr; /* virtual ip address */
+ u16 port;
+ u32 fwmark; /* firwall mark of service */
+
+ /* virtual service options */
+ char *sched_name;
+ char *pe_name;
+ unsigned flags; /* virtual service flags */
+ unsigned timeout; /* persistent timeout in sec */
+ u32 netmask; /* persistent netmask */
+};
+
+
+struct ip_vs_dest_user_kern {
+ /* destination server address */
+ union nf_inet_addr addr;
+ u16 port;
+
+ /* real server options */
+ unsigned conn_flags; /* connection flags */
+ int weight; /* destination weight */
+
+ /* thresholds for active connections */
+ u32 u_threshold; /* upper threshold */
+ u32 l_threshold; /* lower threshold */
+};
+
+
+/*
+ * The information about the virtual service offered to the net
+ * and the forwarding entries
+ */
+struct ip_vs_service {
+ struct list_head s_list; /* for normal service table */
+ struct list_head f_list; /* for fwmark-based service table */
+ atomic_t refcnt; /* reference counter */
+ atomic_t usecnt; /* use counter */
+
+ u16 af; /* address family */
+ __u16 protocol; /* which protocol (TCP/UDP) */
+ union nf_inet_addr addr; /* IP address for virtual service */
+ __be16 port; /* port number for the service */
+ __u32 fwmark; /* firewall mark of the service */
+ unsigned flags; /* service status flags */
+ unsigned timeout; /* persistent timeout in ticks */
+ __be32 netmask; /* grouping granularity */
+ struct net *net;
+
+ struct list_head destinations; /* real server d-linked list */
+ __u32 num_dests; /* number of servers */
+ struct ip_vs_stats stats; /* statistics for the service */
+ struct ip_vs_app *inc; /* bind conns to this app inc */
+
+ /* for scheduling */
+ struct ip_vs_scheduler *scheduler; /* bound scheduler object */
+ rwlock_t sched_lock; /* lock sched_data */
+ void *sched_data; /* scheduler application data */
+
+ /* alternate persistence engine */
+ struct ip_vs_pe *pe;
+};
+
+
+/*
+ * The real server destination forwarding entry
+ * with ip address, port number, and so on.
+ */
+struct ip_vs_dest {
+ struct list_head n_list; /* for the dests in the service */
+ struct list_head d_list; /* for table with all the dests */
+
+ u16 af; /* address family */
+ __be16 port; /* port number of the server */
+ union nf_inet_addr addr; /* IP address of the server */
+ volatile unsigned flags; /* dest status flags */
+ atomic_t conn_flags; /* flags to copy to conn */
+ atomic_t weight; /* server weight */
+
+ atomic_t refcnt; /* reference counter */
+ struct ip_vs_stats stats; /* statistics */
+
+ /* connection counters and thresholds */
+ atomic_t activeconns; /* active connections */
+ atomic_t inactconns; /* inactive connections */
+ atomic_t persistconns; /* persistent connections */
+ __u32 u_threshold; /* upper threshold */
+ __u32 l_threshold; /* lower threshold */
+
+ /* for destination cache */
+ spinlock_t dst_lock; /* lock of dst_cache */
+ struct dst_entry *dst_cache; /* destination cache entry */
+ u32 dst_rtos; /* RT_TOS(tos) for dst */
+ u32 dst_cookie;
+ union nf_inet_addr dst_saddr;
+
+ /* for virtual service */
+ struct ip_vs_service *svc; /* service it belongs to */
+ __u16 protocol; /* which protocol (TCP/UDP) */
+ __be16 vport; /* virtual port number */
+ union nf_inet_addr vaddr; /* virtual IP address */
+ __u32 vfwmark; /* firewall mark of service */
+};
+
+
+/*
+ * The scheduler object
+ */
+struct ip_vs_scheduler {
+ struct list_head n_list; /* d-linked list head */
+ char *name; /* scheduler name */
+ atomic_t refcnt; /* reference counter */
+ struct module *module; /* THIS_MODULE/NULL */
+
+ /* scheduler initializing service */
+ int (*init_service)(struct ip_vs_service *svc);
+ /* scheduling service finish */
+ int (*done_service)(struct ip_vs_service *svc);
+ /* scheduler updating service */
+ int (*update_service)(struct ip_vs_service *svc);
+
+ /* selecting a server from the given service */
+ struct ip_vs_dest* (*schedule)(struct ip_vs_service *svc,
+ const struct sk_buff *skb);
+};
+
+/* The persistence engine object */
+struct ip_vs_pe {
+ struct list_head n_list; /* d-linked list head */
+ char *name; /* scheduler name */
+ atomic_t refcnt; /* reference counter */
+ struct module *module; /* THIS_MODULE/NULL */
+
+ /* get the connection template, if any */
+ int (*fill_param)(struct ip_vs_conn_param *p, struct sk_buff *skb);
+ bool (*ct_match)(const struct ip_vs_conn_param *p,
+ struct ip_vs_conn *ct);
+ u32 (*hashkey_raw)(const struct ip_vs_conn_param *p, u32 initval,
+ bool inverse);
+ int (*show_pe_data)(const struct ip_vs_conn *cp, char *buf);
+};
+
+/*
+ * The application module object (a.k.a. app incarnation)
+ */
+struct ip_vs_app {
+ struct list_head a_list; /* member in app list */
+ int type; /* IP_VS_APP_TYPE_xxx */
+ char *name; /* application module name */
+ __u16 protocol;
+ struct module *module; /* THIS_MODULE/NULL */
+ struct list_head incs_list; /* list of incarnations */
+
+ /* members for application incarnations */
+ struct list_head p_list; /* member in proto app list */
+ struct ip_vs_app *app; /* its real application */
+ __be16 port; /* port number in net order */
+ atomic_t usecnt; /* usage counter */
+
+ /*
+ * output hook: Process packet in inout direction, diff set for TCP.
+ * Return: 0=Error, 1=Payload Not Mangled/Mangled but checksum is ok,
+ * 2=Mangled but checksum was not updated
+ */
+ int (*pkt_out)(struct ip_vs_app *, struct ip_vs_conn *,
+ struct sk_buff *, int *diff);
+
+ /*
+ * input hook: Process packet in outin direction, diff set for TCP.
+ * Return: 0=Error, 1=Payload Not Mangled/Mangled but checksum is ok,
+ * 2=Mangled but checksum was not updated
+ */
+ int (*pkt_in)(struct ip_vs_app *, struct ip_vs_conn *,
+ struct sk_buff *, int *diff);
+
+ /* ip_vs_app initializer */
+ int (*init_conn)(struct ip_vs_app *, struct ip_vs_conn *);
+
+ /* ip_vs_app finish */
+ int (*done_conn)(struct ip_vs_app *, struct ip_vs_conn *);
+
+
+ /* not used now */
+ int (*bind_conn)(struct ip_vs_app *, struct ip_vs_conn *,
+ struct ip_vs_protocol *);
+
+ void (*unbind_conn)(struct ip_vs_app *, struct ip_vs_conn *);
+
+ int * timeout_table;
+ int * timeouts;
+ int timeouts_size;
+
+ int (*conn_schedule)(struct sk_buff *skb, struct ip_vs_app *app,
+ int *verdict, struct ip_vs_conn **cpp);
+
+ struct ip_vs_conn *
+ (*conn_in_get)(const struct sk_buff *skb, struct ip_vs_app *app,
+ const struct iphdr *iph, unsigned int proto_off,
+ int inverse);
+
+ struct ip_vs_conn *
+ (*conn_out_get)(const struct sk_buff *skb, struct ip_vs_app *app,
+ const struct iphdr *iph, unsigned int proto_off,
+ int inverse);
+
+ int (*state_transition)(struct ip_vs_conn *cp, int direction,
+ const struct sk_buff *skb,
+ struct ip_vs_app *app);
+
+ void (*timeout_change)(struct ip_vs_app *app, int flags);
+};
+
+/* IPVS in network namespace */
+struct netns_ipvs {
+ int gen; /* Generation */
+ int enable; /* enable like nf_hooks do */
+ /*
+ * Hash table: for real service lookups
+ */
+ #define IP_VS_RTAB_BITS 4
+ #define IP_VS_RTAB_SIZE (1 << IP_VS_RTAB_BITS)
+ #define IP_VS_RTAB_MASK (IP_VS_RTAB_SIZE - 1)
+
+ struct list_head rs_table[IP_VS_RTAB_SIZE];
+ /* ip_vs_app */
+ struct list_head app_list;
+ /* ip_vs_ftp */
+ struct ip_vs_app *ftp_app;
+ /* ip_vs_proto */
+ #define IP_VS_PROTO_TAB_SIZE 32 /* must be power of 2 */
+ struct ip_vs_proto_data *proto_data_table[IP_VS_PROTO_TAB_SIZE];
+ /* ip_vs_proto_tcp */
+#ifdef CONFIG_IP_VS_PROTO_TCP
+ #define TCP_APP_TAB_BITS 4
+ #define TCP_APP_TAB_SIZE (1 << TCP_APP_TAB_BITS)
+ #define TCP_APP_TAB_MASK (TCP_APP_TAB_SIZE - 1)
+ struct list_head tcp_apps[TCP_APP_TAB_SIZE];
+ spinlock_t tcp_app_lock;
+#endif
+ /* ip_vs_proto_udp */
+#ifdef CONFIG_IP_VS_PROTO_UDP
+ #define UDP_APP_TAB_BITS 4
+ #define UDP_APP_TAB_SIZE (1 << UDP_APP_TAB_BITS)
+ #define UDP_APP_TAB_MASK (UDP_APP_TAB_SIZE - 1)
+ struct list_head udp_apps[UDP_APP_TAB_SIZE];
+ spinlock_t udp_app_lock;
+#endif
+ /* ip_vs_proto_sctp */
+#ifdef CONFIG_IP_VS_PROTO_SCTP
+ #define SCTP_APP_TAB_BITS 4
+ #define SCTP_APP_TAB_SIZE (1 << SCTP_APP_TAB_BITS)
+ #define SCTP_APP_TAB_MASK (SCTP_APP_TAB_SIZE - 1)
+ /* Hash table for SCTP application incarnations */
+ struct list_head sctp_apps[SCTP_APP_TAB_SIZE];
+ spinlock_t sctp_app_lock;
+#endif
+ /* ip_vs_conn */
+ atomic_t conn_count; /* connection counter */
+
+ /* ip_vs_ctl */
+ struct ip_vs_stats tot_stats; /* Statistics & est. */
+
+ int num_services; /* no of virtual services */
+
+ rwlock_t rs_lock; /* real services table */
+ /* Trash for destinations */
+ struct list_head dest_trash;
+ /* Service counters */
+ atomic_t ftpsvc_counter;
+ atomic_t nullsvc_counter;
+
+#ifdef CONFIG_SYSCTL
+ /* 1/rate drop and drop-entry variables */
+ struct delayed_work defense_work; /* Work handler */
+ int drop_rate;
+ int drop_counter;
+ atomic_t dropentry;
+ /* locks in ctl.c */
+ spinlock_t dropentry_lock; /* drop entry handling */
+ spinlock_t droppacket_lock; /* drop packet handling */
+ spinlock_t securetcp_lock; /* state and timeout tables */
+
+ /* sys-ctl struct */
+ struct ctl_table_header *sysctl_hdr;
+ struct ctl_table *sysctl_tbl;
+#endif
+
+ /* sysctl variables */
+ int sysctl_amemthresh;
+ int sysctl_am_droprate;
+ int sysctl_drop_entry;
+ int sysctl_drop_packet;
+ int sysctl_secure_tcp;
+#ifdef CONFIG_IP_VS_NFCT
+ int sysctl_conntrack;
+#endif
+ int sysctl_snat_reroute;
+ int sysctl_sync_ver;
+ int sysctl_cache_bypass;
+ int sysctl_expire_nodest_conn;
+ int sysctl_expire_quiescent_template;
+ int sysctl_sync_threshold[2];
+ int sysctl_nat_icmp_send;
+
+ /* ip_vs_lblc */
+ int sysctl_lblc_expiration;
+ struct ctl_table_header *lblc_ctl_header;
+ struct ctl_table *lblc_ctl_table;
+ /* ip_vs_lblcr */
+ int sysctl_lblcr_expiration;
+ struct ctl_table_header *lblcr_ctl_header;
+ struct ctl_table *lblcr_ctl_table;
+ /* ip_vs_est */
+ struct list_head est_list; /* estimator list */
+ spinlock_t est_lock;
+ struct timer_list est_timer; /* Estimation timer */
+ /* ip_vs_sync */
+ struct list_head sync_queue;
+ spinlock_t sync_lock;
+ struct ip_vs_sync_buff *sync_buff;
+ spinlock_t sync_buff_lock;
+ struct sockaddr_in sync_mcast_addr;
+ struct task_struct *master_thread;
+ struct task_struct *backup_thread;
+ int send_mesg_maxlen;
+ int recv_mesg_maxlen;
+ volatile int sync_state;
+ volatile int master_syncid;
+ volatile int backup_syncid;
+ struct mutex sync_mutex;
+ /* multicast interface name */
+ char master_mcast_ifn[IP_VS_IFNAME_MAXLEN];
+ char backup_mcast_ifn[IP_VS_IFNAME_MAXLEN];
+ /* net name space ptr */
+ struct net *net; /* Needed by timer routines */
+};
+
+#define DEFAULT_SYNC_THRESHOLD 3
+#define DEFAULT_SYNC_PERIOD 50
+#define DEFAULT_SYNC_VER 1
+
+#ifdef CONFIG_SYSCTL
+
+static inline int sysctl_sync_threshold(struct netns_ipvs *ipvs)
+{
+ return ipvs->sysctl_sync_threshold[0];
+}
+
+static inline int sysctl_sync_period(struct netns_ipvs *ipvs)
+{
+ return ipvs->sysctl_sync_threshold[1];
+}
+
+static inline int sysctl_sync_ver(struct netns_ipvs *ipvs)
+{
+ return ipvs->sysctl_sync_ver;
+}
+
+#else
+
+static inline int sysctl_sync_threshold(struct netns_ipvs *ipvs)
+{
+ return DEFAULT_SYNC_THRESHOLD;
+}
+
+static inline int sysctl_sync_period(struct netns_ipvs *ipvs)
+{
+ return DEFAULT_SYNC_PERIOD;
+}
+
+static inline int sysctl_sync_ver(struct netns_ipvs *ipvs)
+{
+ return DEFAULT_SYNC_VER;
+}
+
+#endif
+
+/*
+ * IPVS core functions
+ * (from ip_vs_core.c)
+ */
+extern const char *ip_vs_proto_name(unsigned proto);
+extern void ip_vs_init_hash_table(struct list_head *table, int rows);
+#define IP_VS_INIT_HASH_TABLE(t) ip_vs_init_hash_table((t), ARRAY_SIZE((t)))
+
+#define IP_VS_APP_TYPE_FTP 1
+
+/*
+ * ip_vs_conn handling functions
+ * (from ip_vs_conn.c)
+ */
+
+enum {
+ IP_VS_DIR_INPUT = 0,
+ IP_VS_DIR_OUTPUT,
+ IP_VS_DIR_INPUT_ONLY,
+ IP_VS_DIR_LAST,
+};
+
+static inline void ip_vs_conn_fill_param(struct net *net, int af, int protocol,
+ const union nf_inet_addr *caddr,
+ __be16 cport,
+ const union nf_inet_addr *vaddr,
+ __be16 vport,
+ struct ip_vs_conn_param *p)
+{
+ p->net = net;
+ p->af = af;
+ p->protocol = protocol;
+ p->caddr = caddr;
+ p->cport = cport;
+ p->vaddr = vaddr;
+ p->vport = vport;
+ p->pe = NULL;
+ p->pe_data = NULL;
+}
+
+struct ip_vs_conn *ip_vs_conn_in_get(const struct ip_vs_conn_param *p);
+struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p);
+
+struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
+ const struct ip_vs_iphdr *iph,
+ unsigned int proto_off,
+ int inverse);
+
+struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p);
+
+struct ip_vs_conn * ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,
+ const struct ip_vs_iphdr *iph,
+ unsigned int proto_off,
+ int inverse);
+
+/* put back the conn without restarting its timer */
+static inline void __ip_vs_conn_put(struct ip_vs_conn *cp)
+{
+ atomic_dec(&cp->refcnt);
+}
+extern void ip_vs_conn_put(struct ip_vs_conn *cp);
+extern void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport);
+
+struct ip_vs_conn *ip_vs_conn_new(const struct ip_vs_conn_param *p,
+ const union nf_inet_addr *daddr,
+ __be16 dport, unsigned flags,
+ struct ip_vs_dest *dest, __u32 fwmark);
+extern void ip_vs_conn_expire_now(struct ip_vs_conn *cp);
+
+extern const char * ip_vs_state_name(__u16 proto, int state);
+
+extern void ip_vs_tcp_conn_listen(struct net *net, struct ip_vs_conn *cp);
+extern int ip_vs_check_template(struct ip_vs_conn *ct);
+extern void ip_vs_random_dropentry(struct net *net);
+extern int ip_vs_conn_init(void);
+extern void ip_vs_conn_cleanup(void);
+
+static inline void ip_vs_control_del(struct ip_vs_conn *cp)
+{
+ struct ip_vs_conn *ctl_cp = cp->control;
+ if (!ctl_cp) {
+ IP_VS_ERR_BUF("request control DEL for uncontrolled: "
+ "%s:%d to %s:%d\n",
+ IP_VS_DBG_ADDR(cp->af, &cp->caddr),
+ ntohs(cp->cport),
+ IP_VS_DBG_ADDR(cp->af, &cp->vaddr),
+ ntohs(cp->vport));
+
+ return;
+ }
+
+ IP_VS_DBG_BUF(7, "DELeting control for: "
+ "cp.dst=%s:%d ctl_cp.dst=%s:%d\n",
+ IP_VS_DBG_ADDR(cp->af, &cp->caddr),
+ ntohs(cp->cport),
+ IP_VS_DBG_ADDR(cp->af, &ctl_cp->caddr),
+ ntohs(ctl_cp->cport));
+
+ cp->control = NULL;
+ if (atomic_read(&ctl_cp->n_control) == 0) {
+ IP_VS_ERR_BUF("BUG control DEL with n=0 : "
+ "%s:%d to %s:%d\n",
+ IP_VS_DBG_ADDR(cp->af, &cp->caddr),
+ ntohs(cp->cport),
+ IP_VS_DBG_ADDR(cp->af, &cp->vaddr),
+ ntohs(cp->vport));
+
+ return;
+ }
+ atomic_dec(&ctl_cp->n_control);
+}
+
+static inline void
+ip_vs_control_add(struct ip_vs_conn *cp, struct ip_vs_conn *ctl_cp)
+{
+ if (cp->control) {
+ IP_VS_ERR_BUF("request control ADD for already controlled: "
+ "%s:%d to %s:%d\n",
+ IP_VS_DBG_ADDR(cp->af, &cp->caddr),
+ ntohs(cp->cport),
+ IP_VS_DBG_ADDR(cp->af, &cp->vaddr),
+ ntohs(cp->vport));
+
+ ip_vs_control_del(cp);
+ }
+
+ IP_VS_DBG_BUF(7, "ADDing control for: "
+ "cp.dst=%s:%d ctl_cp.dst=%s:%d\n",
+ IP_VS_DBG_ADDR(cp->af, &cp->caddr),
+ ntohs(cp->cport),
+ IP_VS_DBG_ADDR(cp->af, &ctl_cp->caddr),
+ ntohs(ctl_cp->cport));
+
+ cp->control = ctl_cp;
+ atomic_inc(&ctl_cp->n_control);
+}
+
+/*
+ * IPVS netns init & cleanup functions
+ */
+extern int ip_vs_estimator_net_init(struct net *net);
+extern int ip_vs_control_net_init(struct net *net);
+extern int ip_vs_protocol_net_init(struct net *net);
+extern int ip_vs_app_net_init(struct net *net);
+extern int ip_vs_conn_net_init(struct net *net);
+extern int ip_vs_sync_net_init(struct net *net);
+extern void ip_vs_conn_net_cleanup(struct net *net);
+extern void ip_vs_app_net_cleanup(struct net *net);
+extern void ip_vs_protocol_net_cleanup(struct net *net);
+extern void ip_vs_control_net_cleanup(struct net *net);
+extern void ip_vs_estimator_net_cleanup(struct net *net);
+extern void ip_vs_sync_net_cleanup(struct net *net);
+extern void ip_vs_service_net_cleanup(struct net *net);
+
+/*
+ * IPVS application functions
+ * (from ip_vs_app.c)
+ */
+#define IP_VS_APP_MAX_PORTS 8
+extern int register_ip_vs_app(struct net *net, struct ip_vs_app *app);
+extern void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app);
+extern int ip_vs_bind_app(struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
+extern void ip_vs_unbind_app(struct ip_vs_conn *cp);
+extern int register_ip_vs_app_inc(struct net *net, struct ip_vs_app *app,
+ __u16 proto, __u16 port);
+extern int ip_vs_app_inc_get(struct ip_vs_app *inc);
+extern void ip_vs_app_inc_put(struct ip_vs_app *inc);
+
+extern int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff *skb);
+extern int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff *skb);
+
+void ip_vs_bind_pe(struct ip_vs_service *svc, struct ip_vs_pe *pe);
+void ip_vs_unbind_pe(struct ip_vs_service *svc);
+int register_ip_vs_pe(struct ip_vs_pe *pe);
+int unregister_ip_vs_pe(struct ip_vs_pe *pe);
+struct ip_vs_pe *ip_vs_pe_getbyname(const char *name);
+struct ip_vs_pe *__ip_vs_pe_getbyname(const char *pe_name);
+
+/*
+ * Use a #define to avoid all of module.h just for these trivial ops
+ */
+#define ip_vs_pe_get(pe) \
+ if (pe && pe->module) \
+ __module_get(pe->module);
+
+#define ip_vs_pe_put(pe) \
+ if (pe && pe->module) \
+ module_put(pe->module);
+
+/*
+ * IPVS protocol functions (from ip_vs_proto.c)
+ */
+extern int ip_vs_protocol_init(void);
+extern void ip_vs_protocol_cleanup(void);
+extern void ip_vs_protocol_timeout_change(struct netns_ipvs *ipvs, int flags);
+extern int *ip_vs_create_timeout_table(int *table, int size);
+extern int
+ip_vs_set_state_timeout(int *table, int num, const char *const *names,
+ const char *name, int to);
+extern void
+ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp,
+ const struct sk_buff *skb,
+ int offset, const char *msg);
+
+extern struct ip_vs_protocol ip_vs_protocol_tcp;
+extern struct ip_vs_protocol ip_vs_protocol_udp;
+extern struct ip_vs_protocol ip_vs_protocol_icmp;
+extern struct ip_vs_protocol ip_vs_protocol_esp;
+extern struct ip_vs_protocol ip_vs_protocol_ah;
+extern struct ip_vs_protocol ip_vs_protocol_sctp;
+
+/*
+ * Registering/unregistering scheduler functions
+ * (from ip_vs_sched.c)
+ */
+extern int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+extern int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+extern int ip_vs_bind_scheduler(struct ip_vs_service *svc,
+ struct ip_vs_scheduler *scheduler);
+extern int ip_vs_unbind_scheduler(struct ip_vs_service *svc);
+extern struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name);
+extern void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler);
+extern struct ip_vs_conn *
+ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
+ struct ip_vs_proto_data *pd, int *ignored);
+extern int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
+ struct ip_vs_proto_data *pd);
+
+extern void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg);
+
+
+/*
+ * IPVS control data and functions (from ip_vs_ctl.c)
+ */
+extern struct ip_vs_stats ip_vs_stats;
+extern const struct ctl_path net_vs_ctl_path[];
+extern int sysctl_ip_vs_sync_ver;
+
+extern void ip_vs_sync_switch_mode(struct net *net, int mode);
+extern struct ip_vs_service *
+ip_vs_service_get(struct net *net, int af, __u32 fwmark, __u16 protocol,
+ const union nf_inet_addr *vaddr, __be16 vport);
+
+static inline void ip_vs_service_put(struct ip_vs_service *svc)
+{
+ atomic_dec(&svc->usecnt);
+}
+
+extern struct ip_vs_dest *
+ip_vs_lookup_real_service(struct net *net, int af, __u16 protocol,
+ const union nf_inet_addr *daddr, __be16 dport);
+
+extern int ip_vs_use_count_inc(void);
+extern void ip_vs_use_count_dec(void);
+extern int ip_vs_register_nl_ioctl(void);
+extern void ip_vs_unregister_nl_ioctl(void);
+extern int ip_vs_control_init(void);
+extern void ip_vs_control_cleanup(void);
+extern struct ip_vs_dest *
+ip_vs_find_dest(struct net *net, int af, const union nf_inet_addr *daddr,
+ __be16 dport, const union nf_inet_addr *vaddr, __be16 vport,
+ __u16 protocol, __u32 fwmark, __u32 flags);
+extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp);
+
+
+/*
+ * IPVS sync daemon data and function prototypes
+ * (from ip_vs_sync.c)
+ */
+extern int start_sync_thread(struct net *net, int state, char *mcast_ifn,
+ __u8 syncid);
+extern int stop_sync_thread(struct net *net, int state);
+extern void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp);
+
+
+/*
+ * IPVS rate estimator prototypes (from ip_vs_est.c)
+ */
+extern void ip_vs_start_estimator(struct net *net, struct ip_vs_stats *stats);
+extern void ip_vs_stop_estimator(struct net *net, struct ip_vs_stats *stats);
+extern void ip_vs_zero_estimator(struct ip_vs_stats *stats);
+extern void ip_vs_read_estimator(struct ip_vs_stats_user *dst,
+ struct ip_vs_stats *stats);
+
+/*
+ * Various IPVS packet transmitters (from ip_vs_xmit.c)
+ */
+extern int ip_vs_null_xmit
+(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
+extern int ip_vs_bypass_xmit
+(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
+extern int ip_vs_nat_xmit
+(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
+extern int ip_vs_tunnel_xmit
+(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
+extern int ip_vs_dr_xmit
+(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
+extern int ip_vs_icmp_xmit
+(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp,
+ int offset, unsigned int hooknum);
+extern void ip_vs_dst_reset(struct ip_vs_dest *dest);
+
+#ifdef CONFIG_IP_VS_IPV6
+extern int ip_vs_bypass_xmit_v6
+(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
+extern int ip_vs_nat_xmit_v6
+(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
+extern int ip_vs_tunnel_xmit_v6
+(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
+extern int ip_vs_dr_xmit_v6
+(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
+extern int ip_vs_icmp_xmit_v6
+(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp,
+ int offset, unsigned int hooknum);
+#endif
+
+#ifdef CONFIG_SYSCTL
+/*
+ * This is a simple mechanism to ignore packets when
+ * we are loaded. Just set ip_vs_drop_rate to 'n' and
+ * we start to drop 1/rate of the packets
+ */
+
+static inline int ip_vs_todrop(struct netns_ipvs *ipvs)
+{
+ if (!ipvs->drop_rate)
+ return 0;
+ if (--ipvs->drop_counter > 0)
+ return 0;
+ ipvs->drop_counter = ipvs->drop_rate;
+ return 1;
+}
+#else
+static inline int ip_vs_todrop(struct netns_ipvs *ipvs) { return 0; }
+#endif
+
+/*
+ * ip_vs_fwd_tag returns the forwarding tag of the connection
+ */
+#define IP_VS_FWD_METHOD(cp) (cp->flags & IP_VS_CONN_F_FWD_MASK)
+
+static inline char ip_vs_fwd_tag(struct ip_vs_conn *cp)
+{
+ char fwd;
+
+ switch (IP_VS_FWD_METHOD(cp)) {
+ case IP_VS_CONN_F_MASQ:
+ fwd = 'M'; break;
+ case IP_VS_CONN_F_LOCALNODE:
+ fwd = 'L'; break;
+ case IP_VS_CONN_F_TUNNEL:
+ fwd = 'T'; break;
+ case IP_VS_CONN_F_DROUTE:
+ fwd = 'R'; break;
+ case IP_VS_CONN_F_BYPASS:
+ fwd = 'B'; break;
+ default:
+ fwd = '?'; break;
+ }
+ return fwd;
+}
+
+extern void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
+ struct ip_vs_conn *cp, int dir);
+
+#ifdef CONFIG_IP_VS_IPV6
+extern void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp,
+ struct ip_vs_conn *cp, int dir);
+#endif
+
+extern __sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset);
+
+static inline __wsum ip_vs_check_diff4(__be32 old, __be32 new, __wsum oldsum)
+{
+ __be32 diff[2] = { ~old, new };
+
+ return csum_partial(diff, sizeof(diff), oldsum);
+}
+
+#ifdef CONFIG_IP_VS_IPV6
+static inline __wsum ip_vs_check_diff16(const __be32 *old, const __be32 *new,
+ __wsum oldsum)
+{
+ __be32 diff[8] = { ~old[3], ~old[2], ~old[1], ~old[0],
+ new[3], new[2], new[1], new[0] };
+
+ return csum_partial(diff, sizeof(diff), oldsum);
+}
+#endif
+
+static inline __wsum ip_vs_check_diff2(__be16 old, __be16 new, __wsum oldsum)
+{
+ __be16 diff[2] = { ~old, new };
+
+ return csum_partial(diff, sizeof(diff), oldsum);
+}
+
+/*
+ * Forget current conntrack (unconfirmed) and attach notrack entry
+ */
+static inline void ip_vs_notrack(struct sk_buff *skb)
+{
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+ enum ip_conntrack_info ctinfo;
+ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+
+ if (!ct || !nf_ct_is_untracked(ct)) {
+ nf_reset(skb);
+ skb->nfct = &nf_ct_untracked_get()->ct_general;
+ skb->nfctinfo = IP_CT_NEW;
+ nf_conntrack_get(skb->nfct);
+ }
+#endif
+}
+
+#ifdef CONFIG_IP_VS_NFCT
+/*
+ * Netfilter connection tracking
+ * (from ip_vs_nfct.c)
+ */
+static inline int ip_vs_conntrack_enabled(struct netns_ipvs *ipvs)
+{
+#ifdef CONFIG_SYSCTL
+ return ipvs->sysctl_conntrack;
+#else
+ return 0;
+#endif
+}
+
+extern void ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp,
+ int outin);
+extern int ip_vs_confirm_conntrack(struct sk_buff *skb);
+extern void ip_vs_nfct_expect_related(struct sk_buff *skb, struct nf_conn *ct,
+ struct ip_vs_conn *cp, u_int8_t proto,
+ const __be16 port, int from_rs);
+extern void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp);
+
+#else
+
+static inline int ip_vs_conntrack_enabled(struct netns_ipvs *ipvs)
+{
+ return 0;
+}
+
+static inline void ip_vs_update_conntrack(struct sk_buff *skb,
+ struct ip_vs_conn *cp, int outin)
+{
+}
+
+static inline int ip_vs_confirm_conntrack(struct sk_buff *skb)
+{
+ return NF_ACCEPT;
+}
+
+static inline void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp)
+{
+}
+/* CONFIG_IP_VS_NFCT */
+#endif
+
+static inline unsigned int
+ip_vs_dest_conn_overhead(struct ip_vs_dest *dest)
+{
+ /*
+ * We think the overhead of processing active connections is 256
+ * times higher than that of inactive connections in average. (This
+ * 256 times might not be accurate, we will change it later) We
+ * use the following formula to estimate the overhead now:
+ * dest->activeconns*256 + dest->inactconns
+ */
+ return (atomic_read(&dest->activeconns) << 8) +
+ atomic_read(&dest->inactconns);
+}
+
+#endif /* _NET_IP_VS_H */
diff --git a/include/net/ipcomp.h b/include/net/ipcomp.h
new file mode 100644
index 00000000..cc4f30cd
--- /dev/null
+++ b/include/net/ipcomp.h
@@ -0,0 +1,29 @@
+#ifndef _NET_IPCOMP_H
+#define _NET_IPCOMP_H
+
+#include <linux/types.h>
+
+#define IPCOMP_SCRATCH_SIZE 65400
+
+struct crypto_comp;
+
+struct ipcomp_data {
+ u16 threshold;
+ struct crypto_comp * __percpu *tfms;
+};
+
+struct ip_comp_hdr;
+struct sk_buff;
+struct xfrm_state;
+
+int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb);
+int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb);
+void ipcomp_destroy(struct xfrm_state *x);
+int ipcomp_init_state(struct xfrm_state *x);
+
+static inline struct ip_comp_hdr *ip_comp_hdr(const struct sk_buff *skb)
+{
+ return (struct ip_comp_hdr *)skb_transport_header(skb);
+}
+
+#endif
diff --git a/include/net/ipconfig.h b/include/net/ipconfig.h
new file mode 100644
index 00000000..c74cc1bd
--- /dev/null
+++ b/include/net/ipconfig.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 1997 Martin Mares
+ *
+ * Automatic IP Layer Configuration
+ */
+
+/* The following are initdata: */
+
+extern int ic_proto_enabled; /* Protocols enabled (see IC_xxx) */
+extern int ic_set_manually; /* IPconfig parameters set manually */
+
+extern __be32 ic_myaddr; /* My IP address */
+extern __be32 ic_gateway; /* Gateway IP address */
+
+extern __be32 ic_servaddr; /* Boot server IP address */
+
+extern __be32 root_server_addr; /* Address of NFS server */
+extern u8 root_server_path[]; /* Path to mount as root */
+
+
+/* bits in ic_proto_{enabled,used} */
+#define IC_PROTO 0xFF /* Protocols mask: */
+#define IC_BOOTP 0x01 /* BOOTP (or DHCP, see below) */
+#define IC_RARP 0x02 /* RARP */
+#define IC_USE_DHCP 0x100 /* If on, use DHCP instead of BOOTP */
diff --git a/include/net/ipip.h b/include/net/ipip.h
new file mode 100644
index 00000000..a32654d5
--- /dev/null
+++ b/include/net/ipip.h
@@ -0,0 +1,67 @@
+#ifndef __NET_IPIP_H
+#define __NET_IPIP_H 1
+
+#include <linux/if_tunnel.h>
+#include <net/ip.h>
+
+/* Keep error state on tunnel for 30 sec */
+#define IPTUNNEL_ERR_TIMEO (30*HZ)
+
+/* 6rd prefix/relay information */
+struct ip_tunnel_6rd_parm {
+ struct in6_addr prefix;
+ __be32 relay_prefix;
+ u16 prefixlen;
+ u16 relay_prefixlen;
+};
+
+struct ip_tunnel {
+ struct ip_tunnel __rcu *next;
+ struct net_device *dev;
+
+ int err_count; /* Number of arrived ICMP errors */
+ unsigned long err_time; /* Time when the last ICMP error arrived */
+
+ /* These four fields used only by GRE */
+ __u32 i_seqno; /* The last seen seqno */
+ __u32 o_seqno; /* The last output seqno */
+ int hlen; /* Precalculated GRE header length */
+ int mlink;
+
+ struct ip_tunnel_parm parms;
+
+ /* for SIT */
+#ifdef CONFIG_IPV6_SIT_6RD
+ struct ip_tunnel_6rd_parm ip6rd;
+#endif
+ struct ip_tunnel_prl_entry __rcu *prl; /* potential router list */
+ unsigned int prl_count; /* # of entries in PRL */
+};
+
+struct ip_tunnel_prl_entry {
+ struct ip_tunnel_prl_entry __rcu *next;
+ __be32 addr;
+ u16 flags;
+ struct rcu_head rcu_head;
+};
+
+#define __IPTUNNEL_XMIT(stats1, stats2) do { \
+ int err; \
+ int pkt_len = skb->len - skb_transport_offset(skb); \
+ \
+ skb->ip_summed = CHECKSUM_NONE; \
+ ip_select_ident(iph, &rt->dst, NULL); \
+ \
+ err = ip_local_out(skb); \
+ if (likely(net_xmit_eval(err) == 0)) { \
+ (stats1)->tx_bytes += pkt_len; \
+ (stats1)->tx_packets++; \
+ } else { \
+ (stats2)->tx_errors++; \
+ (stats2)->tx_aborted_errors++; \
+ } \
+} while (0)
+
+#define IPTUNNEL_XMIT() __IPTUNNEL_XMIT(txq, stats)
+
+#endif
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
new file mode 100644
index 00000000..a5a9e4df
--- /dev/null
+++ b/include/net/ipv6.h
@@ -0,0 +1,688 @@
+/*
+ * Linux INET6 implementation
+ *
+ * Authors:
+ * Pedro Roque <roque@di.fc.ul.pt>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _NET_IPV6_H
+#define _NET_IPV6_H
+
+#include <linux/ipv6.h>
+#include <linux/hardirq.h>
+#include <net/if_inet6.h>
+#include <net/ndisc.h>
+#include <net/flow.h>
+#include <net/snmp.h>
+
+#define SIN6_LEN_RFC2133 24
+
+#define IPV6_MAXPLEN 65535
+
+/*
+ * NextHeader field of IPv6 header
+ */
+
+#define NEXTHDR_HOP 0 /* Hop-by-hop option header. */
+#define NEXTHDR_TCP 6 /* TCP segment. */
+#define NEXTHDR_UDP 17 /* UDP message. */
+#define NEXTHDR_IPV6 41 /* IPv6 in IPv6 */
+#define NEXTHDR_ROUTING 43 /* Routing header. */
+#define NEXTHDR_FRAGMENT 44 /* Fragmentation/reassembly header. */
+#define NEXTHDR_ESP 50 /* Encapsulating security payload. */
+#define NEXTHDR_AUTH 51 /* Authentication header. */
+#define NEXTHDR_ICMP 58 /* ICMP for IPv6. */
+#define NEXTHDR_NONE 59 /* No next header */
+#define NEXTHDR_DEST 60 /* Destination options header. */
+#define NEXTHDR_MOBILITY 135 /* Mobility header. */
+
+#define NEXTHDR_MAX 255
+
+
+
+#define IPV6_DEFAULT_HOPLIMIT 64
+#define IPV6_DEFAULT_MCASTHOPS 1
+
+/*
+ * Addr type
+ *
+ * type - unicast | multicast
+ * scope - local | site | global
+ * v4 - compat
+ * v4mapped
+ * any
+ * loopback
+ */
+
+#define IPV6_ADDR_ANY 0x0000U
+
+#define IPV6_ADDR_UNICAST 0x0001U
+#define IPV6_ADDR_MULTICAST 0x0002U
+
+#define IPV6_ADDR_LOOPBACK 0x0010U
+#define IPV6_ADDR_LINKLOCAL 0x0020U
+#define IPV6_ADDR_SITELOCAL 0x0040U
+
+#define IPV6_ADDR_COMPATv4 0x0080U
+
+#define IPV6_ADDR_SCOPE_MASK 0x00f0U
+
+#define IPV6_ADDR_MAPPED 0x1000U
+
+/*
+ * Addr scopes
+ */
+#define IPV6_ADDR_MC_SCOPE(a) \
+ ((a)->s6_addr[1] & 0x0f) /* nonstandard */
+#define __IPV6_ADDR_SCOPE_INVALID -1
+#define IPV6_ADDR_SCOPE_NODELOCAL 0x01
+#define IPV6_ADDR_SCOPE_LINKLOCAL 0x02
+#define IPV6_ADDR_SCOPE_SITELOCAL 0x05
+#define IPV6_ADDR_SCOPE_ORGLOCAL 0x08
+#define IPV6_ADDR_SCOPE_GLOBAL 0x0e
+
+/*
+ * Addr flags
+ */
+#define IPV6_ADDR_MC_FLAG_TRANSIENT(a) \
+ ((a)->s6_addr[1] & 0x10)
+#define IPV6_ADDR_MC_FLAG_PREFIX(a) \
+ ((a)->s6_addr[1] & 0x20)
+#define IPV6_ADDR_MC_FLAG_RENDEZVOUS(a) \
+ ((a)->s6_addr[1] & 0x40)
+
+/*
+ * fragmentation header
+ */
+
+struct frag_hdr {
+ __u8 nexthdr;
+ __u8 reserved;
+ __be16 frag_off;
+ __be32 identification;
+};
+
+#define IP6_MF 0x0001
+
+#include <net/sock.h>
+
+/* sysctls */
+extern int sysctl_mld_max_msf;
+extern struct ctl_path net_ipv6_ctl_path[];
+
+#define _DEVINC(net, statname, modifier, idev, field) \
+({ \
+ struct inet6_dev *_idev = (idev); \
+ if (likely(_idev != NULL)) \
+ SNMP_INC_STATS##modifier((_idev)->stats.statname, (field)); \
+ SNMP_INC_STATS##modifier((net)->mib.statname##_statistics, (field));\
+})
+
+/* per device counters are atomic_long_t */
+#define _DEVINCATOMIC(net, statname, modifier, idev, field) \
+({ \
+ struct inet6_dev *_idev = (idev); \
+ if (likely(_idev != NULL)) \
+ SNMP_INC_STATS_ATOMIC_LONG((_idev)->stats.statname##dev, (field)); \
+ SNMP_INC_STATS##modifier((net)->mib.statname##_statistics, (field));\
+})
+
+/* per device and per net counters are atomic_long_t */
+#define _DEVINC_ATOMIC_ATOMIC(net, statname, idev, field) \
+({ \
+ struct inet6_dev *_idev = (idev); \
+ if (likely(_idev != NULL)) \
+ SNMP_INC_STATS_ATOMIC_LONG((_idev)->stats.statname##dev, (field)); \
+ SNMP_INC_STATS_ATOMIC_LONG((net)->mib.statname##_statistics, (field));\
+})
+
+#define _DEVADD(net, statname, modifier, idev, field, val) \
+({ \
+ struct inet6_dev *_idev = (idev); \
+ if (likely(_idev != NULL)) \
+ SNMP_ADD_STATS##modifier((_idev)->stats.statname, (field), (val)); \
+ SNMP_ADD_STATS##modifier((net)->mib.statname##_statistics, (field), (val));\
+})
+
+#define _DEVUPD(net, statname, modifier, idev, field, val) \
+({ \
+ struct inet6_dev *_idev = (idev); \
+ if (likely(_idev != NULL)) \
+ SNMP_UPD_PO_STATS##modifier((_idev)->stats.statname, field, (val)); \
+ SNMP_UPD_PO_STATS##modifier((net)->mib.statname##_statistics, field, (val));\
+})
+
+/* MIBs */
+
+#define IP6_INC_STATS(net, idev,field) \
+ _DEVINC(net, ipv6, 64, idev, field)
+#define IP6_INC_STATS_BH(net, idev,field) \
+ _DEVINC(net, ipv6, 64_BH, idev, field)
+#define IP6_ADD_STATS(net, idev,field,val) \
+ _DEVADD(net, ipv6, 64, idev, field, val)
+#define IP6_ADD_STATS_BH(net, idev,field,val) \
+ _DEVADD(net, ipv6, 64_BH, idev, field, val)
+#define IP6_UPD_PO_STATS(net, idev,field,val) \
+ _DEVUPD(net, ipv6, 64, idev, field, val)
+#define IP6_UPD_PO_STATS_BH(net, idev,field,val) \
+ _DEVUPD(net, ipv6, 64_BH, idev, field, val)
+#define ICMP6_INC_STATS(net, idev, field) \
+ _DEVINCATOMIC(net, icmpv6, , idev, field)
+#define ICMP6_INC_STATS_BH(net, idev, field) \
+ _DEVINCATOMIC(net, icmpv6, _BH, idev, field)
+
+#define ICMP6MSGOUT_INC_STATS(net, idev, field) \
+ _DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, idev, field +256)
+#define ICMP6MSGOUT_INC_STATS_BH(net, idev, field) \
+ _DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, idev, field +256)
+#define ICMP6MSGIN_INC_STATS_BH(net, idev, field) \
+ _DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, idev, field)
+
+struct ip6_ra_chain {
+ struct ip6_ra_chain *next;
+ struct sock *sk;
+ int sel;
+ void (*destructor)(struct sock *);
+};
+
+extern struct ip6_ra_chain *ip6_ra_chain;
+extern rwlock_t ip6_ra_lock;
+
+/*
+ This structure is prepared by protocol, when parsing
+ ancillary data and passed to IPv6.
+ */
+
+struct ipv6_txoptions {
+ /* Length of this structure */
+ int tot_len;
+
+ /* length of extension headers */
+
+ __u16 opt_flen; /* after fragment hdr */
+ __u16 opt_nflen; /* before fragment hdr */
+
+ struct ipv6_opt_hdr *hopopt;
+ struct ipv6_opt_hdr *dst0opt;
+ struct ipv6_rt_hdr *srcrt; /* Routing Header */
+ struct ipv6_opt_hdr *dst1opt;
+
+ /* Option buffer, as read by IPV6_PKTOPTIONS, starts here. */
+};
+
+struct ip6_flowlabel {
+ struct ip6_flowlabel *next;
+ __be32 label;
+ atomic_t users;
+ struct in6_addr dst;
+ struct ipv6_txoptions *opt;
+ unsigned long linger;
+ u8 share;
+ u32 owner;
+ unsigned long lastuse;
+ unsigned long expires;
+ struct net *fl_net;
+};
+
+#define IPV6_FLOWINFO_MASK cpu_to_be32(0x0FFFFFFF)
+#define IPV6_FLOWLABEL_MASK cpu_to_be32(0x000FFFFF)
+
+struct ipv6_fl_socklist {
+ struct ipv6_fl_socklist *next;
+ struct ip6_flowlabel *fl;
+};
+
+extern struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label);
+extern struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions * opt_space,
+ struct ip6_flowlabel * fl,
+ struct ipv6_txoptions * fopt);
+extern void fl6_free_socklist(struct sock *sk);
+extern int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen);
+extern int ip6_flowlabel_init(void);
+extern void ip6_flowlabel_cleanup(void);
+
+static inline void fl6_sock_release(struct ip6_flowlabel *fl)
+{
+ if (fl)
+ atomic_dec(&fl->users);
+}
+
+extern void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info);
+
+int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
+ struct icmp6hdr *thdr, int len);
+
+struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb,
+ struct sock *sk, struct flowi6 *fl6);
+
+extern int ip6_ra_control(struct sock *sk, int sel);
+
+extern int ipv6_parse_hopopts(struct sk_buff *skb);
+
+extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt);
+extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
+ int newtype,
+ struct ipv6_opt_hdr __user *newopt,
+ int newoptlen);
+struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
+ struct ipv6_txoptions *opt);
+
+extern int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb);
+
+int ip6_frag_nqueues(struct net *net);
+int ip6_frag_mem(struct net *net);
+
+#define IPV6_FRAG_HIGH_THRESH (256 * 1024) /* 262144 */
+#define IPV6_FRAG_LOW_THRESH (192 * 1024) /* 196608 */
+#define IPV6_FRAG_TIMEOUT (60 * HZ) /* 60 seconds */
+
+extern int __ipv6_addr_type(const struct in6_addr *addr);
+static inline int ipv6_addr_type(const struct in6_addr *addr)
+{
+ return __ipv6_addr_type(addr) & 0xffff;
+}
+
+static inline int ipv6_addr_scope(const struct in6_addr *addr)
+{
+ return __ipv6_addr_type(addr) & IPV6_ADDR_SCOPE_MASK;
+}
+
+static inline int __ipv6_addr_src_scope(int type)
+{
+ return (type == IPV6_ADDR_ANY) ? __IPV6_ADDR_SCOPE_INVALID : (type >> 16);
+}
+
+static inline int ipv6_addr_src_scope(const struct in6_addr *addr)
+{
+ return __ipv6_addr_src_scope(__ipv6_addr_type(addr));
+}
+
+static inline bool __ipv6_addr_needs_scope_id(int type)
+{
+ return type & IPV6_ADDR_LINKLOCAL ||
+ (type & IPV6_ADDR_MULTICAST &&
+ (type & (IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL)));
+}
+
+static inline __u32 ipv6_iface_scope_id(const struct in6_addr *addr, int iface)
+{
+ return __ipv6_addr_needs_scope_id(__ipv6_addr_type(addr)) ? iface : 0;
+}
+
+static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr *a2)
+{
+ return memcmp(a1, a2, sizeof(struct in6_addr));
+}
+
+static inline int
+ipv6_masked_addr_cmp(const struct in6_addr *a1, const struct in6_addr *m,
+ const struct in6_addr *a2)
+{
+ return !!(((a1->s6_addr32[0] ^ a2->s6_addr32[0]) & m->s6_addr32[0]) |
+ ((a1->s6_addr32[1] ^ a2->s6_addr32[1]) & m->s6_addr32[1]) |
+ ((a1->s6_addr32[2] ^ a2->s6_addr32[2]) & m->s6_addr32[2]) |
+ ((a1->s6_addr32[3] ^ a2->s6_addr32[3]) & m->s6_addr32[3]));
+}
+
+static inline void ipv6_addr_prefix(struct in6_addr *pfx,
+ const struct in6_addr *addr,
+ int plen)
+{
+ /* caller must guarantee 0 <= plen <= 128 */
+ int o = plen >> 3,
+ b = plen & 0x7;
+
+ memset(pfx->s6_addr, 0, sizeof(pfx->s6_addr));
+ memcpy(pfx->s6_addr, addr, o);
+ if (b != 0)
+ pfx->s6_addr[o] = addr->s6_addr[o] & (0xff00 >> b);
+}
+
+static inline void ipv6_addr_set(struct in6_addr *addr,
+ __be32 w1, __be32 w2,
+ __be32 w3, __be32 w4)
+{
+ addr->s6_addr32[0] = w1;
+ addr->s6_addr32[1] = w2;
+ addr->s6_addr32[2] = w3;
+ addr->s6_addr32[3] = w4;
+}
+
+static inline int ipv6_addr_equal(const struct in6_addr *a1,
+ const struct in6_addr *a2)
+{
+ return ((a1->s6_addr32[0] ^ a2->s6_addr32[0]) |
+ (a1->s6_addr32[1] ^ a2->s6_addr32[1]) |
+ (a1->s6_addr32[2] ^ a2->s6_addr32[2]) |
+ (a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0;
+}
+
+static inline int __ipv6_prefix_equal(const __be32 *a1, const __be32 *a2,
+ unsigned int prefixlen)
+{
+ unsigned pdw, pbi;
+
+ /* check complete u32 in prefix */
+ pdw = prefixlen >> 5;
+ if (pdw && memcmp(a1, a2, pdw << 2))
+ return 0;
+
+ /* check incomplete u32 in prefix */
+ pbi = prefixlen & 0x1f;
+ if (pbi && ((a1[pdw] ^ a2[pdw]) & htonl((0xffffffff) << (32 - pbi))))
+ return 0;
+
+ return 1;
+}
+
+static inline int ipv6_prefix_equal(const struct in6_addr *a1,
+ const struct in6_addr *a2,
+ unsigned int prefixlen)
+{
+ return __ipv6_prefix_equal(a1->s6_addr32, a2->s6_addr32,
+ prefixlen);
+}
+
+struct inet_frag_queue;
+
+enum ip6_defrag_users {
+ IP6_DEFRAG_LOCAL_DELIVER,
+ IP6_DEFRAG_CONNTRACK_IN,
+ __IP6_DEFRAG_CONNTRACK_IN = IP6_DEFRAG_CONNTRACK_IN + USHRT_MAX,
+ IP6_DEFRAG_CONNTRACK_OUT,
+ __IP6_DEFRAG_CONNTRACK_OUT = IP6_DEFRAG_CONNTRACK_OUT + USHRT_MAX,
+ IP6_DEFRAG_CONNTRACK_BRIDGE_IN,
+ __IP6_DEFRAG_CONNTRACK_BRIDGE_IN = IP6_DEFRAG_CONNTRACK_BRIDGE_IN + USHRT_MAX,
+};
+
+struct ip6_create_arg {
+ __be32 id;
+ u32 user;
+ const struct in6_addr *src;
+ const struct in6_addr *dst;
+};
+
+void ip6_frag_init(struct inet_frag_queue *q, void *a);
+int ip6_frag_match(struct inet_frag_queue *q, void *a);
+
+static inline int ipv6_addr_any(const struct in6_addr *a)
+{
+ return (a->s6_addr32[0] | a->s6_addr32[1] |
+ a->s6_addr32[2] | a->s6_addr32[3]) == 0;
+}
+
+static inline int ipv6_addr_loopback(const struct in6_addr *a)
+{
+ return (a->s6_addr32[0] | a->s6_addr32[1] |
+ a->s6_addr32[2] | (a->s6_addr32[3] ^ htonl(1))) == 0;
+}
+
+static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
+{
+ return (a->s6_addr32[0] | a->s6_addr32[1] |
+ (a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0;
+}
+
+/*
+ * Check for a RFC 4843 ORCHID address
+ * (Overlay Routable Cryptographic Hash Identifiers)
+ */
+static inline int ipv6_addr_orchid(const struct in6_addr *a)
+{
+ return (a->s6_addr32[0] & htonl(0xfffffff0)) == htonl(0x20010010);
+}
+
+static inline void ipv6_addr_set_v4mapped(const __be32 addr,
+ struct in6_addr *v4mapped)
+{
+ ipv6_addr_set(v4mapped,
+ 0, 0,
+ htonl(0x0000FFFF),
+ addr);
+}
+
+/*
+ * find the first different bit between two addresses
+ * length of address must be a multiple of 32bits
+ */
+static inline int __ipv6_addr_diff(const void *token1, const void *token2, int addrlen)
+{
+ const __be32 *a1 = token1, *a2 = token2;
+ int i;
+
+ addrlen >>= 2;
+
+ for (i = 0; i < addrlen; i++) {
+ __be32 xb = a1[i] ^ a2[i];
+ if (xb)
+ return i * 32 + 31 - __fls(ntohl(xb));
+ }
+
+ /*
+ * we should *never* get to this point since that
+ * would mean the addrs are equal
+ *
+ * However, we do get to it 8) And exacly, when
+ * addresses are equal 8)
+ *
+ * ip route add 1111::/128 via ...
+ * ip route add 1111::/64 via ...
+ * and we are here.
+ *
+ * Ideally, this function should stop comparison
+ * at prefix length. It does not, but it is still OK,
+ * if returned value is greater than prefix length.
+ * --ANK (980803)
+ */
+ return addrlen << 5;
+}
+
+static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_addr *a2)
+{
+ return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
+}
+
+extern void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt);
+
+/*
+ * Prototypes exported by ipv6
+ */
+
+/*
+ * rcv function (called from netdevice level)
+ */
+
+extern int ipv6_rcv(struct sk_buff *skb,
+ struct net_device *dev,
+ struct packet_type *pt,
+ struct net_device *orig_dev);
+
+extern int ip6_rcv_finish(struct sk_buff *skb);
+
+/*
+ * upper-layer output functions
+ */
+extern int ip6_xmit(struct sock *sk,
+ struct sk_buff *skb,
+ struct flowi6 *fl6,
+ struct ipv6_txoptions *opt,
+ int tclass);
+
+extern int ip6_nd_hdr(struct sock *sk,
+ struct sk_buff *skb,
+ struct net_device *dev,
+ const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ int proto, int len);
+
+extern int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr);
+
+extern int ip6_append_data(struct sock *sk,
+ int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb),
+ void *from,
+ int length,
+ int transhdrlen,
+ int hlimit,
+ int tclass,
+ struct ipv6_txoptions *opt,
+ struct flowi6 *fl6,
+ struct rt6_info *rt,
+ unsigned int flags,
+ int dontfrag);
+
+extern int ip6_push_pending_frames(struct sock *sk);
+
+extern void ip6_flush_pending_frames(struct sock *sk);
+
+extern int ip6_dst_lookup(struct sock *sk,
+ struct dst_entry **dst,
+ struct flowi6 *fl6);
+extern struct dst_entry * ip6_dst_lookup_flow(struct sock *sk,
+ struct flowi6 *fl6,
+ const struct in6_addr *final_dst,
+ bool can_sleep);
+extern struct dst_entry * ip6_sk_dst_lookup_flow(struct sock *sk,
+ struct flowi6 *fl6,
+ const struct in6_addr *final_dst,
+ bool can_sleep);
+extern struct dst_entry * ip6_blackhole_route(struct net *net,
+ struct dst_entry *orig_dst);
+
+/*
+ * skb processing functions
+ */
+
+extern int ip6_output(struct sk_buff *skb);
+extern int ip6_forward(struct sk_buff *skb);
+extern int ip6_input(struct sk_buff *skb);
+extern int ip6_mc_input(struct sk_buff *skb);
+
+extern int __ip6_local_out(struct sk_buff *skb);
+extern int ip6_local_out(struct sk_buff *skb);
+
+/*
+ * Extension header (options) processing
+ */
+
+extern void ipv6_push_nfrag_opts(struct sk_buff *skb,
+ struct ipv6_txoptions *opt,
+ u8 *proto,
+ struct in6_addr **daddr_p);
+extern void ipv6_push_frag_opts(struct sk_buff *skb,
+ struct ipv6_txoptions *opt,
+ u8 *proto);
+
+extern int ipv6_skip_exthdr(const struct sk_buff *, int start,
+ u8 *nexthdrp, __be16 *frag_offp);
+
+extern int ipv6_ext_hdr(u8 nexthdr);
+
+extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type);
+
+extern struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
+ const struct ipv6_txoptions *opt,
+ struct in6_addr *orig);
+
+/*
+ * socket options (ipv6_sockglue.c)
+ */
+
+extern int ipv6_setsockopt(struct sock *sk, int level,
+ int optname,
+ char __user *optval,
+ unsigned int optlen);
+extern int ipv6_getsockopt(struct sock *sk, int level,
+ int optname,
+ char __user *optval,
+ int __user *optlen);
+extern int compat_ipv6_setsockopt(struct sock *sk,
+ int level,
+ int optname,
+ char __user *optval,
+ unsigned int optlen);
+extern int compat_ipv6_getsockopt(struct sock *sk,
+ int level,
+ int optname,
+ char __user *optval,
+ int __user *optlen);
+
+extern int ip6_datagram_connect(struct sock *sk,
+ struct sockaddr *addr, int addr_len);
+
+extern int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len);
+extern int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len);
+extern void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
+ u32 info, u8 *payload);
+extern void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info);
+extern void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu);
+
+extern int inet6_release(struct socket *sock);
+extern int inet6_bind(struct socket *sock, struct sockaddr *uaddr,
+ int addr_len);
+extern int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
+ int *uaddr_len, int peer);
+extern int inet6_ioctl(struct socket *sock, unsigned int cmd,
+ unsigned long arg);
+
+extern int inet6_hash_connect(struct inet_timewait_death_row *death_row,
+ struct sock *sk);
+
+/*
+ * reassembly.c
+ */
+extern const struct proto_ops inet6_stream_ops;
+extern const struct proto_ops inet6_dgram_ops;
+
+struct group_source_req;
+struct group_filter;
+
+extern int ip6_mc_source(int add, int omode, struct sock *sk,
+ struct group_source_req *pgsr);
+extern int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf);
+extern int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
+ struct group_filter __user *optval,
+ int __user *optlen);
+extern unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr,
+ const struct in6_addr *daddr, u32 rnd);
+
+#ifdef CONFIG_PROC_FS
+extern int ac6_proc_init(struct net *net);
+extern void ac6_proc_exit(struct net *net);
+extern int raw6_proc_init(void);
+extern void raw6_proc_exit(void);
+extern int tcp6_proc_init(struct net *net);
+extern void tcp6_proc_exit(struct net *net);
+extern int udp6_proc_init(struct net *net);
+extern void udp6_proc_exit(struct net *net);
+extern int udplite6_proc_init(void);
+extern void udplite6_proc_exit(void);
+extern int ipv6_misc_proc_init(void);
+extern void ipv6_misc_proc_exit(void);
+extern int snmp6_register_dev(struct inet6_dev *idev);
+extern int snmp6_unregister_dev(struct inet6_dev *idev);
+
+#else
+static inline int ac6_proc_init(struct net *net) { return 0; }
+static inline void ac6_proc_exit(struct net *net) { }
+static inline int snmp6_register_dev(struct inet6_dev *idev) { return 0; }
+static inline int snmp6_unregister_dev(struct inet6_dev *idev) { return 0; }
+#endif
+
+#ifdef CONFIG_SYSCTL
+extern ctl_table ipv6_route_table_template[];
+extern ctl_table ipv6_icmp_table_template[];
+
+extern struct ctl_table *ipv6_icmp_sysctl_init(struct net *net);
+extern struct ctl_table *ipv6_route_sysctl_init(struct net *net);
+extern int ipv6_sysctl_register(void);
+extern void ipv6_sysctl_unregister(void);
+extern int ipv6_static_sysctl_register(void);
+extern void ipv6_static_sysctl_unregister(void);
+#endif
+
+#endif /* _NET_IPV6_H */
diff --git a/include/net/ipx.h b/include/net/ipx.h
new file mode 100644
index 00000000..c1fec6b4
--- /dev/null
+++ b/include/net/ipx.h
@@ -0,0 +1,160 @@
+#ifndef _NET_INET_IPX_H_
+#define _NET_INET_IPX_H_
+/*
+ * The following information is in its entirety obtained from:
+ *
+ * Novell 'IPX Router Specification' Version 1.10
+ * Part No. 107-000029-001
+ *
+ * Which is available from ftp.novell.com
+ */
+
+#include <linux/netdevice.h>
+#include <net/datalink.h>
+#include <linux/ipx.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+
+struct ipx_address {
+ __be32 net;
+ __u8 node[IPX_NODE_LEN];
+ __be16 sock;
+};
+
+#define ipx_broadcast_node "\377\377\377\377\377\377"
+#define ipx_this_node "\0\0\0\0\0\0"
+
+#define IPX_MAX_PPROP_HOPS 8
+
+struct ipxhdr {
+ __be16 ipx_checksum __packed;
+#define IPX_NO_CHECKSUM cpu_to_be16(0xFFFF)
+ __be16 ipx_pktsize __packed;
+ __u8 ipx_tctrl;
+ __u8 ipx_type;
+#define IPX_TYPE_UNKNOWN 0x00
+#define IPX_TYPE_RIP 0x01 /* may also be 0 */
+#define IPX_TYPE_SAP 0x04 /* may also be 0 */
+#define IPX_TYPE_SPX 0x05 /* SPX protocol */
+#define IPX_TYPE_NCP 0x11 /* $lots for docs on this (SPIT) */
+#define IPX_TYPE_PPROP 0x14 /* complicated flood fill brdcast */
+ struct ipx_address ipx_dest __packed;
+ struct ipx_address ipx_source __packed;
+};
+
+static __inline__ struct ipxhdr *ipx_hdr(struct sk_buff *skb)
+{
+ return (struct ipxhdr *)skb_transport_header(skb);
+}
+
+struct ipx_interface {
+ /* IPX address */
+ __be32 if_netnum;
+ unsigned char if_node[IPX_NODE_LEN];
+ atomic_t refcnt;
+
+ /* physical device info */
+ struct net_device *if_dev;
+ struct datalink_proto *if_dlink;
+ __be16 if_dlink_type;
+
+ /* socket support */
+ unsigned short if_sknum;
+ struct hlist_head if_sklist;
+ spinlock_t if_sklist_lock;
+
+ /* administrative overhead */
+ int if_ipx_offset;
+ unsigned char if_internal;
+ unsigned char if_primary;
+
+ struct list_head node; /* node in ipx_interfaces list */
+};
+
+struct ipx_route {
+ __be32 ir_net;
+ struct ipx_interface *ir_intrfc;
+ unsigned char ir_routed;
+ unsigned char ir_router_node[IPX_NODE_LEN];
+ struct list_head node; /* node in ipx_routes list */
+ atomic_t refcnt;
+};
+
+struct ipx_cb {
+ u8 ipx_tctrl;
+ __be32 ipx_dest_net;
+ __be32 ipx_source_net;
+ struct {
+ __be32 netnum;
+ int index;
+ } last_hop;
+};
+
+#include <net/sock.h>
+
+struct ipx_sock {
+ /* struct sock has to be the first member of ipx_sock */
+ struct sock sk;
+ struct ipx_address dest_addr;
+ struct ipx_interface *intrfc;
+ __be16 port;
+#ifdef CONFIG_IPX_INTERN
+ unsigned char node[IPX_NODE_LEN];
+#endif
+ unsigned short type;
+ /*
+ * To handle special ncp connection-handling sockets for mars_nwe,
+ * the connection number must be stored in the socket.
+ */
+ unsigned short ipx_ncp_conn;
+};
+
+static inline struct ipx_sock *ipx_sk(struct sock *sk)
+{
+ return (struct ipx_sock *)sk;
+}
+
+#define IPX_SKB_CB(__skb) ((struct ipx_cb *)&((__skb)->cb[0]))
+
+#define IPX_MIN_EPHEMERAL_SOCKET 0x4000
+#define IPX_MAX_EPHEMERAL_SOCKET 0x7fff
+
+extern struct list_head ipx_routes;
+extern rwlock_t ipx_routes_lock;
+
+extern struct list_head ipx_interfaces;
+extern struct ipx_interface *ipx_interfaces_head(void);
+extern spinlock_t ipx_interfaces_lock;
+
+extern struct ipx_interface *ipx_primary_net;
+
+extern int ipx_proc_init(void);
+extern void ipx_proc_exit(void);
+
+extern const char *ipx_frame_name(__be16);
+extern const char *ipx_device_name(struct ipx_interface *intrfc);
+
+static __inline__ void ipxitf_hold(struct ipx_interface *intrfc)
+{
+ atomic_inc(&intrfc->refcnt);
+}
+
+extern void ipxitf_down(struct ipx_interface *intrfc);
+
+static __inline__ void ipxitf_put(struct ipx_interface *intrfc)
+{
+ if (atomic_dec_and_test(&intrfc->refcnt))
+ ipxitf_down(intrfc);
+}
+
+static __inline__ void ipxrtr_hold(struct ipx_route *rt)
+{
+ atomic_inc(&rt->refcnt);
+}
+
+static __inline__ void ipxrtr_put(struct ipx_route *rt)
+{
+ if (atomic_dec_and_test(&rt->refcnt))
+ kfree(rt);
+}
+#endif /* _NET_INET_IPX_H_ */
diff --git a/include/net/irda/af_irda.h b/include/net/irda/af_irda.h
new file mode 100644
index 00000000..0df57493
--- /dev/null
+++ b/include/net/irda/af_irda.h
@@ -0,0 +1,87 @@
+/*********************************************************************
+ *
+ * Filename: af_irda.h
+ * Version: 1.0
+ * Description: IrDA sockets declarations
+ * Status: Stable
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Tue Dec 9 21:13:12 1997
+ * Modified at: Fri Jan 28 13:16:32 2000
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998-2000 Dag Brattli, All Rights Reserved.
+ * Copyright (c) 2000-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef AF_IRDA_H
+#define AF_IRDA_H
+
+#include <linux/irda.h>
+#include <net/irda/irda.h>
+#include <net/irda/iriap.h> /* struct iriap_cb */
+#include <net/irda/irias_object.h> /* struct ias_value */
+#include <net/irda/irlmp.h> /* struct lsap_cb */
+#include <net/irda/irttp.h> /* struct tsap_cb */
+#include <net/irda/discovery.h> /* struct discovery_t */
+#include <net/sock.h>
+
+/* IrDA Socket */
+struct irda_sock {
+ /* struct sock has to be the first member of irda_sock */
+ struct sock sk;
+ __u32 saddr; /* my local address */
+ __u32 daddr; /* peer address */
+
+ struct lsap_cb *lsap; /* LSAP used by Ultra */
+ __u8 pid; /* Protocol IP (PID) used by Ultra */
+
+ struct tsap_cb *tsap; /* TSAP used by this connection */
+ __u8 dtsap_sel; /* remote TSAP address */
+ __u8 stsap_sel; /* local TSAP address */
+
+ __u32 max_sdu_size_rx;
+ __u32 max_sdu_size_tx;
+ __u32 max_data_size;
+ __u8 max_header_size;
+ struct qos_info qos_tx;
+
+ __u16_host_order mask; /* Hint bits mask */
+ __u16_host_order hints; /* Hint bits */
+
+ void *ckey; /* IrLMP client handle */
+ void *skey; /* IrLMP service handle */
+
+ struct ias_object *ias_obj; /* Our service name + lsap in IAS */
+ struct iriap_cb *iriap; /* Used to query remote IAS */
+ struct ias_value *ias_result; /* Result of remote IAS query */
+
+ hashbin_t *cachelog; /* Result of discovery query */
+ __u32 cachedaddr; /* Result of selective discovery query */
+
+ int nslots; /* Number of slots to use for discovery */
+
+ int errno; /* status of the IAS query */
+
+ wait_queue_head_t query_wait; /* Wait for the answer to a query */
+ struct timer_list watchdog; /* Timeout for discovery */
+
+ LOCAL_FLOW tx_flow;
+ LOCAL_FLOW rx_flow;
+};
+
+static inline struct irda_sock *irda_sk(struct sock *sk)
+{
+ return (struct irda_sock *)sk;
+}
+
+#endif /* AF_IRDA_H */
diff --git a/include/net/irda/crc.h b/include/net/irda/crc.h
new file mode 100644
index 00000000..f202296d
--- /dev/null
+++ b/include/net/irda/crc.h
@@ -0,0 +1,29 @@
+/*********************************************************************
+ *
+ * Filename: crc.h
+ * Version:
+ * Description: CRC routines
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Mon Aug 4 20:40:53 1997
+ * Modified at: Sun May 2 20:25:23 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ ********************************************************************/
+
+#ifndef IRDA_CRC_H
+#define IRDA_CRC_H
+
+#include <linux/types.h>
+#include <linux/crc-ccitt.h>
+
+#define INIT_FCS 0xffff /* Initial FCS value */
+#define GOOD_FCS 0xf0b8 /* Good final FCS value */
+
+/* Recompute the FCS with one more character appended. */
+#define irda_fcs(fcs, c) crc_ccitt_byte(fcs, c)
+
+/* Recompute the FCS with len bytes appended. */
+#define irda_calc_crc16(fcs, buf, len) crc_ccitt(fcs, buf, len)
+
+#endif
diff --git a/include/net/irda/discovery.h b/include/net/irda/discovery.h
new file mode 100644
index 00000000..0ce93398
--- /dev/null
+++ b/include/net/irda/discovery.h
@@ -0,0 +1,97 @@
+/*********************************************************************
+ *
+ * Filename: discovery.h
+ * Version:
+ * Description:
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Tue Apr 6 16:53:53 1999
+ * Modified at: Tue Oct 5 10:05:10 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ * Copyright (c) 2000-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ********************************************************************/
+
+#ifndef DISCOVERY_H
+#define DISCOVERY_H
+
+#include <asm/param.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irqueue.h> /* irda_queue_t */
+#include <net/irda/irlap_event.h> /* LAP_REASON */
+
+#define DISCOVERY_EXPIRE_TIMEOUT (2*sysctl_discovery_timeout*HZ)
+#define DISCOVERY_DEFAULT_SLOTS 0
+
+/*
+ * This type is used by the protocols that transmit 16 bits words in
+ * little endian format. A little endian machine stores MSB of word in
+ * byte[1] and LSB in byte[0]. A big endian machine stores MSB in byte[0]
+ * and LSB in byte[1].
+ *
+ * This structure is used in the code for things that are endian neutral
+ * but that fit in a word so that we can manipulate them efficiently.
+ * By endian neutral, I mean things that are really an array of bytes,
+ * and always used as such, for example the hint bits. Jean II
+ */
+typedef union {
+ __u16 word;
+ __u8 byte[2];
+} __u16_host_order;
+
+/* Types of discovery */
+typedef enum {
+ DISCOVERY_LOG, /* What's in our discovery log */
+ DISCOVERY_ACTIVE, /* Doing our own discovery on the medium */
+ DISCOVERY_PASSIVE, /* Peer doing discovery on the medium */
+ EXPIRY_TIMEOUT, /* Entry expired due to timeout */
+} DISCOVERY_MODE;
+
+#define NICKNAME_MAX_LEN 21
+
+/* Basic discovery information about a peer */
+typedef struct irda_device_info discinfo_t; /* linux/irda.h */
+
+/*
+ * The DISCOVERY structure is used for both discovery requests and responses
+ */
+typedef struct discovery_t {
+ irda_queue_t q; /* Must be first! */
+
+ discinfo_t data; /* Basic discovery information */
+ int name_len; /* Length of nickname */
+
+ LAP_REASON condition; /* More info about the discovery */
+ int gen_addr_bit; /* Need to generate a new device
+ * address? */
+ int nslots; /* Number of slots to use when
+ * discovering */
+ unsigned long timestamp; /* Last time discovered */
+ unsigned long firststamp; /* First time discovered */
+} discovery_t;
+
+void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *discovery);
+void irlmp_add_discovery_log(hashbin_t *cachelog, hashbin_t *log);
+void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force);
+struct irda_device_info *irlmp_copy_discoveries(hashbin_t *log, int *pn,
+ __u16 mask, int old_entries);
+
+#endif
diff --git a/include/net/irda/ircomm_core.h b/include/net/irda/ircomm_core.h
new file mode 100644
index 00000000..69b610ac
--- /dev/null
+++ b/include/net/irda/ircomm_core.h
@@ -0,0 +1,108 @@
+/*********************************************************************
+ *
+ * Filename: ircomm_core.h
+ * Version:
+ * Description:
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Wed Jun 9 08:58:43 1999
+ * Modified at: Mon Dec 13 11:52:29 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ********************************************************************/
+
+#ifndef IRCOMM_CORE_H
+#define IRCOMM_CORE_H
+
+#include <net/irda/irda.h>
+#include <net/irda/irqueue.h>
+#include <net/irda/ircomm_event.h>
+
+#define IRCOMM_MAGIC 0x98347298
+#define IRCOMM_HEADER_SIZE 1
+
+struct ircomm_cb; /* Forward decl. */
+
+/*
+ * A small call-table, so we don't have to check the service-type whenever
+ * we want to do something
+ */
+typedef struct {
+ int (*data_request)(struct ircomm_cb *, struct sk_buff *, int clen);
+ int (*connect_request)(struct ircomm_cb *, struct sk_buff *,
+ struct ircomm_info *);
+ int (*connect_response)(struct ircomm_cb *, struct sk_buff *);
+ int (*disconnect_request)(struct ircomm_cb *, struct sk_buff *,
+ struct ircomm_info *);
+} call_t;
+
+struct ircomm_cb {
+ irda_queue_t queue;
+ magic_t magic;
+
+ notify_t notify;
+ call_t issue;
+
+ int state;
+ int line; /* Which TTY line we are using */
+
+ struct tsap_cb *tsap;
+ struct lsap_cb *lsap;
+
+ __u8 dlsap_sel; /* Destination LSAP/TSAP selector */
+ __u8 slsap_sel; /* Source LSAP/TSAP selector */
+
+ __u32 saddr; /* Source device address (link we are using) */
+ __u32 daddr; /* Destination device address */
+
+ int max_header_size; /* Header space we must reserve for each frame */
+ int max_data_size; /* The amount of data we can fill in each frame */
+
+ LOCAL_FLOW flow_status; /* Used by ircomm_lmp */
+ int pkt_count; /* Number of frames we have sent to IrLAP */
+
+ __u8 service_type;
+};
+
+extern hashbin_t *ircomm;
+
+struct ircomm_cb *ircomm_open(notify_t *notify, __u8 service_type, int line);
+int ircomm_close(struct ircomm_cb *self);
+
+int ircomm_data_request(struct ircomm_cb *self, struct sk_buff *skb);
+void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb);
+void ircomm_process_data(struct ircomm_cb *self, struct sk_buff *skb);
+int ircomm_control_request(struct ircomm_cb *self, struct sk_buff *skb);
+int ircomm_connect_request(struct ircomm_cb *self, __u8 dlsap_sel,
+ __u32 saddr, __u32 daddr, struct sk_buff *skb,
+ __u8 service_type);
+void ircomm_connect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+ struct ircomm_info *info);
+void ircomm_connect_confirm(struct ircomm_cb *self, struct sk_buff *skb,
+ struct ircomm_info *info);
+int ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata);
+int ircomm_disconnect_request(struct ircomm_cb *self, struct sk_buff *userdata);
+void ircomm_disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+ struct ircomm_info *info);
+void ircomm_flow_request(struct ircomm_cb *self, LOCAL_FLOW flow);
+
+#define ircomm_is_connected(self) (self->state == IRCOMM_CONN)
+
+#endif
diff --git a/include/net/irda/ircomm_event.h b/include/net/irda/ircomm_event.h
new file mode 100644
index 00000000..bc0c6f31
--- /dev/null
+++ b/include/net/irda/ircomm_event.h
@@ -0,0 +1,85 @@
+/*********************************************************************
+ *
+ * Filename: ircomm_event.h
+ * Version:
+ * Description:
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Sun Jun 6 23:51:13 1999
+ * Modified at: Thu Jun 10 08:36:25 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ********************************************************************/
+
+#ifndef IRCOMM_EVENT_H
+#define IRCOMM_EVENT_H
+
+#include <net/irda/irmod.h>
+
+typedef enum {
+ IRCOMM_IDLE,
+ IRCOMM_WAITI,
+ IRCOMM_WAITR,
+ IRCOMM_CONN,
+} IRCOMM_STATE;
+
+/* IrCOMM Events */
+typedef enum {
+ IRCOMM_CONNECT_REQUEST,
+ IRCOMM_CONNECT_RESPONSE,
+ IRCOMM_TTP_CONNECT_INDICATION,
+ IRCOMM_LMP_CONNECT_INDICATION,
+ IRCOMM_TTP_CONNECT_CONFIRM,
+ IRCOMM_LMP_CONNECT_CONFIRM,
+
+ IRCOMM_LMP_DISCONNECT_INDICATION,
+ IRCOMM_TTP_DISCONNECT_INDICATION,
+ IRCOMM_DISCONNECT_REQUEST,
+
+ IRCOMM_TTP_DATA_INDICATION,
+ IRCOMM_LMP_DATA_INDICATION,
+ IRCOMM_DATA_REQUEST,
+ IRCOMM_CONTROL_REQUEST,
+ IRCOMM_CONTROL_INDICATION,
+} IRCOMM_EVENT;
+
+/*
+ * Used for passing information through the state-machine
+ */
+struct ircomm_info {
+ __u32 saddr; /* Source device address */
+ __u32 daddr; /* Destination device address */
+ __u8 dlsap_sel;
+ LM_REASON reason; /* Reason for disconnect */
+ __u32 max_data_size;
+ __u32 max_header_size;
+
+ struct qos_info *qos;
+};
+
+extern const char *const ircomm_state[];
+
+struct ircomm_cb; /* Forward decl. */
+
+int ircomm_do_event(struct ircomm_cb *self, IRCOMM_EVENT event,
+ struct sk_buff *skb, struct ircomm_info *info);
+void ircomm_next_state(struct ircomm_cb *self, IRCOMM_STATE state);
+
+#endif
diff --git a/include/net/irda/ircomm_lmp.h b/include/net/irda/ircomm_lmp.h
new file mode 100644
index 00000000..ae02106b
--- /dev/null
+++ b/include/net/irda/ircomm_lmp.h
@@ -0,0 +1,38 @@
+/*********************************************************************
+ *
+ * Filename: ircomm_lmp.h
+ * Version:
+ * Description:
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Wed Jun 9 10:06:07 1999
+ * Modified at: Fri Aug 13 07:32:32 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ********************************************************************/
+
+#ifndef IRCOMM_LMP_H
+#define IRCOMM_LMP_H
+
+#include <net/irda/ircomm_core.h>
+
+int ircomm_open_lsap(struct ircomm_cb *self);
+
+#endif
diff --git a/include/net/irda/ircomm_param.h b/include/net/irda/ircomm_param.h
new file mode 100644
index 00000000..e6678800
--- /dev/null
+++ b/include/net/irda/ircomm_param.h
@@ -0,0 +1,149 @@
+/*********************************************************************
+ *
+ * Filename: ircomm_param.h
+ * Version: 1.0
+ * Description: Parameter handling for the IrCOMM protocol
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Mon Jun 7 08:47:28 1999
+ * Modified at: Wed Aug 25 13:46:33 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ********************************************************************/
+
+#ifndef IRCOMM_PARAMS_H
+#define IRCOMM_PARAMS_H
+
+#include <net/irda/parameters.h>
+
+/* Parameters common to all service types */
+#define IRCOMM_SERVICE_TYPE 0x00
+#define IRCOMM_PORT_TYPE 0x01 /* Only used in LM-IAS */
+#define IRCOMM_PORT_NAME 0x02 /* Only used in LM-IAS */
+
+/* Parameters for both 3 wire and 9 wire */
+#define IRCOMM_DATA_RATE 0x10
+#define IRCOMM_DATA_FORMAT 0x11
+#define IRCOMM_FLOW_CONTROL 0x12
+#define IRCOMM_XON_XOFF 0x13
+#define IRCOMM_ENQ_ACK 0x14
+#define IRCOMM_LINE_STATUS 0x15
+#define IRCOMM_BREAK 0x16
+
+/* Parameters for 9 wire */
+#define IRCOMM_DTE 0x20
+#define IRCOMM_DCE 0x21
+#define IRCOMM_POLL 0x22
+
+/* Service type (details) */
+#define IRCOMM_3_WIRE_RAW 0x01
+#define IRCOMM_3_WIRE 0x02
+#define IRCOMM_9_WIRE 0x04
+#define IRCOMM_CENTRONICS 0x08
+
+/* Port type (details) */
+#define IRCOMM_SERIAL 0x00
+#define IRCOMM_PARALLEL 0x01
+
+/* Data format (details) */
+#define IRCOMM_WSIZE_5 0x00
+#define IRCOMM_WSIZE_6 0x01
+#define IRCOMM_WSIZE_7 0x02
+#define IRCOMM_WSIZE_8 0x03
+
+#define IRCOMM_1_STOP_BIT 0x00
+#define IRCOMM_2_STOP_BIT 0x04 /* 1.5 if char len 5 */
+
+#define IRCOMM_PARITY_DISABLE 0x00
+#define IRCOMM_PARITY_ENABLE 0x08
+
+#define IRCOMM_PARITY_ODD 0x00
+#define IRCOMM_PARITY_EVEN 0x10
+#define IRCOMM_PARITY_MARK 0x20
+#define IRCOMM_PARITY_SPACE 0x30
+
+/* Flow control */
+#define IRCOMM_XON_XOFF_IN 0x01
+#define IRCOMM_XON_XOFF_OUT 0x02
+#define IRCOMM_RTS_CTS_IN 0x04
+#define IRCOMM_RTS_CTS_OUT 0x08
+#define IRCOMM_DSR_DTR_IN 0x10
+#define IRCOMM_DSR_DTR_OUT 0x20
+#define IRCOMM_ENQ_ACK_IN 0x40
+#define IRCOMM_ENQ_ACK_OUT 0x80
+
+/* Line status */
+#define IRCOMM_OVERRUN_ERROR 0x02
+#define IRCOMM_PARITY_ERROR 0x04
+#define IRCOMM_FRAMING_ERROR 0x08
+
+/* DTE (Data terminal equipment) line settings */
+#define IRCOMM_DELTA_DTR 0x01
+#define IRCOMM_DELTA_RTS 0x02
+#define IRCOMM_DTR 0x04
+#define IRCOMM_RTS 0x08
+
+/* DCE (Data communications equipment) line settings */
+#define IRCOMM_DELTA_CTS 0x01 /* Clear to send has changed */
+#define IRCOMM_DELTA_DSR 0x02 /* Data set ready has changed */
+#define IRCOMM_DELTA_RI 0x04 /* Ring indicator has changed */
+#define IRCOMM_DELTA_CD 0x08 /* Carrier detect has changed */
+#define IRCOMM_CTS 0x10 /* Clear to send is high */
+#define IRCOMM_DSR 0x20 /* Data set ready is high */
+#define IRCOMM_RI 0x40 /* Ring indicator is high */
+#define IRCOMM_CD 0x80 /* Carrier detect is high */
+#define IRCOMM_DCE_DELTA_ANY 0x0f
+
+/*
+ * Parameter state
+ */
+struct ircomm_params {
+ /* General control params */
+ __u8 service_type;
+ __u8 port_type;
+ char port_name[32];
+
+ /* Control params for 3- and 9-wire service type */
+ __u32 data_rate; /* Data rate in bps */
+ __u8 data_format;
+ __u8 flow_control;
+ char xonxoff[2];
+ char enqack[2];
+ __u8 line_status;
+ __u8 _break;
+
+ __u8 null_modem;
+
+ /* Control params for 9-wire service type */
+ __u8 dte;
+ __u8 dce;
+ __u8 poll;
+
+ /* Control params for Centronics service type */
+};
+
+struct ircomm_tty_cb; /* Forward decl. */
+
+int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush);
+
+extern pi_param_info_t ircomm_param_info;
+
+#endif /* IRCOMM_PARAMS_H */
+
diff --git a/include/net/irda/ircomm_ttp.h b/include/net/irda/ircomm_ttp.h
new file mode 100644
index 00000000..403081ed
--- /dev/null
+++ b/include/net/irda/ircomm_ttp.h
@@ -0,0 +1,39 @@
+/*********************************************************************
+ *
+ * Filename: ircomm_ttp.h
+ * Version:
+ * Description:
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Wed Jun 9 10:06:07 1999
+ * Modified at: Fri Aug 13 07:32:22 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ********************************************************************/
+
+#ifndef IRCOMM_TTP_H
+#define IRCOMM_TTP_H
+
+#include <net/irda/ircomm_core.h>
+
+int ircomm_open_tsap(struct ircomm_cb *self);
+
+#endif
+
diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h
new file mode 100644
index 00000000..59ba38bc
--- /dev/null
+++ b/include/net/irda/ircomm_tty.h
@@ -0,0 +1,138 @@
+/*********************************************************************
+ *
+ * Filename: ircomm_tty.h
+ * Version:
+ * Description:
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Sun Jun 6 23:24:22 1999
+ * Modified at: Fri Jan 28 13:16:57 2000
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ********************************************************************/
+
+#ifndef IRCOMM_TTY_H
+#define IRCOMM_TTY_H
+
+#include <linux/serial.h>
+#include <linux/termios.h>
+#include <linux/timer.h>
+#include <linux/tty.h> /* struct tty_struct */
+
+#include <net/irda/irias_object.h>
+#include <net/irda/ircomm_core.h>
+#include <net/irda/ircomm_param.h>
+
+#define IRCOMM_TTY_PORTS 32
+#define IRCOMM_TTY_MAGIC 0x3432
+#define IRCOMM_TTY_MAJOR 161
+#define IRCOMM_TTY_MINOR 0
+
+/* This is used as an initial value to max_header_size before the proper
+ * value is filled in (5 for ttp, 4 for lmp). This allow us to detect
+ * the state of the underlying connection. - Jean II */
+#define IRCOMM_TTY_HDR_UNINITIALISED 16
+/* Same for payload size. See qos.c for the smallest max data size */
+#define IRCOMM_TTY_DATA_UNINITIALISED (64 - IRCOMM_TTY_HDR_UNINITIALISED)
+
+/* Those are really defined in include/linux/serial.h - Jean II */
+#define ASYNC_B_INITIALIZED 31 /* Serial port was initialized */
+#define ASYNC_B_NORMAL_ACTIVE 29 /* Normal device is active */
+#define ASYNC_B_CLOSING 27 /* Serial port is closing */
+
+/*
+ * IrCOMM TTY driver state
+ */
+struct ircomm_tty_cb {
+ irda_queue_t queue; /* Must be first */
+ magic_t magic;
+
+ int state; /* Connect state */
+
+ struct tty_struct *tty;
+ struct ircomm_cb *ircomm; /* IrCOMM layer instance */
+
+ struct sk_buff *tx_skb; /* Transmit buffer */
+ struct sk_buff *ctrl_skb; /* Control data buffer */
+
+ /* Parameters */
+ struct ircomm_params settings;
+
+ __u8 service_type; /* The service that we support */
+ int client; /* True if we are a client */
+ LOCAL_FLOW flow; /* IrTTP flow status */
+
+ int line;
+ unsigned long flags;
+
+ __u8 dlsap_sel;
+ __u8 slsap_sel;
+
+ __u32 saddr;
+ __u32 daddr;
+
+ __u32 max_data_size; /* Max data we can transmit in one packet */
+ __u32 max_header_size; /* The amount of header space we must reserve */
+ __u32 tx_data_size; /* Max data size of current tx_skb */
+
+ struct iriap_cb *iriap; /* Instance used for querying remote IAS */
+ struct ias_object* obj;
+ void *skey;
+ void *ckey;
+
+ wait_queue_head_t open_wait;
+ wait_queue_head_t close_wait;
+ struct timer_list watchdog_timer;
+ struct work_struct tqueue;
+
+ unsigned short close_delay;
+ unsigned short closing_wait; /* time to wait before closing */
+
+ int open_count;
+ int blocked_open; /* # of blocked opens */
+
+ /* Protect concurent access to :
+ * o self->open_count
+ * o self->ctrl_skb
+ * o self->tx_skb
+ * Maybe other things may gain to be protected as well...
+ * Jean II */
+ spinlock_t spinlock;
+};
+
+void ircomm_tty_start(struct tty_struct *tty);
+void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self);
+
+extern int ircomm_tty_tiocmget(struct tty_struct *tty);
+extern int ircomm_tty_tiocmset(struct tty_struct *tty,
+ unsigned int set, unsigned int clear);
+extern int ircomm_tty_ioctl(struct tty_struct *tty,
+ unsigned int cmd, unsigned long arg);
+extern void ircomm_tty_set_termios(struct tty_struct *tty,
+ struct ktermios *old_termios);
+
+#endif
+
+
+
+
+
+
+
diff --git a/include/net/irda/ircomm_tty_attach.h b/include/net/irda/ircomm_tty_attach.h
new file mode 100644
index 00000000..0a63bbb9
--- /dev/null
+++ b/include/net/irda/ircomm_tty_attach.h
@@ -0,0 +1,94 @@
+/*********************************************************************
+ *
+ * Filename: ircomm_tty_attach.h
+ * Version:
+ * Description:
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Wed Jun 9 15:55:18 1999
+ * Modified at: Fri Dec 10 21:04:55 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ********************************************************************/
+
+#ifndef IRCOMM_TTY_ATTACH_H
+#define IRCOMM_TTY_ATTACH_H
+
+#include <net/irda/ircomm_tty.h>
+
+typedef enum {
+ IRCOMM_TTY_IDLE,
+ IRCOMM_TTY_SEARCH,
+ IRCOMM_TTY_QUERY_PARAMETERS,
+ IRCOMM_TTY_QUERY_LSAP_SEL,
+ IRCOMM_TTY_SETUP,
+ IRCOMM_TTY_READY,
+} IRCOMM_TTY_STATE;
+
+/* IrCOMM TTY Events */
+typedef enum {
+ IRCOMM_TTY_ATTACH_CABLE,
+ IRCOMM_TTY_DETACH_CABLE,
+ IRCOMM_TTY_DATA_REQUEST,
+ IRCOMM_TTY_DATA_INDICATION,
+ IRCOMM_TTY_DISCOVERY_REQUEST,
+ IRCOMM_TTY_DISCOVERY_INDICATION,
+ IRCOMM_TTY_CONNECT_CONFIRM,
+ IRCOMM_TTY_CONNECT_INDICATION,
+ IRCOMM_TTY_DISCONNECT_REQUEST,
+ IRCOMM_TTY_DISCONNECT_INDICATION,
+ IRCOMM_TTY_WD_TIMER_EXPIRED,
+ IRCOMM_TTY_GOT_PARAMETERS,
+ IRCOMM_TTY_GOT_LSAPSEL,
+} IRCOMM_TTY_EVENT;
+
+/* Used for passing information through the state-machine */
+struct ircomm_tty_info {
+ __u32 saddr; /* Source device address */
+ __u32 daddr; /* Destination device address */
+ __u8 dlsap_sel;
+};
+
+extern const char *const ircomm_state[];
+extern const char *const ircomm_tty_state[];
+
+int ircomm_tty_do_event(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
+ struct sk_buff *skb, struct ircomm_tty_info *info);
+
+
+int ircomm_tty_attach_cable(struct ircomm_tty_cb *self);
+void ircomm_tty_detach_cable(struct ircomm_tty_cb *self);
+void ircomm_tty_connect_confirm(void *instance, void *sap,
+ struct qos_info *qos,
+ __u32 max_sdu_size,
+ __u8 max_header_size,
+ struct sk_buff *skb);
+void ircomm_tty_disconnect_indication(void *instance, void *sap,
+ LM_REASON reason,
+ struct sk_buff *skb);
+void ircomm_tty_connect_indication(void *instance, void *sap,
+ struct qos_info *qos,
+ __u32 max_sdu_size,
+ __u8 max_header_size,
+ struct sk_buff *skb);
+int ircomm_tty_send_initial_parameters(struct ircomm_tty_cb *self);
+void ircomm_tty_link_established(struct ircomm_tty_cb *self);
+
+#endif /* IRCOMM_TTY_ATTACH_H */
diff --git a/include/net/irda/irda.h b/include/net/irda/irda.h
new file mode 100644
index 00000000..3bed61d3
--- /dev/null
+++ b/include/net/irda/irda.h
@@ -0,0 +1,131 @@
+/*********************************************************************
+ *
+ * Filename: irda.h
+ * Version: 1.0
+ * Description: IrDA common include file for kernel internal use
+ * Status: Stable
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Tue Dec 9 21:13:12 1997
+ * Modified at: Fri Jan 28 13:16:32 2000
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998-2000 Dag Brattli, All Rights Reserved.
+ * Copyright (c) 2000-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef NET_IRDA_H
+#define NET_IRDA_H
+
+#include <linux/skbuff.h> /* struct sk_buff */
+#include <linux/kernel.h>
+#include <linux/if.h> /* sa_family_t in <linux/irda.h> */
+#include <linux/irda.h>
+
+typedef __u32 magic_t;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/* Hack to do small backoff when setting media busy in IrLAP */
+#ifndef SMALL
+#define SMALL 5
+#endif
+
+#ifndef IRDA_MIN /* Lets not mix this MIN with other header files */
+#define IRDA_MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef IRDA_ALIGN
+# define IRDA_ALIGN __attribute__((aligned))
+#endif
+
+#ifdef CONFIG_IRDA_DEBUG
+
+extern unsigned int irda_debug;
+
+/* use 0 for production, 1 for verification, >2 for debug */
+#define IRDA_DEBUG_LEVEL 0
+
+#define IRDA_DEBUG(n, args...) \
+do { if (irda_debug >= (n)) \
+ printk(KERN_DEBUG args); \
+} while (0)
+#define IRDA_ASSERT(expr, func) \
+do { if(!(expr)) { \
+ printk( "Assertion failed! %s:%s:%d %s\n", \
+ __FILE__,__func__,__LINE__,(#expr) ); \
+ func } } while (0)
+#define IRDA_ASSERT_LABEL(label) label
+#else
+#define IRDA_DEBUG(n, args...) do { } while (0)
+#define IRDA_ASSERT(expr, func) do { (void)(expr); } while (0)
+#define IRDA_ASSERT_LABEL(label)
+#endif /* CONFIG_IRDA_DEBUG */
+
+#define IRDA_WARNING(args...) do { if (net_ratelimit()) printk(KERN_WARNING args); } while (0)
+#define IRDA_MESSAGE(args...) do { if (net_ratelimit()) printk(KERN_INFO args); } while (0)
+#define IRDA_ERROR(args...) do { if (net_ratelimit()) printk(KERN_ERR args); } while (0)
+
+/*
+ * Magic numbers used by Linux-IrDA. Random numbers which must be unique to
+ * give the best protection
+ */
+
+#define IRTTY_MAGIC 0x2357
+#define LAP_MAGIC 0x1357
+#define LMP_MAGIC 0x4321
+#define LMP_LSAP_MAGIC 0x69333
+#define LMP_LAP_MAGIC 0x3432
+#define IRDA_DEVICE_MAGIC 0x63454
+#define IAS_MAGIC 0x007
+#define TTP_MAGIC 0x241169
+#define TTP_TSAP_MAGIC 0x4345
+#define IROBEX_MAGIC 0x341324
+#define HB_MAGIC 0x64534
+#define IRLAN_MAGIC 0x754
+#define IAS_OBJECT_MAGIC 0x34234
+#define IAS_ATTRIB_MAGIC 0x45232
+#define IRDA_TASK_MAGIC 0x38423
+
+#define IAS_DEVICE_ID 0x0000 /* Defined by IrDA, IrLMP section 4.1 (page 68) */
+#define IAS_PNP_ID 0xd342
+#define IAS_OBEX_ID 0x34323
+#define IAS_IRLAN_ID 0x34234
+#define IAS_IRCOMM_ID 0x2343
+#define IAS_IRLPT_ID 0x9876
+
+struct net_device;
+struct packet_type;
+
+extern void irda_proc_register(void);
+extern void irda_proc_unregister(void);
+
+extern int irda_sysctl_register(void);
+extern void irda_sysctl_unregister(void);
+
+extern int irsock_init(void);
+extern void irsock_cleanup(void);
+
+extern int irda_nl_register(void);
+extern void irda_nl_unregister(void);
+
+extern int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *ptype,
+ struct net_device *orig_dev);
+
+#endif /* NET_IRDA_H */
diff --git a/include/net/irda/irda_device.h b/include/net/irda/irda_device.h
new file mode 100644
index 00000000..94c852d4
--- /dev/null
+++ b/include/net/irda/irda_device.h
@@ -0,0 +1,287 @@
+/*********************************************************************
+ *
+ * Filename: irda_device.h
+ * Version: 0.9
+ * Description: Contains various declarations used by the drivers
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Tue Apr 14 12:41:42 1998
+ * Modified at: Mon Mar 20 09:08:57 2000
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
+ * Copyright (c) 1998 Thomas Davis, <ratbert@radiks.net>,
+ * Copyright (c) 2000-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ********************************************************************/
+
+/*
+ * This header contains all the IrDA definitions a driver really
+ * needs, and therefore the driver should not need to include
+ * any other IrDA headers - Jean II
+ */
+
+#ifndef IRDA_DEVICE_H
+#define IRDA_DEVICE_H
+
+#include <linux/tty.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.h> /* struct sk_buff */
+#include <linux/irda.h>
+#include <linux/types.h>
+
+#include <net/pkt_sched.h>
+#include <net/irda/irda.h>
+#include <net/irda/qos.h> /* struct qos_info */
+#include <net/irda/irqueue.h> /* irda_queue_t */
+
+/* A few forward declarations (to make compiler happy) */
+struct irlap_cb;
+
+/* Some non-standard interface flags (should not conflict with any in if.h) */
+#define IFF_SIR 0x0001 /* Supports SIR speeds */
+#define IFF_MIR 0x0002 /* Supports MIR speeds */
+#define IFF_FIR 0x0004 /* Supports FIR speeds */
+#define IFF_VFIR 0x0008 /* Supports VFIR speeds */
+#define IFF_PIO 0x0010 /* Supports PIO transfer of data */
+#define IFF_DMA 0x0020 /* Supports DMA transfer of data */
+#define IFF_SHM 0x0040 /* Supports shared memory data transfers */
+#define IFF_DONGLE 0x0080 /* Interface has a dongle attached */
+#define IFF_AIR 0x0100 /* Supports Advanced IR (AIR) standards */
+
+#define IO_XMIT 0x01
+#define IO_RECV 0x02
+
+typedef enum {
+ IRDA_IRLAP, /* IrDA mode, and deliver to IrLAP */
+ IRDA_RAW, /* IrDA mode */
+ SHARP_ASK,
+ TV_REMOTE, /* Also known as Consumer Electronics IR */
+} INFRARED_MODE;
+
+typedef enum {
+ IRDA_TASK_INIT, /* All tasks are initialized with this state */
+ IRDA_TASK_DONE, /* Signals that the task is finished */
+ IRDA_TASK_WAIT,
+ IRDA_TASK_WAIT1,
+ IRDA_TASK_WAIT2,
+ IRDA_TASK_WAIT3,
+ IRDA_TASK_CHILD_INIT, /* Initializing child task */
+ IRDA_TASK_CHILD_WAIT, /* Waiting for child task to finish */
+ IRDA_TASK_CHILD_DONE /* Child task is finished */
+} IRDA_TASK_STATE;
+
+struct irda_task;
+typedef int (*IRDA_TASK_CALLBACK) (struct irda_task *task);
+
+struct irda_task {
+ irda_queue_t q;
+ magic_t magic;
+
+ IRDA_TASK_STATE state;
+ IRDA_TASK_CALLBACK function;
+ IRDA_TASK_CALLBACK finished;
+
+ struct irda_task *parent;
+ struct timer_list timer;
+
+ void *instance; /* Instance being called */
+ void *param; /* Parameter to be used by instance */
+};
+
+/* Dongle info */
+struct dongle_reg;
+typedef struct {
+ struct dongle_reg *issue; /* Registration info */
+ struct net_device *dev; /* Device we are attached to */
+ struct irda_task *speed_task; /* Task handling speed change */
+ struct irda_task *reset_task; /* Task handling reset */
+ __u32 speed; /* Current speed */
+
+ /* Callbacks to the IrDA device driver */
+ int (*set_mode)(struct net_device *, int mode);
+ int (*read)(struct net_device *dev, __u8 *buf, int len);
+ int (*write)(struct net_device *dev, __u8 *buf, int len);
+ int (*set_dtr_rts)(struct net_device *dev, int dtr, int rts);
+} dongle_t;
+
+/* Dongle registration info */
+struct dongle_reg {
+ irda_queue_t q; /* Must be first */
+ IRDA_DONGLE type;
+
+ void (*open)(dongle_t *dongle, struct qos_info *qos);
+ void (*close)(dongle_t *dongle);
+ int (*reset)(struct irda_task *task);
+ int (*change_speed)(struct irda_task *task);
+ struct module *owner;
+};
+
+/*
+ * Per-packet information we need to hide inside sk_buff
+ * (must not exceed 48 bytes, check with struct sk_buff)
+ * The default_qdisc_pad field is a temporary hack.
+ */
+struct irda_skb_cb {
+ unsigned int default_qdisc_pad;
+ magic_t magic; /* Be sure that we can trust the information */
+ __u32 next_speed; /* The Speed to be set *after* this frame */
+ __u16 mtt; /* Minimum turn around time */
+ __u16 xbofs; /* Number of xbofs required, used by SIR mode */
+ __u16 next_xbofs; /* Number of xbofs required *after* this frame */
+ void *context; /* May be used by drivers */
+ void (*destructor)(struct sk_buff *skb); /* Used for flow control */
+ __u16 xbofs_delay; /* Number of xbofs used for generating the mtt */
+ __u8 line; /* Used by IrCOMM in IrLPT mode */
+};
+
+/* Chip specific info */
+typedef struct {
+ int cfg_base; /* Config register IO base */
+ int sir_base; /* SIR IO base */
+ int fir_base; /* FIR IO base */
+ int mem_base; /* Shared memory base */
+ int sir_ext; /* Length of SIR iobase */
+ int fir_ext; /* Length of FIR iobase */
+ int irq, irq2; /* Interrupts used */
+ int dma, dma2; /* DMA channel(s) used */
+ int fifo_size; /* FIFO size */
+ int irqflags; /* interrupt flags (ie, IRQF_SHARED|IRQF_DISABLED) */
+ int direction; /* Link direction, used by some FIR drivers */
+ int enabled; /* Powered on? */
+ int suspended; /* Suspended by APM */
+ __u32 speed; /* Currently used speed */
+ __u32 new_speed; /* Speed we must change to when Tx is finished */
+ int dongle_id; /* Dongle or transceiver currently used */
+} chipio_t;
+
+/* IO buffer specific info (inspired by struct sk_buff) */
+typedef struct {
+ int state; /* Receiving state (transmit state not used) */
+ int in_frame; /* True if receiving frame */
+
+ __u8 *head; /* start of buffer */
+ __u8 *data; /* start of data in buffer */
+
+ int len; /* current length of data */
+ int truesize; /* total allocated size of buffer */
+ __u16 fcs;
+
+ struct sk_buff *skb; /* ZeroCopy Rx in async_unwrap_char() */
+} iobuff_t;
+
+/* Maximum SIR frame (skb) that we expect to receive *unwrapped*.
+ * Max LAP MTU (I field) is 2048 bytes max (IrLAP 1.1, chapt 6.6.5, p40).
+ * Max LAP header is 2 bytes (for now).
+ * Max CRC is 2 bytes at SIR, 4 bytes at FIR.
+ * Need 1 byte for skb_reserve() to align IP header for IrLAN.
+ * Add a few extra bytes just to be safe (buffer is power of two anyway)
+ * Jean II */
+#define IRDA_SKB_MAX_MTU 2064
+/* Maximum SIR frame that we expect to send, wrapped (i.e. with XBOFS
+ * and escaped characters on top of above). */
+#define IRDA_SIR_MAX_FRAME 4269
+
+/* The SIR unwrapper async_unwrap_char() will use a Rx-copy-break mechanism
+ * when using the optional ZeroCopy Rx, where only small frames are memcpy
+ * to a smaller skb to save memory. This is the threshold under which copy
+ * will happen (and over which it won't happen).
+ * Some FIR drivers may use this #define as well...
+ * This is the same value as various Ethernet drivers. - Jean II */
+#define IRDA_RX_COPY_THRESHOLD 256
+
+/* Function prototypes */
+int irda_device_init(void);
+void irda_device_cleanup(void);
+
+/* IrLAP entry points used by the drivers.
+ * We declare them here to avoid the driver pulling a whole bunch stack
+ * headers they don't really need - Jean II */
+struct irlap_cb *irlap_open(struct net_device *dev, struct qos_info *qos,
+ const char *hw_name);
+void irlap_close(struct irlap_cb *self);
+
+/* Interface to be uses by IrLAP */
+void irda_device_set_media_busy(struct net_device *dev, int status);
+int irda_device_is_media_busy(struct net_device *dev);
+int irda_device_is_receiving(struct net_device *dev);
+
+/* Interface for internal use */
+static inline int irda_device_txqueue_empty(const struct net_device *dev)
+{
+ return qdisc_all_tx_empty(dev);
+}
+int irda_device_set_raw_mode(struct net_device* self, int status);
+struct net_device *alloc_irdadev(int sizeof_priv);
+
+void irda_setup_dma(int channel, dma_addr_t buffer, int count, int mode);
+
+/*
+ * Function irda_get_mtt (skb)
+ *
+ * Utility function for getting the minimum turnaround time out of
+ * the skb, where it has been hidden in the cb field.
+ */
+static inline __u16 irda_get_mtt(const struct sk_buff *skb)
+{
+ const struct irda_skb_cb *cb = (const struct irda_skb_cb *) skb->cb;
+ return (cb->magic == LAP_MAGIC) ? cb->mtt : 10000;
+}
+
+/*
+ * Function irda_get_next_speed (skb)
+ *
+ * Extract the speed that should be set *after* this frame from the skb
+ *
+ * Note : return -1 for user space frames
+ */
+static inline __u32 irda_get_next_speed(const struct sk_buff *skb)
+{
+ const struct irda_skb_cb *cb = (const struct irda_skb_cb *) skb->cb;
+ return (cb->magic == LAP_MAGIC) ? cb->next_speed : -1;
+}
+
+/*
+ * Function irda_get_next_xbofs (skb)
+ *
+ * Extract the xbofs that should be set for this frame from the skb
+ *
+ * Note : default to 10 for user space frames
+ */
+static inline __u16 irda_get_xbofs(const struct sk_buff *skb)
+{
+ const struct irda_skb_cb *cb = (const struct irda_skb_cb *) skb->cb;
+ return (cb->magic == LAP_MAGIC) ? cb->xbofs : 10;
+}
+
+/*
+ * Function irda_get_next_xbofs (skb)
+ *
+ * Extract the xbofs that should be set *after* this frame from the skb
+ *
+ * Note : return -1 for user space frames
+ */
+static inline __u16 irda_get_next_xbofs(const struct sk_buff *skb)
+{
+ const struct irda_skb_cb *cb = (const struct irda_skb_cb *) skb->cb;
+ return (cb->magic == LAP_MAGIC) ? cb->next_xbofs : -1;
+}
+#endif /* IRDA_DEVICE_H */
+
+
diff --git a/include/net/irda/iriap.h b/include/net/irda/iriap.h
new file mode 100644
index 00000000..fcc89649
--- /dev/null
+++ b/include/net/irda/iriap.h
@@ -0,0 +1,108 @@
+/*********************************************************************
+ *
+ * Filename: iriap.h
+ * Version: 0.5
+ * Description: Information Access Protocol (IAP)
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Thu Aug 21 00:02:07 1997
+ * Modified at: Sat Dec 25 16:42:09 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1997-1999 Dag Brattli <dagb@cs.uit.no>,
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef IRIAP_H
+#define IRIAP_H
+
+#include <linux/types.h>
+#include <linux/skbuff.h>
+
+#include <net/irda/iriap_event.h>
+#include <net/irda/irias_object.h>
+#include <net/irda/irqueue.h> /* irda_queue_t */
+#include <net/irda/timer.h> /* struct timer_list */
+
+#define IAP_LST 0x80
+#define IAP_ACK 0x40
+
+#define IAS_SERVER 0
+#define IAS_CLIENT 1
+
+/* IrIAP Op-codes */
+#define GET_INFO_BASE 0x01
+#define GET_OBJECTS 0x02
+#define GET_VALUE 0x03
+#define GET_VALUE_BY_CLASS 0x04
+#define GET_OBJECT_INFO 0x05
+#define GET_ATTRIB_NAMES 0x06
+
+#define IAS_SUCCESS 0
+#define IAS_CLASS_UNKNOWN 1
+#define IAS_ATTRIB_UNKNOWN 2
+#define IAS_DISCONNECT 10
+
+typedef void (*CONFIRM_CALLBACK)(int result, __u16 obj_id,
+ struct ias_value *value, void *priv);
+
+struct iriap_cb {
+ irda_queue_t q; /* Must be first */
+ magic_t magic; /* Magic cookie */
+
+ int mode; /* Client or server */
+
+ __u32 saddr;
+ __u32 daddr;
+ __u8 operation;
+
+ struct sk_buff *request_skb;
+ struct lsap_cb *lsap;
+ __u8 slsap_sel;
+
+ /* Client states */
+ IRIAP_STATE client_state;
+ IRIAP_STATE call_state;
+
+ /* Server states */
+ IRIAP_STATE server_state;
+ IRIAP_STATE r_connect_state;
+
+ CONFIRM_CALLBACK confirm;
+ void *priv; /* Used to identify client */
+
+ __u8 max_header_size;
+ __u32 max_data_size;
+
+ struct timer_list watchdog_timer;
+};
+
+int iriap_init(void);
+void iriap_cleanup(void);
+
+struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv,
+ CONFIRM_CALLBACK callback);
+void iriap_close(struct iriap_cb *self);
+
+int iriap_getvaluebyclass_request(struct iriap_cb *self,
+ __u32 saddr, __u32 daddr,
+ char *name, char *attr);
+void iriap_connect_request(struct iriap_cb *self);
+void iriap_send_ack( struct iriap_cb *self);
+void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb);
+
+void iriap_register_server(void);
+
+#endif
+
+
diff --git a/include/net/irda/iriap_event.h b/include/net/irda/iriap_event.h
new file mode 100644
index 00000000..89747f06
--- /dev/null
+++ b/include/net/irda/iriap_event.h
@@ -0,0 +1,85 @@
+/*********************************************************************
+ *
+ * Filename: iriap_event.h
+ * Version:
+ * Description:
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Mon Aug 4 20:40:53 1997
+ * Modified at: Sun Oct 31 22:02:54 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef IRIAP_FSM_H
+#define IRIAP_FSM_H
+
+/* Forward because of circular include dependecies */
+struct iriap_cb;
+
+/* IrIAP states */
+typedef enum {
+ /* Client */
+ S_DISCONNECT,
+ S_CONNECTING,
+ S_CALL,
+
+ /* S-Call */
+ S_MAKE_CALL,
+ S_CALLING,
+ S_OUTSTANDING,
+ S_REPLYING,
+ S_WAIT_FOR_CALL,
+ S_WAIT_ACTIVE,
+
+ /* Server */
+ R_DISCONNECT,
+ R_CALL,
+
+ /* R-Connect */
+ R_WAITING,
+ R_WAIT_ACTIVE,
+ R_RECEIVING,
+ R_EXECUTE,
+ R_RETURNING,
+} IRIAP_STATE;
+
+typedef enum {
+ IAP_CALL_REQUEST,
+ IAP_CALL_REQUEST_GVBC,
+ IAP_CALL_RESPONSE,
+ IAP_RECV_F_LST,
+ IAP_LM_DISCONNECT_INDICATION,
+ IAP_LM_CONNECT_INDICATION,
+ IAP_LM_CONNECT_CONFIRM,
+} IRIAP_EVENT;
+
+void iriap_next_client_state (struct iriap_cb *self, IRIAP_STATE state);
+void iriap_next_call_state (struct iriap_cb *self, IRIAP_STATE state);
+void iriap_next_server_state (struct iriap_cb *self, IRIAP_STATE state);
+void iriap_next_r_connect_state(struct iriap_cb *self, IRIAP_STATE state);
+
+
+void iriap_do_client_event(struct iriap_cb *self, IRIAP_EVENT event,
+ struct sk_buff *skb);
+void iriap_do_call_event (struct iriap_cb *self, IRIAP_EVENT event,
+ struct sk_buff *skb);
+
+void iriap_do_server_event (struct iriap_cb *self, IRIAP_EVENT event,
+ struct sk_buff *skb);
+void iriap_do_r_connect_event(struct iriap_cb *self, IRIAP_EVENT event,
+ struct sk_buff *skb);
+
+#endif /* IRIAP_FSM_H */
+
diff --git a/include/net/irda/irias_object.h b/include/net/irda/irias_object.h
new file mode 100644
index 00000000..83f78081
--- /dev/null
+++ b/include/net/irda/irias_object.h
@@ -0,0 +1,108 @@
+/*********************************************************************
+ *
+ * Filename: irias_object.h
+ * Version:
+ * Description:
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Thu Oct 1 22:49:50 1998
+ * Modified at: Wed Dec 15 11:20:57 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef LM_IAS_OBJECT_H
+#define LM_IAS_OBJECT_H
+
+#include <net/irda/irda.h>
+#include <net/irda/irqueue.h>
+
+/* LM-IAS Attribute types */
+#define IAS_MISSING 0
+#define IAS_INTEGER 1
+#define IAS_OCT_SEQ 2
+#define IAS_STRING 3
+
+/* Object ownership of attributes (user or kernel) */
+#define IAS_KERNEL_ATTR 0
+#define IAS_USER_ATTR 1
+
+/*
+ * LM-IAS Object
+ */
+struct ias_object {
+ irda_queue_t q; /* Must be first! */
+ magic_t magic;
+
+ char *name;
+ int id;
+ hashbin_t *attribs;
+};
+
+/*
+ * Values used by LM-IAS attributes
+ */
+struct ias_value {
+ __u8 type; /* Value description */
+ __u8 owner; /* Managed from user/kernel space */
+ int charset; /* Only used by string type */
+ int len;
+
+ /* Value */
+ union {
+ int integer;
+ char *string;
+ __u8 *oct_seq;
+ } t;
+};
+
+/*
+ * Attributes used by LM-IAS objects
+ */
+struct ias_attrib {
+ irda_queue_t q; /* Must be first! */
+ int magic;
+
+ char *name; /* Attribute name */
+ struct ias_value *value; /* Attribute value */
+};
+
+struct ias_object *irias_new_object(char *name, int id);
+void irias_insert_object(struct ias_object *obj);
+int irias_delete_object(struct ias_object *obj);
+int irias_delete_attrib(struct ias_object *obj, struct ias_attrib *attrib,
+ int cleanobject);
+void __irias_delete_object(struct ias_object *obj);
+
+void irias_add_integer_attrib(struct ias_object *obj, char *name, int value,
+ int user);
+void irias_add_string_attrib(struct ias_object *obj, char *name, char *value,
+ int user);
+void irias_add_octseq_attrib(struct ias_object *obj, char *name, __u8 *octets,
+ int len, int user);
+int irias_object_change_attribute(char *obj_name, char *attrib_name,
+ struct ias_value *new_value);
+struct ias_object *irias_find_object(char *name);
+struct ias_attrib *irias_find_attrib(struct ias_object *obj, char *name);
+
+struct ias_value *irias_new_string_value(char *string);
+struct ias_value *irias_new_integer_value(int integer);
+struct ias_value *irias_new_octseq_value(__u8 *octseq , int len);
+struct ias_value *irias_new_missing_value(void);
+void irias_delete_value(struct ias_value *value);
+
+extern struct ias_value irias_missing;
+extern hashbin_t *irias_objects;
+
+#endif
diff --git a/include/net/irda/irlan_client.h b/include/net/irda/irlan_client.h
new file mode 100644
index 00000000..fa8455ed
--- /dev/null
+++ b/include/net/irda/irlan_client.h
@@ -0,0 +1,42 @@
+/*********************************************************************
+ *
+ * Filename: irlan_client.h
+ * Version: 0.3
+ * Description: IrDA LAN access layer
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Sun Aug 31 20:14:37 1997
+ * Modified at: Thu Apr 22 14:13:34 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef IRLAN_CLIENT_H
+#define IRLAN_CLIENT_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+#include <net/irda/irias_object.h>
+#include <net/irda/irlan_event.h>
+
+void irlan_client_discovery_indication(discinfo_t *, DISCOVERY_MODE, void *);
+void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr);
+
+void irlan_client_parse_response(struct irlan_cb *self, struct sk_buff *skb);
+void irlan_client_get_value_confirm(int result, __u16 obj_id,
+ struct ias_value *value, void *priv);
+#endif
diff --git a/include/net/irda/irlan_common.h b/include/net/irda/irlan_common.h
new file mode 100644
index 00000000..0af8b8df
--- /dev/null
+++ b/include/net/irda/irlan_common.h
@@ -0,0 +1,229 @@
+/*********************************************************************
+ *
+ * Filename: irlan_common.h
+ * Version: 0.8
+ * Description: IrDA LAN access layer
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Sun Aug 31 20:14:37 1997
+ * Modified at: Sun Oct 31 19:41:24 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef IRLAN_H
+#define IRLAN_H
+
+#include <asm/param.h> /* for HZ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+#include <net/irda/irttp.h>
+
+#define IRLAN_MTU 1518
+#define IRLAN_TIMEOUT 10*HZ /* 10 seconds */
+
+/* Command packet types */
+#define CMD_GET_PROVIDER_INFO 0
+#define CMD_GET_MEDIA_CHAR 1
+#define CMD_OPEN_DATA_CHANNEL 2
+#define CMD_CLOSE_DATA_CHAN 3
+#define CMD_RECONNECT_DATA_CHAN 4
+#define CMD_FILTER_OPERATION 5
+
+/* Some responses */
+#define RSP_SUCCESS 0
+#define RSP_INSUFFICIENT_RESOURCES 1
+#define RSP_INVALID_COMMAND_FORMAT 2
+#define RSP_COMMAND_NOT_SUPPORTED 3
+#define RSP_PARAM_NOT_SUPPORTED 4
+#define RSP_VALUE_NOT_SUPPORTED 5
+#define RSP_NOT_OPEN 6
+#define RSP_AUTHENTICATION_REQUIRED 7
+#define RSP_INVALID_PASSWORD 8
+#define RSP_PROTOCOL_ERROR 9
+#define RSP_ASYNCHRONOUS_ERROR 255
+
+/* Media types */
+#define MEDIA_802_3 1
+#define MEDIA_802_5 2
+
+/* Filter parameters */
+#define DATA_CHAN 1
+#define FILTER_TYPE 2
+#define FILTER_MODE 3
+
+/* Filter types */
+#define IRLAN_DIRECTED 0x01
+#define IRLAN_FUNCTIONAL 0x02
+#define IRLAN_GROUP 0x04
+#define IRLAN_MAC_FRAME 0x08
+#define IRLAN_MULTICAST 0x10
+#define IRLAN_BROADCAST 0x20
+#define IRLAN_IPX_SOCKET 0x40
+
+/* Filter modes */
+#define ALL 1
+#define FILTER 2
+#define NONE 3
+
+/* Filter operations */
+#define GET 1
+#define CLEAR 2
+#define ADD 3
+#define REMOVE 4
+#define DYNAMIC 5
+
+/* Access types */
+#define ACCESS_DIRECT 1
+#define ACCESS_PEER 2
+#define ACCESS_HOSTED 3
+
+#define IRLAN_BYTE 0
+#define IRLAN_SHORT 1
+#define IRLAN_ARRAY 2
+
+/* IrLAN sits on top if IrTTP */
+#define IRLAN_MAX_HEADER (TTP_HEADER+LMP_HEADER)
+/* 1 byte for the command code and 1 byte for the parameter count */
+#define IRLAN_CMD_HEADER 2
+
+#define IRLAN_STRING_PARAMETER_LEN(name, value) (1 + strlen((name)) + 2 \
+ + strlen ((value)))
+#define IRLAN_BYTE_PARAMETER_LEN(name) (1 + strlen((name)) + 2 + 1)
+#define IRLAN_SHORT_PARAMETER_LEN(name) (1 + strlen((name)) + 2 + 2)
+
+/*
+ * IrLAN client
+ */
+struct irlan_client_cb {
+ int state;
+
+ int open_retries;
+
+ struct tsap_cb *tsap_ctrl;
+ __u32 max_sdu_size;
+ __u8 max_header_size;
+
+ int access_type; /* Access type of provider */
+ __u8 reconnect_key[255];
+ __u8 key_len;
+
+ __u16 recv_arb_val;
+ __u16 max_frame;
+ int filter_type;
+
+ int unicast_open;
+ int broadcast_open;
+
+ int tx_busy;
+ struct sk_buff_head txq; /* Transmit control queue */
+
+ struct iriap_cb *iriap;
+
+ struct timer_list kick_timer;
+};
+
+/*
+ * IrLAN provider
+ */
+struct irlan_provider_cb {
+ int state;
+
+ struct tsap_cb *tsap_ctrl;
+ __u32 max_sdu_size;
+ __u8 max_header_size;
+
+ /*
+ * Store some values here which are used by the provider to parse
+ * the filter operations
+ */
+ int data_chan;
+ int filter_type;
+ int filter_mode;
+ int filter_operation;
+ int filter_entry;
+ int access_type; /* Access type */
+ __u16 send_arb_val;
+
+ __u8 mac_address[6]; /* Generated MAC address for peer device */
+};
+
+/*
+ * IrLAN control block
+ */
+struct irlan_cb {
+ int magic;
+ struct list_head dev_list;
+ struct net_device *dev; /* Ethernet device structure*/
+
+ __u32 saddr; /* Source device address */
+ __u32 daddr; /* Destination device address */
+ int disconnect_reason; /* Why we got disconnected */
+
+ int media; /* Media type */
+ __u8 version[2]; /* IrLAN version */
+
+ struct tsap_cb *tsap_data; /* Data TSAP */
+
+ int use_udata; /* Use Unit Data transfers */
+
+ __u8 stsap_sel_data; /* Source data TSAP selector */
+ __u8 dtsap_sel_data; /* Destination data TSAP selector */
+ __u8 dtsap_sel_ctrl; /* Destination ctrl TSAP selector */
+
+ struct irlan_client_cb client; /* Client specific fields */
+ struct irlan_provider_cb provider; /* Provider specific fields */
+
+ __u32 max_sdu_size;
+ __u8 max_header_size;
+
+ wait_queue_head_t open_wait;
+ struct timer_list watchdog_timer;
+};
+
+void irlan_close(struct irlan_cb *self);
+void irlan_close_tsaps(struct irlan_cb *self);
+
+int irlan_register_netdev(struct irlan_cb *self);
+void irlan_ias_register(struct irlan_cb *self, __u8 tsap_sel);
+void irlan_start_watchdog_timer(struct irlan_cb *self, int timeout);
+
+void irlan_open_data_tsap(struct irlan_cb *self);
+
+int irlan_run_ctrl_tx_queue(struct irlan_cb *self);
+
+struct irlan_cb *irlan_get_any(void);
+void irlan_get_provider_info(struct irlan_cb *self);
+void irlan_get_media_char(struct irlan_cb *self);
+void irlan_open_data_channel(struct irlan_cb *self);
+void irlan_close_data_channel(struct irlan_cb *self);
+void irlan_set_multicast_filter(struct irlan_cb *self, int status);
+void irlan_set_broadcast_filter(struct irlan_cb *self, int status);
+
+int irlan_insert_byte_param(struct sk_buff *skb, char *param, __u8 value);
+int irlan_insert_short_param(struct sk_buff *skb, char *param, __u16 value);
+int irlan_insert_string_param(struct sk_buff *skb, char *param, char *value);
+int irlan_insert_array_param(struct sk_buff *skb, char *name, __u8 *value,
+ __u16 value_len);
+
+int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len);
+
+#endif
+
+
diff --git a/include/net/irda/irlan_eth.h b/include/net/irda/irlan_eth.h
new file mode 100644
index 00000000..de5c8169
--- /dev/null
+++ b/include/net/irda/irlan_eth.h
@@ -0,0 +1,32 @@
+/*********************************************************************
+ *
+ * Filename: irlan_eth.h
+ * Version:
+ * Description:
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Thu Oct 15 08:36:58 1998
+ * Modified at: Fri May 14 23:29:00 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef IRLAN_ETH_H
+#define IRLAN_ETH_H
+
+struct net_device *alloc_irlandev(const char *name);
+int irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb);
+
+void irlan_eth_flow_indication( void *instance, void *sap, LOCAL_FLOW flow);
+#endif
diff --git a/include/net/irda/irlan_event.h b/include/net/irda/irlan_event.h
new file mode 100644
index 00000000..018b5a77
--- /dev/null
+++ b/include/net/irda/irlan_event.h
@@ -0,0 +1,81 @@
+/*********************************************************************
+ *
+ * Filename: irlan_event.h
+ * Version:
+ * Description: LAN access
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Sun Aug 31 20:14:37 1997
+ * Modified at: Tue Feb 2 09:45:17 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef IRLAN_EVENT_H
+#define IRLAN_EVENT_H
+
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+
+#include <net/irda/irlan_common.h>
+
+typedef enum {
+ IRLAN_IDLE,
+ IRLAN_QUERY,
+ IRLAN_CONN,
+ IRLAN_INFO,
+ IRLAN_MEDIA,
+ IRLAN_OPEN,
+ IRLAN_WAIT,
+ IRLAN_ARB,
+ IRLAN_DATA,
+ IRLAN_CLOSE,
+ IRLAN_SYNC
+} IRLAN_STATE;
+
+typedef enum {
+ IRLAN_DISCOVERY_INDICATION,
+ IRLAN_IAS_PROVIDER_AVAIL,
+ IRLAN_IAS_PROVIDER_NOT_AVAIL,
+ IRLAN_LAP_DISCONNECT,
+ IRLAN_LMP_DISCONNECT,
+ IRLAN_CONNECT_COMPLETE,
+ IRLAN_DATA_INDICATION,
+ IRLAN_DATA_CONNECT_INDICATION,
+ IRLAN_RETRY_CONNECT,
+
+ IRLAN_CONNECT_INDICATION,
+ IRLAN_GET_INFO_CMD,
+ IRLAN_GET_MEDIA_CMD,
+ IRLAN_OPEN_DATA_CMD,
+ IRLAN_FILTER_CONFIG_CMD,
+
+ IRLAN_CHECK_CON_ARB,
+ IRLAN_PROVIDER_SIGNAL,
+
+ IRLAN_WATCHDOG_TIMEOUT,
+} IRLAN_EVENT;
+
+extern const char * const irlan_state[];
+
+void irlan_do_client_event(struct irlan_cb *self, IRLAN_EVENT event,
+ struct sk_buff *skb);
+
+void irlan_do_provider_event(struct irlan_cb *self, IRLAN_EVENT event,
+ struct sk_buff *skb);
+
+void irlan_next_client_state(struct irlan_cb *self, IRLAN_STATE state);
+void irlan_next_provider_state(struct irlan_cb *self, IRLAN_STATE state);
+
+#endif
diff --git a/include/net/irda/irlan_filter.h b/include/net/irda/irlan_filter.h
new file mode 100644
index 00000000..a5a25394
--- /dev/null
+++ b/include/net/irda/irlan_filter.h
@@ -0,0 +1,35 @@
+/*********************************************************************
+ *
+ * Filename: irlan_filter.h
+ * Version:
+ * Description:
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Fri Jan 29 15:24:08 1999
+ * Modified at: Sun Feb 7 23:35:31 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef IRLAN_FILTER_H
+#define IRLAN_FILTER_H
+
+void irlan_check_command_param(struct irlan_cb *self, char *param,
+ char *value);
+void irlan_filter_request(struct irlan_cb *self, struct sk_buff *skb);
+#ifdef CONFIG_PROC_FS
+void irlan_print_filter(struct seq_file *seq, int filter_type);
+#endif
+
+#endif /* IRLAN_FILTER_H */
diff --git a/include/net/irda/irlan_provider.h b/include/net/irda/irlan_provider.h
new file mode 100644
index 00000000..92f3b0e1
--- /dev/null
+++ b/include/net/irda/irlan_provider.h
@@ -0,0 +1,52 @@
+/*********************************************************************
+ *
+ * Filename: irlan_provider.h
+ * Version: 0.1
+ * Description: IrDA LAN access layer
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Sun Aug 31 20:14:37 1997
+ * Modified at: Sun May 9 12:26:11 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef IRLAN_SERVER_H
+#define IRLAN_SERVER_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+#include <net/irda/irlan_common.h>
+
+void irlan_provider_ctrl_disconnect_indication(void *instance, void *sap,
+ LM_REASON reason,
+ struct sk_buff *skb);
+
+
+void irlan_provider_connect_response(struct irlan_cb *, struct tsap_cb *);
+
+int irlan_parse_open_data_cmd(struct irlan_cb *self, struct sk_buff *skb);
+int irlan_provider_parse_command(struct irlan_cb *self, int cmd,
+ struct sk_buff *skb);
+
+void irlan_provider_send_reply(struct irlan_cb *self, int command,
+ int ret_code);
+int irlan_provider_open_ctrl_tsap(struct irlan_cb *self);
+
+#endif
+
+
diff --git a/include/net/irda/irlap.h b/include/net/irda/irlap.h
new file mode 100644
index 00000000..fb4b76d5
--- /dev/null
+++ b/include/net/irda/irlap.h
@@ -0,0 +1,311 @@
+/*********************************************************************
+ *
+ * Filename: irlap.h
+ * Version: 0.8
+ * Description: An IrDA LAP driver for Linux
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Mon Aug 4 20:40:53 1997
+ * Modified at: Fri Dec 10 13:21:17 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
+ * All Rights Reserved.
+ * Copyright (c) 2000-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef IRLAP_H
+#define IRLAP_H
+
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/timer.h>
+
+#include <net/irda/irqueue.h> /* irda_queue_t */
+#include <net/irda/qos.h> /* struct qos_info */
+#include <net/irda/discovery.h> /* discovery_t */
+#include <net/irda/irlap_event.h> /* IRLAP_STATE, ... */
+#include <net/irda/irmod.h> /* struct notify_t */
+
+#define CONFIG_IRDA_DYNAMIC_WINDOW 1
+
+#define LAP_RELIABLE 1
+#define LAP_UNRELIABLE 0
+
+#define LAP_ADDR_HEADER 1 /* IrLAP Address Header */
+#define LAP_CTRL_HEADER 1 /* IrLAP Control Header */
+
+/* May be different when we get VFIR */
+#define LAP_MAX_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER)
+
+/* Each IrDA device gets a random 32 bits IRLAP device address */
+#define LAP_ALEN 4
+
+#define BROADCAST 0xffffffff /* Broadcast device address */
+#define CBROADCAST 0xfe /* Connection broadcast address */
+#define XID_FORMAT 0x01 /* Discovery XID format */
+
+/* Nobody seems to use this constant. */
+#define LAP_WINDOW_SIZE 8
+/* We keep the LAP queue very small to minimise the amount of buffering.
+ * this improve latency and reduce resource consumption.
+ * This work only because we have synchronous refilling of IrLAP through
+ * the flow control mechanism (via scheduler and IrTTP).
+ * 2 buffers is the minimum we can work with, one that we send while polling
+ * IrTTP, and another to know that we should not send the pf bit.
+ * Jean II */
+#define LAP_HIGH_THRESHOLD 2
+/* Some rare non TTP clients don't implement flow control, and
+ * so don't comply with the above limit (and neither with this one).
+ * For IAP and management, it doesn't matter, because they never transmit much.
+ *.For IrLPT, this should be fixed.
+ * - Jean II */
+#define LAP_MAX_QUEUE 10
+/* Please note that all IrDA management frames (LMP/TTP conn req/disc and
+ * IAS queries) fall in the second category and are sent to LAP even if TTP
+ * is stopped. This means that those frames will wait only a maximum of
+ * two (2) data frames before beeing sent on the "wire", which speed up
+ * new socket setup when the link is saturated.
+ * Same story for two sockets competing for the medium : if one saturates
+ * the LAP, when the other want to transmit it only has to wait for
+ * maximum three (3) packets (2 + one scheduling), which improve performance
+ * of delay sensitive applications.
+ * Jean II */
+
+#define NR_EXPECTED 1
+#define NR_UNEXPECTED 0
+#define NR_INVALID -1
+
+#define NS_EXPECTED 1
+#define NS_UNEXPECTED 0
+#define NS_INVALID -1
+
+/*
+ * Meta information passed within the IrLAP state machine
+ */
+struct irlap_info {
+ __u8 caddr; /* Connection address */
+ __u8 control; /* Frame type */
+ __u8 cmd;
+
+ __u32 saddr;
+ __u32 daddr;
+
+ int pf; /* Poll/final bit set */
+
+ __u8 nr; /* Sequence number of next frame expected */
+ __u8 ns; /* Sequence number of frame sent */
+
+ int S; /* Number of slots */
+ int slot; /* Random chosen slot */
+ int s; /* Current slot */
+
+ discovery_t *discovery; /* Discovery information */
+};
+
+/* Main structure of IrLAP */
+struct irlap_cb {
+ irda_queue_t q; /* Must be first */
+ magic_t magic;
+
+ /* Device we are attached to */
+ struct net_device *netdev;
+ char hw_name[2*IFNAMSIZ + 1];
+
+ /* Connection state */
+ volatile IRLAP_STATE state; /* Current state */
+
+ /* Timers used by IrLAP */
+ struct timer_list query_timer;
+ struct timer_list slot_timer;
+ struct timer_list discovery_timer;
+ struct timer_list final_timer;
+ struct timer_list poll_timer;
+ struct timer_list wd_timer;
+ struct timer_list backoff_timer;
+
+ /* Media busy stuff */
+ struct timer_list media_busy_timer;
+ int media_busy;
+
+ /* Timeouts which will be different with different turn time */
+ int slot_timeout;
+ int poll_timeout;
+ int final_timeout;
+ int wd_timeout;
+
+ struct sk_buff_head txq; /* Frames to be transmitted */
+ struct sk_buff_head txq_ultra;
+
+ __u8 caddr; /* Connection address */
+ __u32 saddr; /* Source device address */
+ __u32 daddr; /* Destination device address */
+
+ int retry_count; /* Times tried to establish connection */
+ int add_wait; /* True if we are waiting for frame */
+
+ __u8 connect_pending;
+ __u8 disconnect_pending;
+
+ /* To send a faster RR if tx queue empty */
+#ifdef CONFIG_IRDA_FAST_RR
+ int fast_RR_timeout;
+ int fast_RR;
+#endif /* CONFIG_IRDA_FAST_RR */
+
+ int N1; /* N1 * F-timer = Negitiated link disconnect warning threshold */
+ int N2; /* N2 * F-timer = Negitiated link disconnect time */
+ int N3; /* Connection retry count */
+
+ int local_busy;
+ int remote_busy;
+ int xmitflag;
+
+ __u8 vs; /* Next frame to be sent */
+ __u8 vr; /* Next frame to be received */
+ __u8 va; /* Last frame acked */
+ int window; /* Nr of I-frames allowed to send */
+ int window_size; /* Current negotiated window size */
+
+#ifdef CONFIG_IRDA_DYNAMIC_WINDOW
+ __u32 line_capacity; /* Number of bytes allowed to send */
+ __u32 bytes_left; /* Number of bytes still allowed to transmit */
+#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
+
+ struct sk_buff_head wx_list;
+
+ __u8 ack_required;
+
+ /* XID parameters */
+ __u8 S; /* Number of slots */
+ __u8 slot; /* Random chosen slot */
+ __u8 s; /* Current slot */
+ int frame_sent; /* Have we sent reply? */
+
+ hashbin_t *discovery_log;
+ discovery_t *discovery_cmd;
+
+ __u32 speed; /* Link speed */
+
+ struct qos_info qos_tx; /* QoS requested by peer */
+ struct qos_info qos_rx; /* QoS requested by self */
+ struct qos_info *qos_dev; /* QoS supported by device */
+
+ notify_t notify; /* Callbacks to IrLMP */
+
+ int mtt_required; /* Minimum turnaround time required */
+ int xbofs_delay; /* Nr of XBOF's used to MTT */
+ int bofs_count; /* Negotiated extra BOFs */
+ int next_bofs; /* Negotiated extra BOFs after next frame */
+
+ int mode; /* IrLAP mode (primary, secondary or monitor) */
+};
+
+/*
+ * Function prototypes
+ */
+int irlap_init(void);
+void irlap_cleanup(void);
+
+struct irlap_cb *irlap_open(struct net_device *dev, struct qos_info *qos,
+ const char *hw_name);
+void irlap_close(struct irlap_cb *self);
+
+void irlap_connect_request(struct irlap_cb *self, __u32 daddr,
+ struct qos_info *qos, int sniff);
+void irlap_connect_response(struct irlap_cb *self, struct sk_buff *skb);
+void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb);
+void irlap_connect_confirm(struct irlap_cb *, struct sk_buff *skb);
+
+void irlap_data_indication(struct irlap_cb *, struct sk_buff *, int unreliable);
+void irlap_data_request(struct irlap_cb *, struct sk_buff *, int unreliable);
+
+#ifdef CONFIG_IRDA_ULTRA
+void irlap_unitdata_request(struct irlap_cb *, struct sk_buff *);
+void irlap_unitdata_indication(struct irlap_cb *, struct sk_buff *);
+#endif /* CONFIG_IRDA_ULTRA */
+
+void irlap_disconnect_request(struct irlap_cb *);
+void irlap_disconnect_indication(struct irlap_cb *, LAP_REASON reason);
+
+void irlap_status_indication(struct irlap_cb *, int quality_of_link);
+
+void irlap_test_request(__u8 *info, int len);
+
+void irlap_discovery_request(struct irlap_cb *, discovery_t *discovery);
+void irlap_discovery_confirm(struct irlap_cb *, hashbin_t *discovery_log);
+void irlap_discovery_indication(struct irlap_cb *, discovery_t *discovery);
+
+void irlap_reset_indication(struct irlap_cb *self);
+void irlap_reset_confirm(void);
+
+void irlap_update_nr_received(struct irlap_cb *, int nr);
+int irlap_validate_nr_received(struct irlap_cb *, int nr);
+int irlap_validate_ns_received(struct irlap_cb *, int ns);
+
+int irlap_generate_rand_time_slot(int S, int s);
+void irlap_initiate_connection_state(struct irlap_cb *);
+void irlap_flush_all_queues(struct irlap_cb *);
+void irlap_wait_min_turn_around(struct irlap_cb *, struct qos_info *);
+
+void irlap_apply_default_connection_parameters(struct irlap_cb *self);
+void irlap_apply_connection_parameters(struct irlap_cb *self, int now);
+
+#define IRLAP_GET_HEADER_SIZE(self) (LAP_MAX_HEADER)
+#define IRLAP_GET_TX_QUEUE_LEN(self) skb_queue_len(&self->txq)
+
+/* Return TRUE if the node is in primary mode (i.e. master)
+ * - Jean II */
+static inline int irlap_is_primary(struct irlap_cb *self)
+{
+ int ret;
+ switch(self->state) {
+ case LAP_XMIT_P:
+ case LAP_NRM_P:
+ ret = 1;
+ break;
+ case LAP_XMIT_S:
+ case LAP_NRM_S:
+ ret = 0;
+ break;
+ default:
+ ret = -1;
+ }
+ return ret;
+}
+
+/* Clear a pending IrLAP disconnect. - Jean II */
+static inline void irlap_clear_disconnect(struct irlap_cb *self)
+{
+ self->disconnect_pending = FALSE;
+}
+
+/*
+ * Function irlap_next_state (self, state)
+ *
+ * Switches state and provides debug information
+ *
+ */
+static inline void irlap_next_state(struct irlap_cb *self, IRLAP_STATE state)
+{
+ /*
+ if (!self || self->magic != LAP_MAGIC)
+ return;
+
+ IRDA_DEBUG(4, "next LAP state = %s\n", irlap_state[state]);
+ */
+ self->state = state;
+}
+
+#endif
diff --git a/include/net/irda/irlap_event.h b/include/net/irda/irlap_event.h
new file mode 100644
index 00000000..4c90824c
--- /dev/null
+++ b/include/net/irda/irlap_event.h
@@ -0,0 +1,131 @@
+/*********************************************************************
+ *
+ *
+ * Filename: irlap_event.h
+ * Version: 0.1
+ * Description:
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Sat Aug 16 00:59:29 1997
+ * Modified at: Tue Dec 21 11:20:30 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
+ * All Rights Reserved.
+ * Copyright (c) 2000-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ********************************************************************/
+
+#ifndef IRLAP_EVENT_H
+#define IRLAP_EVENT_H
+
+#include <net/irda/irda.h>
+
+/* A few forward declarations (to make compiler happy) */
+struct irlap_cb;
+struct irlap_info;
+
+/* IrLAP States */
+typedef enum {
+ LAP_NDM, /* Normal disconnected mode */
+ LAP_QUERY,
+ LAP_REPLY,
+ LAP_CONN, /* Connect indication */
+ LAP_SETUP, /* Setting up connection */
+ LAP_OFFLINE, /* A really boring state */
+ LAP_XMIT_P,
+ LAP_PCLOSE,
+ LAP_NRM_P, /* Normal response mode as primary */
+ LAP_RESET_WAIT,
+ LAP_RESET,
+ LAP_NRM_S, /* Normal response mode as secondary */
+ LAP_XMIT_S,
+ LAP_SCLOSE,
+ LAP_RESET_CHECK,
+} IRLAP_STATE;
+
+/* IrLAP Events */
+typedef enum {
+ /* Services events */
+ DISCOVERY_REQUEST,
+ CONNECT_REQUEST,
+ CONNECT_RESPONSE,
+ DISCONNECT_REQUEST,
+ DATA_REQUEST,
+ RESET_REQUEST,
+ RESET_RESPONSE,
+
+ /* Send events */
+ SEND_I_CMD,
+ SEND_UI_FRAME,
+
+ /* Receive events */
+ RECV_DISCOVERY_XID_CMD,
+ RECV_DISCOVERY_XID_RSP,
+ RECV_SNRM_CMD,
+ RECV_TEST_CMD,
+ RECV_TEST_RSP,
+ RECV_UA_RSP,
+ RECV_DM_RSP,
+ RECV_RD_RSP,
+ RECV_I_CMD,
+ RECV_I_RSP,
+ RECV_UI_FRAME,
+ RECV_FRMR_RSP,
+ RECV_RR_CMD,
+ RECV_RR_RSP,
+ RECV_RNR_CMD,
+ RECV_RNR_RSP,
+ RECV_REJ_CMD,
+ RECV_REJ_RSP,
+ RECV_SREJ_CMD,
+ RECV_SREJ_RSP,
+ RECV_DISC_CMD,
+
+ /* Timer events */
+ SLOT_TIMER_EXPIRED,
+ QUERY_TIMER_EXPIRED,
+ FINAL_TIMER_EXPIRED,
+ POLL_TIMER_EXPIRED,
+ DISCOVERY_TIMER_EXPIRED,
+ WD_TIMER_EXPIRED,
+ BACKOFF_TIMER_EXPIRED,
+ MEDIA_BUSY_TIMER_EXPIRED,
+} IRLAP_EVENT;
+
+/*
+ * Disconnect reason code
+ */
+typedef enum { /* FIXME check the two first reason codes */
+ LAP_DISC_INDICATION=1, /* Received a disconnect request from peer */
+ LAP_NO_RESPONSE, /* To many retransmits without response */
+ LAP_RESET_INDICATION, /* To many retransmits, or invalid nr/ns */
+ LAP_FOUND_NONE, /* No devices were discovered */
+ LAP_MEDIA_BUSY,
+ LAP_PRIMARY_CONFLICT,
+} LAP_REASON;
+
+extern const char *const irlap_state[];
+
+void irlap_do_event(struct irlap_cb *self, IRLAP_EVENT event,
+ struct sk_buff *skb, struct irlap_info *info);
+void irlap_print_event(IRLAP_EVENT event);
+
+extern int irlap_qos_negotiate(struct irlap_cb *self, struct sk_buff *skb);
+
+#endif
diff --git a/include/net/irda/irlap_frame.h b/include/net/irda/irlap_frame.h
new file mode 100644
index 00000000..6b1dc4f8
--- /dev/null
+++ b/include/net/irda/irlap_frame.h
@@ -0,0 +1,169 @@
+/*********************************************************************
+ *
+ * Filename: irlap_frame.h
+ * Version: 0.9
+ * Description: IrLAP frame declarations
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Tue Aug 19 10:27:26 1997
+ * Modified at: Sat Dec 25 21:07:26 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1997-1999 Dag Brattli <dagb@cs.uit.no>,
+ * All Rights Reserved.
+ * Copyright (c) 2000-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ********************************************************************/
+
+#ifndef IRLAP_FRAME_H
+#define IRLAP_FRAME_H
+
+#include <linux/skbuff.h>
+
+#include <net/irda/irda.h>
+
+/* A few forward declarations (to make compiler happy) */
+struct irlap_cb;
+struct discovery_t;
+
+/* Frame types and templates */
+#define INVALID 0xff
+
+/* Unnumbered (U) commands */
+#define SNRM_CMD 0x83 /* Set Normal Response Mode */
+#define DISC_CMD 0x43 /* Disconnect */
+#define XID_CMD 0x2f /* Exchange Station Identification */
+#define TEST_CMD 0xe3 /* Test */
+
+/* Unnumbered responses */
+#define RNRM_RSP 0x83 /* Request Normal Response Mode */
+#define UA_RSP 0x63 /* Unnumbered Acknowledgement */
+#define FRMR_RSP 0x87 /* Frame Reject */
+#define DM_RSP 0x0f /* Disconnect Mode */
+#define RD_RSP 0x43 /* Request Disconnection */
+#define XID_RSP 0xaf /* Exchange Station Identification */
+#define TEST_RSP 0xe3 /* Test frame */
+
+/* Supervisory (S) */
+#define RR 0x01 /* Receive Ready */
+#define REJ 0x09 /* Reject */
+#define RNR 0x05 /* Receive Not Ready */
+#define SREJ 0x0d /* Selective Reject */
+
+/* Information (I) */
+#define I_FRAME 0x00 /* Information Format */
+#define UI_FRAME 0x03 /* Unnumbered Information */
+
+#define CMD_FRAME 0x01
+#define RSP_FRAME 0x00
+
+#define PF_BIT 0x10 /* Poll/final bit */
+
+/* Some IrLAP field lengths */
+/*
+ * Only baud rate triplet is 4 bytes (PV can be 2 bytes).
+ * All others params (7) are 3 bytes, so that's 7*3 + 1*4 bytes.
+ */
+#define IRLAP_NEGOCIATION_PARAMS_LEN 25
+#define IRLAP_DISCOVERY_INFO_LEN 32
+
+struct disc_frame {
+ __u8 caddr; /* Connection address */
+ __u8 control;
+} __packed;
+
+struct xid_frame {
+ __u8 caddr; /* Connection address */
+ __u8 control;
+ __u8 ident; /* Should always be XID_FORMAT */
+ __le32 saddr; /* Source device address */
+ __le32 daddr; /* Destination device address */
+ __u8 flags; /* Discovery flags */
+ __u8 slotnr;
+ __u8 version;
+} __packed;
+
+struct test_frame {
+ __u8 caddr; /* Connection address */
+ __u8 control;
+ __le32 saddr; /* Source device address */
+ __le32 daddr; /* Destination device address */
+} __packed;
+
+struct ua_frame {
+ __u8 caddr;
+ __u8 control;
+ __le32 saddr; /* Source device address */
+ __le32 daddr; /* Dest device address */
+} __packed;
+
+struct dm_frame {
+ __u8 caddr; /* Connection address */
+ __u8 control;
+} __packed;
+
+struct rd_frame {
+ __u8 caddr; /* Connection address */
+ __u8 control;
+} __packed;
+
+struct rr_frame {
+ __u8 caddr; /* Connection address */
+ __u8 control;
+} __packed;
+
+struct i_frame {
+ __u8 caddr;
+ __u8 control;
+} __packed;
+
+struct snrm_frame {
+ __u8 caddr;
+ __u8 control;
+ __le32 saddr;
+ __le32 daddr;
+ __u8 ncaddr;
+} __packed;
+
+void irlap_queue_xmit(struct irlap_cb *self, struct sk_buff *skb);
+void irlap_send_discovery_xid_frame(struct irlap_cb *, int S, __u8 s,
+ __u8 command,
+ struct discovery_t *discovery);
+void irlap_send_snrm_frame(struct irlap_cb *, struct qos_info *);
+void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr,
+ struct sk_buff *cmd);
+void irlap_send_ua_response_frame(struct irlap_cb *, struct qos_info *);
+void irlap_send_dm_frame(struct irlap_cb *self);
+void irlap_send_rd_frame(struct irlap_cb *self);
+void irlap_send_disc_frame(struct irlap_cb *self);
+void irlap_send_rr_frame(struct irlap_cb *self, int command);
+
+void irlap_send_data_primary(struct irlap_cb *, struct sk_buff *);
+void irlap_send_data_primary_poll(struct irlap_cb *, struct sk_buff *);
+void irlap_send_data_secondary(struct irlap_cb *, struct sk_buff *);
+void irlap_send_data_secondary_final(struct irlap_cb *, struct sk_buff *);
+void irlap_resend_rejected_frames(struct irlap_cb *, int command);
+void irlap_resend_rejected_frame(struct irlap_cb *self, int command);
+
+void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
+ __u8 caddr, int command);
+
+extern int irlap_insert_qos_negotiation_params(struct irlap_cb *self,
+ struct sk_buff *skb);
+
+#endif
diff --git a/include/net/irda/irlmp.h b/include/net/irda/irlmp.h
new file mode 100644
index 00000000..fff11b7f
--- /dev/null
+++ b/include/net/irda/irlmp.h
@@ -0,0 +1,294 @@
+/*********************************************************************
+ *
+ * Filename: irlmp.h
+ * Version: 0.9
+ * Description: IrDA Link Management Protocol (LMP) layer
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Sun Aug 17 20:54:32 1997
+ * Modified at: Fri Dec 10 13:23:01 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
+ * All Rights Reserved.
+ * Copyright (c) 2000-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef IRLMP_H
+#define IRLMP_H
+
+#include <asm/param.h> /* for HZ */
+
+#include <linux/types.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/qos.h>
+#include <net/irda/irlap.h> /* LAP_MAX_HEADER, ... */
+#include <net/irda/irlmp_event.h>
+#include <net/irda/irqueue.h>
+#include <net/irda/discovery.h>
+
+/* LSAP-SEL's */
+#define LSAP_MASK 0x7f
+#define LSAP_IAS 0x00
+#define LSAP_ANY 0xff
+#define LSAP_MAX 0x6f /* 0x70-0x7f are reserved */
+#define LSAP_CONNLESS 0x70 /* Connectionless LSAP, mostly used for Ultra */
+
+#define DEV_ADDR_ANY 0xffffffff
+
+#define LMP_HEADER 2 /* Dest LSAP + Source LSAP */
+#define LMP_CONTROL_HEADER 4 /* LMP_HEADER + opcode + parameter */
+#define LMP_PID_HEADER 1 /* Used by Ultra */
+#define LMP_MAX_HEADER (LMP_CONTROL_HEADER+LAP_MAX_HEADER)
+
+#define LM_MAX_CONNECTIONS 10
+
+#define LM_IDLE_TIMEOUT 2*HZ /* 2 seconds for now */
+
+typedef enum {
+ S_PNP = 0,
+ S_PDA,
+ S_COMPUTER,
+ S_PRINTER,
+ S_MODEM,
+ S_FAX,
+ S_LAN,
+ S_TELEPHONY,
+ S_COMM,
+ S_OBEX,
+ S_ANY,
+ S_END,
+} SERVICE;
+
+/* For selective discovery */
+typedef void (*DISCOVERY_CALLBACK1) (discinfo_t *, DISCOVERY_MODE, void *);
+/* For expiry (the same) */
+typedef void (*DISCOVERY_CALLBACK2) (discinfo_t *, DISCOVERY_MODE, void *);
+
+typedef struct {
+ irda_queue_t queue; /* Must be first */
+
+ __u16_host_order hints; /* Hint bits */
+} irlmp_service_t;
+
+typedef struct {
+ irda_queue_t queue; /* Must be first */
+
+ __u16_host_order hint_mask;
+
+ DISCOVERY_CALLBACK1 disco_callback; /* Selective discovery */
+ DISCOVERY_CALLBACK2 expir_callback; /* Selective expiration */
+ void *priv; /* Used to identify client */
+} irlmp_client_t;
+
+/*
+ * Information about each logical LSAP connection
+ */
+struct lsap_cb {
+ irda_queue_t queue; /* Must be first */
+ magic_t magic;
+
+ unsigned long connected; /* set_bit used on this */
+ int persistent;
+
+ __u8 slsap_sel; /* Source (this) LSAP address */
+ __u8 dlsap_sel; /* Destination LSAP address (if connected) */
+#ifdef CONFIG_IRDA_ULTRA
+ __u8 pid; /* Used by connectionless LSAP */
+#endif /* CONFIG_IRDA_ULTRA */
+ struct sk_buff *conn_skb; /* Store skb here while connecting */
+
+ struct timer_list watchdog_timer;
+
+ LSAP_STATE lsap_state; /* Connection state */
+ notify_t notify; /* Indication/Confirm entry points */
+ struct qos_info qos; /* QoS for this connection */
+
+ struct lap_cb *lap; /* Pointer to LAP connection structure */
+};
+
+/*
+ * Used for caching the last slsap->dlsap->handle mapping
+ *
+ * We don't need to keep/match the remote address in the cache because
+ * we are associated with a specific LAP (which implies it).
+ * Jean II
+ */
+typedef struct {
+ int valid;
+
+ __u8 slsap_sel;
+ __u8 dlsap_sel;
+ struct lsap_cb *lsap;
+} CACHE_ENTRY;
+
+/*
+ * Information about each registred IrLAP layer
+ */
+struct lap_cb {
+ irda_queue_t queue; /* Must be first */
+ magic_t magic;
+
+ int reason; /* LAP disconnect reason */
+
+ IRLMP_STATE lap_state;
+
+ struct irlap_cb *irlap; /* Instance of IrLAP layer */
+ hashbin_t *lsaps; /* LSAP associated with this link */
+ struct lsap_cb *flow_next; /* Next lsap to be polled for Tx */
+
+ __u8 caddr; /* Connection address */
+ __u32 saddr; /* Source device address */
+ __u32 daddr; /* Destination device address */
+
+ struct qos_info *qos; /* LAP QoS for this session */
+ struct timer_list idle_timer;
+
+#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
+ /* The lsap cache was moved from struct irlmp_cb to here because
+ * it must be associated with the specific LAP. Also, this
+ * improves performance. - Jean II */
+ CACHE_ENTRY cache; /* Caching last slsap->dlsap->handle mapping */
+#endif
+};
+
+/*
+ * Main structure for IrLMP
+ */
+struct irlmp_cb {
+ magic_t magic;
+
+ __u8 conflict_flag;
+
+ discovery_t discovery_cmd; /* Discovery command to use by IrLAP */
+ discovery_t discovery_rsp; /* Discovery response to use by IrLAP */
+
+ /* Last lsap picked automatically by irlmp_find_free_slsap() */
+ int last_lsap_sel;
+
+ struct timer_list discovery_timer;
+
+ hashbin_t *links; /* IrLAP connection table */
+ hashbin_t *unconnected_lsaps;
+ hashbin_t *clients;
+ hashbin_t *services;
+
+ hashbin_t *cachelog; /* Current discovery log */
+
+ int running;
+
+ __u16_host_order hints; /* Hint bits */
+};
+
+/* Prototype declarations */
+int irlmp_init(void);
+void irlmp_cleanup(void);
+struct lsap_cb *irlmp_open_lsap(__u8 slsap, notify_t *notify, __u8 pid);
+void irlmp_close_lsap( struct lsap_cb *self);
+
+__u16 irlmp_service_to_hint(int service);
+void *irlmp_register_service(__u16 hints);
+int irlmp_unregister_service(void *handle);
+void *irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb,
+ DISCOVERY_CALLBACK2 expir_clb, void *priv);
+int irlmp_unregister_client(void *handle);
+int irlmp_update_client(void *handle, __u16 hint_mask,
+ DISCOVERY_CALLBACK1 disco_clb,
+ DISCOVERY_CALLBACK2 expir_clb, void *priv);
+
+void irlmp_register_link(struct irlap_cb *, __u32 saddr, notify_t *);
+void irlmp_unregister_link(__u32 saddr);
+
+int irlmp_connect_request(struct lsap_cb *, __u8 dlsap_sel,
+ __u32 saddr, __u32 daddr,
+ struct qos_info *, struct sk_buff *);
+void irlmp_connect_indication(struct lsap_cb *self, struct sk_buff *skb);
+int irlmp_connect_response(struct lsap_cb *, struct sk_buff *);
+void irlmp_connect_confirm(struct lsap_cb *, struct sk_buff *);
+struct lsap_cb *irlmp_dup(struct lsap_cb *self, void *instance);
+
+void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason,
+ struct sk_buff *userdata);
+int irlmp_disconnect_request(struct lsap_cb *, struct sk_buff *userdata);
+
+void irlmp_discovery_confirm(hashbin_t *discovery_log, DISCOVERY_MODE mode);
+void irlmp_discovery_request(int nslots);
+discinfo_t *irlmp_get_discoveries(int *pn, __u16 mask, int nslots);
+void irlmp_do_expiry(void);
+void irlmp_do_discovery(int nslots);
+discovery_t *irlmp_get_discovery_response(void);
+void irlmp_discovery_expiry(discinfo_t *expiry, int number);
+
+int irlmp_data_request(struct lsap_cb *, struct sk_buff *);
+void irlmp_data_indication(struct lsap_cb *, struct sk_buff *);
+
+int irlmp_udata_request(struct lsap_cb *, struct sk_buff *);
+void irlmp_udata_indication(struct lsap_cb *, struct sk_buff *);
+
+#ifdef CONFIG_IRDA_ULTRA
+int irlmp_connless_data_request(struct lsap_cb *, struct sk_buff *, __u8);
+void irlmp_connless_data_indication(struct lsap_cb *, struct sk_buff *);
+#endif /* CONFIG_IRDA_ULTRA */
+
+void irlmp_status_indication(struct lap_cb *, LINK_STATUS link, LOCK_STATUS lock);
+void irlmp_flow_indication(struct lap_cb *self, LOCAL_FLOW flow);
+
+LM_REASON irlmp_convert_lap_reason(LAP_REASON);
+
+static inline __u32 irlmp_get_saddr(const struct lsap_cb *self)
+{
+ return (self && self->lap) ? self->lap->saddr : 0;
+}
+
+static inline __u32 irlmp_get_daddr(const struct lsap_cb *self)
+{
+ return (self && self->lap) ? self->lap->daddr : 0;
+}
+
+extern const char *irlmp_reasons[];
+extern int sysctl_discovery_timeout;
+extern int sysctl_discovery_slots;
+extern int sysctl_discovery;
+extern int sysctl_lap_keepalive_time; /* in ms, default is LM_IDLE_TIMEOUT */
+extern struct irlmp_cb *irlmp;
+
+/* Check if LAP queue is full.
+ * Used by IrTTP for low control, see comments in irlap.h - Jean II */
+static inline int irlmp_lap_tx_queue_full(struct lsap_cb *self)
+{
+ if (self == NULL)
+ return 0;
+ if (self->lap == NULL)
+ return 0;
+ if (self->lap->irlap == NULL)
+ return 0;
+
+ return IRLAP_GET_TX_QUEUE_LEN(self->lap->irlap) >= LAP_HIGH_THRESHOLD;
+}
+
+/* After doing a irlmp_dup(), this get one of the two socket back into
+ * a state where it's waiting incomming connections.
+ * Note : this can be used *only* if the socket is not yet connected
+ * (i.e. NO irlmp_connect_response() done on this socket).
+ * - Jean II */
+static inline void irlmp_listen(struct lsap_cb *self)
+{
+ self->dlsap_sel = LSAP_ANY;
+ self->lap = NULL;
+ self->lsap_state = LSAP_DISCONNECTED;
+ /* Started when we received the LM_CONNECT_INDICATION */
+ del_timer(&self->watchdog_timer);
+}
+
+#endif
diff --git a/include/net/irda/irlmp_event.h b/include/net/irda/irlmp_event.h
new file mode 100644
index 00000000..9e4ec17a
--- /dev/null
+++ b/include/net/irda/irlmp_event.h
@@ -0,0 +1,98 @@
+/*********************************************************************
+ *
+ * Filename: irlmp_event.h
+ * Version: 0.1
+ * Description: IrDA-LMP event handling
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Mon Aug 4 20:40:53 1997
+ * Modified at: Thu Jul 8 12:18:54 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>,
+ * All Rights Reserved.
+ * Copyright (c) 2000-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef IRLMP_EVENT_H
+#define IRLMP_EVENT_H
+
+/* A few forward declarations (to make compiler happy) */
+struct irlmp_cb;
+struct lsap_cb;
+struct lap_cb;
+struct discovery_t;
+
+/* LAP states */
+typedef enum {
+ /* IrLAP connection control states */
+ LAP_STANDBY, /* No LAP connection */
+ LAP_U_CONNECT, /* Starting LAP connection */
+ LAP_ACTIVE, /* LAP connection is active */
+} IRLMP_STATE;
+
+/* LSAP connection control states */
+typedef enum {
+ LSAP_DISCONNECTED, /* No LSAP connection */
+ LSAP_CONNECT, /* Connect indication from peer */
+ LSAP_CONNECT_PEND, /* Connect request from service user */
+ LSAP_DATA_TRANSFER_READY, /* LSAP connection established */
+ LSAP_SETUP, /* Trying to set up LSAP connection */
+ LSAP_SETUP_PEND, /* Request to start LAP connection */
+} LSAP_STATE;
+
+typedef enum {
+ /* LSAP events */
+ LM_CONNECT_REQUEST,
+ LM_CONNECT_CONFIRM,
+ LM_CONNECT_RESPONSE,
+ LM_CONNECT_INDICATION,
+
+ LM_DISCONNECT_INDICATION,
+ LM_DISCONNECT_REQUEST,
+
+ LM_DATA_REQUEST,
+ LM_UDATA_REQUEST,
+ LM_DATA_INDICATION,
+ LM_UDATA_INDICATION,
+
+ LM_WATCHDOG_TIMEOUT,
+
+ /* IrLAP events */
+ LM_LAP_CONNECT_REQUEST,
+ LM_LAP_CONNECT_INDICATION,
+ LM_LAP_CONNECT_CONFIRM,
+ LM_LAP_DISCONNECT_INDICATION,
+ LM_LAP_DISCONNECT_REQUEST,
+ LM_LAP_DISCOVERY_REQUEST,
+ LM_LAP_DISCOVERY_CONFIRM,
+ LM_LAP_IDLE_TIMEOUT,
+} IRLMP_EVENT;
+
+extern const char *const irlmp_state[];
+extern const char *const irlsap_state[];
+
+void irlmp_watchdog_timer_expired(void *data);
+void irlmp_discovery_timer_expired(void *data);
+void irlmp_idle_timer_expired(void *data);
+
+void irlmp_do_lap_event(struct lap_cb *self, IRLMP_EVENT event,
+ struct sk_buff *skb);
+int irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event,
+ struct sk_buff *skb);
+
+#endif /* IRLMP_EVENT_H */
+
+
+
+
diff --git a/include/net/irda/irlmp_frame.h b/include/net/irda/irlmp_frame.h
new file mode 100644
index 00000000..1906eb71
--- /dev/null
+++ b/include/net/irda/irlmp_frame.h
@@ -0,0 +1,62 @@
+/*********************************************************************
+ *
+ * Filename: irlmp_frame.h
+ * Version: 0.9
+ * Description:
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Tue Aug 19 02:09:59 1997
+ * Modified at: Fri Dec 10 13:21:53 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>,
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef IRMLP_FRAME_H
+#define IRMLP_FRAME_H
+
+#include <linux/skbuff.h>
+
+#include <net/irda/discovery.h>
+
+/* IrLMP frame opcodes */
+#define CONNECT_CMD 0x01
+#define CONNECT_CNF 0x81
+#define DISCONNECT 0x02
+#define ACCESSMODE_CMD 0x03
+#define ACCESSMODE_CNF 0x83
+
+#define CONTROL_BIT 0x80
+
+void irlmp_send_data_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap,
+ int expedited, struct sk_buff *skb);
+void irlmp_send_lcf_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap,
+ __u8 opcode, struct sk_buff *skb);
+void irlmp_link_data_indication(struct lap_cb *, struct sk_buff *,
+ int unreliable);
+#ifdef CONFIG_IRDA_ULTRA
+void irlmp_link_unitdata_indication(struct lap_cb *, struct sk_buff *);
+#endif /* CONFIG_IRDA_ULTRA */
+
+void irlmp_link_connect_indication(struct lap_cb *, __u32 saddr, __u32 daddr,
+ struct qos_info *qos, struct sk_buff *skb);
+void irlmp_link_connect_request(__u32 daddr);
+void irlmp_link_connect_confirm(struct lap_cb *self, struct qos_info *qos,
+ struct sk_buff *skb);
+void irlmp_link_disconnect_indication(struct lap_cb *, struct irlap_cb *,
+ LAP_REASON reason, struct sk_buff *);
+void irlmp_link_discovery_confirm(struct lap_cb *self, hashbin_t *log);
+void irlmp_link_discovery_indication(struct lap_cb *, discovery_t *discovery);
+
+#endif
diff --git a/include/net/irda/irmod.h b/include/net/irda/irmod.h
new file mode 100644
index 00000000..86f0dbb8
--- /dev/null
+++ b/include/net/irda/irmod.h
@@ -0,0 +1,109 @@
+/*********************************************************************
+ *
+ * Filename: irmod.h
+ * Version: 0.3
+ * Description: IrDA module and utilities functions
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Mon Dec 15 13:58:52 1997
+ * Modified at: Fri Jan 28 13:15:24 2000
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998-2000 Dag Brattli, All Rights Reserved.
+ * Copyright (c) 2000-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charg.
+ *
+ ********************************************************************/
+
+#ifndef IRMOD_H
+#define IRMOD_H
+
+/* Misc status information */
+typedef enum {
+ STATUS_OK,
+ STATUS_ABORTED,
+ STATUS_NO_ACTIVITY,
+ STATUS_NOISY,
+ STATUS_REMOTE,
+} LINK_STATUS;
+
+typedef enum {
+ LOCK_NO_CHANGE,
+ LOCK_LOCKED,
+ LOCK_UNLOCKED,
+} LOCK_STATUS;
+
+typedef enum { FLOW_STOP, FLOW_START } LOCAL_FLOW;
+
+/*
+ * IrLMP disconnect reasons. The order is very important, since they
+ * correspond to disconnect reasons sent in IrLMP disconnect frames, so
+ * please do not touch :-)
+ */
+typedef enum {
+ LM_USER_REQUEST = 1, /* User request */
+ LM_LAP_DISCONNECT, /* Unexpected IrLAP disconnect */
+ LM_CONNECT_FAILURE, /* Failed to establish IrLAP connection */
+ LM_LAP_RESET, /* IrLAP reset */
+ LM_INIT_DISCONNECT, /* Link Management initiated disconnect */
+ LM_LSAP_NOTCONN, /* Data delivered on unconnected LSAP */
+ LM_NON_RESP_CLIENT, /* Non responsive LM-MUX client */
+ LM_NO_AVAIL_CLIENT, /* No available LM-MUX client */
+ LM_CONN_HALF_OPEN, /* Connection is half open */
+ LM_BAD_SOURCE_ADDR, /* Illegal source address (i.e 0x00) */
+} LM_REASON;
+#define LM_UNKNOWN 0xff /* Unspecified disconnect reason */
+
+/* A few forward declarations (to make compiler happy) */
+struct qos_info; /* in <net/irda/qos.h> */
+
+/*
+ * Notify structure used between transport and link management layers
+ */
+typedef struct {
+ int (*data_indication)(void *priv, void *sap, struct sk_buff *skb);
+ int (*udata_indication)(void *priv, void *sap, struct sk_buff *skb);
+ void (*connect_confirm)(void *instance, void *sap,
+ struct qos_info *qos, __u32 max_sdu_size,
+ __u8 max_header_size, struct sk_buff *skb);
+ void (*connect_indication)(void *instance, void *sap,
+ struct qos_info *qos, __u32 max_sdu_size,
+ __u8 max_header_size, struct sk_buff *skb);
+ void (*disconnect_indication)(void *instance, void *sap,
+ LM_REASON reason, struct sk_buff *);
+ void (*flow_indication)(void *instance, void *sap, LOCAL_FLOW flow);
+ void (*status_indication)(void *instance,
+ LINK_STATUS link, LOCK_STATUS lock);
+ void *instance; /* Layer instance pointer */
+ char name[16]; /* Name of layer */
+} notify_t;
+
+#define NOTIFY_MAX_NAME 16
+
+/* Zero the notify structure */
+void irda_notify_init(notify_t *notify);
+
+/* Locking wrapper - Note the inverted logic on irda_lock().
+ * Those function basically return false if the lock is already in the
+ * position you want to set it. - Jean II */
+#define irda_lock(lock) (! test_and_set_bit(0, (void *) (lock)))
+#define irda_unlock(lock) (test_and_clear_bit(0, (void *) (lock)))
+
+#endif /* IRMOD_H */
+
+
+
+
+
+
+
+
+
diff --git a/include/net/irda/irqueue.h b/include/net/irda/irqueue.h
new file mode 100644
index 00000000..37f512bd
--- /dev/null
+++ b/include/net/irda/irqueue.h
@@ -0,0 +1,96 @@
+/*********************************************************************
+ *
+ * Filename: irqueue.h
+ * Version: 0.3
+ * Description: General queue implementation
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Tue Jun 9 13:26:50 1998
+ * Modified at: Thu Oct 7 13:25:16 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (C) 1998-1999, Aage Kvalnes <aage@cs.uit.no>
+ * Copyright (c) 1998, Dag Brattli
+ * All Rights Reserved.
+ *
+ * This code is taken from the Vortex Operating System written by Aage
+ * Kvalnes and has been ported to Linux and Linux/IR by Dag Brattli
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+
+#ifndef IRDA_QUEUE_H
+#define IRDA_QUEUE_H
+
+#define NAME_SIZE 32
+
+/*
+ * Hash types (some flags can be xored)
+ * See comments in irqueue.c for which one to use...
+ */
+#define HB_NOLOCK 0 /* No concurent access prevention */
+#define HB_LOCK 1 /* Prevent concurent write with global lock */
+
+/*
+ * Hash defines
+ */
+#define HASHBIN_SIZE 8
+#define HASHBIN_MASK 0x7
+
+#ifndef IRDA_ALIGN
+#define IRDA_ALIGN __attribute__((aligned))
+#endif
+
+#define Q_NULL { NULL, NULL, "", 0 }
+
+typedef void (*FREE_FUNC)(void *arg);
+
+struct irda_queue {
+ struct irda_queue *q_next;
+ struct irda_queue *q_prev;
+
+ char q_name[NAME_SIZE];
+ long q_hash; /* Must be able to cast a (void *) */
+};
+typedef struct irda_queue irda_queue_t;
+
+typedef struct hashbin_t {
+ __u32 magic;
+ int hb_type;
+ int hb_size;
+ spinlock_t hb_spinlock; /* HB_LOCK - Can be used by the user */
+
+ irda_queue_t* hb_queue[HASHBIN_SIZE] IRDA_ALIGN;
+
+ irda_queue_t* hb_current;
+} hashbin_t;
+
+hashbin_t *hashbin_new(int type);
+int hashbin_delete(hashbin_t* hashbin, FREE_FUNC func);
+int hashbin_clear(hashbin_t* hashbin, FREE_FUNC free_func);
+void hashbin_insert(hashbin_t* hashbin, irda_queue_t* entry, long hashv,
+ const char* name);
+void* hashbin_remove(hashbin_t* hashbin, long hashv, const char* name);
+void* hashbin_remove_first(hashbin_t *hashbin);
+void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry);
+void* hashbin_find(hashbin_t* hashbin, long hashv, const char* name);
+void* hashbin_lock_find(hashbin_t* hashbin, long hashv, const char* name);
+void* hashbin_find_next(hashbin_t* hashbin, long hashv, const char* name,
+ void ** pnext);
+irda_queue_t *hashbin_get_first(hashbin_t *hashbin);
+irda_queue_t *hashbin_get_next(hashbin_t *hashbin);
+
+#define HASHBIN_GET_SIZE(hashbin) hashbin->hb_size
+
+#endif
diff --git a/include/net/irda/irttp.h b/include/net/irda/irttp.h
new file mode 100644
index 00000000..af4b8772
--- /dev/null
+++ b/include/net/irda/irttp.h
@@ -0,0 +1,210 @@
+/*********************************************************************
+ *
+ * Filename: irttp.h
+ * Version: 1.0
+ * Description: Tiny Transport Protocol (TTP) definitions
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Sun Aug 31 20:14:31 1997
+ * Modified at: Sun Dec 12 13:09:07 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
+ * All Rights Reserved.
+ * Copyright (c) 2000-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef IRTTP_H
+#define IRTTP_H
+
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irlmp.h> /* struct lsap_cb */
+#include <net/irda/qos.h> /* struct qos_info */
+#include <net/irda/irqueue.h>
+
+#define TTP_MAX_CONNECTIONS LM_MAX_CONNECTIONS
+#define TTP_HEADER 1
+#define TTP_MAX_HEADER (TTP_HEADER + LMP_MAX_HEADER)
+#define TTP_SAR_HEADER 5
+#define TTP_PARAMETERS 0x80
+#define TTP_MORE 0x80
+
+/* Transmission queue sizes */
+/* Worst case scenario, two window of data - Jean II */
+#define TTP_TX_MAX_QUEUE 14
+/* We need to keep at least 5 frames to make sure that we can refill
+ * appropriately the LAP layer. LAP keeps only two buffers, and we need
+ * to have 7 to make a full window - Jean II */
+#define TTP_TX_LOW_THRESHOLD 5
+/* Most clients are synchronous with respect to flow control, so we can
+ * keep a low number of Tx buffers in TTP - Jean II */
+#define TTP_TX_HIGH_THRESHOLD 7
+
+/* Receive queue sizes */
+/* Minimum of credit that the peer should hold.
+ * If the peer has less credits than 9 frames, we will explicitly send
+ * him some credits (through irttp_give_credit() and a specific frame).
+ * Note that when we give credits it's likely that it won't be sent in
+ * this LAP window, but in the next one. So, we make sure that the peer
+ * has something to send while waiting for credits (one LAP window == 7
+ * + 1 frames while he process the credits). - Jean II */
+#define TTP_RX_MIN_CREDIT 8
+/* This is the default maximum number of credits held by the peer, so the
+ * default maximum number of frames he can send us before needing flow
+ * control answer from us (this may be negociated differently at TSAP setup).
+ * We want to minimise the number of times we have to explicitly send some
+ * credit to the peer, hoping we can piggyback it on the return data. In
+ * particular, it doesn't make sense for us to send credit more than once
+ * per LAP window.
+ * Moreover, giving credits has some latency, so we need strictly more than
+ * a LAP window, otherwise we may already have credits in our Tx queue.
+ * But on the other hand, we don't want to keep too many Rx buffer here
+ * before starting to flow control the other end, so make it exactly one
+ * LAP window + 1 + MIN_CREDITS. - Jean II */
+#define TTP_RX_DEFAULT_CREDIT 16
+/* Maximum number of credits we can allow the peer to have, and therefore
+ * maximum Rx queue size.
+ * Note that we try to deliver packets to the higher layer every time we
+ * receive something, so in normal mode the Rx queue will never contains
+ * more than one or two packets. - Jean II */
+#define TTP_RX_MAX_CREDIT 21
+
+/* What clients should use when calling ttp_open_tsap() */
+#define DEFAULT_INITIAL_CREDIT TTP_RX_DEFAULT_CREDIT
+
+/* Some priorities for disconnect requests */
+#define P_NORMAL 0
+#define P_HIGH 1
+
+#define TTP_SAR_DISABLE 0
+#define TTP_SAR_UNBOUND 0xffffffff
+
+/* Parameters */
+#define TTP_MAX_SDU_SIZE 0x01
+
+/*
+ * This structure contains all data associated with one instance of a TTP
+ * connection.
+ */
+struct tsap_cb {
+ irda_queue_t q; /* Must be first */
+ magic_t magic; /* Just in case */
+
+ __u8 stsap_sel; /* Source TSAP */
+ __u8 dtsap_sel; /* Destination TSAP */
+
+ struct lsap_cb *lsap; /* Corresponding LSAP to this TSAP */
+
+ __u8 connected; /* TSAP connected */
+
+ __u8 initial_credit; /* Initial credit to give peer */
+
+ int avail_credit; /* Available credit to return to peer */
+ int remote_credit; /* Credit held by peer TTP entity */
+ int send_credit; /* Credit held by local TTP entity */
+
+ struct sk_buff_head tx_queue; /* Frames to be transmitted */
+ struct sk_buff_head rx_queue; /* Received frames */
+ struct sk_buff_head rx_fragments;
+ int tx_queue_lock;
+ int rx_queue_lock;
+ spinlock_t lock;
+
+ notify_t notify; /* Callbacks to client layer */
+
+ struct net_device_stats stats;
+ struct timer_list todo_timer;
+
+ __u32 max_seg_size; /* Max data that fit into an IrLAP frame */
+ __u8 max_header_size;
+
+ int rx_sdu_busy; /* RxSdu.busy */
+ __u32 rx_sdu_size; /* Current size of a partially received frame */
+ __u32 rx_max_sdu_size; /* Max receive user data size */
+
+ int tx_sdu_busy; /* TxSdu.busy */
+ __u32 tx_max_sdu_size; /* Max transmit user data size */
+
+ int close_pend; /* Close, but disconnect_pend */
+ unsigned long disconnect_pend; /* Disconnect, but still data to send */
+ struct sk_buff *disconnect_skb;
+};
+
+struct irttp_cb {
+ magic_t magic;
+ hashbin_t *tsaps;
+};
+
+int irttp_init(void);
+void irttp_cleanup(void);
+
+struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify);
+int irttp_close_tsap(struct tsap_cb *self);
+
+int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb);
+int irttp_udata_request(struct tsap_cb *self, struct sk_buff *skb);
+
+int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
+ __u32 saddr, __u32 daddr,
+ struct qos_info *qos, __u32 max_sdu_size,
+ struct sk_buff *userdata);
+int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
+ struct sk_buff *userdata);
+int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *skb,
+ int priority);
+void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow);
+struct tsap_cb *irttp_dup(struct tsap_cb *self, void *instance);
+
+static inline __u32 irttp_get_saddr(struct tsap_cb *self)
+{
+ return irlmp_get_saddr(self->lsap);
+}
+
+static inline __u32 irttp_get_daddr(struct tsap_cb *self)
+{
+ return irlmp_get_daddr(self->lsap);
+}
+
+static inline __u32 irttp_get_max_seg_size(struct tsap_cb *self)
+{
+ return self->max_seg_size;
+}
+
+/* After doing a irttp_dup(), this get one of the two socket back into
+ * a state where it's waiting incomming connections.
+ * Note : this can be used *only* if the socket is not yet connected
+ * (i.e. NO irttp_connect_response() done on this socket).
+ * - Jean II */
+static inline void irttp_listen(struct tsap_cb *self)
+{
+ irlmp_listen(self->lsap);
+ self->dtsap_sel = LSAP_ANY;
+}
+
+/* Return TRUE if the node is in primary mode (i.e. master)
+ * - Jean II */
+static inline int irttp_is_primary(struct tsap_cb *self)
+{
+ if ((self == NULL) ||
+ (self->lsap == NULL) ||
+ (self->lsap->lap == NULL) ||
+ (self->lsap->lap->irlap == NULL))
+ return -2;
+ return irlap_is_primary(self->lsap->lap->irlap);
+}
+
+#endif /* IRTTP_H */
diff --git a/include/net/irda/parameters.h b/include/net/irda/parameters.h
new file mode 100644
index 00000000..c0d93884
--- /dev/null
+++ b/include/net/irda/parameters.h
@@ -0,0 +1,102 @@
+/*********************************************************************
+ *
+ * Filename: parameters.h
+ * Version: 1.0
+ * Description: A more general way to handle (pi,pl,pv) parameters
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Mon Jun 7 08:47:28 1999
+ * Modified at: Sun Jan 30 14:05:14 2000
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Michel Dänzer <daenzer@debian.org>, 10/2001
+ * - simplify irda_pv_t to avoid endianness issues
+ *
+ ********************************************************************/
+
+#ifndef IRDA_PARAMS_H
+#define IRDA_PARAMS_H
+
+/*
+ * The currently supported types. Beware not to change the sequence since
+ * it a good reason why the sized integers has a value equal to their size
+ */
+typedef enum {
+ PV_INTEGER, /* Integer of any (pl) length */
+ PV_INT_8_BITS, /* Integer of 8 bits in length */
+ PV_INT_16_BITS, /* Integer of 16 bits in length */
+ PV_STRING, /* \0 terminated string */
+ PV_INT_32_BITS, /* Integer of 32 bits in length */
+ PV_OCT_SEQ, /* Octet sequence */
+ PV_NO_VALUE /* Does not contain any value (pl=0) */
+} PV_TYPE;
+
+/* Bit 7 of type field */
+#define PV_BIG_ENDIAN 0x80
+#define PV_LITTLE_ENDIAN 0x00
+#define PV_MASK 0x7f /* To mask away endian bit */
+
+#define PV_PUT 0
+#define PV_GET 1
+
+typedef union {
+ char *c;
+ __u32 i;
+ __u32 *ip;
+} irda_pv_t;
+
+typedef struct {
+ __u8 pi;
+ __u8 pl;
+ irda_pv_t pv;
+} irda_param_t;
+
+typedef int (*PI_HANDLER)(void *self, irda_param_t *param, int get);
+typedef int (*PV_HANDLER)(void *self, __u8 *buf, int len, __u8 pi,
+ PV_TYPE type, PI_HANDLER func);
+
+typedef struct {
+ PI_HANDLER func; /* Handler for this parameter identifier */
+ PV_TYPE type; /* Data type for this parameter */
+} pi_minor_info_t;
+
+typedef struct {
+ pi_minor_info_t *pi_minor_call_table;
+ int len;
+} pi_major_info_t;
+
+typedef struct {
+ pi_major_info_t *tables;
+ int len;
+ __u8 pi_mask;
+ int pi_major_offset;
+} pi_param_info_t;
+
+int irda_param_pack(__u8 *buf, char *fmt, ...);
+
+int irda_param_insert(void *self, __u8 pi, __u8 *buf, int len,
+ pi_param_info_t *info);
+int irda_param_extract_all(void *self, __u8 *buf, int len,
+ pi_param_info_t *info);
+
+#define irda_param_insert_byte(buf,pi,pv) irda_param_pack(buf,"bbb",pi,1,pv)
+
+#endif /* IRDA_PARAMS_H */
+
diff --git a/include/net/irda/qos.h b/include/net/irda/qos.h
new file mode 100644
index 00000000..cc577dc0
--- /dev/null
+++ b/include/net/irda/qos.h
@@ -0,0 +1,103 @@
+/*********************************************************************
+ *
+ * Filename: qos.h
+ * Version: 1.0
+ * Description: Quality of Service definitions
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Fri Sep 19 23:21:09 1997
+ * Modified at: Thu Dec 2 13:51:54 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ********************************************************************/
+
+#ifndef IRDA_QOS_H
+#define IRDA_QOS_H
+
+#include <linux/skbuff.h>
+
+#include <net/irda/parameters.h>
+
+#define PI_BAUD_RATE 0x01
+#define PI_MAX_TURN_TIME 0x82
+#define PI_DATA_SIZE 0x83
+#define PI_WINDOW_SIZE 0x84
+#define PI_ADD_BOFS 0x85
+#define PI_MIN_TURN_TIME 0x86
+#define PI_LINK_DISC 0x08
+
+#define IR_115200_MAX 0x3f
+
+/* Baud rates (first byte) */
+#define IR_2400 0x01
+#define IR_9600 0x02
+#define IR_19200 0x04
+#define IR_38400 0x08
+#define IR_57600 0x10
+#define IR_115200 0x20
+#define IR_576000 0x40
+#define IR_1152000 0x80
+
+/* Baud rates (second byte) */
+#define IR_4000000 0x01
+#define IR_16000000 0x02
+
+/* Quality of Service information */
+typedef struct {
+ __u32 value;
+ __u16 bits; /* LSB is first byte, MSB is second byte */
+} qos_value_t;
+
+struct qos_info {
+ magic_t magic;
+
+ qos_value_t baud_rate; /* IR_11520O | ... */
+ qos_value_t max_turn_time;
+ qos_value_t data_size;
+ qos_value_t window_size;
+ qos_value_t additional_bofs;
+ qos_value_t min_turn_time;
+ qos_value_t link_disc_time;
+
+ qos_value_t power;
+};
+
+extern int sysctl_max_baud_rate;
+extern int sysctl_max_inactive_time;
+
+void irda_init_max_qos_capabilies(struct qos_info *qos);
+void irda_qos_compute_intersection(struct qos_info *, struct qos_info *);
+
+__u32 irlap_max_line_capacity(__u32 speed, __u32 max_turn_time);
+
+void irda_qos_bits_to_value(struct qos_info *qos);
+
+/* So simple, how could we not inline those two ?
+ * Note : one byte is 10 bits if you include start and stop bits
+ * Jean II */
+#define irlap_min_turn_time_in_bytes(speed, min_turn_time) ( \
+ speed * min_turn_time / 10000000 \
+)
+#define irlap_xbofs_in_usec(speed, xbofs) ( \
+ xbofs * 10000000 / speed \
+)
+
+#endif
+
diff --git a/include/net/irda/timer.h b/include/net/irda/timer.h
new file mode 100644
index 00000000..cb2615cc
--- /dev/null
+++ b/include/net/irda/timer.h
@@ -0,0 +1,105 @@
+/*********************************************************************
+ *
+ * Filename: timer.h
+ * Version:
+ * Description:
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Sat Aug 16 00:59:29 1997
+ * Modified at: Thu Oct 7 12:25:24 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1997, 1998-1999 Dag Brattli <dagb@cs.uit.no>,
+ * All Rights Reserved.
+ * Copyright (c) 2000-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef TIMER_H
+#define TIMER_H
+
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+
+#include <asm/param.h> /* for HZ */
+
+#include <net/irda/irda.h>
+
+/* A few forward declarations (to make compiler happy) */
+struct irlmp_cb;
+struct irlap_cb;
+struct lsap_cb;
+struct lap_cb;
+
+/*
+ * Timeout definitions, some defined in IrLAP 6.13.5 - p. 92
+ */
+#define POLL_TIMEOUT (450*HZ/1000) /* Must never exceed 500 ms */
+#define FINAL_TIMEOUT (500*HZ/1000) /* Must never exceed 500 ms */
+
+/*
+ * Normally twice of p-timer. Note 3, IrLAP 6.3.11.2 - p. 60 suggests
+ * at least twice duration of the P-timer.
+ */
+#define WD_TIMEOUT (POLL_TIMEOUT*2)
+
+#define MEDIABUSY_TIMEOUT (500*HZ/1000) /* 500 msec */
+#define SMALLBUSY_TIMEOUT (100*HZ/1000) /* 100 msec - IrLAP 6.13.4 */
+
+/*
+ * Slot timer must never exceed 85 ms, and must always be at least 25 ms,
+ * suggested to 75-85 msec by IrDA lite. This doesn't work with a lot of
+ * devices, and other stackes uses a lot more, so it's best we do it as well
+ * (Note : this is the default value and sysctl overides it - Jean II)
+ */
+#define SLOT_TIMEOUT (90*HZ/1000)
+
+/*
+ * The latest discovery frame (XID) is longer due to the extra discovery
+ * information (hints, device name...). This is its extra length.
+ * We use that when setting the query timeout. Jean II
+ */
+#define XIDEXTRA_TIMEOUT (34*HZ/1000) /* 34 msec */
+
+#define WATCHDOG_TIMEOUT (20*HZ) /* 20 sec */
+
+typedef void (*TIMER_CALLBACK)(void *);
+
+static inline void irda_start_timer(struct timer_list *ptimer, int timeout,
+ void* data, TIMER_CALLBACK callback)
+{
+ ptimer->function = (void (*)(unsigned long)) callback;
+ ptimer->data = (unsigned long) data;
+
+ /* Set new value for timer (update or add timer).
+ * We use mod_timer() because it's more efficient and also
+ * safer with respect to race conditions - Jean II */
+ mod_timer(ptimer, jiffies + timeout);
+}
+
+
+void irlap_start_slot_timer(struct irlap_cb *self, int timeout);
+void irlap_start_query_timer(struct irlap_cb *self, int S, int s);
+void irlap_start_final_timer(struct irlap_cb *self, int timeout);
+void irlap_start_wd_timer(struct irlap_cb *self, int timeout);
+void irlap_start_backoff_timer(struct irlap_cb *self, int timeout);
+
+void irlap_start_mbusy_timer(struct irlap_cb *self, int timeout);
+void irlap_stop_mbusy_timer(struct irlap_cb *);
+
+void irlmp_start_watchdog_timer(struct lsap_cb *, int timeout);
+void irlmp_start_discovery_timer(struct irlmp_cb *, int timeout);
+void irlmp_start_idle_timer(struct lap_cb *, int timeout);
+void irlmp_stop_idle_timer(struct lap_cb *self);
+
+#endif
+
diff --git a/include/net/irda/wrapper.h b/include/net/irda/wrapper.h
new file mode 100644
index 00000000..eef53ebe
--- /dev/null
+++ b/include/net/irda/wrapper.h
@@ -0,0 +1,58 @@
+/*********************************************************************
+ *
+ * Filename: wrapper.h
+ * Version: 1.2
+ * Description: IrDA SIR async wrapper layer
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Mon Aug 4 20:40:53 1997
+ * Modified at: Tue Jan 11 12:37:29 2000
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef WRAPPER_H
+#define WRAPPER_H
+
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+#include <net/irda/irda_device.h> /* iobuff_t */
+
+#define BOF 0xc0 /* Beginning of frame */
+#define XBOF 0xff
+#define EOF 0xc1 /* End of frame */
+#define CE 0x7d /* Control escape */
+
+#define STA BOF /* Start flag */
+#define STO EOF /* End flag */
+
+#define IRDA_TRANS 0x20 /* Asynchronous transparency modifier */
+
+/* States for receiving a frame in async mode */
+enum {
+ OUTSIDE_FRAME,
+ BEGIN_FRAME,
+ LINK_ESCAPE,
+ INSIDE_FRAME
+};
+
+/* Proto definitions */
+int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize);
+void async_unwrap_char(struct net_device *dev, struct net_device_stats *stats,
+ iobuff_t *buf, __u8 byte);
+
+#endif
diff --git a/include/net/iucv/af_iucv.h b/include/net/iucv/af_iucv.h
new file mode 100644
index 00000000..cc7c1973
--- /dev/null
+++ b/include/net/iucv/af_iucv.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2006 IBM Corporation
+ * IUCV protocol stack for Linux on zSeries
+ * Version 1.0
+ * Author(s): Jennifer Hunt <jenhunt@us.ibm.com>
+ *
+ */
+
+#ifndef __AFIUCV_H
+#define __AFIUCV_H
+
+#include <asm/types.h>
+#include <asm/byteorder.h>
+#include <linux/list.h>
+#include <linux/poll.h>
+#include <linux/socket.h>
+#include <net/iucv/iucv.h>
+
+#ifndef AF_IUCV
+#define AF_IUCV 32
+#define PF_IUCV AF_IUCV
+#endif
+
+/* Connection and socket states */
+enum {
+ IUCV_CONNECTED = 1,
+ IUCV_OPEN,
+ IUCV_BOUND,
+ IUCV_LISTEN,
+ IUCV_DISCONN,
+ IUCV_CLOSING,
+ IUCV_CLOSED
+};
+
+#define IUCV_QUEUELEN_DEFAULT 65535
+#define IUCV_HIPER_MSGLIM_DEFAULT 128
+#define IUCV_CONN_TIMEOUT (HZ * 40)
+#define IUCV_DISCONN_TIMEOUT (HZ * 2)
+#define IUCV_CONN_IDLE_TIMEOUT (HZ * 60)
+#define IUCV_BUFSIZE_DEFAULT 32768
+
+/* IUCV socket address */
+struct sockaddr_iucv {
+ sa_family_t siucv_family;
+ unsigned short siucv_port; /* Reserved */
+ unsigned int siucv_addr; /* Reserved */
+ char siucv_nodeid[8]; /* Reserved */
+ char siucv_user_id[8]; /* Guest User Id */
+ char siucv_name[8]; /* Application Name */
+};
+
+
+/* Common socket structures and functions */
+struct sock_msg_q {
+ struct iucv_path *path;
+ struct iucv_message msg;
+ struct list_head list;
+ spinlock_t lock;
+};
+
+#define AF_IUCV_FLAG_ACK 0x1
+#define AF_IUCV_FLAG_SYN 0x2
+#define AF_IUCV_FLAG_FIN 0x4
+#define AF_IUCV_FLAG_WIN 0x8
+#define AF_IUCV_FLAG_SHT 0x10
+
+struct af_iucv_trans_hdr {
+ u16 magic;
+ u8 version;
+ u8 flags;
+ u16 window;
+ char destNodeID[8];
+ char destUserID[8];
+ char destAppName[16];
+ char srcNodeID[8];
+ char srcUserID[8];
+ char srcAppName[16]; /* => 70 bytes */
+ struct iucv_message iucv_hdr; /* => 33 bytes */
+ u8 pad; /* total 104 bytes */
+} __packed;
+
+enum iucv_tx_notify {
+ /* transmission of skb is completed and was successful */
+ TX_NOTIFY_OK = 0,
+ /* target is unreachable */
+ TX_NOTIFY_UNREACHABLE = 1,
+ /* transfer pending queue full */
+ TX_NOTIFY_TPQFULL = 2,
+ /* general error */
+ TX_NOTIFY_GENERALERROR = 3,
+ /* transmission of skb is pending - may interleave
+ * with TX_NOTIFY_DELAYED_* */
+ TX_NOTIFY_PENDING = 4,
+ /* transmission of skb was done successfully (delayed) */
+ TX_NOTIFY_DELAYED_OK = 5,
+ /* target unreachable (detected delayed) */
+ TX_NOTIFY_DELAYED_UNREACHABLE = 6,
+ /* general error (detected delayed) */
+ TX_NOTIFY_DELAYED_GENERALERROR = 7,
+};
+
+#define iucv_sk(__sk) ((struct iucv_sock *) __sk)
+
+#define AF_IUCV_TRANS_IUCV 0
+#define AF_IUCV_TRANS_HIPER 1
+
+struct iucv_sock {
+ struct sock sk;
+ char src_user_id[8];
+ char src_name[8];
+ char dst_user_id[8];
+ char dst_name[8];
+ struct list_head accept_q;
+ spinlock_t accept_q_lock;
+ struct sock *parent;
+ struct iucv_path *path;
+ struct net_device *hs_dev;
+ struct sk_buff_head send_skb_q;
+ struct sk_buff_head backlog_skb_q;
+ struct sock_msg_q message_q;
+ unsigned int send_tag;
+ u8 flags;
+ u16 msglimit;
+ u16 msglimit_peer;
+ atomic_t msg_sent;
+ atomic_t msg_recv;
+ atomic_t pendings;
+ int transport;
+ void (*sk_txnotify)(struct sk_buff *skb,
+ enum iucv_tx_notify n);
+};
+
+/* iucv socket options (SOL_IUCV) */
+#define SO_IPRMDATA_MSG 0x0080 /* send/recv IPRM_DATA msgs */
+#define SO_MSGLIMIT 0x1000 /* get/set IUCV MSGLIMIT */
+#define SO_MSGSIZE 0x0800 /* get maximum msgsize */
+
+/* iucv related control messages (scm) */
+#define SCM_IUCV_TRGCLS 0x0001 /* target class control message */
+
+struct iucv_sock_list {
+ struct hlist_head head;
+ rwlock_t lock;
+ atomic_t autobind_name;
+};
+
+unsigned int iucv_sock_poll(struct file *file, struct socket *sock,
+ poll_table *wait);
+void iucv_sock_link(struct iucv_sock_list *l, struct sock *s);
+void iucv_sock_unlink(struct iucv_sock_list *l, struct sock *s);
+void iucv_accept_enqueue(struct sock *parent, struct sock *sk);
+void iucv_accept_unlink(struct sock *sk);
+struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock);
+
+#endif /* __IUCV_H */
diff --git a/include/net/iucv/iucv.h b/include/net/iucv/iucv.h
new file mode 100644
index 00000000..0894ced3
--- /dev/null
+++ b/include/net/iucv/iucv.h
@@ -0,0 +1,495 @@
+/*
+ * drivers/s390/net/iucv.h
+ * IUCV base support.
+ *
+ * S390 version
+ * Copyright 2000, 2006 IBM Corporation
+ * Author(s):Alan Altmark (Alan_Altmark@us.ibm.com)
+ * Xenia Tkatschow (xenia@us.ibm.com)
+ * Rewritten for af_iucv:
+ * Martin Schwidefsky <schwidefsky@de.ibm.com>
+ *
+ *
+ * Functionality:
+ * To explore any of the IUCV functions, one must first register their
+ * program using iucv_register(). Once your program has successfully
+ * completed a register, it can exploit the other functions.
+ * For furthur reference on all IUCV functionality, refer to the
+ * CP Programming Services book, also available on the web thru
+ * www.vm.ibm.com/pubs, manual # SC24-6084
+ *
+ * Definition of Return Codes
+ * - All positive return codes including zero are reflected back
+ * from CP. The definition of each return code can be found in
+ * CP Programming Services book.
+ * - Return Code of:
+ * -EINVAL: Invalid value
+ * -ENOMEM: storage allocation failed
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <asm/debug.h>
+
+/*
+ * IUCV option flags usable by device drivers:
+ *
+ * IUCV_IPRMDATA Indicates that your program can handle a message in the
+ * parameter list / a message is sent in the parameter list.
+ * Used for iucv_path_accept, iucv_path_connect,
+ * iucv_message_reply, iucv_message_send, iucv_message_send2way.
+ * IUCV_IPQUSCE Indicates that you do not want to receive messages on this
+ * path until an iucv_path_resume is issued.
+ * Used for iucv_path_accept, iucv_path_connect.
+ * IUCV_IPBUFLST Indicates that an address list is used for the message data.
+ * Used for iucv_message_receive, iucv_message_send,
+ * iucv_message_send2way.
+ * IUCV_IPPRTY Specifies that you want to send priority messages.
+ * Used for iucv_path_accept, iucv_path_connect,
+ * iucv_message_reply, iucv_message_send, iucv_message_send2way.
+ * IUCV_IPSYNC Indicates a synchronous send request.
+ * Used for iucv_message_send, iucv_message_send2way.
+ * IUCV_IPANSLST Indicates that an address list is used for the reply data.
+ * Used for iucv_message_reply, iucv_message_send2way.
+ * IUCV_IPLOCAL Specifies that the communication partner has to be on the
+ * local system. If local is specified no target class can be
+ * specified.
+ * Used for iucv_path_connect.
+ *
+ * All flags are defined in the input field IPFLAGS1 of each function
+ * and can be found in CP Programming Services.
+ */
+#define IUCV_IPRMDATA 0x80
+#define IUCV_IPQUSCE 0x40
+#define IUCV_IPBUFLST 0x40
+#define IUCV_IPPRTY 0x20
+#define IUCV_IPANSLST 0x08
+#define IUCV_IPSYNC 0x04
+#define IUCV_IPLOCAL 0x01
+
+/*
+ * iucv_array : Defines buffer array.
+ * Inside the array may be 31- bit addresses and 31-bit lengths.
+ * Use a pointer to an iucv_array as the buffer, reply or answer
+ * parameter on iucv_message_send, iucv_message_send2way, iucv_message_receive
+ * and iucv_message_reply if IUCV_IPBUFLST or IUCV_IPANSLST are used.
+ */
+struct iucv_array {
+ u32 address;
+ u32 length;
+} __attribute__ ((aligned (8)));
+
+extern struct bus_type iucv_bus;
+extern struct device *iucv_root;
+
+/*
+ * struct iucv_path
+ * pathid: 16 bit path identification
+ * msglim: 16 bit message limit
+ * flags: properties of the path: IPRMDATA, IPQUSCE, IPPRTY
+ * handler: address of iucv handler structure
+ * private: private information of the handler associated with the path
+ * list: list_head for the iucv_handler path list.
+ */
+struct iucv_path {
+ u16 pathid;
+ u16 msglim;
+ u8 flags;
+ void *private;
+ struct iucv_handler *handler;
+ struct list_head list;
+};
+
+/*
+ * struct iucv_message
+ * id: 32 bit message id
+ * audit: 32 bit error information of purged or replied messages
+ * class: 32 bit target class of a message (source class for replies)
+ * tag: 32 bit tag to be associated with the message
+ * length: 32 bit length of the message / reply
+ * reply_size: 32 bit maximum allowed length of the reply
+ * rmmsg: 8 byte inline message
+ * flags: message properties (IUCV_IPPRTY)
+ */
+struct iucv_message {
+ u32 id;
+ u32 audit;
+ u32 class;
+ u32 tag;
+ u32 length;
+ u32 reply_size;
+ u8 rmmsg[8];
+ u8 flags;
+} __packed;
+
+/*
+ * struct iucv_handler
+ *
+ * A vector of functions that handle IUCV interrupts. Each functions gets
+ * a parameter area as defined by the CP Programming Services and private
+ * pointer that is provided by the user of the interface.
+ */
+struct iucv_handler {
+ /*
+ * The path_pending function is called after an iucv interrupt
+ * type 0x01 has been received. The base code allocates a path
+ * structure and "asks" the handler if this path belongs to the
+ * handler. To accept the path the path_pending function needs
+ * to call iucv_path_accept and return 0. If the callback returns
+ * a value != 0 the iucv base code will continue with the next
+ * handler. The order in which the path_pending functions are
+ * called is the order of the registration of the iucv handlers
+ * to the base code.
+ */
+ int (*path_pending)(struct iucv_path *, u8 ipvmid[8], u8 ipuser[16]);
+ /*
+ * The path_complete function is called after an iucv interrupt
+ * type 0x02 has been received for a path that has been established
+ * for this handler with iucv_path_connect and got accepted by the
+ * peer with iucv_path_accept.
+ */
+ void (*path_complete)(struct iucv_path *, u8 ipuser[16]);
+ /*
+ * The path_severed function is called after an iucv interrupt
+ * type 0x03 has been received. The communication peer shutdown
+ * his end of the communication path. The path still exists and
+ * remaining messages can be received until a iucv_path_sever
+ * shuts down the other end of the path as well.
+ */
+ void (*path_severed)(struct iucv_path *, u8 ipuser[16]);
+ /*
+ * The path_quiesced function is called after an icuv interrupt
+ * type 0x04 has been received. The communication peer has quiesced
+ * the path. Delivery of messages is stopped until iucv_path_resume
+ * has been called.
+ */
+ void (*path_quiesced)(struct iucv_path *, u8 ipuser[16]);
+ /*
+ * The path_resumed function is called after an icuv interrupt
+ * type 0x05 has been received. The communication peer has resumed
+ * the path.
+ */
+ void (*path_resumed)(struct iucv_path *, u8 ipuser[16]);
+ /*
+ * The message_pending function is called after an icuv interrupt
+ * type 0x06 or type 0x07 has been received. A new message is
+ * available and can be received with iucv_message_receive.
+ */
+ void (*message_pending)(struct iucv_path *, struct iucv_message *);
+ /*
+ * The message_complete function is called after an icuv interrupt
+ * type 0x08 or type 0x09 has been received. A message send with
+ * iucv_message_send2way has been replied to. The reply can be
+ * received with iucv_message_receive.
+ */
+ void (*message_complete)(struct iucv_path *, struct iucv_message *);
+
+ struct list_head list;
+ struct list_head paths;
+};
+
+/**
+ * iucv_register:
+ * @handler: address of iucv handler structure
+ * @smp: != 0 indicates that the handler can deal with out of order messages
+ *
+ * Registers a driver with IUCV.
+ *
+ * Returns 0 on success, -ENOMEM if the memory allocation for the pathid
+ * table failed, or -EIO if IUCV_DECLARE_BUFFER failed on all cpus.
+ */
+int iucv_register(struct iucv_handler *handler, int smp);
+
+/**
+ * iucv_unregister
+ * @handler: address of iucv handler structure
+ * @smp: != 0 indicates that the handler can deal with out of order messages
+ *
+ * Unregister driver from IUCV.
+ */
+void iucv_unregister(struct iucv_handler *handle, int smp);
+
+/**
+ * iucv_path_alloc
+ * @msglim: initial message limit
+ * @flags: initial flags
+ * @gfp: kmalloc allocation flag
+ *
+ * Allocate a new path structure for use with iucv_connect.
+ *
+ * Returns NULL if the memory allocation failed or a pointer to the
+ * path structure.
+ */
+static inline struct iucv_path *iucv_path_alloc(u16 msglim, u8 flags, gfp_t gfp)
+{
+ struct iucv_path *path;
+
+ path = kzalloc(sizeof(struct iucv_path), gfp);
+ if (path) {
+ path->msglim = msglim;
+ path->flags = flags;
+ }
+ return path;
+}
+
+/**
+ * iucv_path_free
+ * @path: address of iucv path structure
+ *
+ * Frees a path structure.
+ */
+static inline void iucv_path_free(struct iucv_path *path)
+{
+ kfree(path);
+}
+
+/**
+ * iucv_path_accept
+ * @path: address of iucv path structure
+ * @handler: address of iucv handler structure
+ * @userdata: 16 bytes of data reflected to the communication partner
+ * @private: private data passed to interrupt handlers for this path
+ *
+ * This function is issued after the user received a connection pending
+ * external interrupt and now wishes to complete the IUCV communication path.
+ *
+ * Returns the result of the CP IUCV call.
+ */
+int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler,
+ u8 userdata[16], void *private);
+
+/**
+ * iucv_path_connect
+ * @path: address of iucv path structure
+ * @handler: address of iucv handler structure
+ * @userid: 8-byte user identification
+ * @system: 8-byte target system identification
+ * @userdata: 16 bytes of data reflected to the communication partner
+ * @private: private data passed to interrupt handlers for this path
+ *
+ * This function establishes an IUCV path. Although the connect may complete
+ * successfully, you are not able to use the path until you receive an IUCV
+ * Connection Complete external interrupt.
+ *
+ * Returns the result of the CP IUCV call.
+ */
+int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
+ u8 userid[8], u8 system[8], u8 userdata[16],
+ void *private);
+
+/**
+ * iucv_path_quiesce:
+ * @path: address of iucv path structure
+ * @userdata: 16 bytes of data reflected to the communication partner
+ *
+ * This function temporarily suspends incoming messages on an IUCV path.
+ * You can later reactivate the path by invoking the iucv_resume function.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_path_quiesce(struct iucv_path *path, u8 userdata[16]);
+
+/**
+ * iucv_path_resume:
+ * @path: address of iucv path structure
+ * @userdata: 16 bytes of data reflected to the communication partner
+ *
+ * This function resumes incoming messages on an IUCV path that has
+ * been stopped with iucv_path_quiesce.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_path_resume(struct iucv_path *path, u8 userdata[16]);
+
+/**
+ * iucv_path_sever
+ * @path: address of iucv path structure
+ * @userdata: 16 bytes of data reflected to the communication partner
+ *
+ * This function terminates an IUCV path.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_path_sever(struct iucv_path *path, u8 userdata[16]);
+
+/**
+ * iucv_message_purge
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @srccls: source class of message
+ *
+ * Cancels a message you have sent.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg,
+ u32 srccls);
+
+/**
+ * iucv_message_receive
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @flags: flags that affect how the message is received (IUCV_IPBUFLST)
+ * @buffer: address of data buffer or address of struct iucv_array
+ * @size: length of data buffer
+ * @residual:
+ *
+ * This function receives messages that are being sent to you over
+ * established paths. This function will deal with RMDATA messages
+ * embedded in struct iucv_message as well.
+ *
+ * Locking: local_bh_enable/local_bh_disable
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
+ u8 flags, void *buffer, size_t size, size_t *residual);
+
+/**
+ * __iucv_message_receive
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @flags: flags that affect how the message is received (IUCV_IPBUFLST)
+ * @buffer: address of data buffer or address of struct iucv_array
+ * @size: length of data buffer
+ * @residual:
+ *
+ * This function receives messages that are being sent to you over
+ * established paths. This function will deal with RMDATA messages
+ * embedded in struct iucv_message as well.
+ *
+ * Locking: no locking.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int __iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
+ u8 flags, void *buffer, size_t size,
+ size_t *residual);
+
+/**
+ * iucv_message_reject
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ *
+ * The reject function refuses a specified message. Between the time you
+ * are notified of a message and the time that you complete the message,
+ * the message may be rejected.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg);
+
+/**
+ * iucv_message_reply
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @flags: how the reply is sent (IUCV_IPRMDATA, IUCV_IPPRTY, IUCV_IPBUFLST)
+ * @reply: address of data buffer or address of struct iucv_array
+ * @size: length of reply data buffer
+ *
+ * This function responds to the two-way messages that you receive. You
+ * must identify completely the message to which you wish to reply. ie,
+ * pathid, msgid, and trgcls. Prmmsg signifies the data is moved into
+ * the parameter list.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg,
+ u8 flags, void *reply, size_t size);
+
+/**
+ * iucv_message_send
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @flags: how the message is sent (IUCV_IPRMDATA, IUCV_IPPRTY, IUCV_IPBUFLST)
+ * @srccls: source class of message
+ * @buffer: address of data buffer or address of struct iucv_array
+ * @size: length of send buffer
+ *
+ * This function transmits data to another application. Data to be
+ * transmitted is in a buffer and this is a one-way message and the
+ * receiver will not reply to the message.
+ *
+ * Locking: local_bh_enable/local_bh_disable
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
+ u8 flags, u32 srccls, void *buffer, size_t size);
+
+/**
+ * __iucv_message_send
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @flags: how the message is sent (IUCV_IPRMDATA, IUCV_IPPRTY, IUCV_IPBUFLST)
+ * @srccls: source class of message
+ * @buffer: address of data buffer or address of struct iucv_array
+ * @size: length of send buffer
+ *
+ * This function transmits data to another application. Data to be
+ * transmitted is in a buffer and this is a one-way message and the
+ * receiver will not reply to the message.
+ *
+ * Locking: no locking.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int __iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
+ u8 flags, u32 srccls, void *buffer, size_t size);
+
+/**
+ * iucv_message_send2way
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @flags: how the message is sent and the reply is received
+ * (IUCV_IPRMDATA, IUCV_IPBUFLST, IUCV_IPPRTY, IUCV_ANSLST)
+ * @srccls: source class of message
+ * @buffer: address of data buffer or address of struct iucv_array
+ * @size: length of send buffer
+ * @ansbuf: address of answer buffer or address of struct iucv_array
+ * @asize: size of reply buffer
+ *
+ * This function transmits data to another application. Data to be
+ * transmitted is in a buffer. The receiver of the send is expected to
+ * reply to the message and a buffer is provided into which IUCV moves
+ * the reply to this message.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg,
+ u8 flags, u32 srccls, void *buffer, size_t size,
+ void *answer, size_t asize, size_t *residual);
+
+struct iucv_interface {
+ int (*message_receive)(struct iucv_path *path, struct iucv_message *msg,
+ u8 flags, void *buffer, size_t size, size_t *residual);
+ int (*__message_receive)(struct iucv_path *path,
+ struct iucv_message *msg, u8 flags, void *buffer, size_t size,
+ size_t *residual);
+ int (*message_reply)(struct iucv_path *path, struct iucv_message *msg,
+ u8 flags, void *reply, size_t size);
+ int (*message_reject)(struct iucv_path *path, struct iucv_message *msg);
+ int (*message_send)(struct iucv_path *path, struct iucv_message *msg,
+ u8 flags, u32 srccls, void *buffer, size_t size);
+ int (*__message_send)(struct iucv_path *path, struct iucv_message *msg,
+ u8 flags, u32 srccls, void *buffer, size_t size);
+ int (*message_send2way)(struct iucv_path *path,
+ struct iucv_message *msg, u8 flags, u32 srccls, void *buffer,
+ size_t size, void *answer, size_t asize, size_t *residual);
+ int (*message_purge)(struct iucv_path *path, struct iucv_message *msg,
+ u32 srccls);
+ int (*path_accept)(struct iucv_path *path, struct iucv_handler *handler,
+ u8 userdata[16], void *private);
+ int (*path_connect)(struct iucv_path *path,
+ struct iucv_handler *handler,
+ u8 userid[8], u8 system[8], u8 userdata[16], void *private);
+ int (*path_quiesce)(struct iucv_path *path, u8 userdata[16]);
+ int (*path_resume)(struct iucv_path *path, u8 userdata[16]);
+ int (*path_sever)(struct iucv_path *path, u8 userdata[16]);
+ int (*iucv_register)(struct iucv_handler *handler, int smp);
+ void (*iucv_unregister)(struct iucv_handler *handler, int smp);
+ struct bus_type *bus;
+ struct device *root;
+};
+
+extern struct iucv_interface iucv_if;
diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h
new file mode 100644
index 00000000..5d5a6a47
--- /dev/null
+++ b/include/net/iw_handler.h
@@ -0,0 +1,587 @@
+/*
+ * This file define the new driver API for Wireless Extensions
+ *
+ * Version : 8 16.3.07
+ *
+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+ * Copyright (c) 2001-2007 Jean Tourrilhes, All Rights Reserved.
+ */
+
+#ifndef _IW_HANDLER_H
+#define _IW_HANDLER_H
+
+/************************** DOCUMENTATION **************************/
+/*
+ * Initial driver API (1996 -> onward) :
+ * -----------------------------------
+ * The initial API just sends the IOCTL request received from user space
+ * to the driver (via the driver ioctl handler). The driver has to
+ * handle all the rest...
+ *
+ * The initial API also defines a specific handler in struct net_device
+ * to handle wireless statistics.
+ *
+ * The initial APIs served us well and has proven a reasonably good design.
+ * However, there is a few shortcommings :
+ * o No events, everything is a request to the driver.
+ * o Large ioctl function in driver with gigantic switch statement
+ * (i.e. spaghetti code).
+ * o Driver has to mess up with copy_to/from_user, and in many cases
+ * does it unproperly. Common mistakes are :
+ * * buffer overflows (no checks or off by one checks)
+ * * call copy_to/from_user with irq disabled
+ * o The user space interface is tied to ioctl because of the use
+ * copy_to/from_user.
+ *
+ * New driver API (2002 -> onward) :
+ * -------------------------------
+ * The new driver API is just a bunch of standard functions (handlers),
+ * each handling a specific Wireless Extension. The driver just export
+ * the list of handler it supports, and those will be called apropriately.
+ *
+ * I tried to keep the main advantage of the previous API (simplicity,
+ * efficiency and light weight), and also I provide a good dose of backward
+ * compatibility (most structures are the same, driver can use both API
+ * simultaneously, ...).
+ * Hopefully, I've also addressed the shortcomming of the initial API.
+ *
+ * The advantage of the new API are :
+ * o Handling of Extensions in driver broken in small contained functions
+ * o Tighter checks of ioctl before calling the driver
+ * o Flexible commit strategy (at least, the start of it)
+ * o Backward compatibility (can be mixed with old API)
+ * o Driver doesn't have to worry about memory and user-space issues
+ * The last point is important for the following reasons :
+ * o You are now able to call the new driver API from any API you
+ * want (including from within other parts of the kernel).
+ * o Common mistakes are avoided (buffer overflow, user space copy
+ * with irq disabled and so on).
+ *
+ * The Drawback of the new API are :
+ * o bloat (especially kernel)
+ * o need to migrate existing drivers to new API
+ * My initial testing shows that the new API adds around 3kB to the kernel
+ * and save between 0 and 5kB from a typical driver.
+ * Also, as all structures and data types are unchanged, the migration is
+ * quite straightforward (but tedious).
+ *
+ * ---
+ *
+ * The new driver API is defined below in this file. User space should
+ * not be aware of what's happening down there...
+ *
+ * A new kernel wrapper is in charge of validating the IOCTLs and calling
+ * the appropriate driver handler. This is implemented in :
+ * # net/core/wireless.c
+ *
+ * The driver export the list of handlers in :
+ * # include/linux/netdevice.h (one place)
+ *
+ * The new driver API is available for WIRELESS_EXT >= 13.
+ * Good luck with migration to the new API ;-)
+ */
+
+/* ---------------------- THE IMPLEMENTATION ---------------------- */
+/*
+ * Some of the choice I've made are pretty controversials. Defining an
+ * API is very much weighting compromises. This goes into some of the
+ * details and the thinking behind the implementation.
+ *
+ * Implementation goals :
+ * --------------------
+ * The implementation goals were as follow :
+ * o Obvious : you should not need a PhD to understand what's happening,
+ * the benefit is easier maintenance.
+ * o Flexible : it should accommodate a wide variety of driver
+ * implementations and be as flexible as the old API.
+ * o Lean : it should be efficient memory wise to minimise the impact
+ * on kernel footprint.
+ * o Transparent to user space : the large number of user space
+ * applications that use Wireless Extensions should not need
+ * any modifications.
+ *
+ * Array of functions versus Struct of functions
+ * ---------------------------------------------
+ * 1) Having an array of functions allow the kernel code to access the
+ * handler in a single lookup, which is much more efficient (think hash
+ * table here).
+ * 2) The only drawback is that driver writer may put their handler in
+ * the wrong slot. This is trivial to test (I set the frequency, the
+ * bitrate changes). Once the handler is in the proper slot, it will be
+ * there forever, because the array is only extended at the end.
+ * 3) Backward/forward compatibility : adding new handler just require
+ * extending the array, so you can put newer driver in older kernel
+ * without having to patch the kernel code (and vice versa).
+ *
+ * All handler are of the same generic type
+ * ----------------------------------------
+ * That's a feature !!!
+ * 1) Having a generic handler allow to have generic code, which is more
+ * efficient. If each of the handler was individually typed I would need
+ * to add a big switch in the kernel (== more bloat). This solution is
+ * more scalable, adding new Wireless Extensions doesn't add new code.
+ * 2) You can use the same handler in different slots of the array. For
+ * hardware, it may be more efficient or logical to handle multiple
+ * Wireless Extensions with a single function, and the API allow you to
+ * do that. (An example would be a single record on the card to control
+ * both bitrate and frequency, the handler would read the old record,
+ * modify it according to info->cmd and rewrite it).
+ *
+ * Functions prototype uses union iwreq_data
+ * -----------------------------------------
+ * Some would have preferred functions defined this way :
+ * static int mydriver_ioctl_setrate(struct net_device *dev,
+ * long rate, int auto)
+ * 1) The kernel code doesn't "validate" the content of iwreq_data, and
+ * can't do it (different hardware may have different notion of what a
+ * valid frequency is), so we don't pretend that we do it.
+ * 2) The above form is not extendable. If I want to add a flag (for
+ * example to distinguish setting max rate and basic rate), I would
+ * break the prototype. Using iwreq_data is more flexible.
+ * 3) Also, the above form is not generic (see above).
+ * 4) I don't expect driver developper using the wrong field of the
+ * union (Doh !), so static typechecking doesn't add much value.
+ * 5) Lastly, you can skip the union by doing :
+ * static int mydriver_ioctl_setrate(struct net_device *dev,
+ * struct iw_request_info *info,
+ * struct iw_param *rrq,
+ * char *extra)
+ * And then adding the handler in the array like this :
+ * (iw_handler) mydriver_ioctl_setrate, // SIOCSIWRATE
+ *
+ * Using functions and not a registry
+ * ----------------------------------
+ * Another implementation option would have been for every instance to
+ * define a registry (a struct containing all the Wireless Extensions)
+ * and only have a function to commit the registry to the hardware.
+ * 1) This approach can be emulated by the current code, but not
+ * vice versa.
+ * 2) Some drivers don't keep any configuration in the driver, for them
+ * adding such a registry would be a significant bloat.
+ * 3) The code to translate from Wireless Extension to native format is
+ * needed anyway, so it would not reduce significantely the amount of code.
+ * 4) The current approach only selectively translate Wireless Extensions
+ * to native format and only selectively set, whereas the registry approach
+ * would require to translate all WE and set all parameters for any single
+ * change.
+ * 5) For many Wireless Extensions, the GET operation return the current
+ * dynamic value, not the value that was set.
+ *
+ * This header is <net/iw_handler.h>
+ * ---------------------------------
+ * 1) This header is kernel space only and should not be exported to
+ * user space. Headers in "include/linux/" are exported, headers in
+ * "include/net/" are not.
+ *
+ * Mixed 32/64 bit issues
+ * ----------------------
+ * The Wireless Extensions are designed to be 64 bit clean, by using only
+ * datatypes with explicit storage size.
+ * There are some issues related to kernel and user space using different
+ * memory model, and in particular 64bit kernel with 32bit user space.
+ * The problem is related to struct iw_point, that contains a pointer
+ * that *may* need to be translated.
+ * This is quite messy. The new API doesn't solve this problem (it can't),
+ * but is a step in the right direction :
+ * 1) Meta data about each ioctl is easily available, so we know what type
+ * of translation is needed.
+ * 2) The move of data between kernel and user space is only done in a single
+ * place in the kernel, so adding specific hooks in there is possible.
+ * 3) In the long term, it allows to move away from using ioctl as the
+ * user space API.
+ *
+ * So many comments and so few code
+ * --------------------------------
+ * That's a feature. Comments won't bloat the resulting kernel binary.
+ */
+
+/***************************** INCLUDES *****************************/
+
+#include <linux/wireless.h> /* IOCTL user space API */
+#include <linux/if_ether.h>
+
+/***************************** VERSION *****************************/
+/*
+ * This constant is used to know which version of the driver API is
+ * available. Hopefully, this will be pretty stable and no changes
+ * will be needed...
+ * I just plan to increment with each new version.
+ */
+#define IW_HANDLER_VERSION 8
+
+/*
+ * Changes :
+ *
+ * V2 to V3
+ * --------
+ * - Move event definition in <linux/wireless.h>
+ * - Add Wireless Event support :
+ * o wireless_send_event() prototype
+ * o iwe_stream_add_event/point() inline functions
+ * V3 to V4
+ * --------
+ * - Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes
+ *
+ * V4 to V5
+ * --------
+ * - Add new spy support : struct iw_spy_data & prototypes
+ *
+ * V5 to V6
+ * --------
+ * - Change the way we get to spy_data method for added safety
+ * - Remove spy #ifdef, they are always on -> cleaner code
+ * - Add IW_DESCR_FLAG_NOMAX flag for very large requests
+ * - Start migrating get_wireless_stats to struct iw_handler_def
+ *
+ * V6 to V7
+ * --------
+ * - Add struct ieee80211_device pointer in struct iw_public_data
+ * - Remove (struct iw_point *)->pointer from events and streams
+ * - Remove spy_offset from struct iw_handler_def
+ * - Add "check" version of event macros for ieee802.11 stack
+ *
+ * V7 to V8
+ * ----------
+ * - Prevent leaking of kernel space in stream on 64 bits.
+ */
+
+/**************************** CONSTANTS ****************************/
+
+/* Enhanced spy support available */
+#define IW_WIRELESS_SPY
+#define IW_WIRELESS_THRSPY
+
+/* Special error message for the driver to indicate that we
+ * should do a commit after return from the iw_handler */
+#define EIWCOMMIT EINPROGRESS
+
+/* Flags available in struct iw_request_info */
+#define IW_REQUEST_FLAG_COMPAT 0x0001 /* Compat ioctl call */
+
+/* Type of headers we know about (basically union iwreq_data) */
+#define IW_HEADER_TYPE_NULL 0 /* Not available */
+#define IW_HEADER_TYPE_CHAR 2 /* char [IFNAMSIZ] */
+#define IW_HEADER_TYPE_UINT 4 /* __u32 */
+#define IW_HEADER_TYPE_FREQ 5 /* struct iw_freq */
+#define IW_HEADER_TYPE_ADDR 6 /* struct sockaddr */
+#define IW_HEADER_TYPE_POINT 8 /* struct iw_point */
+#define IW_HEADER_TYPE_PARAM 9 /* struct iw_param */
+#define IW_HEADER_TYPE_QUAL 10 /* struct iw_quality */
+
+/* Handling flags */
+/* Most are not implemented. I just use them as a reminder of some
+ * cool features we might need one day ;-) */
+#define IW_DESCR_FLAG_NONE 0x0000 /* Obvious */
+/* Wrapper level flags */
+#define IW_DESCR_FLAG_DUMP 0x0001 /* Not part of the dump command */
+#define IW_DESCR_FLAG_EVENT 0x0002 /* Generate an event on SET */
+#define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET : request is ROOT only */
+ /* SET : Omit payload from generated iwevent */
+#define IW_DESCR_FLAG_NOMAX 0x0008 /* GET : no limit on request size */
+/* Driver level flags */
+#define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */
+
+/****************************** TYPES ******************************/
+
+/* ----------------------- WIRELESS HANDLER ----------------------- */
+/*
+ * A wireless handler is just a standard function, that looks like the
+ * ioctl handler.
+ * We also define there how a handler list look like... As the Wireless
+ * Extension space is quite dense, we use a simple array, which is faster
+ * (that's the perfect hash table ;-).
+ */
+
+/*
+ * Meta data about the request passed to the iw_handler.
+ * Most handlers can safely ignore what's in there.
+ * The 'cmd' field might come handy if you want to use the same handler
+ * for multiple command...
+ * This struct is also my long term insurance. I can add new fields here
+ * without breaking the prototype of iw_handler...
+ */
+struct iw_request_info {
+ __u16 cmd; /* Wireless Extension command */
+ __u16 flags; /* More to come ;-) */
+};
+
+struct net_device;
+
+/*
+ * This is how a function handling a Wireless Extension should look
+ * like (both get and set, standard and private).
+ */
+typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+
+/*
+ * This define all the handler that the driver export.
+ * As you need only one per driver type, please use a static const
+ * shared by all driver instances... Same for the members...
+ * This will be linked from net_device in <linux/netdevice.h>
+ */
+struct iw_handler_def {
+
+ /* Array of handlers for standard ioctls
+ * We will call dev->wireless_handlers->standard[ioctl - SIOCIWFIRST]
+ */
+ const iw_handler * standard;
+ /* Number of handlers defined (more precisely, index of the
+ * last defined handler + 1) */
+ __u16 num_standard;
+
+#ifdef CONFIG_WEXT_PRIV
+ __u16 num_private;
+ /* Number of private arg description */
+ __u16 num_private_args;
+ /* Array of handlers for private ioctls
+ * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV]
+ */
+ const iw_handler * private;
+
+ /* Arguments of private handler. This one is just a list, so you
+ * can put it in any order you want and should not leave holes...
+ * We will automatically export that to user space... */
+ const struct iw_priv_args * private_args;
+#endif
+
+ /* New location of get_wireless_stats, to de-bloat struct net_device.
+ * The old pointer in struct net_device will be gradually phased
+ * out, and drivers are encouraged to use this one... */
+ struct iw_statistics* (*get_wireless_stats)(struct net_device *dev);
+};
+
+/* ---------------------- IOCTL DESCRIPTION ---------------------- */
+/*
+ * One of the main goal of the new interface is to deal entirely with
+ * user space/kernel space memory move.
+ * For that, we need to know :
+ * o if iwreq is a pointer or contain the full data
+ * o what is the size of the data to copy
+ *
+ * For private IOCTLs, we use the same rules as used by iwpriv and
+ * defined in struct iw_priv_args.
+ *
+ * For standard IOCTLs, things are quite different and we need to
+ * use the stuctures below. Actually, this struct is also more
+ * efficient, but that's another story...
+ */
+
+/*
+ * Describe how a standard IOCTL looks like.
+ */
+struct iw_ioctl_description {
+ __u8 header_type; /* NULL, iw_point or other */
+ __u8 token_type; /* Future */
+ __u16 token_size; /* Granularity of payload */
+ __u16 min_tokens; /* Min acceptable token number */
+ __u16 max_tokens; /* Max acceptable token number */
+ __u32 flags; /* Special handling of the request */
+};
+
+/* Need to think of short header translation table. Later. */
+
+/* --------------------- ENHANCED SPY SUPPORT --------------------- */
+/*
+ * In the old days, the driver was handling spy support all by itself.
+ * Now, the driver can delegate this task to Wireless Extensions.
+ * It needs to include this struct in its private part and use the
+ * standard spy iw_handler.
+ */
+
+/*
+ * Instance specific spy data, i.e. addresses spied and quality for them.
+ */
+struct iw_spy_data {
+ /* --- Standard spy support --- */
+ int spy_number;
+ u_char spy_address[IW_MAX_SPY][ETH_ALEN];
+ struct iw_quality spy_stat[IW_MAX_SPY];
+ /* --- Enhanced spy support (event) */
+ struct iw_quality spy_thr_low; /* Low threshold */
+ struct iw_quality spy_thr_high; /* High threshold */
+ u_char spy_thr_under[IW_MAX_SPY];
+};
+
+/* --------------------- DEVICE WIRELESS DATA --------------------- */
+/*
+ * This is all the wireless data specific to a device instance that
+ * is managed by the core of Wireless Extensions or the 802.11 layer.
+ * We only keep pointer to those structures, so that a driver is free
+ * to share them between instances.
+ * This structure should be initialised before registering the device.
+ * Access to this data follow the same rules as any other struct net_device
+ * data (i.e. valid as long as struct net_device exist, same locking rules).
+ */
+/* Forward declaration */
+struct libipw_device;
+/* The struct */
+struct iw_public_data {
+ /* Driver enhanced spy support */
+ struct iw_spy_data * spy_data;
+ /* Legacy structure managed by the ipw2x00-specific IEEE 802.11 layer */
+ struct libipw_device * libipw;
+};
+
+/**************************** PROTOTYPES ****************************/
+/*
+ * Functions part of the Wireless Extensions (defined in net/core/wireless.c).
+ * Those may be called only within the kernel.
+ */
+
+/* First : function strictly used inside the kernel */
+
+/* Handle /proc/net/wireless, called in net/code/dev.c */
+extern int dev_get_wireless_info(char * buffer, char **start, off_t offset,
+ int length);
+
+/* Second : functions that may be called by driver modules */
+
+/* Send a single event to user space */
+extern void wireless_send_event(struct net_device * dev,
+ unsigned int cmd,
+ union iwreq_data * wrqu,
+ const char * extra);
+
+/* We may need a function to send a stream of events to user space.
+ * More on that later... */
+
+/* Standard handler for SIOCSIWSPY */
+extern int iw_handler_set_spy(struct net_device * dev,
+ struct iw_request_info * info,
+ union iwreq_data * wrqu,
+ char * extra);
+/* Standard handler for SIOCGIWSPY */
+extern int iw_handler_get_spy(struct net_device * dev,
+ struct iw_request_info * info,
+ union iwreq_data * wrqu,
+ char * extra);
+/* Standard handler for SIOCSIWTHRSPY */
+extern int iw_handler_set_thrspy(struct net_device * dev,
+ struct iw_request_info *info,
+ union iwreq_data * wrqu,
+ char * extra);
+/* Standard handler for SIOCGIWTHRSPY */
+extern int iw_handler_get_thrspy(struct net_device * dev,
+ struct iw_request_info *info,
+ union iwreq_data * wrqu,
+ char * extra);
+/* Driver call to update spy records */
+extern void wireless_spy_update(struct net_device * dev,
+ unsigned char * address,
+ struct iw_quality * wstats);
+
+/************************* INLINE FUNTIONS *************************/
+/*
+ * Function that are so simple that it's more efficient inlining them
+ */
+
+static inline int iwe_stream_lcp_len(struct iw_request_info *info)
+{
+#ifdef CONFIG_COMPAT
+ if (info->flags & IW_REQUEST_FLAG_COMPAT)
+ return IW_EV_COMPAT_LCP_LEN;
+#endif
+ return IW_EV_LCP_LEN;
+}
+
+static inline int iwe_stream_point_len(struct iw_request_info *info)
+{
+#ifdef CONFIG_COMPAT
+ if (info->flags & IW_REQUEST_FLAG_COMPAT)
+ return IW_EV_COMPAT_POINT_LEN;
+#endif
+ return IW_EV_POINT_LEN;
+}
+
+static inline int iwe_stream_event_len_adjust(struct iw_request_info *info,
+ int event_len)
+{
+#ifdef CONFIG_COMPAT
+ if (info->flags & IW_REQUEST_FLAG_COMPAT) {
+ event_len -= IW_EV_LCP_LEN;
+ event_len += IW_EV_COMPAT_LCP_LEN;
+ }
+#endif
+
+ return event_len;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wrapper to add an Wireless Event to a stream of events.
+ */
+static inline char *
+iwe_stream_add_event(struct iw_request_info *info, char *stream, char *ends,
+ struct iw_event *iwe, int event_len)
+{
+ int lcp_len = iwe_stream_lcp_len(info);
+
+ event_len = iwe_stream_event_len_adjust(info, event_len);
+
+ /* Check if it's possible */
+ if(likely((stream + event_len) < ends)) {
+ iwe->len = event_len;
+ /* Beware of alignement issues on 64 bits */
+ memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN);
+ memcpy(stream + lcp_len, &iwe->u,
+ event_len - lcp_len);
+ stream += event_len;
+ }
+ return stream;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wrapper to add an short Wireless Event containing a pointer to a
+ * stream of events.
+ */
+static inline char *
+iwe_stream_add_point(struct iw_request_info *info, char *stream, char *ends,
+ struct iw_event *iwe, char *extra)
+{
+ int event_len = iwe_stream_point_len(info) + iwe->u.data.length;
+ int point_len = iwe_stream_point_len(info);
+ int lcp_len = iwe_stream_lcp_len(info);
+
+ /* Check if it's possible */
+ if(likely((stream + event_len) < ends)) {
+ iwe->len = event_len;
+ memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN);
+ memcpy(stream + lcp_len,
+ ((char *) &iwe->u) + IW_EV_POINT_OFF,
+ IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN);
+ memcpy(stream + point_len, extra, iwe->u.data.length);
+ stream += event_len;
+ }
+ return stream;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wrapper to add a value to a Wireless Event in a stream of events.
+ * Be careful, this one is tricky to use properly :
+ * At the first run, you need to have (value = event + IW_EV_LCP_LEN).
+ */
+static inline char *
+iwe_stream_add_value(struct iw_request_info *info, char *event, char *value,
+ char *ends, struct iw_event *iwe, int event_len)
+{
+ int lcp_len = iwe_stream_lcp_len(info);
+
+ /* Don't duplicate LCP */
+ event_len -= IW_EV_LCP_LEN;
+
+ /* Check if it's possible */
+ if(likely((value + event_len) < ends)) {
+ /* Add new value */
+ memcpy(value, &iwe->u, event_len);
+ value += event_len;
+ /* Patch LCP */
+ iwe->len = value - event;
+ memcpy(event, (char *) iwe, lcp_len);
+ }
+ return value;
+}
+
+#endif /* _IW_HANDLER_H */
diff --git a/include/net/lapb.h b/include/net/lapb.h
new file mode 100644
index 00000000..fd2bf572
--- /dev/null
+++ b/include/net/lapb.h
@@ -0,0 +1,152 @@
+#ifndef _LAPB_H
+#define _LAPB_H
+#include <linux/lapb.h>
+
+#define LAPB_HEADER_LEN 20 /* LAPB over Ethernet + a bit more */
+
+#define LAPB_ACK_PENDING_CONDITION 0x01
+#define LAPB_REJECT_CONDITION 0x02
+#define LAPB_PEER_RX_BUSY_CONDITION 0x04
+
+/* Control field templates */
+#define LAPB_I 0x00 /* Information frames */
+#define LAPB_S 0x01 /* Supervisory frames */
+#define LAPB_U 0x03 /* Unnumbered frames */
+
+#define LAPB_RR 0x01 /* Receiver ready */
+#define LAPB_RNR 0x05 /* Receiver not ready */
+#define LAPB_REJ 0x09 /* Reject */
+
+#define LAPB_SABM 0x2F /* Set Asynchronous Balanced Mode */
+#define LAPB_SABME 0x6F /* Set Asynchronous Balanced Mode Extended */
+#define LAPB_DISC 0x43 /* Disconnect */
+#define LAPB_DM 0x0F /* Disconnected mode */
+#define LAPB_UA 0x63 /* Unnumbered acknowledge */
+#define LAPB_FRMR 0x87 /* Frame reject */
+
+#define LAPB_ILLEGAL 0x100 /* Impossible to be a real frame type */
+
+#define LAPB_SPF 0x10 /* Poll/final bit for standard LAPB */
+#define LAPB_EPF 0x01 /* Poll/final bit for extended LAPB */
+
+#define LAPB_FRMR_W 0x01 /* Control field invalid */
+#define LAPB_FRMR_X 0x02 /* I field invalid */
+#define LAPB_FRMR_Y 0x04 /* I field too long */
+#define LAPB_FRMR_Z 0x08 /* Invalid N(R) */
+
+#define LAPB_POLLOFF 0
+#define LAPB_POLLON 1
+
+/* LAPB C-bit */
+#define LAPB_COMMAND 1
+#define LAPB_RESPONSE 2
+
+#define LAPB_ADDR_A 0x03
+#define LAPB_ADDR_B 0x01
+#define LAPB_ADDR_C 0x0F
+#define LAPB_ADDR_D 0x07
+
+/* Define Link State constants. */
+enum {
+ LAPB_STATE_0, /* Disconnected State */
+ LAPB_STATE_1, /* Awaiting Connection State */
+ LAPB_STATE_2, /* Awaiting Disconnection State */
+ LAPB_STATE_3, /* Data Transfer State */
+ LAPB_STATE_4 /* Frame Reject State */
+};
+
+#define LAPB_DEFAULT_MODE (LAPB_STANDARD | LAPB_SLP | LAPB_DTE)
+#define LAPB_DEFAULT_WINDOW 7 /* Window=7 */
+#define LAPB_DEFAULT_T1 (5 * HZ) /* T1=5s */
+#define LAPB_DEFAULT_T2 (1 * HZ) /* T2=1s */
+#define LAPB_DEFAULT_N2 20 /* N2=20 */
+
+#define LAPB_SMODULUS 8
+#define LAPB_EMODULUS 128
+
+/*
+ * Information about the current frame.
+ */
+struct lapb_frame {
+ unsigned short type; /* Parsed type */
+ unsigned short nr, ns; /* N(R), N(S) */
+ unsigned char cr; /* Command/Response */
+ unsigned char pf; /* Poll/Final */
+ unsigned char control[2]; /* Original control data*/
+};
+
+/*
+ * The per LAPB connection control structure.
+ */
+struct lapb_cb {
+ struct list_head node;
+ struct net_device *dev;
+
+ /* Link status fields */
+ unsigned int mode;
+ unsigned char state;
+ unsigned short vs, vr, va;
+ unsigned char condition;
+ unsigned short n2, n2count;
+ unsigned short t1, t2;
+ struct timer_list t1timer, t2timer;
+
+ /* Internal control information */
+ struct sk_buff_head write_queue;
+ struct sk_buff_head ack_queue;
+ unsigned char window;
+ const struct lapb_register_struct *callbacks;
+
+ /* FRMR control information */
+ struct lapb_frame frmr_data;
+ unsigned char frmr_type;
+
+ atomic_t refcnt;
+};
+
+/* lapb_iface.c */
+extern void lapb_connect_confirmation(struct lapb_cb *lapb, int);
+extern void lapb_connect_indication(struct lapb_cb *lapb, int);
+extern void lapb_disconnect_confirmation(struct lapb_cb *lapb, int);
+extern void lapb_disconnect_indication(struct lapb_cb *lapb, int);
+extern int lapb_data_indication(struct lapb_cb *lapb, struct sk_buff *);
+extern int lapb_data_transmit(struct lapb_cb *lapb, struct sk_buff *);
+
+/* lapb_in.c */
+extern void lapb_data_input(struct lapb_cb *lapb, struct sk_buff *);
+
+/* lapb_out.c */
+extern void lapb_kick(struct lapb_cb *lapb);
+extern void lapb_transmit_buffer(struct lapb_cb *lapb, struct sk_buff *, int);
+extern void lapb_establish_data_link(struct lapb_cb *lapb);
+extern void lapb_enquiry_response(struct lapb_cb *lapb);
+extern void lapb_timeout_response(struct lapb_cb *lapb);
+extern void lapb_check_iframes_acked(struct lapb_cb *lapb, unsigned short);
+extern void lapb_check_need_response(struct lapb_cb *lapb, int, int);
+
+/* lapb_subr.c */
+extern void lapb_clear_queues(struct lapb_cb *lapb);
+extern void lapb_frames_acked(struct lapb_cb *lapb, unsigned short);
+extern void lapb_requeue_frames(struct lapb_cb *lapb);
+extern int lapb_validate_nr(struct lapb_cb *lapb, unsigned short);
+extern int lapb_decode(struct lapb_cb *lapb, struct sk_buff *, struct lapb_frame *);
+extern void lapb_send_control(struct lapb_cb *lapb, int, int, int);
+extern void lapb_transmit_frmr(struct lapb_cb *lapb);
+
+/* lapb_timer.c */
+extern void lapb_start_t1timer(struct lapb_cb *lapb);
+extern void lapb_start_t2timer(struct lapb_cb *lapb);
+extern void lapb_stop_t1timer(struct lapb_cb *lapb);
+extern void lapb_stop_t2timer(struct lapb_cb *lapb);
+extern int lapb_t1timer_running(struct lapb_cb *lapb);
+
+/*
+ * Debug levels.
+ * 0 = Off
+ * 1 = State Changes
+ * 2 = Packets I/O and State Changes
+ * 3 = Hex dumps, Packets I/O and State Changes.
+ */
+#define LAPB_DEBUG 0
+
+#endif
diff --git a/include/net/lib80211.h b/include/net/lib80211.h
new file mode 100644
index 00000000..d178c26a
--- /dev/null
+++ b/include/net/lib80211.h
@@ -0,0 +1,124 @@
+/*
+ * lib80211.h -- common bits for IEEE802.11 wireless drivers
+ *
+ * Copyright (c) 2008, John W. Linville <linville@tuxdriver.com>
+ *
+ * Some bits copied from old ieee80211 component, w/ original copyright
+ * notices below:
+ *
+ * Original code based on Host AP (software wireless LAN access point) driver
+ * for Intersil Prism2/2.5/3.
+ *
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <j@w1.fi>
+ * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
+ *
+ * Adaption to a generic IEEE 802.11 stack by James Ketrenos
+ * <jketreno@linux.intel.com>
+ *
+ * Copyright (c) 2004, Intel Corporation
+ *
+ */
+
+#ifndef LIB80211_H
+#define LIB80211_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/atomic.h>
+#include <linux/if.h>
+#include <linux/skbuff.h>
+#include <linux/ieee80211.h>
+#include <linux/timer.h>
+/* print_ssid() is intended to be used in debug (and possibly error)
+ * messages. It should never be used for passing ssid to user space. */
+const char *print_ssid(char *buf, const char *ssid, u8 ssid_len);
+#define DECLARE_SSID_BUF(var) char var[IEEE80211_MAX_SSID_LEN * 4 + 1] __maybe_unused
+
+#define NUM_WEP_KEYS 4
+
+enum {
+ IEEE80211_CRYPTO_TKIP_COUNTERMEASURES = (1 << 0),
+};
+
+struct module;
+
+struct lib80211_crypto_ops {
+ const char *name;
+ struct list_head list;
+
+ /* init new crypto context (e.g., allocate private data space,
+ * select IV, etc.); returns NULL on failure or pointer to allocated
+ * private data on success */
+ void *(*init) (int keyidx);
+
+ /* deinitialize crypto context and free allocated private data */
+ void (*deinit) (void *priv);
+
+ /* encrypt/decrypt return < 0 on error or >= 0 on success. The return
+ * value from decrypt_mpdu is passed as the keyidx value for
+ * decrypt_msdu. skb must have enough head and tail room for the
+ * encryption; if not, error will be returned; these functions are
+ * called for all MPDUs (i.e., fragments).
+ */
+ int (*encrypt_mpdu) (struct sk_buff * skb, int hdr_len, void *priv);
+ int (*decrypt_mpdu) (struct sk_buff * skb, int hdr_len, void *priv);
+
+ /* These functions are called for full MSDUs, i.e. full frames.
+ * These can be NULL if full MSDU operations are not needed. */
+ int (*encrypt_msdu) (struct sk_buff * skb, int hdr_len, void *priv);
+ int (*decrypt_msdu) (struct sk_buff * skb, int keyidx, int hdr_len,
+ void *priv);
+
+ int (*set_key) (void *key, int len, u8 * seq, void *priv);
+ int (*get_key) (void *key, int len, u8 * seq, void *priv);
+
+ /* procfs handler for printing out key information and possible
+ * statistics */
+ char *(*print_stats) (char *p, void *priv);
+
+ /* Crypto specific flag get/set for configuration settings */
+ unsigned long (*get_flags) (void *priv);
+ unsigned long (*set_flags) (unsigned long flags, void *priv);
+
+ /* maximum number of bytes added by encryption; encrypt buf is
+ * allocated with extra_prefix_len bytes, copy of in_buf, and
+ * extra_postfix_len; encrypt need not use all this space, but
+ * the result must start at the beginning of the buffer and correct
+ * length must be returned */
+ int extra_mpdu_prefix_len, extra_mpdu_postfix_len;
+ int extra_msdu_prefix_len, extra_msdu_postfix_len;
+
+ struct module *owner;
+};
+
+struct lib80211_crypt_data {
+ struct list_head list; /* delayed deletion list */
+ struct lib80211_crypto_ops *ops;
+ void *priv;
+ atomic_t refcnt;
+};
+
+struct lib80211_crypt_info {
+ char *name;
+ /* Most clients will already have a lock,
+ so just point to that. */
+ spinlock_t *lock;
+
+ struct lib80211_crypt_data *crypt[NUM_WEP_KEYS];
+ int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
+ struct list_head crypt_deinit_list;
+ struct timer_list crypt_deinit_timer;
+ int crypt_quiesced;
+};
+
+int lib80211_crypt_info_init(struct lib80211_crypt_info *info, char *name,
+ spinlock_t *lock);
+void lib80211_crypt_info_free(struct lib80211_crypt_info *info);
+int lib80211_register_crypto_ops(struct lib80211_crypto_ops *ops);
+int lib80211_unregister_crypto_ops(struct lib80211_crypto_ops *ops);
+struct lib80211_crypto_ops *lib80211_get_crypto_ops(const char *name);
+void lib80211_crypt_delayed_deinit(struct lib80211_crypt_info *info,
+ struct lib80211_crypt_data **crypt);
+
+#endif /* LIB80211_H */
diff --git a/include/net/llc.h b/include/net/llc.h
new file mode 100644
index 00000000..226c846c
--- /dev/null
+++ b/include/net/llc.h
@@ -0,0 +1,159 @@
+#ifndef LLC_H
+#define LLC_H
+/*
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+
+#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/rculist_nulls.h>
+#include <linux/hash.h>
+#include <linux/jhash.h>
+
+#include <linux/atomic.h>
+
+struct net_device;
+struct packet_type;
+struct sk_buff;
+
+struct llc_addr {
+ unsigned char lsap;
+ unsigned char mac[IFHWADDRLEN];
+};
+
+#define LLC_SAP_STATE_INACTIVE 1
+#define LLC_SAP_STATE_ACTIVE 2
+
+#define LLC_SK_DEV_HASH_BITS 6
+#define LLC_SK_DEV_HASH_ENTRIES (1<<LLC_SK_DEV_HASH_BITS)
+
+#define LLC_SK_LADDR_HASH_BITS 6
+#define LLC_SK_LADDR_HASH_ENTRIES (1<<LLC_SK_LADDR_HASH_BITS)
+
+/**
+ * struct llc_sap - Defines the SAP component
+ *
+ * @station - station this sap belongs to
+ * @state - sap state
+ * @p_bit - only lowest-order bit used
+ * @f_bit - only lowest-order bit used
+ * @laddr - SAP value in this 'lsap'
+ * @node - entry in station sap_list
+ * @sk_list - LLC sockets this one manages
+ */
+struct llc_sap {
+ unsigned char state;
+ unsigned char p_bit;
+ unsigned char f_bit;
+ atomic_t refcnt;
+ int (*rcv_func)(struct sk_buff *skb,
+ struct net_device *dev,
+ struct packet_type *pt,
+ struct net_device *orig_dev);
+ struct llc_addr laddr;
+ struct list_head node;
+ spinlock_t sk_lock;
+ int sk_count;
+ struct hlist_nulls_head sk_laddr_hash[LLC_SK_LADDR_HASH_ENTRIES];
+ struct hlist_head sk_dev_hash[LLC_SK_DEV_HASH_ENTRIES];
+};
+
+static inline
+struct hlist_head *llc_sk_dev_hash(struct llc_sap *sap, int ifindex)
+{
+ return &sap->sk_dev_hash[ifindex % LLC_SK_DEV_HASH_ENTRIES];
+}
+
+static inline
+u32 llc_sk_laddr_hashfn(struct llc_sap *sap, const struct llc_addr *laddr)
+{
+ return hash_32(jhash(laddr->mac, sizeof(laddr->mac), 0),
+ LLC_SK_LADDR_HASH_BITS);
+}
+
+static inline
+struct hlist_nulls_head *llc_sk_laddr_hash(struct llc_sap *sap,
+ const struct llc_addr *laddr)
+{
+ return &sap->sk_laddr_hash[llc_sk_laddr_hashfn(sap, laddr)];
+}
+
+#define LLC_DEST_INVALID 0 /* Invalid LLC PDU type */
+#define LLC_DEST_SAP 1 /* Type 1 goes here */
+#define LLC_DEST_CONN 2 /* Type 2 goes here */
+
+extern struct list_head llc_sap_list;
+extern spinlock_t llc_sap_list_lock;
+
+extern int llc_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt, struct net_device *orig_dev);
+
+extern int llc_mac_hdr_init(struct sk_buff *skb,
+ const unsigned char *sa, const unsigned char *da);
+
+extern void llc_add_pack(int type, void (*handler)(struct llc_sap *sap,
+ struct sk_buff *skb));
+extern void llc_remove_pack(int type);
+
+extern void llc_set_station_handler(void (*handler)(struct sk_buff *skb));
+
+extern struct llc_sap *llc_sap_open(unsigned char lsap,
+ int (*rcv)(struct sk_buff *skb,
+ struct net_device *dev,
+ struct packet_type *pt,
+ struct net_device *orig_dev));
+static inline void llc_sap_hold(struct llc_sap *sap)
+{
+ atomic_inc(&sap->refcnt);
+}
+
+extern void llc_sap_close(struct llc_sap *sap);
+
+static inline void llc_sap_put(struct llc_sap *sap)
+{
+ if (atomic_dec_and_test(&sap->refcnt))
+ llc_sap_close(sap);
+}
+
+extern struct llc_sap *llc_sap_find(unsigned char sap_value);
+
+extern int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
+ unsigned char *dmac, unsigned char dsap);
+
+extern void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb);
+extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb);
+
+extern int llc_station_init(void);
+extern void llc_station_exit(void);
+
+#ifdef CONFIG_PROC_FS
+extern int llc_proc_init(void);
+extern void llc_proc_exit(void);
+#else
+#define llc_proc_init() (0)
+#define llc_proc_exit() do { } while(0)
+#endif /* CONFIG_PROC_FS */
+#ifdef CONFIG_SYSCTL
+extern int llc_sysctl_init(void);
+extern void llc_sysctl_exit(void);
+
+extern int sysctl_llc2_ack_timeout;
+extern int sysctl_llc2_busy_timeout;
+extern int sysctl_llc2_p_timeout;
+extern int sysctl_llc2_rej_timeout;
+extern int sysctl_llc_station_ack_timeout;
+#else
+#define llc_sysctl_init() (0)
+#define llc_sysctl_exit() do { } while(0)
+#endif /* CONFIG_SYSCTL */
+#endif /* LLC_H */
diff --git a/include/net/llc_c_ac.h b/include/net/llc_c_ac.h
new file mode 100644
index 00000000..df83f69d
--- /dev/null
+++ b/include/net/llc_c_ac.h
@@ -0,0 +1,202 @@
+#ifndef LLC_C_AC_H
+#define LLC_C_AC_H
+/*
+ * Copyright (c) 1997 by Procom Technology,Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+/* Connection component state transition actions */
+/*
+ * Connection state transition actions
+ * (Fb = F bit; Pb = P bit; Xb = X bit)
+ */
+#define LLC_CONN_AC_CLR_REMOTE_BUSY 1
+#define LLC_CONN_AC_CONN_IND 2
+#define LLC_CONN_AC_CONN_CONFIRM 3
+#define LLC_CONN_AC_DATA_IND 4
+#define LLC_CONN_AC_DISC_IND 5
+#define LLC_CONN_AC_RESET_IND 6
+#define LLC_CONN_AC_RESET_CONFIRM 7
+#define LLC_CONN_AC_REPORT_STATUS 8
+#define LLC_CONN_AC_CLR_REMOTE_BUSY_IF_Fb_EQ_1 9
+#define LLC_CONN_AC_STOP_REJ_TMR_IF_DATA_FLAG_EQ_2 10
+#define LLC_CONN_AC_SEND_DISC_CMD_Pb_SET_X 11
+#define LLC_CONN_AC_SEND_DM_RSP_Fb_SET_Pb 12
+#define LLC_CONN_AC_SEND_DM_RSP_Fb_SET_1 13
+#define LLC_CONN_AC_SEND_DM_RSP_Fb_SET_F_FLAG 14
+#define LLC_CONN_AC_SEND_FRMR_RSP_Fb_SET_X 15
+#define LLC_CONN_AC_RESEND_FRMR_RSP_Fb_SET_0 16
+#define LLC_CONN_AC_RESEND_FRMR_RSP_Fb_SET_Pb 17
+#define LLC_CONN_AC_SEND_I_CMD_Pb_SET_1 18
+#define LLC_CONN_AC_RESEND_I_CMD_Pb_SET_1 19
+#define LLC_CONN_AC_RESEND_I_CMD_Pb_SET_1_OR_SEND_RR 20
+#define LLC_CONN_AC_SEND_I_XXX_Xb_SET_0 21
+#define LLC_CONN_AC_RESEND_I_XXX_Xb_SET_0 22
+#define LLC_CONN_AC_RESEND_I_XXX_Xb_SET_0_OR_SEND_RR 23
+#define LLC_CONN_AC_RESEND_I_RSP_Fb_SET_1 24
+#define LLC_CONN_AC_SEND_REJ_CMD_Pb_SET_1 25
+#define LLC_CONN_AC_SEND_REJ_RSP_Fb_SET_1 26
+#define LLC_CONN_AC_SEND_REJ_XXX_Xb_SET_0 27
+#define LLC_CONN_AC_SEND_RNR_CMD_Pb_SET_1 28
+#define LLC_CONN_AC_SEND_RNR_RSP_Fb_SET_1 29
+#define LLC_CONN_AC_SEND_RNR_XXX_Xb_SET_0 30
+#define LLC_CONN_AC_SET_REMOTE_BUSY 31
+#define LLC_CONN_AC_OPTIONAL_SEND_RNR_XXX_Xb_SET_0 32
+#define LLC_CONN_AC_SEND_RR_CMD_Pb_SET_1 33
+#define LLC_CONN_AC_SEND_ACK_CMD_Pb_SET_1 34
+#define LLC_CONN_AC_SEND_RR_RSP_Fb_SET_1 35
+#define LLC_CONN_AC_SEND_ACK_RSP_Fb_SET_1 36
+#define LLC_CONN_AC_SEND_RR_XXX_Xb_SET_0 37
+#define LLC_CONN_AC_SEND_ACK_XXX_Xb_SET_0 38
+#define LLC_CONN_AC_SEND_SABME_CMD_Pb_SET_X 39
+#define LLC_CONN_AC_SEND_UA_RSP_Fb_SET_Pb 40
+#define LLC_CONN_AC_SEND_UA_RSP_Fb_SET_F_FLAG 41
+#define LLC_CONN_AC_S_FLAG_SET_0 42
+#define LLC_CONN_AC_S_FLAG_SET_1 43
+#define LLC_CONN_AC_START_P_TMR 44
+#define LLC_CONN_AC_START_ACK_TMR 45
+#define LLC_CONN_AC_START_REJ_TMR 46
+#define LLC_CONN_AC_START_ACK_TMR_IF_NOT_RUNNING 47
+#define LLC_CONN_AC_STOP_ACK_TMR 48
+#define LLC_CONN_AC_STOP_P_TMR 49
+#define LLC_CONN_AC_STOP_REJ_TMR 50
+#define LLC_CONN_AC_STOP_ALL_TMRS 51
+#define LLC_CONN_AC_STOP_OTHER_TMRS 52
+#define LLC_CONN_AC_UPDATE_Nr_RECEIVED 53
+#define LLC_CONN_AC_UPDATE_P_FLAG 54
+#define LLC_CONN_AC_DATA_FLAG_SET_2 55
+#define LLC_CONN_AC_DATA_FLAG_SET_0 56
+#define LLC_CONN_AC_DATA_FLAG_SET_1 57
+#define LLC_CONN_AC_DATA_FLAG_SET_1_IF_DATA_FLAG_EQ_0 58
+#define LLC_CONN_AC_P_FLAG_SET_0 59
+#define LLC_CONN_AC_P_FLAG_SET_P 60
+#define LLC_CONN_AC_REMOTE_BUSY_SET_0 61
+#define LLC_CONN_AC_RETRY_CNT_SET_0 62
+#define LLC_CONN_AC_RETRY_CNT_INC_BY_1 63
+#define LLC_CONN_AC_Vr_SET_0 64
+#define LLC_CONN_AC_Vr_INC_BY_1 65
+#define LLC_CONN_AC_Vs_SET_0 66
+#define LLC_CONN_AC_Vs_SET_Nr 67
+#define LLC_CONN_AC_F_FLAG_SET_P 68
+#define LLC_CONN_AC_STOP_SENDACK_TMR 70
+#define LLC_CONN_AC_START_SENDACK_TMR_IF_NOT_RUNNING 71
+
+typedef int (*llc_conn_action_t)(struct sock *sk, struct sk_buff *skb);
+
+extern int llc_conn_ac_clear_remote_busy(struct sock *sk, struct sk_buff *skb);
+extern int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb);
+extern int llc_conn_ac_conn_confirm(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_data_ind(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_disc_ind(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_rst_ind(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_rst_confirm(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_clear_remote_busy_if_f_eq_1(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_send_disc_cmd_p_set_x(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_send_dm_rsp_f_set_p(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_send_dm_rsp_f_set_1(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_send_i_cmd_p_set_1(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_send_i_xxx_x_set_0(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_resend_i_xxx_x_set_0(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_resend_i_rsp_f_set_1(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_send_rej_cmd_p_set_1(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_send_rej_rsp_f_set_1(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_send_rej_xxx_x_set_0(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_set_remote_busy(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_send_rr_cmd_p_set_1(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_send_rr_rsp_f_set_1(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_send_ack_rsp_f_set_1(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_send_rr_xxx_x_set_0(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_send_ack_xxx_x_set_0(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_send_ua_rsp_f_set_p(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_set_s_flag_0(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_set_s_flag_1(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_start_p_timer(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_start_ack_timer(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_start_rej_timer(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_start_ack_tmr_if_not_running(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_stop_ack_timer(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_stop_p_timer(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_stop_rej_timer(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_stop_all_timers(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_stop_other_timers(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_upd_nr_received(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_inc_tx_win_size(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_dec_tx_win_size(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_upd_p_flag(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_set_data_flag_2(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_set_data_flag_0(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_set_data_flag_1(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_set_data_flag_1_if_data_flag_eq_0(struct sock* sk,
+ struct sk_buff *skb);
+extern int llc_conn_ac_set_p_flag_0(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_set_remote_busy_0(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_set_retry_cnt_0(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_set_cause_flag_0(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_set_cause_flag_1(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_inc_retry_cnt_by_1(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_set_vr_0(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_inc_vr_by_1(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_set_vs_0(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_set_vs_nr(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_rst_vs(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_upd_vs(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_disc(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_reset(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_disc_confirm(struct sock* sk, struct sk_buff *skb);
+extern u8 llc_circular_between(u8 a, u8 b, u8 c);
+extern int llc_conn_ac_send_ack_if_needed(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_adjust_npta_by_rr(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_adjust_npta_by_rnr(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_rst_sendack_flag(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_send_i_rsp_as_ack(struct sock* sk, struct sk_buff *skb);
+extern int llc_conn_ac_send_i_as_ack(struct sock* sk, struct sk_buff *skb);
+
+extern void llc_conn_busy_tmr_cb(unsigned long timeout_data);
+extern void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data);
+extern void llc_conn_ack_tmr_cb(unsigned long timeout_data);
+extern void llc_conn_rej_tmr_cb(unsigned long timeout_data);
+
+extern void llc_conn_set_p_flag(struct sock *sk, u8 value);
+#endif /* LLC_C_AC_H */
diff --git a/include/net/llc_c_ev.h b/include/net/llc_c_ev.h
new file mode 100644
index 00000000..23a40938
--- /dev/null
+++ b/include/net/llc_c_ev.h
@@ -0,0 +1,269 @@
+#ifndef LLC_C_EV_H
+#define LLC_C_EV_H
+/*
+ * Copyright (c) 1997 by Procom Technology,Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+
+#include <net/sock.h>
+
+/* Connection component state transition event qualifiers */
+/* Types of events (possible values in 'ev->type') */
+#define LLC_CONN_EV_TYPE_SIMPLE 1
+#define LLC_CONN_EV_TYPE_CONDITION 2
+#define LLC_CONN_EV_TYPE_PRIM 3
+#define LLC_CONN_EV_TYPE_PDU 4 /* command/response PDU */
+#define LLC_CONN_EV_TYPE_ACK_TMR 5
+#define LLC_CONN_EV_TYPE_P_TMR 6
+#define LLC_CONN_EV_TYPE_REJ_TMR 7
+#define LLC_CONN_EV_TYPE_BUSY_TMR 8
+#define LLC_CONN_EV_TYPE_RPT_STATUS 9
+#define LLC_CONN_EV_TYPE_SENDACK_TMR 10
+
+#define NBR_CONN_EV 5
+/* Connection events which cause state transitions when fully qualified */
+
+#define LLC_CONN_EV_CONN_REQ 1
+#define LLC_CONN_EV_CONN_RESP 2
+#define LLC_CONN_EV_DATA_REQ 3
+#define LLC_CONN_EV_DISC_REQ 4
+#define LLC_CONN_EV_RESET_REQ 5
+#define LLC_CONN_EV_RESET_RESP 6
+#define LLC_CONN_EV_LOCAL_BUSY_DETECTED 7
+#define LLC_CONN_EV_LOCAL_BUSY_CLEARED 8
+#define LLC_CONN_EV_RX_BAD_PDU 9
+#define LLC_CONN_EV_RX_DISC_CMD_Pbit_SET_X 10
+#define LLC_CONN_EV_RX_DM_RSP_Fbit_SET_X 11
+#define LLC_CONN_EV_RX_FRMR_RSP_Fbit_SET_X 12
+#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_X 13
+#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_X_UNEXPD_Ns 14
+#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_X_INVAL_Ns 15
+#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_X 16
+#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_X_UNEXPD_Ns 17
+#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_X_INVAL_Ns 18
+#define LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_X 19
+#define LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_X 20
+#define LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_X 21
+#define LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_X 22
+#define LLC_CONN_EV_RX_RR_CMD_Pbit_SET_X 23
+#define LLC_CONN_EV_RX_RR_RSP_Fbit_SET_X 24
+#define LLC_CONN_EV_RX_SABME_CMD_Pbit_SET_X 25
+#define LLC_CONN_EV_RX_UA_RSP_Fbit_SET_X 26
+#define LLC_CONN_EV_RX_XXX_CMD_Pbit_SET_X 27
+#define LLC_CONN_EV_RX_XXX_RSP_Fbit_SET_X 28
+#define LLC_CONN_EV_RX_XXX_YYY 29
+#define LLC_CONN_EV_RX_ZZZ_CMD_Pbit_SET_X_INVAL_Nr 30
+#define LLC_CONN_EV_RX_ZZZ_RSP_Fbit_SET_X_INVAL_Nr 31
+#define LLC_CONN_EV_P_TMR_EXP 32
+#define LLC_CONN_EV_ACK_TMR_EXP 33
+#define LLC_CONN_EV_REJ_TMR_EXP 34
+#define LLC_CONN_EV_BUSY_TMR_EXP 35
+#define LLC_CONN_EV_RX_XXX_CMD_Pbit_SET_1 36
+#define LLC_CONN_EV_RX_XXX_CMD_Pbit_SET_0 37
+#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_0_UNEXPD_Ns 38
+#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_0_UNEXPD_Ns 39
+#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_1_UNEXPD_Ns 40
+#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_1_UNEXPD_Ns 41
+#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 42
+#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_0 43
+#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_1 44
+#define LLC_CONN_EV_RX_RR_CMD_Pbit_SET_0 45
+#define LLC_CONN_EV_RX_RR_RSP_Fbit_SET_0 46
+#define LLC_CONN_EV_RX_RR_RSP_Fbit_SET_1 47
+#define LLC_CONN_EV_RX_RR_CMD_Pbit_SET_1 48
+#define LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_0 49
+#define LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_0 50
+#define LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_1 51
+#define LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_1 52
+#define LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 53
+#define LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_0 54
+#define LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_1 55
+#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_1 56
+#define LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_1 57
+#define LLC_CONN_EV_RX_XXX_RSP_Fbit_SET_1 58
+#define LLC_CONN_EV_TX_BUFF_FULL 59
+
+#define LLC_CONN_EV_INIT_P_F_CYCLE 100
+/*
+ * Connection event qualifiers; for some events a certain combination of
+ * these qualifiers must be TRUE before event recognized valid for state;
+ * these constants act as indexes into the Event Qualifier function
+ * table
+ */
+#define LLC_CONN_EV_QFY_DATA_FLAG_EQ_1 1
+#define LLC_CONN_EV_QFY_DATA_FLAG_EQ_0 2
+#define LLC_CONN_EV_QFY_DATA_FLAG_EQ_2 3
+#define LLC_CONN_EV_QFY_P_FLAG_EQ_1 4
+#define LLC_CONN_EV_QFY_P_FLAG_EQ_0 5
+#define LLC_CONN_EV_QFY_P_FLAG_EQ_Fbit 6
+#define LLC_CONN_EV_QFY_REMOTE_BUSY_EQ_0 7
+#define LLC_CONN_EV_QFY_RETRY_CNT_LT_N2 8
+#define LLC_CONN_EV_QFY_RETRY_CNT_GTE_N2 9
+#define LLC_CONN_EV_QFY_S_FLAG_EQ_1 10
+#define LLC_CONN_EV_QFY_S_FLAG_EQ_0 11
+#define LLC_CONN_EV_QFY_INIT_P_F_CYCLE 12
+
+struct llc_conn_state_ev {
+ u8 type;
+ u8 prim;
+ u8 prim_type;
+ u8 reason;
+ u8 status;
+ u8 ind_prim;
+ u8 cfm_prim;
+};
+
+static __inline__ struct llc_conn_state_ev *llc_conn_ev(struct sk_buff *skb)
+{
+ return (struct llc_conn_state_ev *)skb->cb;
+}
+
+typedef int (*llc_conn_ev_t)(struct sock *sk, struct sk_buff *skb);
+typedef int (*llc_conn_ev_qfyr_t)(struct sock *sk, struct sk_buff *skb);
+
+extern int llc_conn_ev_conn_req(struct sock *sk, struct sk_buff *skb);
+extern int llc_conn_ev_data_req(struct sock *sk, struct sk_buff *skb);
+extern int llc_conn_ev_disc_req(struct sock *sk, struct sk_buff *skb);
+extern int llc_conn_ev_rst_req(struct sock *sk, struct sk_buff *skb);
+extern int llc_conn_ev_local_busy_detected(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_local_busy_cleared(struct sock *sk, struct sk_buff *skb);
+extern int llc_conn_ev_rx_bad_pdu(struct sock *sk, struct sk_buff *skb);
+extern int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_sabme_cmd_pbit_set_x(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_ua_rsp_fbit_set_x(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_p_tmr_exp(struct sock *sk, struct sk_buff *skb);
+extern int llc_conn_ev_ack_tmr_exp(struct sock *sk, struct sk_buff *skb);
+extern int llc_conn_ev_rej_tmr_exp(struct sock *sk, struct sk_buff *skb);
+extern int llc_conn_ev_busy_tmr_exp(struct sock *sk, struct sk_buff *skb);
+extern int llc_conn_ev_sendack_tmr_exp(struct sock *sk, struct sk_buff *skb);
+/* NOT_USED functions and their variations */
+extern int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_xxx_rsp_fbit_set_1(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_rx_any_frame(struct sock *sk, struct sk_buff *skb);
+extern int llc_conn_ev_tx_buffer_full(struct sock *sk, struct sk_buff *skb);
+extern int llc_conn_ev_init_p_f_cycle(struct sock *sk, struct sk_buff *skb);
+
+/* Available connection action qualifiers */
+extern int llc_conn_ev_qlfy_data_flag_eq_1(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_data_flag_eq_0(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_data_flag_eq_2(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_p_flag_eq_1(struct sock *sk, struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_last_frame_eq_1(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_last_frame_eq_0(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_p_flag_eq_0(struct sock *sk, struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_p_flag_eq_f(struct sock *sk, struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_remote_busy_eq_0(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_remote_busy_eq_1(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_retry_cnt_lt_n2(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_retry_cnt_gte_n2(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_s_flag_eq_1(struct sock *sk, struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_s_flag_eq_0(struct sock *sk, struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_cause_flag_eq_1(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_cause_flag_eq_0(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_set_status_conn(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_set_status_disc(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_set_status_failed(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_set_status_remote_busy(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_set_status_refuse(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_set_status_conflict(struct sock *sk,
+ struct sk_buff *skb);
+extern int llc_conn_ev_qlfy_set_status_rst_done(struct sock *sk,
+ struct sk_buff *skb);
+
+static __inline__ int llc_conn_space(struct sock *sk, struct sk_buff *skb)
+{
+ return atomic_read(&sk->sk_rmem_alloc) + skb->truesize <
+ (unsigned)sk->sk_rcvbuf;
+}
+#endif /* LLC_C_EV_H */
diff --git a/include/net/llc_c_st.h b/include/net/llc_c_st.h
new file mode 100644
index 00000000..0e79cfba
--- /dev/null
+++ b/include/net/llc_c_st.h
@@ -0,0 +1,48 @@
+#ifndef LLC_C_ST_H
+#define LLC_C_ST_H
+/*
+ * Copyright (c) 1997 by Procom Technology,Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+/* Connection component state management */
+/* connection states */
+#define LLC_CONN_OUT_OF_SVC 0 /* prior to allocation */
+
+#define LLC_CONN_STATE_ADM 1 /* disc, initial state */
+#define LLC_CONN_STATE_SETUP 2 /* disconnected state */
+#define LLC_CONN_STATE_NORMAL 3 /* connected state */
+#define LLC_CONN_STATE_BUSY 4 /* connected state */
+#define LLC_CONN_STATE_REJ 5 /* connected state */
+#define LLC_CONN_STATE_AWAIT 6 /* connected state */
+#define LLC_CONN_STATE_AWAIT_BUSY 7 /* connected state */
+#define LLC_CONN_STATE_AWAIT_REJ 8 /* connected state */
+#define LLC_CONN_STATE_D_CONN 9 /* disconnected state */
+#define LLC_CONN_STATE_RESET 10 /* disconnected state */
+#define LLC_CONN_STATE_ERROR 11 /* disconnected state */
+#define LLC_CONN_STATE_TEMP 12 /* disconnected state */
+
+#define NBR_CONN_STATES 12 /* size of state table */
+#define NO_STATE_CHANGE 100
+
+/* Connection state table structure */
+struct llc_conn_state_trans {
+ llc_conn_ev_t ev;
+ u8 next_state;
+ llc_conn_ev_qfyr_t *ev_qualifiers;
+ llc_conn_action_t *ev_actions;
+};
+
+struct llc_conn_state {
+ u8 current_state;
+ struct llc_conn_state_trans **transitions;
+};
+
+extern struct llc_conn_state llc_conn_state_table[];
+#endif /* LLC_C_ST_H */
diff --git a/include/net/llc_conn.h b/include/net/llc_conn.h
new file mode 100644
index 00000000..2f97d8dd
--- /dev/null
+++ b/include/net/llc_conn.h
@@ -0,0 +1,122 @@
+#ifndef LLC_CONN_H
+#define LLC_CONN_H
+/*
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001, 2002 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/timer.h>
+#include <net/llc_if.h>
+#include <net/sock.h>
+#include <linux/llc.h>
+
+#define LLC_EVENT 1
+#define LLC_PACKET 2
+
+#define LLC2_P_TIME 2
+#define LLC2_ACK_TIME 1
+#define LLC2_REJ_TIME 3
+#define LLC2_BUSY_TIME 3
+
+struct llc_timer {
+ struct timer_list timer;
+ unsigned long expire; /* timer expire time */
+};
+
+struct llc_sock {
+ /* struct sock must be the first member of llc_sock */
+ struct sock sk;
+ struct sockaddr_llc addr; /* address sock is bound to */
+ u8 state; /* state of connection */
+ struct llc_sap *sap; /* pointer to parent SAP */
+ struct llc_addr laddr; /* lsap/mac pair */
+ struct llc_addr daddr; /* dsap/mac pair */
+ struct net_device *dev; /* device to send to remote */
+ u32 copied_seq; /* head of yet unread data */
+ u8 retry_count; /* number of retries */
+ u8 ack_must_be_send;
+ u8 first_pdu_Ns;
+ u8 npta;
+ struct llc_timer ack_timer;
+ struct llc_timer pf_cycle_timer;
+ struct llc_timer rej_sent_timer;
+ struct llc_timer busy_state_timer; /* ind busy clr at remote LLC */
+ u8 vS; /* seq# next in-seq I-PDU tx'd*/
+ u8 vR; /* seq# next in-seq I-PDU rx'd*/
+ u32 n2; /* max nbr re-tx's for timeout*/
+ u32 n1; /* max nbr octets in I PDU */
+ u8 k; /* tx window size; max = 127 */
+ u8 rw; /* rx window size; max = 127 */
+ u8 p_flag; /* state flags */
+ u8 f_flag;
+ u8 s_flag;
+ u8 data_flag;
+ u8 remote_busy_flag;
+ u8 cause_flag;
+ struct sk_buff_head pdu_unack_q; /* PUDs sent/waiting ack */
+ u16 link; /* network layer link number */
+ u8 X; /* a temporary variable */
+ u8 ack_pf; /* this flag indicates what is
+ the P-bit of acknowledge */
+ u8 failed_data_req; /* recognize that already exist a
+ failed llc_data_req_handler
+ (tx_buffer_full or unacceptable
+ state */
+ u8 dec_step;
+ u8 inc_cntr;
+ u8 dec_cntr;
+ u8 connect_step;
+ u8 last_nr; /* NR of last pdu received */
+ u32 rx_pdu_hdr; /* used for saving header of last pdu
+ received and caused sending FRMR.
+ Used for resending FRMR */
+ u32 cmsg_flags;
+ struct hlist_node dev_hash_node;
+};
+
+static inline struct llc_sock *llc_sk(const struct sock *sk)
+{
+ return (struct llc_sock *)sk;
+}
+
+static __inline__ void llc_set_backlog_type(struct sk_buff *skb, char type)
+{
+ skb->cb[sizeof(skb->cb) - 1] = type;
+}
+
+static __inline__ char llc_backlog_type(struct sk_buff *skb)
+{
+ return skb->cb[sizeof(skb->cb) - 1];
+}
+
+extern struct sock *llc_sk_alloc(struct net *net, int family, gfp_t priority,
+ struct proto *prot);
+extern void llc_sk_free(struct sock *sk);
+
+extern void llc_sk_reset(struct sock *sk);
+
+/* Access to a connection */
+extern int llc_conn_state_process(struct sock *sk, struct sk_buff *skb);
+extern void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb);
+extern void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb);
+extern void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr,
+ u8 first_p_bit);
+extern void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr,
+ u8 first_f_bit);
+extern int llc_conn_remove_acked_pdus(struct sock *conn, u8 nr,
+ u16 *how_many_unacked);
+extern struct sock *llc_lookup_established(struct llc_sap *sap,
+ struct llc_addr *daddr,
+ struct llc_addr *laddr);
+extern void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk);
+extern void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk);
+
+extern u8 llc_data_accept_state(u8 state);
+extern void llc_build_offset_table(void);
+#endif /* LLC_CONN_H */
diff --git a/include/net/llc_if.h b/include/net/llc_if.h
new file mode 100644
index 00000000..b595a004
--- /dev/null
+++ b/include/net/llc_if.h
@@ -0,0 +1,99 @@
+#ifndef LLC_IF_H
+#define LLC_IF_H
+/*
+ * Copyright (c) 1997 by Procom Technology,Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+/* Defines LLC interface to network layer */
+/* Available primitives */
+#include <linux/if.h>
+#include <linux/if_arp.h>
+#include <linux/llc.h>
+#include <linux/etherdevice.h>
+#include <net/llc.h>
+
+#define LLC_DATAUNIT_PRIM 1
+#define LLC_CONN_PRIM 2
+#define LLC_DATA_PRIM 3
+#define LLC_DISC_PRIM 4
+#define LLC_RESET_PRIM 5
+#define LLC_FLOWCONTROL_PRIM 6 /* Not supported at this time */
+#define LLC_DISABLE_PRIM 7
+#define LLC_XID_PRIM 8
+#define LLC_TEST_PRIM 9
+#define LLC_SAP_ACTIVATION 10
+#define LLC_SAP_DEACTIVATION 11
+
+#define LLC_NBR_PRIMITIVES 11
+
+#define LLC_IND 1
+#define LLC_CONFIRM 2
+
+/* Primitive type */
+#define LLC_PRIM_TYPE_REQ 1
+#define LLC_PRIM_TYPE_IND 2
+#define LLC_PRIM_TYPE_RESP 3
+#define LLC_PRIM_TYPE_CONFIRM 4
+
+/* Reset reasons, remote entity or local LLC */
+#define LLC_RESET_REASON_REMOTE 1
+#define LLC_RESET_REASON_LOCAL 2
+
+/* Disconnect reasons */
+#define LLC_DISC_REASON_RX_DM_RSP_PDU 0
+#define LLC_DISC_REASON_RX_DISC_CMD_PDU 1
+#define LLC_DISC_REASON_ACK_TMR_EXP 2
+
+/* Confirm reasons */
+#define LLC_STATUS_CONN 0 /* connect confirm & reset confirm */
+#define LLC_STATUS_DISC 1 /* connect confirm & reset confirm */
+#define LLC_STATUS_FAILED 2 /* connect confirm & reset confirm */
+#define LLC_STATUS_IMPOSSIBLE 3 /* connect confirm */
+#define LLC_STATUS_RECEIVED 4 /* data conn */
+#define LLC_STATUS_REMOTE_BUSY 5 /* data conn */
+#define LLC_STATUS_REFUSE 6 /* data conn */
+#define LLC_STATUS_CONFLICT 7 /* disconnect conn */
+#define LLC_STATUS_RESET_DONE 8 /* */
+
+/**
+ * llc_mac_null - determines if a address is a null mac address
+ * @mac: Mac address to test if null.
+ *
+ * Determines if a given address is a null mac address. Returns 0 if the
+ * address is not a null mac, 1 if the address is a null mac.
+ */
+static inline int llc_mac_null(const u8 *mac)
+{
+ return is_zero_ether_addr(mac);
+}
+
+static inline int llc_mac_multicast(const u8 *mac)
+{
+ return is_multicast_ether_addr(mac);
+}
+/**
+ * llc_mac_match - determines if two mac addresses are the same
+ * @mac1: First mac address to compare.
+ * @mac2: Second mac address to compare.
+ *
+ * Determines if two given mac address are the same. Returns 0 if there
+ * is not a complete match up to len, 1 if a complete match up to len is
+ * found.
+ */
+static inline int llc_mac_match(const u8 *mac1, const u8 *mac2)
+{
+ return !compare_ether_addr(mac1, mac2);
+}
+
+extern int llc_establish_connection(struct sock *sk, u8 *lmac,
+ u8 *dmac, u8 dsap);
+extern int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb);
+extern int llc_send_disc(struct sock *sk);
+#endif /* LLC_IF_H */
diff --git a/include/net/llc_pdu.h b/include/net/llc_pdu.h
new file mode 100644
index 00000000..f57e7d46
--- /dev/null
+++ b/include/net/llc_pdu.h
@@ -0,0 +1,437 @@
+#ifndef LLC_PDU_H
+#define LLC_PDU_H
+/*
+ * Copyright (c) 1997 by Procom Technology,Inc.
+ * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+
+#include <linux/if_ether.h>
+#include <linux/if_tr.h>
+
+/* Lengths of frame formats */
+#define LLC_PDU_LEN_I 4 /* header and 2 control bytes */
+#define LLC_PDU_LEN_S 4
+#define LLC_PDU_LEN_U 3 /* header and 1 control byte */
+/* Known SAP addresses */
+#define LLC_GLOBAL_SAP 0xFF
+#define LLC_NULL_SAP 0x00 /* not network-layer visible */
+#define LLC_MGMT_INDIV 0x02 /* station LLC mgmt indiv addr */
+#define LLC_MGMT_GRP 0x03 /* station LLC mgmt group addr */
+#define LLC_RDE_SAP 0xA6 /* route ... */
+
+/* SAP field bit masks */
+#define LLC_ISO_RESERVED_SAP 0x02
+#define LLC_SAP_GROUP_DSAP 0x01
+#define LLC_SAP_RESP_SSAP 0x01
+
+/* Group/individual DSAP indicator is DSAP field */
+#define LLC_PDU_GROUP_DSAP_MASK 0x01
+#define LLC_PDU_IS_GROUP_DSAP(pdu) \
+ ((pdu->dsap & LLC_PDU_GROUP_DSAP_MASK) ? 0 : 1)
+#define LLC_PDU_IS_INDIV_DSAP(pdu) \
+ (!(pdu->dsap & LLC_PDU_GROUP_DSAP_MASK) ? 0 : 1)
+
+/* Command/response PDU indicator in SSAP field */
+#define LLC_PDU_CMD_RSP_MASK 0x01
+#define LLC_PDU_CMD 0
+#define LLC_PDU_RSP 1
+#define LLC_PDU_IS_CMD(pdu) ((pdu->ssap & LLC_PDU_RSP) ? 0 : 1)
+#define LLC_PDU_IS_RSP(pdu) ((pdu->ssap & LLC_PDU_RSP) ? 1 : 0)
+
+/* Get PDU type from 2 lowest-order bits of control field first byte */
+#define LLC_PDU_TYPE_I_MASK 0x01 /* 16-bit control field */
+#define LLC_PDU_TYPE_S_MASK 0x03
+#define LLC_PDU_TYPE_U_MASK 0x03 /* 8-bit control field */
+#define LLC_PDU_TYPE_MASK 0x03
+
+#define LLC_PDU_TYPE_I 0 /* first bit */
+#define LLC_PDU_TYPE_S 1 /* first two bits */
+#define LLC_PDU_TYPE_U 3 /* first two bits */
+
+#define LLC_PDU_TYPE_IS_I(pdu) \
+ ((!(pdu->ctrl_1 & LLC_PDU_TYPE_I_MASK)) ? 1 : 0)
+
+#define LLC_PDU_TYPE_IS_U(pdu) \
+ (((pdu->ctrl_1 & LLC_PDU_TYPE_U_MASK) == LLC_PDU_TYPE_U) ? 1 : 0)
+
+#define LLC_PDU_TYPE_IS_S(pdu) \
+ (((pdu->ctrl_1 & LLC_PDU_TYPE_S_MASK) == LLC_PDU_TYPE_S) ? 1 : 0)
+
+/* U-format PDU control field masks */
+#define LLC_U_PF_BIT_MASK 0x10 /* P/F bit mask */
+#define LLC_U_PF_IS_1(pdu) ((pdu->ctrl_1 & LLC_U_PF_BIT_MASK) ? 1 : 0)
+#define LLC_U_PF_IS_0(pdu) ((!(pdu->ctrl_1 & LLC_U_PF_BIT_MASK)) ? 1 : 0)
+
+#define LLC_U_PDU_CMD_MASK 0xEC /* cmd/rsp mask */
+#define LLC_U_PDU_CMD(pdu) (pdu->ctrl_1 & LLC_U_PDU_CMD_MASK)
+#define LLC_U_PDU_RSP(pdu) (pdu->ctrl_1 & LLC_U_PDU_CMD_MASK)
+
+#define LLC_1_PDU_CMD_UI 0x00 /* Type 1 cmds/rsps */
+#define LLC_1_PDU_CMD_XID 0xAC
+#define LLC_1_PDU_CMD_TEST 0xE0
+
+#define LLC_2_PDU_CMD_SABME 0x6C /* Type 2 cmds/rsps */
+#define LLC_2_PDU_CMD_DISC 0x40
+#define LLC_2_PDU_RSP_UA 0x60
+#define LLC_2_PDU_RSP_DM 0x0C
+#define LLC_2_PDU_RSP_FRMR 0x84
+
+/* Type 1 operations */
+
+/* XID information field bit masks */
+
+/* LLC format identifier (byte 1) */
+#define LLC_XID_FMT_ID 0x81 /* first byte must be this */
+
+/* LLC types/classes identifier (byte 2) */
+#define LLC_XID_CLASS_ZEROS_MASK 0xE0 /* these must be zeros */
+#define LLC_XID_CLASS_MASK 0x1F /* AND with byte to get below */
+
+#define LLC_XID_NULL_CLASS_1 0x01 /* if NULL LSAP...use these */
+#define LLC_XID_NULL_CLASS_2 0x03
+#define LLC_XID_NULL_CLASS_3 0x05
+#define LLC_XID_NULL_CLASS_4 0x07
+
+#define LLC_XID_NNULL_TYPE_1 0x01 /* if non-NULL LSAP...use these */
+#define LLC_XID_NNULL_TYPE_2 0x02
+#define LLC_XID_NNULL_TYPE_3 0x04
+#define LLC_XID_NNULL_TYPE_1_2 0x03
+#define LLC_XID_NNULL_TYPE_1_3 0x05
+#define LLC_XID_NNULL_TYPE_2_3 0x06
+#define LLC_XID_NNULL_ALL 0x07
+
+/* Sender Receive Window (byte 3) */
+#define LLC_XID_RW_MASK 0xFE /* AND with value to get below */
+
+#define LLC_XID_MIN_RW 0x02 /* lowest-order bit always zero */
+
+/* Type 2 operations */
+
+#define LLC_2_SEQ_NBR_MODULO ((u8) 128)
+
+/* I-PDU masks ('ctrl' is I-PDU control word) */
+#define LLC_I_GET_NS(pdu) (u8)((pdu->ctrl_1 & 0xFE) >> 1)
+#define LLC_I_GET_NR(pdu) (u8)((pdu->ctrl_2 & 0xFE) >> 1)
+
+#define LLC_I_PF_BIT_MASK 0x01
+
+#define LLC_I_PF_IS_0(pdu) ((!(pdu->ctrl_2 & LLC_I_PF_BIT_MASK)) ? 1 : 0)
+#define LLC_I_PF_IS_1(pdu) ((pdu->ctrl_2 & LLC_I_PF_BIT_MASK) ? 1 : 0)
+
+/* S-PDU supervisory commands and responses */
+
+#define LLC_S_PDU_CMD_MASK 0x0C
+#define LLC_S_PDU_CMD(pdu) (pdu->ctrl_1 & LLC_S_PDU_CMD_MASK)
+#define LLC_S_PDU_RSP(pdu) (pdu->ctrl_1 & LLC_S_PDU_CMD_MASK)
+
+#define LLC_2_PDU_CMD_RR 0x00 /* rx ready cmd */
+#define LLC_2_PDU_RSP_RR 0x00 /* rx ready rsp */
+#define LLC_2_PDU_CMD_REJ 0x08 /* reject PDU cmd */
+#define LLC_2_PDU_RSP_REJ 0x08 /* reject PDU rsp */
+#define LLC_2_PDU_CMD_RNR 0x04 /* rx not ready cmd */
+#define LLC_2_PDU_RSP_RNR 0x04 /* rx not ready rsp */
+
+#define LLC_S_PF_BIT_MASK 0x01
+#define LLC_S_PF_IS_0(pdu) ((!(pdu->ctrl_2 & LLC_S_PF_BIT_MASK)) ? 1 : 0)
+#define LLC_S_PF_IS_1(pdu) ((pdu->ctrl_2 & LLC_S_PF_BIT_MASK) ? 1 : 0)
+
+#define PDU_SUPV_GET_Nr(pdu) ((pdu->ctrl_2 & 0xFE) >> 1)
+#define PDU_GET_NEXT_Vr(sn) (++sn & ~LLC_2_SEQ_NBR_MODULO)
+
+/* FRMR information field macros */
+
+#define FRMR_INFO_LENGTH 5 /* 5 bytes of information */
+
+/*
+ * info is pointer to FRMR info field structure; 'rej_ctrl' is byte pointer
+ * (if U-PDU) or word pointer to rejected PDU control field
+ */
+#define FRMR_INFO_SET_REJ_CNTRL(info,rej_ctrl) \
+ info->rej_pdu_ctrl = ((*((u8 *) rej_ctrl) & \
+ LLC_PDU_TYPE_U) != LLC_PDU_TYPE_U ? \
+ (u16)*((u16 *) rej_ctrl) : \
+ (((u16) *((u8 *) rej_ctrl)) & 0x00FF))
+
+/*
+ * Info is pointer to FRMR info field structure; 'vs' is a byte containing
+ * send state variable value in low-order 7 bits (insure the lowest-order
+ * bit remains zero (0))
+ */
+#define FRMR_INFO_SET_Vs(info,vs) (info->curr_ssv = (((u8) vs) << 1))
+#define FRMR_INFO_SET_Vr(info,vr) (info->curr_rsv = (((u8) vr) << 1))
+
+/*
+ * Info is pointer to FRMR info field structure; 'cr' is a byte containing
+ * the C/R bit value in the low-order bit
+ */
+#define FRMR_INFO_SET_C_R_BIT(info, cr) (info->curr_rsv |= (((u8) cr) & 0x01))
+
+/*
+ * In the remaining five macros, 'info' is pointer to FRMR info field
+ * structure; 'ind' is a byte containing the bit value to set in the
+ * lowest-order bit)
+ */
+#define FRMR_INFO_SET_INVALID_PDU_CTRL_IND(info, ind) \
+ (info->ind_bits = ((info->ind_bits & 0xFE) | (((u8) ind) & 0x01)))
+
+#define FRMR_INFO_SET_INVALID_PDU_INFO_IND(info, ind) \
+ (info->ind_bits = ( (info->ind_bits & 0xFD) | (((u8) ind) & 0x02)))
+
+#define FRMR_INFO_SET_PDU_INFO_2LONG_IND(info, ind) \
+ (info->ind_bits = ( (info->ind_bits & 0xFB) | (((u8) ind) & 0x04)))
+
+#define FRMR_INFO_SET_PDU_INVALID_Nr_IND(info, ind) \
+ (info->ind_bits = ( (info->ind_bits & 0xF7) | (((u8) ind) & 0x08)))
+
+#define FRMR_INFO_SET_PDU_INVALID_Ns_IND(info, ind) \
+ (info->ind_bits = ( (info->ind_bits & 0xEF) | (((u8) ind) & 0x10)))
+
+/* Sequence-numbered PDU format (4 bytes in length) */
+struct llc_pdu_sn {
+ u8 dsap;
+ u8 ssap;
+ u8 ctrl_1;
+ u8 ctrl_2;
+} __packed;
+
+static inline struct llc_pdu_sn *llc_pdu_sn_hdr(struct sk_buff *skb)
+{
+ return (struct llc_pdu_sn *)skb_network_header(skb);
+}
+
+/* Un-numbered PDU format (3 bytes in length) */
+struct llc_pdu_un {
+ u8 dsap;
+ u8 ssap;
+ u8 ctrl_1;
+} __packed;
+
+static inline struct llc_pdu_un *llc_pdu_un_hdr(struct sk_buff *skb)
+{
+ return (struct llc_pdu_un *)skb_network_header(skb);
+}
+
+/**
+ * llc_pdu_header_init - initializes pdu header
+ * @skb: input skb that header must be set into it.
+ * @type: type of PDU (U, I or S).
+ * @ssap: source sap.
+ * @dsap: destination sap.
+ * @cr: command/response bit (0 or 1).
+ *
+ * This function sets DSAP, SSAP and command/Response bit in LLC header.
+ */
+static inline void llc_pdu_header_init(struct sk_buff *skb, u8 type,
+ u8 ssap, u8 dsap, u8 cr)
+{
+ const int hlen = type == LLC_PDU_TYPE_U ? 3 : 4;
+ struct llc_pdu_un *pdu;
+
+ skb_push(skb, hlen);
+ skb_reset_network_header(skb);
+ pdu = llc_pdu_un_hdr(skb);
+ pdu->dsap = dsap;
+ pdu->ssap = ssap;
+ pdu->ssap |= cr;
+}
+
+/**
+ * llc_pdu_decode_sa - extracs source address (MAC) of input frame
+ * @skb: input skb that source address must be extracted from it.
+ * @sa: pointer to source address (6 byte array).
+ *
+ * This function extracts source address(MAC) of input frame.
+ */
+static inline void llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa)
+{
+ if (skb->protocol == htons(ETH_P_802_2))
+ memcpy(sa, eth_hdr(skb)->h_source, ETH_ALEN);
+ else if (skb->protocol == htons(ETH_P_TR_802_2)) {
+ memcpy(sa, tr_hdr(skb)->saddr, ETH_ALEN);
+ *sa &= 0x7F;
+ }
+}
+
+/**
+ * llc_pdu_decode_da - extracts dest address of input frame
+ * @skb: input skb that destination address must be extracted from it
+ * @sa: pointer to destination address (6 byte array).
+ *
+ * This function extracts destination address(MAC) of input frame.
+ */
+static inline void llc_pdu_decode_da(struct sk_buff *skb, u8 *da)
+{
+ if (skb->protocol == htons(ETH_P_802_2))
+ memcpy(da, eth_hdr(skb)->h_dest, ETH_ALEN);
+ else if (skb->protocol == htons(ETH_P_TR_802_2))
+ memcpy(da, tr_hdr(skb)->daddr, ETH_ALEN);
+}
+
+/**
+ * llc_pdu_decode_ssap - extracts source SAP of input frame
+ * @skb: input skb that source SAP must be extracted from it.
+ * @ssap: source SAP (output argument).
+ *
+ * This function extracts source SAP of input frame. Right bit of SSAP is
+ * command/response bit.
+ */
+static inline void llc_pdu_decode_ssap(struct sk_buff *skb, u8 *ssap)
+{
+ *ssap = llc_pdu_un_hdr(skb)->ssap & 0xFE;
+}
+
+/**
+ * llc_pdu_decode_dsap - extracts dest SAP of input frame
+ * @skb: input skb that destination SAP must be extracted from it.
+ * @dsap: destination SAP (output argument).
+ *
+ * This function extracts destination SAP of input frame. right bit of
+ * DSAP designates individual/group SAP.
+ */
+static inline void llc_pdu_decode_dsap(struct sk_buff *skb, u8 *dsap)
+{
+ *dsap = llc_pdu_un_hdr(skb)->dsap & 0xFE;
+}
+
+/**
+ * llc_pdu_init_as_ui_cmd - sets LLC header as UI PDU
+ * @skb: input skb that header must be set into it.
+ *
+ * This function sets third byte of LLC header as a UI PDU.
+ */
+static inline void llc_pdu_init_as_ui_cmd(struct sk_buff *skb)
+{
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_U;
+ pdu->ctrl_1 |= LLC_1_PDU_CMD_UI;
+}
+
+/**
+ * llc_pdu_init_as_test_cmd - sets PDU as TEST
+ * @skb - Address of the skb to build
+ *
+ * Sets a PDU as TEST
+ */
+static inline void llc_pdu_init_as_test_cmd(struct sk_buff *skb)
+{
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_U;
+ pdu->ctrl_1 |= LLC_1_PDU_CMD_TEST;
+ pdu->ctrl_1 |= LLC_U_PF_BIT_MASK;
+}
+
+/**
+ * llc_pdu_init_as_test_rsp - build TEST response PDU
+ * @skb: Address of the skb to build
+ * @ev_skb: The received TEST command PDU frame
+ *
+ * Builds a pdu frame as a TEST response.
+ */
+static inline void llc_pdu_init_as_test_rsp(struct sk_buff *skb,
+ struct sk_buff *ev_skb)
+{
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_U;
+ pdu->ctrl_1 |= LLC_1_PDU_CMD_TEST;
+ pdu->ctrl_1 |= LLC_U_PF_BIT_MASK;
+ if (ev_skb->protocol == htons(ETH_P_802_2)) {
+ struct llc_pdu_un *ev_pdu = llc_pdu_un_hdr(ev_skb);
+ int dsize;
+
+ dsize = ntohs(eth_hdr(ev_skb)->h_proto) - 3;
+ memcpy(((u8 *)pdu) + 3, ((u8 *)ev_pdu) + 3, dsize);
+ skb_put(skb, dsize);
+ }
+}
+
+/* LLC Type 1 XID command/response information fields format */
+struct llc_xid_info {
+ u8 fmt_id; /* always 0x81 for LLC */
+ u8 type; /* different if NULL/non-NULL LSAP */
+ u8 rw; /* sender receive window */
+} __packed;
+
+/**
+ * llc_pdu_init_as_xid_cmd - sets bytes 3, 4 & 5 of LLC header as XID
+ * @skb: input skb that header must be set into it.
+ *
+ * This function sets third,fourth,fifth and sixth bytes of LLC header as
+ * a XID PDU.
+ */
+static inline void llc_pdu_init_as_xid_cmd(struct sk_buff *skb,
+ u8 svcs_supported, u8 rx_window)
+{
+ struct llc_xid_info *xid_info;
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_U;
+ pdu->ctrl_1 |= LLC_1_PDU_CMD_XID;
+ pdu->ctrl_1 |= LLC_U_PF_BIT_MASK;
+ xid_info = (struct llc_xid_info *)(((u8 *)&pdu->ctrl_1) + 1);
+ xid_info->fmt_id = LLC_XID_FMT_ID; /* 0x81 */
+ xid_info->type = svcs_supported;
+ xid_info->rw = rx_window << 1; /* size of receive window */
+ skb_put(skb, sizeof(struct llc_xid_info));
+}
+
+/**
+ * llc_pdu_init_as_xid_rsp - builds XID response PDU
+ * @skb: Address of the skb to build
+ * @svcs_supported: The class of the LLC (I or II)
+ * @rx_window: The size of the receive window of the LLC
+ *
+ * Builds a pdu frame as an XID response.
+ */
+static inline void llc_pdu_init_as_xid_rsp(struct sk_buff *skb,
+ u8 svcs_supported, u8 rx_window)
+{
+ struct llc_xid_info *xid_info;
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_U;
+ pdu->ctrl_1 |= LLC_1_PDU_CMD_XID;
+ pdu->ctrl_1 |= LLC_U_PF_BIT_MASK;
+
+ xid_info = (struct llc_xid_info *)(((u8 *)&pdu->ctrl_1) + 1);
+ xid_info->fmt_id = LLC_XID_FMT_ID;
+ xid_info->type = svcs_supported;
+ xid_info->rw = rx_window << 1;
+ skb_put(skb, sizeof(struct llc_xid_info));
+}
+
+/* LLC Type 2 FRMR response information field format */
+struct llc_frmr_info {
+ u16 rej_pdu_ctrl; /* bits 1-8 if U-PDU */
+ u8 curr_ssv; /* current send state variable val */
+ u8 curr_rsv; /* current receive state variable */
+ u8 ind_bits; /* indicator bits set with macro */
+} __packed;
+
+extern void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 type);
+extern void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value);
+extern void llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit);
+extern void llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit);
+extern void llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr);
+extern void llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr);
+extern void llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr);
+extern void llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr);
+extern void llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit);
+extern void llc_pdu_init_as_dm_rsp(struct sk_buff *skb, u8 f_bit);
+extern void llc_pdu_init_as_frmr_rsp(struct sk_buff *skb,
+ struct llc_pdu_sn *prev_pdu,
+ u8 f_bit, u8 vs, u8 vr, u8 vzyxw);
+extern void llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr);
+extern void llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr);
+extern void llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr);
+extern void llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit);
+#endif /* LLC_PDU_H */
diff --git a/include/net/llc_s_ac.h b/include/net/llc_s_ac.h
new file mode 100644
index 00000000..37a3bbd0
--- /dev/null
+++ b/include/net/llc_s_ac.h
@@ -0,0 +1,39 @@
+#ifndef LLC_S_AC_H
+#define LLC_S_AC_H
+/*
+ * Copyright (c) 1997 by Procom Technology,Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+/* SAP component actions */
+#define SAP_ACT_UNITDATA_IND 1
+#define SAP_ACT_SEND_UI 2
+#define SAP_ACT_SEND_XID_C 3
+#define SAP_ACT_SEND_XID_R 4
+#define SAP_ACT_SEND_TEST_C 5
+#define SAP_ACT_SEND_TEST_R 6
+#define SAP_ACT_REPORT_STATUS 7
+#define SAP_ACT_XID_IND 8
+#define SAP_ACT_TEST_IND 9
+
+/* All action functions must look like this */
+typedef int (*llc_sap_action_t)(struct llc_sap *sap, struct sk_buff *skb);
+
+extern int llc_sap_action_unitdata_ind(struct llc_sap *sap,
+ struct sk_buff *skb);
+extern int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb);
+extern int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb);
+extern int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb);
+extern int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb);
+extern int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb);
+extern int llc_sap_action_report_status(struct llc_sap *sap,
+ struct sk_buff *skb);
+extern int llc_sap_action_xid_ind(struct llc_sap *sap, struct sk_buff *skb);
+extern int llc_sap_action_test_ind(struct llc_sap *sap, struct sk_buff *skb);
+#endif /* LLC_S_AC_H */
diff --git a/include/net/llc_s_ev.h b/include/net/llc_s_ev.h
new file mode 100644
index 00000000..e3acb932
--- /dev/null
+++ b/include/net/llc_s_ev.h
@@ -0,0 +1,67 @@
+#ifndef LLC_S_EV_H
+#define LLC_S_EV_H
+/*
+ * Copyright (c) 1997 by Procom Technology,Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+
+#include <linux/skbuff.h>
+
+/* Defines SAP component events */
+/* Types of events (possible values in 'ev->type') */
+#define LLC_SAP_EV_TYPE_SIMPLE 1
+#define LLC_SAP_EV_TYPE_CONDITION 2
+#define LLC_SAP_EV_TYPE_PRIM 3
+#define LLC_SAP_EV_TYPE_PDU 4 /* command/response PDU */
+#define LLC_SAP_EV_TYPE_ACK_TMR 5
+#define LLC_SAP_EV_TYPE_RPT_STATUS 6
+
+#define LLC_SAP_EV_ACTIVATION_REQ 1
+#define LLC_SAP_EV_RX_UI 2
+#define LLC_SAP_EV_UNITDATA_REQ 3
+#define LLC_SAP_EV_XID_REQ 4
+#define LLC_SAP_EV_RX_XID_C 5
+#define LLC_SAP_EV_RX_XID_R 6
+#define LLC_SAP_EV_TEST_REQ 7
+#define LLC_SAP_EV_RX_TEST_C 8
+#define LLC_SAP_EV_RX_TEST_R 9
+#define LLC_SAP_EV_DEACTIVATION_REQ 10
+
+struct llc_sap_state_ev {
+ u8 prim;
+ u8 prim_type;
+ u8 type;
+ u8 reason;
+ u8 ind_cfm_flag;
+ struct llc_addr saddr;
+ struct llc_addr daddr;
+};
+
+static __inline__ struct llc_sap_state_ev *llc_sap_ev(struct sk_buff *skb)
+{
+ return (struct llc_sap_state_ev *)skb->cb;
+}
+
+struct llc_sap;
+
+typedef int (*llc_sap_ev_t)(struct llc_sap *sap, struct sk_buff *skb);
+
+extern int llc_sap_ev_activation_req(struct llc_sap *sap, struct sk_buff *skb);
+extern int llc_sap_ev_rx_ui(struct llc_sap *sap, struct sk_buff *skb);
+extern int llc_sap_ev_unitdata_req(struct llc_sap *sap, struct sk_buff *skb);
+extern int llc_sap_ev_xid_req(struct llc_sap *sap, struct sk_buff *skb);
+extern int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct sk_buff *skb);
+extern int llc_sap_ev_rx_xid_r(struct llc_sap *sap, struct sk_buff *skb);
+extern int llc_sap_ev_test_req(struct llc_sap *sap, struct sk_buff *skb);
+extern int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct sk_buff *skb);
+extern int llc_sap_ev_rx_test_r(struct llc_sap *sap, struct sk_buff *skb);
+extern int llc_sap_ev_deactivation_req(struct llc_sap *sap,
+ struct sk_buff *skb);
+#endif /* LLC_S_EV_H */
diff --git a/include/net/llc_s_st.h b/include/net/llc_s_st.h
new file mode 100644
index 00000000..567c681f
--- /dev/null
+++ b/include/net/llc_s_st.h
@@ -0,0 +1,32 @@
+#ifndef LLC_S_ST_H
+#define LLC_S_ST_H
+/*
+ * Copyright (c) 1997 by Procom Technology,Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+
+#define LLC_NR_SAP_STATES 2 /* size of state table */
+
+/* structures and types */
+/* SAP state table structure */
+struct llc_sap_state_trans {
+ llc_sap_ev_t ev;
+ u8 next_state;
+ llc_sap_action_t *ev_actions;
+};
+
+struct llc_sap_state {
+ u8 curr_state;
+ struct llc_sap_state_trans **transitions;
+};
+
+/* only access to SAP state table */
+extern struct llc_sap_state llc_sap_state_table[LLC_NR_SAP_STATES];
+#endif /* LLC_S_ST_H */
diff --git a/include/net/llc_sap.h b/include/net/llc_sap.h
new file mode 100644
index 00000000..ed25bec2
--- /dev/null
+++ b/include/net/llc_sap.h
@@ -0,0 +1,36 @@
+#ifndef LLC_SAP_H
+#define LLC_SAP_H
+
+#include <asm/types.h>
+
+/*
+ * Copyright (c) 1997 by Procom Technology,Inc.
+ * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+struct llc_sap;
+struct net_device;
+struct sk_buff;
+struct sock;
+
+extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb);
+extern void llc_save_primitive(struct sock *sk, struct sk_buff* skb,
+ unsigned char prim);
+extern struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev,
+ u8 type, u32 data_size);
+
+extern void llc_build_and_send_test_pkt(struct llc_sap *sap,
+ struct sk_buff *skb,
+ unsigned char *dmac,
+ unsigned char dsap);
+extern void llc_build_and_send_xid_pkt(struct llc_sap *sap,
+ struct sk_buff *skb,
+ unsigned char *dmac,
+ unsigned char dsap);
+#endif /* LLC_SAP_H */
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
new file mode 100644
index 00000000..9210bdc7
--- /dev/null
+++ b/include/net/mac80211.h
@@ -0,0 +1,3713 @@
+/*
+ * mac80211 <-> driver interface
+ *
+ * Copyright 2002-2005, Devicescape Software, Inc.
+ * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
+ * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MAC80211_H
+#define MAC80211_H
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <linux/if_ether.h>
+#include <linux/skbuff.h>
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
+#include <asm/unaligned.h>
+
+/**
+ * DOC: Introduction
+ *
+ * mac80211 is the Linux stack for 802.11 hardware that implements
+ * only partial functionality in hard- or firmware. This document
+ * defines the interface between mac80211 and low-level hardware
+ * drivers.
+ */
+
+/**
+ * DOC: Calling mac80211 from interrupts
+ *
+ * Only ieee80211_tx_status_irqsafe() and ieee80211_rx_irqsafe() can be
+ * called in hardware interrupt context. The low-level driver must not call any
+ * other functions in hardware interrupt context. If there is a need for such
+ * call, the low-level driver should first ACK the interrupt and perform the
+ * IEEE 802.11 code call after this, e.g. from a scheduled workqueue or even
+ * tasklet function.
+ *
+ * NOTE: If the driver opts to use the _irqsafe() functions, it may not also
+ * use the non-IRQ-safe functions!
+ */
+
+/**
+ * DOC: Warning
+ *
+ * If you're reading this document and not the header file itself, it will
+ * be incomplete because not all documentation has been converted yet.
+ */
+
+/**
+ * DOC: Frame format
+ *
+ * As a general rule, when frames are passed between mac80211 and the driver,
+ * they start with the IEEE 802.11 header and include the same octets that are
+ * sent over the air except for the FCS which should be calculated by the
+ * hardware.
+ *
+ * There are, however, various exceptions to this rule for advanced features:
+ *
+ * The first exception is for hardware encryption and decryption offload
+ * where the IV/ICV may or may not be generated in hardware.
+ *
+ * Secondly, when the hardware handles fragmentation, the frame handed to
+ * the driver from mac80211 is the MSDU, not the MPDU.
+ *
+ * Finally, for received frames, the driver is able to indicate that it has
+ * filled a radiotap header and put that in front of the frame; if it does
+ * not do so then mac80211 may add this under certain circumstances.
+ */
+
+/**
+ * DOC: mac80211 workqueue
+ *
+ * mac80211 provides its own workqueue for drivers and internal mac80211 use.
+ * The workqueue is a single threaded workqueue and can only be accessed by
+ * helpers for sanity checking. Drivers must ensure all work added onto the
+ * mac80211 workqueue should be cancelled on the driver stop() callback.
+ *
+ * mac80211 will flushed the workqueue upon interface removal and during
+ * suspend.
+ *
+ * All work performed on the mac80211 workqueue must not acquire the RTNL lock.
+ *
+ */
+
+struct device;
+
+/**
+ * enum ieee80211_max_queues - maximum number of queues
+ *
+ * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues.
+ */
+enum ieee80211_max_queues {
+ IEEE80211_MAX_QUEUES = 4,
+};
+
+/**
+ * enum ieee80211_ac_numbers - AC numbers as used in mac80211
+ * @IEEE80211_AC_VO: voice
+ * @IEEE80211_AC_VI: video
+ * @IEEE80211_AC_BE: best effort
+ * @IEEE80211_AC_BK: background
+ */
+enum ieee80211_ac_numbers {
+ IEEE80211_AC_VO = 0,
+ IEEE80211_AC_VI = 1,
+ IEEE80211_AC_BE = 2,
+ IEEE80211_AC_BK = 3,
+};
+#define IEEE80211_NUM_ACS 4
+
+/**
+ * struct ieee80211_tx_queue_params - transmit queue configuration
+ *
+ * The information provided in this structure is required for QoS
+ * transmit queue configuration. Cf. IEEE 802.11 7.3.2.29.
+ *
+ * @aifs: arbitration interframe space [0..255]
+ * @cw_min: minimum contention window [a value of the form
+ * 2^n-1 in the range 1..32767]
+ * @cw_max: maximum contention window [like @cw_min]
+ * @txop: maximum burst time in units of 32 usecs, 0 meaning disabled
+ * @uapsd: is U-APSD mode enabled for the queue
+ */
+struct ieee80211_tx_queue_params {
+ u16 txop;
+ u16 cw_min;
+ u16 cw_max;
+ u8 aifs;
+ bool uapsd;
+};
+
+struct ieee80211_low_level_stats {
+ unsigned int dot11ACKFailureCount;
+ unsigned int dot11RTSFailureCount;
+ unsigned int dot11FCSErrorCount;
+ unsigned int dot11RTSSuccessCount;
+};
+
+/**
+ * enum ieee80211_bss_change - BSS change notification flags
+ *
+ * These flags are used with the bss_info_changed() callback
+ * to indicate which BSS parameter changed.
+ *
+ * @BSS_CHANGED_ASSOC: association status changed (associated/disassociated),
+ * also implies a change in the AID.
+ * @BSS_CHANGED_ERP_CTS_PROT: CTS protection changed
+ * @BSS_CHANGED_ERP_PREAMBLE: preamble changed
+ * @BSS_CHANGED_ERP_SLOT: slot timing changed
+ * @BSS_CHANGED_HT: 802.11n parameters changed
+ * @BSS_CHANGED_BASIC_RATES: Basic rateset changed
+ * @BSS_CHANGED_BEACON_INT: Beacon interval changed
+ * @BSS_CHANGED_BSSID: BSSID changed, for whatever
+ * reason (IBSS and managed mode)
+ * @BSS_CHANGED_BEACON: Beacon data changed, retrieve
+ * new beacon (beaconing modes)
+ * @BSS_CHANGED_BEACON_ENABLED: Beaconing should be
+ * enabled/disabled (beaconing modes)
+ * @BSS_CHANGED_CQM: Connection quality monitor config changed
+ * @BSS_CHANGED_IBSS: IBSS join status changed
+ * @BSS_CHANGED_ARP_FILTER: Hardware ARP filter address list or state changed.
+ * @BSS_CHANGED_QOS: QoS for this association was enabled/disabled. Note
+ * that it is only ever disabled for station mode.
+ * @BSS_CHANGED_IDLE: Idle changed for this BSS/interface.
+ * @BSS_CHANGED_SSID: SSID changed for this BSS (AP mode)
+ * @BSS_CHANGED_AP_PROBE_RESP: Probe Response changed for this BSS (AP mode)
+ */
+enum ieee80211_bss_change {
+ BSS_CHANGED_ASSOC = 1<<0,
+ BSS_CHANGED_ERP_CTS_PROT = 1<<1,
+ BSS_CHANGED_ERP_PREAMBLE = 1<<2,
+ BSS_CHANGED_ERP_SLOT = 1<<3,
+ BSS_CHANGED_HT = 1<<4,
+ BSS_CHANGED_BASIC_RATES = 1<<5,
+ BSS_CHANGED_BEACON_INT = 1<<6,
+ BSS_CHANGED_BSSID = 1<<7,
+ BSS_CHANGED_BEACON = 1<<8,
+ BSS_CHANGED_BEACON_ENABLED = 1<<9,
+ BSS_CHANGED_CQM = 1<<10,
+ BSS_CHANGED_IBSS = 1<<11,
+ BSS_CHANGED_ARP_FILTER = 1<<12,
+ BSS_CHANGED_QOS = 1<<13,
+ BSS_CHANGED_IDLE = 1<<14,
+ BSS_CHANGED_SSID = 1<<15,
+ BSS_CHANGED_AP_PROBE_RESP = 1<<16,
+
+ /* when adding here, make sure to change ieee80211_reconfig */
+};
+
+/*
+ * The maximum number of IPv4 addresses listed for ARP filtering. If the number
+ * of addresses for an interface increase beyond this value, hardware ARP
+ * filtering will be disabled.
+ */
+#define IEEE80211_BSS_ARP_ADDR_LIST_LEN 4
+
+/**
+ * enum ieee80211_rssi_event - RSSI threshold event
+ * An indicator for when RSSI goes below/above a certain threshold.
+ * @RSSI_EVENT_HIGH: AP's rssi crossed the high threshold set by the driver.
+ * @RSSI_EVENT_LOW: AP's rssi crossed the low threshold set by the driver.
+ */
+enum ieee80211_rssi_event {
+ RSSI_EVENT_HIGH,
+ RSSI_EVENT_LOW,
+};
+
+/**
+ * struct ieee80211_bss_conf - holds the BSS's changing parameters
+ *
+ * This structure keeps information about a BSS (and an association
+ * to that BSS) that can change during the lifetime of the BSS.
+ *
+ * @assoc: association status
+ * @ibss_joined: indicates whether this station is part of an IBSS
+ * or not
+ * @aid: association ID number, valid only when @assoc is true
+ * @use_cts_prot: use CTS protection
+ * @use_short_preamble: use 802.11b short preamble;
+ * if the hardware cannot handle this it must set the
+ * IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE hardware flag
+ * @use_short_slot: use short slot time (only relevant for ERP);
+ * if the hardware cannot handle this it must set the
+ * IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE hardware flag
+ * @dtim_period: num of beacons before the next DTIM, for beaconing,
+ * valid in station mode only while @assoc is true and if also
+ * requested by %IEEE80211_HW_NEED_DTIM_PERIOD (cf. also hw conf
+ * @ps_dtim_period)
+ * @last_tsf: last beacon's/probe response's TSF timestamp (could be old
+ * as it may have been received during scanning long ago)
+ * @beacon_int: beacon interval
+ * @assoc_capability: capabilities taken from assoc resp
+ * @basic_rates: bitmap of basic rates, each bit stands for an
+ * index into the rate table configured by the driver in
+ * the current band.
+ * @mcast_rate: per-band multicast rate index + 1 (0: disabled)
+ * @bssid: The BSSID for this BSS
+ * @enable_beacon: whether beaconing should be enabled or not
+ * @channel_type: Channel type for this BSS -- the hardware might be
+ * configured for HT40+ while this BSS only uses no-HT, for
+ * example.
+ * @ht_operation_mode: HT operation mode (like in &struct ieee80211_ht_info).
+ * This field is only valid when the channel type is one of the HT types.
+ * @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value
+ * implies disabled
+ * @cqm_rssi_hyst: Connection quality monitor RSSI hysteresis
+ * @arp_addr_list: List of IPv4 addresses for hardware ARP filtering. The
+ * may filter ARP queries targeted for other addresses than listed here.
+ * The driver must allow ARP queries targeted for all address listed here
+ * to pass through. An empty list implies no ARP queries need to pass.
+ * @arp_addr_cnt: Number of addresses currently on the list.
+ * @arp_filter_enabled: Enable ARP filtering - if enabled, the hardware may
+ * filter ARP queries based on the @arp_addr_list, if disabled, the
+ * hardware must not perform any ARP filtering. Note, that the filter will
+ * be enabled also in promiscuous mode.
+ * @qos: This is a QoS-enabled BSS.
+ * @idle: This interface is idle. There's also a global idle flag in the
+ * hardware config which may be more appropriate depending on what
+ * your driver/device needs to do.
+ * @ssid: The SSID of the current vif. Only valid in AP-mode.
+ * @ssid_len: Length of SSID given in @ssid.
+ * @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode.
+ */
+struct ieee80211_bss_conf {
+ const u8 *bssid;
+ /* association related data */
+ bool assoc, ibss_joined;
+ u16 aid;
+ /* erp related data */
+ bool use_cts_prot;
+ bool use_short_preamble;
+ bool use_short_slot;
+ bool enable_beacon;
+ u8 dtim_period;
+ u16 beacon_int;
+ u16 assoc_capability;
+ u64 last_tsf;
+ u32 basic_rates;
+ int mcast_rate[IEEE80211_NUM_BANDS];
+ u16 ht_operation_mode;
+ s32 cqm_rssi_thold;
+ u32 cqm_rssi_hyst;
+ enum nl80211_channel_type channel_type;
+ __be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
+ u8 arp_addr_cnt;
+ bool arp_filter_enabled;
+ bool qos;
+ bool idle;
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+ size_t ssid_len;
+ bool hidden_ssid;
+};
+
+/**
+ * enum mac80211_tx_control_flags - flags to describe transmission information/status
+ *
+ * These flags are used with the @flags member of &ieee80211_tx_info.
+ *
+ * @IEEE80211_TX_CTL_REQ_TX_STATUS: require TX status callback for this frame.
+ * @IEEE80211_TX_CTL_ASSIGN_SEQ: The driver has to assign a sequence
+ * number to this frame, taking care of not overwriting the fragment
+ * number and increasing the sequence number only when the
+ * IEEE80211_TX_CTL_FIRST_FRAGMENT flag is set. mac80211 will properly
+ * assign sequence numbers to QoS-data frames but cannot do so correctly
+ * for non-QoS-data and management frames because beacons need them from
+ * that counter as well and mac80211 cannot guarantee proper sequencing.
+ * If this flag is set, the driver should instruct the hardware to
+ * assign a sequence number to the frame or assign one itself. Cf. IEEE
+ * 802.11-2007 7.1.3.4.1 paragraph 3. This flag will always be set for
+ * beacons and always be clear for frames without a sequence number field.
+ * @IEEE80211_TX_CTL_NO_ACK: tell the low level not to wait for an ack
+ * @IEEE80211_TX_CTL_CLEAR_PS_FILT: clear powersave filter for destination
+ * station
+ * @IEEE80211_TX_CTL_FIRST_FRAGMENT: this is a first fragment of the frame
+ * @IEEE80211_TX_CTL_SEND_AFTER_DTIM: send this frame after DTIM beacon
+ * @IEEE80211_TX_CTL_AMPDU: this frame should be sent as part of an A-MPDU
+ * @IEEE80211_TX_CTL_INJECTED: Frame was injected, internal to mac80211.
+ * @IEEE80211_TX_STAT_TX_FILTERED: The frame was not transmitted
+ * because the destination STA was in powersave mode. Note that to
+ * avoid race conditions, the filter must be set by the hardware or
+ * firmware upon receiving a frame that indicates that the station
+ * went to sleep (must be done on device to filter frames already on
+ * the queue) and may only be unset after mac80211 gives the OK for
+ * that by setting the IEEE80211_TX_CTL_CLEAR_PS_FILT (see above),
+ * since only then is it guaranteed that no more frames are in the
+ * hardware queue.
+ * @IEEE80211_TX_STAT_ACK: Frame was acknowledged
+ * @IEEE80211_TX_STAT_AMPDU: The frame was aggregated, so status
+ * is for the whole aggregation.
+ * @IEEE80211_TX_STAT_AMPDU_NO_BACK: no block ack was returned,
+ * so consider using block ack request (BAR).
+ * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be
+ * set by rate control algorithms to indicate probe rate, will
+ * be cleared for fragmented frames (except on the last fragment)
+ * @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211,
+ * used to indicate that a pending frame requires TX processing before
+ * it can be sent out.
+ * @IEEE80211_TX_INTFL_RETRIED: completely internal to mac80211,
+ * used to indicate that a frame was already retried due to PS
+ * @IEEE80211_TX_INTFL_DONT_ENCRYPT: completely internal to mac80211,
+ * used to indicate frame should not be encrypted
+ * @IEEE80211_TX_CTL_NO_PS_BUFFER: This frame is a response to a poll
+ * frame (PS-Poll or uAPSD) or a non-bufferable MMPDU and must
+ * be sent although the station is in powersave mode.
+ * @IEEE80211_TX_CTL_MORE_FRAMES: More frames will be passed to the
+ * transmit function after the current frame, this can be used
+ * by drivers to kick the DMA queue only if unset or when the
+ * queue gets full.
+ * @IEEE80211_TX_INTFL_RETRANSMISSION: This frame is being retransmitted
+ * after TX status because the destination was asleep, it must not
+ * be modified again (no seqno assignment, crypto, etc.)
+ * @IEEE80211_TX_INTFL_NL80211_FRAME_TX: Frame was requested through nl80211
+ * MLME command (internal to mac80211 to figure out whether to send TX
+ * status to user space)
+ * @IEEE80211_TX_CTL_LDPC: tells the driver to use LDPC for this frame
+ * @IEEE80211_TX_CTL_STBC: Enables Space-Time Block Coding (STBC) for this
+ * frame and selects the maximum number of streams that it can use.
+ * @IEEE80211_TX_CTL_TX_OFFCHAN: Marks this packet to be transmitted on
+ * the off-channel channel when a remain-on-channel offload is done
+ * in hardware -- normal packets still flow and are expected to be
+ * handled properly by the device.
+ * @IEEE80211_TX_INTFL_TKIP_MIC_FAILURE: Marks this packet to be used for TKIP
+ * testing. It will be sent out with incorrect Michael MIC key to allow
+ * TKIP countermeasures to be tested.
+ * @IEEE80211_TX_CTL_NO_CCK_RATE: This frame will be sent at non CCK rate.
+ * This flag is actually used for management frame especially for P2P
+ * frames not being sent at CCK rate in 2GHz band.
+ * @IEEE80211_TX_STATUS_EOSP: This packet marks the end of service period,
+ * when its status is reported the service period ends. For frames in
+ * an SP that mac80211 transmits, it is already set; for driver frames
+ * the driver may set this flag. It is also used to do the same for
+ * PS-Poll responses.
+ * @IEEE80211_TX_CTL_USE_MINRATE: This frame will be sent at lowest rate.
+ * This flag is used to send nullfunc frame at minimum rate when
+ * the nullfunc is used for connection monitoring purpose.
+ * @IEEE80211_TX_CTL_DONTFRAG: Don't fragment this packet even if it
+ * would be fragmented by size (this is optional, only used for
+ * monitor injection).
+ *
+ * Note: If you have to add new flags to the enumeration, then don't
+ * forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary.
+ */
+enum mac80211_tx_control_flags {
+ IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0),
+ IEEE80211_TX_CTL_ASSIGN_SEQ = BIT(1),
+ IEEE80211_TX_CTL_NO_ACK = BIT(2),
+ IEEE80211_TX_CTL_CLEAR_PS_FILT = BIT(3),
+ IEEE80211_TX_CTL_FIRST_FRAGMENT = BIT(4),
+ IEEE80211_TX_CTL_SEND_AFTER_DTIM = BIT(5),
+ IEEE80211_TX_CTL_AMPDU = BIT(6),
+ IEEE80211_TX_CTL_INJECTED = BIT(7),
+ IEEE80211_TX_STAT_TX_FILTERED = BIT(8),
+ IEEE80211_TX_STAT_ACK = BIT(9),
+ IEEE80211_TX_STAT_AMPDU = BIT(10),
+ IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11),
+ IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12),
+ IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14),
+ IEEE80211_TX_INTFL_RETRIED = BIT(15),
+ IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16),
+ IEEE80211_TX_CTL_NO_PS_BUFFER = BIT(17),
+ IEEE80211_TX_CTL_MORE_FRAMES = BIT(18),
+ IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19),
+ /* hole at 20, use later */
+ IEEE80211_TX_INTFL_NL80211_FRAME_TX = BIT(21),
+ IEEE80211_TX_CTL_LDPC = BIT(22),
+ IEEE80211_TX_CTL_STBC = BIT(23) | BIT(24),
+ IEEE80211_TX_CTL_TX_OFFCHAN = BIT(25),
+ IEEE80211_TX_INTFL_TKIP_MIC_FAILURE = BIT(26),
+ IEEE80211_TX_CTL_NO_CCK_RATE = BIT(27),
+ IEEE80211_TX_STATUS_EOSP = BIT(28),
+ IEEE80211_TX_CTL_USE_MINRATE = BIT(29),
+ IEEE80211_TX_CTL_DONTFRAG = BIT(30),
+};
+
+#define IEEE80211_TX_CTL_STBC_SHIFT 23
+
+/*
+ * This definition is used as a mask to clear all temporary flags, which are
+ * set by the tx handlers for each transmission attempt by the mac80211 stack.
+ */
+#define IEEE80211_TX_TEMPORARY_FLAGS (IEEE80211_TX_CTL_NO_ACK | \
+ IEEE80211_TX_CTL_CLEAR_PS_FILT | IEEE80211_TX_CTL_FIRST_FRAGMENT | \
+ IEEE80211_TX_CTL_SEND_AFTER_DTIM | IEEE80211_TX_CTL_AMPDU | \
+ IEEE80211_TX_STAT_TX_FILTERED | IEEE80211_TX_STAT_ACK | \
+ IEEE80211_TX_STAT_AMPDU | IEEE80211_TX_STAT_AMPDU_NO_BACK | \
+ IEEE80211_TX_CTL_RATE_CTRL_PROBE | IEEE80211_TX_CTL_NO_PS_BUFFER | \
+ IEEE80211_TX_CTL_MORE_FRAMES | IEEE80211_TX_CTL_LDPC | \
+ IEEE80211_TX_CTL_STBC | IEEE80211_TX_STATUS_EOSP)
+
+/**
+ * enum mac80211_rate_control_flags - per-rate flags set by the
+ * Rate Control algorithm.
+ *
+ * These flags are set by the Rate control algorithm for each rate during tx,
+ * in the @flags member of struct ieee80211_tx_rate.
+ *
+ * @IEEE80211_TX_RC_USE_RTS_CTS: Use RTS/CTS exchange for this rate.
+ * @IEEE80211_TX_RC_USE_CTS_PROTECT: CTS-to-self protection is required.
+ * This is set if the current BSS requires ERP protection.
+ * @IEEE80211_TX_RC_USE_SHORT_PREAMBLE: Use short preamble.
+ * @IEEE80211_TX_RC_MCS: HT rate.
+ * @IEEE80211_TX_RC_GREEN_FIELD: Indicates whether this rate should be used in
+ * Greenfield mode.
+ * @IEEE80211_TX_RC_40_MHZ_WIDTH: Indicates if the Channel Width should be 40 MHz.
+ * @IEEE80211_TX_RC_DUP_DATA: The frame should be transmitted on both of the
+ * adjacent 20 MHz channels, if the current channel type is
+ * NL80211_CHAN_HT40MINUS or NL80211_CHAN_HT40PLUS.
+ * @IEEE80211_TX_RC_SHORT_GI: Short Guard interval should be used for this rate.
+ */
+enum mac80211_rate_control_flags {
+ IEEE80211_TX_RC_USE_RTS_CTS = BIT(0),
+ IEEE80211_TX_RC_USE_CTS_PROTECT = BIT(1),
+ IEEE80211_TX_RC_USE_SHORT_PREAMBLE = BIT(2),
+
+ /* rate index is an MCS rate number instead of an index */
+ IEEE80211_TX_RC_MCS = BIT(3),
+ IEEE80211_TX_RC_GREEN_FIELD = BIT(4),
+ IEEE80211_TX_RC_40_MHZ_WIDTH = BIT(5),
+ IEEE80211_TX_RC_DUP_DATA = BIT(6),
+ IEEE80211_TX_RC_SHORT_GI = BIT(7),
+};
+
+
+/* there are 40 bytes if you don't need the rateset to be kept */
+#define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40
+
+/* if you do need the rateset, then you have less space */
+#define IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE 24
+
+/* maximum number of rate stages */
+#define IEEE80211_TX_MAX_RATES 5
+
+/**
+ * struct ieee80211_tx_rate - rate selection/status
+ *
+ * @idx: rate index to attempt to send with
+ * @flags: rate control flags (&enum mac80211_rate_control_flags)
+ * @count: number of tries in this rate before going to the next rate
+ *
+ * A value of -1 for @idx indicates an invalid rate and, if used
+ * in an array of retry rates, that no more rates should be tried.
+ *
+ * When used for transmit status reporting, the driver should
+ * always report the rate along with the flags it used.
+ *
+ * &struct ieee80211_tx_info contains an array of these structs
+ * in the control information, and it will be filled by the rate
+ * control algorithm according to what should be sent. For example,
+ * if this array contains, in the format { <idx>, <count> } the
+ * information
+ * { 3, 2 }, { 2, 2 }, { 1, 4 }, { -1, 0 }, { -1, 0 }
+ * then this means that the frame should be transmitted
+ * up to twice at rate 3, up to twice at rate 2, and up to four
+ * times at rate 1 if it doesn't get acknowledged. Say it gets
+ * acknowledged by the peer after the fifth attempt, the status
+ * information should then contain
+ * { 3, 2 }, { 2, 2 }, { 1, 1 }, { -1, 0 } ...
+ * since it was transmitted twice at rate 3, twice at rate 2
+ * and once at rate 1 after which we received an acknowledgement.
+ */
+struct ieee80211_tx_rate {
+ s8 idx;
+ u8 count;
+ u8 flags;
+} __packed;
+
+/**
+ * struct ieee80211_tx_info - skb transmit information
+ *
+ * This structure is placed in skb->cb for three uses:
+ * (1) mac80211 TX control - mac80211 tells the driver what to do
+ * (2) driver internal use (if applicable)
+ * (3) TX status information - driver tells mac80211 what happened
+ *
+ * The TX control's sta pointer is only valid during the ->tx call,
+ * it may be NULL.
+ *
+ * @flags: transmit info flags, defined above
+ * @band: the band to transmit on (use for checking for races)
+ * @antenna_sel_tx: antenna to use, 0 for automatic diversity
+ * @ack_frame_id: internal frame ID for TX status, used internally
+ * @control: union for control data
+ * @status: union for status data
+ * @driver_data: array of driver_data pointers
+ * @ampdu_ack_len: number of acked aggregated frames.
+ * relevant only if IEEE80211_TX_STAT_AMPDU was set.
+ * @ampdu_len: number of aggregated frames.
+ * relevant only if IEEE80211_TX_STAT_AMPDU was set.
+ * @ack_signal: signal strength of the ACK frame
+ */
+struct ieee80211_tx_info {
+ /* common information */
+ u32 flags;
+ u8 band;
+
+ u8 antenna_sel_tx;
+
+ u16 ack_frame_id;
+
+ union {
+ struct {
+ union {
+ /* rate control */
+ struct {
+ struct ieee80211_tx_rate rates[
+ IEEE80211_TX_MAX_RATES];
+ s8 rts_cts_rate_idx;
+ };
+ /* only needed before rate control */
+ unsigned long jiffies;
+ };
+ /* NB: vif can be NULL for injected frames */
+ struct ieee80211_vif *vif;
+ struct ieee80211_key_conf *hw_key;
+ struct ieee80211_sta *sta;
+ } control;
+ struct {
+ struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES];
+ u8 ampdu_ack_len;
+ int ack_signal;
+ u8 ampdu_len;
+ /* 15 bytes free */
+ } status;
+ struct {
+ struct ieee80211_tx_rate driver_rates[
+ IEEE80211_TX_MAX_RATES];
+ void *rate_driver_data[
+ IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE / sizeof(void *)];
+ };
+ void *driver_data[
+ IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *)];
+ };
+};
+
+/**
+ * struct ieee80211_sched_scan_ies - scheduled scan IEs
+ *
+ * This structure is used to pass the appropriate IEs to be used in scheduled
+ * scans for all bands. It contains both the IEs passed from the userspace
+ * and the ones generated by mac80211.
+ *
+ * @ie: array with the IEs for each supported band
+ * @len: array with the total length of the IEs for each band
+ */
+struct ieee80211_sched_scan_ies {
+ u8 *ie[IEEE80211_NUM_BANDS];
+ size_t len[IEEE80211_NUM_BANDS];
+};
+
+static inline struct ieee80211_tx_info *IEEE80211_SKB_CB(struct sk_buff *skb)
+{
+ return (struct ieee80211_tx_info *)skb->cb;
+}
+
+static inline struct ieee80211_rx_status *IEEE80211_SKB_RXCB(struct sk_buff *skb)
+{
+ return (struct ieee80211_rx_status *)skb->cb;
+}
+
+/**
+ * ieee80211_tx_info_clear_status - clear TX status
+ *
+ * @info: The &struct ieee80211_tx_info to be cleared.
+ *
+ * When the driver passes an skb back to mac80211, it must report
+ * a number of things in TX status. This function clears everything
+ * in the TX status but the rate control information (it does clear
+ * the count since you need to fill that in anyway).
+ *
+ * NOTE: You can only use this function if you do NOT use
+ * info->driver_data! Use info->rate_driver_data
+ * instead if you need only the less space that allows.
+ */
+static inline void
+ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
+{
+ int i;
+
+ BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) !=
+ offsetof(struct ieee80211_tx_info, control.rates));
+ BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) !=
+ offsetof(struct ieee80211_tx_info, driver_rates));
+ BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) != 8);
+ /* clear the rate counts */
+ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++)
+ info->status.rates[i].count = 0;
+
+ BUILD_BUG_ON(
+ offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23);
+ memset(&info->status.ampdu_ack_len, 0,
+ sizeof(struct ieee80211_tx_info) -
+ offsetof(struct ieee80211_tx_info, status.ampdu_ack_len));
+}
+
+
+/**
+ * enum mac80211_rx_flags - receive flags
+ *
+ * These flags are used with the @flag member of &struct ieee80211_rx_status.
+ * @RX_FLAG_MMIC_ERROR: Michael MIC error was reported on this frame.
+ * Use together with %RX_FLAG_MMIC_STRIPPED.
+ * @RX_FLAG_DECRYPTED: This frame was decrypted in hardware.
+ * @RX_FLAG_MMIC_STRIPPED: the Michael MIC is stripped off this frame,
+ * verification has been done by the hardware.
+ * @RX_FLAG_IV_STRIPPED: The IV/ICV are stripped from this frame.
+ * If this flag is set, the stack cannot do any replay detection
+ * hence the driver or hardware will have to do that.
+ * @RX_FLAG_FAILED_FCS_CRC: Set this flag if the FCS check failed on
+ * the frame.
+ * @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on
+ * the frame.
+ * @RX_FLAG_MACTIME_MPDU: The timestamp passed in the RX status (@mactime
+ * field) is valid and contains the time the first symbol of the MPDU
+ * was received. This is useful in monitor mode and for proper IBSS
+ * merging.
+ * @RX_FLAG_SHORTPRE: Short preamble was used for this frame
+ * @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index
+ * @RX_FLAG_40MHZ: HT40 (40 MHz) was used
+ * @RX_FLAG_SHORT_GI: Short guard interval was used
+ * @RX_FLAG_NO_SIGNAL_VAL: The signal strength value is not present.
+ * Valid only for data frames (mainly A-MPDU)
+ */
+enum mac80211_rx_flags {
+ RX_FLAG_MMIC_ERROR = 1<<0,
+ RX_FLAG_DECRYPTED = 1<<1,
+ RX_FLAG_MMIC_STRIPPED = 1<<3,
+ RX_FLAG_IV_STRIPPED = 1<<4,
+ RX_FLAG_FAILED_FCS_CRC = 1<<5,
+ RX_FLAG_FAILED_PLCP_CRC = 1<<6,
+ RX_FLAG_MACTIME_MPDU = 1<<7,
+ RX_FLAG_SHORTPRE = 1<<8,
+ RX_FLAG_HT = 1<<9,
+ RX_FLAG_40MHZ = 1<<10,
+ RX_FLAG_SHORT_GI = 1<<11,
+ RX_FLAG_NO_SIGNAL_VAL = 1<<12,
+};
+
+/**
+ * struct ieee80211_rx_status - receive status
+ *
+ * The low-level driver should provide this information (the subset
+ * supported by hardware) to the 802.11 code with each received
+ * frame, in the skb's control buffer (cb).
+ *
+ * @mactime: value in microseconds of the 64-bit Time Synchronization Function
+ * (TSF) timer when the first data symbol (MPDU) arrived at the hardware.
+ * @band: the active band when this frame was received
+ * @freq: frequency the radio was tuned to when receiving this frame, in MHz
+ * @signal: signal strength when receiving this frame, either in dBm, in dB or
+ * unspecified depending on the hardware capabilities flags
+ * @IEEE80211_HW_SIGNAL_*
+ * @antenna: antenna used
+ * @rate_idx: index of data rate into band's supported rates or MCS index if
+ * HT rates are use (RX_FLAG_HT)
+ * @flag: %RX_FLAG_*
+ * @rx_flags: internal RX flags for mac80211
+ */
+struct ieee80211_rx_status {
+ u64 mactime;
+ enum ieee80211_band band;
+ int freq;
+ int signal;
+ int antenna;
+ int rate_idx;
+ int flag;
+ unsigned int rx_flags;
+};
+
+/**
+ * enum ieee80211_conf_flags - configuration flags
+ *
+ * Flags to define PHY configuration options
+ *
+ * @IEEE80211_CONF_MONITOR: there's a monitor interface present -- use this
+ * to determine for example whether to calculate timestamps for packets
+ * or not, do not use instead of filter flags!
+ * @IEEE80211_CONF_PS: Enable 802.11 power save mode (managed mode only).
+ * This is the power save mode defined by IEEE 802.11-2007 section 11.2,
+ * meaning that the hardware still wakes up for beacons, is able to
+ * transmit frames and receive the possible acknowledgment frames.
+ * Not to be confused with hardware specific wakeup/sleep states,
+ * driver is responsible for that. See the section "Powersave support"
+ * for more.
+ * @IEEE80211_CONF_IDLE: The device is running, but idle; if the flag is set
+ * the driver should be prepared to handle configuration requests but
+ * may turn the device off as much as possible. Typically, this flag will
+ * be set when an interface is set UP but not associated or scanning, but
+ * it can also be unset in that case when monitor interfaces are active.
+ * @IEEE80211_CONF_OFFCHANNEL: The device is currently not on its main
+ * operating channel.
+ */
+enum ieee80211_conf_flags {
+ IEEE80211_CONF_MONITOR = (1<<0),
+ IEEE80211_CONF_PS = (1<<1),
+ IEEE80211_CONF_IDLE = (1<<2),
+ IEEE80211_CONF_OFFCHANNEL = (1<<3),
+};
+
+
+/**
+ * enum ieee80211_conf_changed - denotes which configuration changed
+ *
+ * @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed
+ * @IEEE80211_CONF_CHANGE_MONITOR: the monitor flag changed
+ * @IEEE80211_CONF_CHANGE_PS: the PS flag or dynamic PS timeout changed
+ * @IEEE80211_CONF_CHANGE_POWER: the TX power changed
+ * @IEEE80211_CONF_CHANGE_CHANNEL: the channel/channel_type changed
+ * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed
+ * @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed
+ * @IEEE80211_CONF_CHANGE_SMPS: Spatial multiplexing powersave mode changed
+ */
+enum ieee80211_conf_changed {
+ IEEE80211_CONF_CHANGE_SMPS = BIT(1),
+ IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2),
+ IEEE80211_CONF_CHANGE_MONITOR = BIT(3),
+ IEEE80211_CONF_CHANGE_PS = BIT(4),
+ IEEE80211_CONF_CHANGE_POWER = BIT(5),
+ IEEE80211_CONF_CHANGE_CHANNEL = BIT(6),
+ IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(7),
+ IEEE80211_CONF_CHANGE_IDLE = BIT(8),
+};
+
+/**
+ * enum ieee80211_smps_mode - spatial multiplexing power save mode
+ *
+ * @IEEE80211_SMPS_AUTOMATIC: automatic
+ * @IEEE80211_SMPS_OFF: off
+ * @IEEE80211_SMPS_STATIC: static
+ * @IEEE80211_SMPS_DYNAMIC: dynamic
+ * @IEEE80211_SMPS_NUM_MODES: internal, don't use
+ */
+enum ieee80211_smps_mode {
+ IEEE80211_SMPS_AUTOMATIC,
+ IEEE80211_SMPS_OFF,
+ IEEE80211_SMPS_STATIC,
+ IEEE80211_SMPS_DYNAMIC,
+
+ /* keep last */
+ IEEE80211_SMPS_NUM_MODES,
+};
+
+/**
+ * struct ieee80211_conf - configuration of the device
+ *
+ * This struct indicates how the driver shall configure the hardware.
+ *
+ * @flags: configuration flags defined above
+ *
+ * @listen_interval: listen interval in units of beacon interval
+ * @max_sleep_period: the maximum number of beacon intervals to sleep for
+ * before checking the beacon for a TIM bit (managed mode only); this
+ * value will be only achievable between DTIM frames, the hardware
+ * needs to check for the multicast traffic bit in DTIM beacons.
+ * This variable is valid only when the CONF_PS flag is set.
+ * @ps_dtim_period: The DTIM period of the AP we're connected to, for use
+ * in power saving. Power saving will not be enabled until a beacon
+ * has been received and the DTIM period is known.
+ * @dynamic_ps_timeout: The dynamic powersave timeout (in ms), see the
+ * powersave documentation below. This variable is valid only when
+ * the CONF_PS flag is set.
+ *
+ * @power_level: requested transmit power (in dBm)
+ *
+ * @channel: the channel to tune to
+ * @channel_type: the channel (HT) type
+ *
+ * @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame
+ * (a frame not RTS protected), called "dot11LongRetryLimit" in 802.11,
+ * but actually means the number of transmissions not the number of retries
+ * @short_frame_max_tx_count: Maximum number of transmissions for a "short"
+ * frame, called "dot11ShortRetryLimit" in 802.11, but actually means the
+ * number of transmissions not the number of retries
+ *
+ * @smps_mode: spatial multiplexing powersave mode; note that
+ * %IEEE80211_SMPS_STATIC is used when the device is not
+ * configured for an HT channel
+ */
+struct ieee80211_conf {
+ u32 flags;
+ int power_level, dynamic_ps_timeout;
+ int max_sleep_period;
+
+ u16 listen_interval;
+ u8 ps_dtim_period;
+
+ u8 long_frame_max_tx_count, short_frame_max_tx_count;
+
+ struct ieee80211_channel *channel;
+ enum nl80211_channel_type channel_type;
+ enum ieee80211_smps_mode smps_mode;
+};
+
+/**
+ * struct ieee80211_channel_switch - holds the channel switch data
+ *
+ * The information provided in this structure is required for channel switch
+ * operation.
+ *
+ * @timestamp: value in microseconds of the 64-bit Time Synchronization
+ * Function (TSF) timer when the frame containing the channel switch
+ * announcement was received. This is simply the rx.mactime parameter
+ * the driver passed into mac80211.
+ * @block_tx: Indicates whether transmission must be blocked before the
+ * scheduled channel switch, as indicated by the AP.
+ * @channel: the new channel to switch to
+ * @count: the number of TBTT's until the channel switch event
+ */
+struct ieee80211_channel_switch {
+ u64 timestamp;
+ bool block_tx;
+ struct ieee80211_channel *channel;
+ u8 count;
+};
+
+/**
+ * enum ieee80211_vif_flags - virtual interface flags
+ *
+ * @IEEE80211_VIF_BEACON_FILTER: the device performs beacon filtering
+ * on this virtual interface to avoid unnecessary CPU wakeups
+ * @IEEE80211_VIF_SUPPORTS_CQM_RSSI: the device can do connection quality
+ * monitoring on this virtual interface -- i.e. it can monitor
+ * connection quality related parameters, such as the RSSI level and
+ * provide notifications if configured trigger levels are reached.
+ */
+enum ieee80211_vif_flags {
+ IEEE80211_VIF_BEACON_FILTER = BIT(0),
+ IEEE80211_VIF_SUPPORTS_CQM_RSSI = BIT(1),
+};
+
+/**
+ * struct ieee80211_vif - per-interface data
+ *
+ * Data in this structure is continually present for driver
+ * use during the life of a virtual interface.
+ *
+ * @type: type of this virtual interface
+ * @bss_conf: BSS configuration for this interface, either our own
+ * or the BSS we're associated to
+ * @addr: address of this interface
+ * @p2p: indicates whether this AP or STA interface is a p2p
+ * interface, i.e. a GO or p2p-sta respectively
+ * @driver_flags: flags/capabilities the driver has for this interface,
+ * these need to be set (or cleared) when the interface is added
+ * or, if supported by the driver, the interface type is changed
+ * at runtime, mac80211 will never touch this field
+ * @drv_priv: data area for driver use, will always be aligned to
+ * sizeof(void *).
+ */
+struct ieee80211_vif {
+ enum nl80211_iftype type;
+ struct ieee80211_bss_conf bss_conf;
+ u8 addr[ETH_ALEN];
+ bool p2p;
+ u32 driver_flags;
+ /* must be last */
+ u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
+};
+
+static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
+{
+#ifdef CONFIG_MAC80211_MESH
+ return vif->type == NL80211_IFTYPE_MESH_POINT;
+#endif
+ return false;
+}
+
+/**
+ * enum ieee80211_key_flags - key flags
+ *
+ * These flags are used for communication about keys between the driver
+ * and mac80211, with the @flags parameter of &struct ieee80211_key_conf.
+ *
+ * @IEEE80211_KEY_FLAG_WMM_STA: Set by mac80211, this flag indicates
+ * that the STA this key will be used with could be using QoS.
+ * @IEEE80211_KEY_FLAG_GENERATE_IV: This flag should be set by the
+ * driver to indicate that it requires IV generation for this
+ * particular key.
+ * @IEEE80211_KEY_FLAG_GENERATE_MMIC: This flag should be set by
+ * the driver for a TKIP key if it requires Michael MIC
+ * generation in software.
+ * @IEEE80211_KEY_FLAG_PAIRWISE: Set by mac80211, this flag indicates
+ * that the key is pairwise rather then a shared key.
+ * @IEEE80211_KEY_FLAG_SW_MGMT: This flag should be set by the driver for a
+ * CCMP key if it requires CCMP encryption of management frames (MFP) to
+ * be done in software.
+ * @IEEE80211_KEY_FLAG_PUT_IV_SPACE: This flag should be set by the driver
+ * for a CCMP key if space should be prepared for the IV, but the IV
+ * itself should not be generated. Do not set together with
+ * @IEEE80211_KEY_FLAG_GENERATE_IV on the same key.
+ */
+enum ieee80211_key_flags {
+ IEEE80211_KEY_FLAG_WMM_STA = 1<<0,
+ IEEE80211_KEY_FLAG_GENERATE_IV = 1<<1,
+ IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2,
+ IEEE80211_KEY_FLAG_PAIRWISE = 1<<3,
+ IEEE80211_KEY_FLAG_SW_MGMT = 1<<4,
+ IEEE80211_KEY_FLAG_PUT_IV_SPACE = 1<<5,
+};
+
+/**
+ * struct ieee80211_key_conf - key information
+ *
+ * This key information is given by mac80211 to the driver by
+ * the set_key() callback in &struct ieee80211_ops.
+ *
+ * @hw_key_idx: To be set by the driver, this is the key index the driver
+ * wants to be given when a frame is transmitted and needs to be
+ * encrypted in hardware.
+ * @cipher: The key's cipher suite selector.
+ * @flags: key flags, see &enum ieee80211_key_flags.
+ * @keyidx: the key index (0-3)
+ * @keylen: key material length
+ * @key: key material. For ALG_TKIP the key is encoded as a 256-bit (32 byte)
+ * data block:
+ * - Temporal Encryption Key (128 bits)
+ * - Temporal Authenticator Tx MIC Key (64 bits)
+ * - Temporal Authenticator Rx MIC Key (64 bits)
+ * @icv_len: The ICV length for this key type
+ * @iv_len: The IV length for this key type
+ */
+struct ieee80211_key_conf {
+ u32 cipher;
+ u8 icv_len;
+ u8 iv_len;
+ u8 hw_key_idx;
+ u8 flags;
+ s8 keyidx;
+ u8 keylen;
+ u8 key[0];
+};
+
+/**
+ * enum set_key_cmd - key command
+ *
+ * Used with the set_key() callback in &struct ieee80211_ops, this
+ * indicates whether a key is being removed or added.
+ *
+ * @SET_KEY: a key is set
+ * @DISABLE_KEY: a key must be disabled
+ */
+enum set_key_cmd {
+ SET_KEY, DISABLE_KEY,
+};
+
+/**
+ * enum ieee80211_sta_state - station state
+ *
+ * @IEEE80211_STA_NOTEXIST: station doesn't exist at all,
+ * this is a special state for add/remove transitions
+ * @IEEE80211_STA_NONE: station exists without special state
+ * @IEEE80211_STA_AUTH: station is authenticated
+ * @IEEE80211_STA_ASSOC: station is associated
+ * @IEEE80211_STA_AUTHORIZED: station is authorized (802.1X)
+ */
+enum ieee80211_sta_state {
+ /* NOTE: These need to be ordered correctly! */
+ IEEE80211_STA_NOTEXIST,
+ IEEE80211_STA_NONE,
+ IEEE80211_STA_AUTH,
+ IEEE80211_STA_ASSOC,
+ IEEE80211_STA_AUTHORIZED,
+};
+
+/**
+ * struct ieee80211_sta - station table entry
+ *
+ * A station table entry represents a station we are possibly
+ * communicating with. Since stations are RCU-managed in
+ * mac80211, any ieee80211_sta pointer you get access to must
+ * either be protected by rcu_read_lock() explicitly or implicitly,
+ * or you must take good care to not use such a pointer after a
+ * call to your sta_remove callback that removed it.
+ *
+ * @addr: MAC address
+ * @aid: AID we assigned to the station if we're an AP
+ * @supp_rates: Bitmap of supported rates (per band)
+ * @ht_cap: HT capabilities of this STA; restricted to our own TX capabilities
+ * @wme: indicates whether the STA supports WME. Only valid during AP-mode.
+ * @drv_priv: data area for driver use, will always be aligned to
+ * sizeof(void *), size is determined in hw information.
+ * @uapsd_queues: bitmap of queues configured for uapsd. Only valid
+ * if wme is supported.
+ * @max_sp: max Service Period. Only valid if wme is supported.
+ */
+struct ieee80211_sta {
+ u32 supp_rates[IEEE80211_NUM_BANDS];
+ u8 addr[ETH_ALEN];
+ u16 aid;
+ struct ieee80211_sta_ht_cap ht_cap;
+ bool wme;
+ u8 uapsd_queues;
+ u8 max_sp;
+
+ /* must be last */
+ u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
+};
+
+/**
+ * enum sta_notify_cmd - sta notify command
+ *
+ * Used with the sta_notify() callback in &struct ieee80211_ops, this
+ * indicates if an associated station made a power state transition.
+ *
+ * @STA_NOTIFY_SLEEP: a station is now sleeping
+ * @STA_NOTIFY_AWAKE: a sleeping station woke up
+ */
+enum sta_notify_cmd {
+ STA_NOTIFY_SLEEP, STA_NOTIFY_AWAKE,
+};
+
+/**
+ * enum ieee80211_hw_flags - hardware flags
+ *
+ * These flags are used to indicate hardware capabilities to
+ * the stack. Generally, flags here should have their meaning
+ * done in a way that the simplest hardware doesn't need setting
+ * any particular flags. There are some exceptions to this rule,
+ * however, so you are advised to review these flags carefully.
+ *
+ * @IEEE80211_HW_HAS_RATE_CONTROL:
+ * The hardware or firmware includes rate control, and cannot be
+ * controlled by the stack. As such, no rate control algorithm
+ * should be instantiated, and the TX rate reported to userspace
+ * will be taken from the TX status instead of the rate control
+ * algorithm.
+ * Note that this requires that the driver implement a number of
+ * callbacks so it has the correct information, it needs to have
+ * the @set_rts_threshold callback and must look at the BSS config
+ * @use_cts_prot for G/N protection, @use_short_slot for slot
+ * timing in 2.4 GHz and @use_short_preamble for preambles for
+ * CCK frames.
+ *
+ * @IEEE80211_HW_RX_INCLUDES_FCS:
+ * Indicates that received frames passed to the stack include
+ * the FCS at the end.
+ *
+ * @IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING:
+ * Some wireless LAN chipsets buffer broadcast/multicast frames
+ * for power saving stations in the hardware/firmware and others
+ * rely on the host system for such buffering. This option is used
+ * to configure the IEEE 802.11 upper layer to buffer broadcast and
+ * multicast frames when there are power saving stations so that
+ * the driver can fetch them with ieee80211_get_buffered_bc().
+ *
+ * @IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE:
+ * Hardware is not capable of short slot operation on the 2.4 GHz band.
+ *
+ * @IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE:
+ * Hardware is not capable of receiving frames with short preamble on
+ * the 2.4 GHz band.
+ *
+ * @IEEE80211_HW_SIGNAL_UNSPEC:
+ * Hardware can provide signal values but we don't know its units. We
+ * expect values between 0 and @max_signal.
+ * If possible please provide dB or dBm instead.
+ *
+ * @IEEE80211_HW_SIGNAL_DBM:
+ * Hardware gives signal values in dBm, decibel difference from
+ * one milliwatt. This is the preferred method since it is standardized
+ * between different devices. @max_signal does not need to be set.
+ *
+ * @IEEE80211_HW_SPECTRUM_MGMT:
+ * Hardware supports spectrum management defined in 802.11h
+ * Measurement, Channel Switch, Quieting, TPC
+ *
+ * @IEEE80211_HW_AMPDU_AGGREGATION:
+ * Hardware supports 11n A-MPDU aggregation.
+ *
+ * @IEEE80211_HW_SUPPORTS_PS:
+ * Hardware has power save support (i.e. can go to sleep).
+ *
+ * @IEEE80211_HW_PS_NULLFUNC_STACK:
+ * Hardware requires nullfunc frame handling in stack, implies
+ * stack support for dynamic PS.
+ *
+ * @IEEE80211_HW_SUPPORTS_DYNAMIC_PS:
+ * Hardware has support for dynamic PS.
+ *
+ * @IEEE80211_HW_MFP_CAPABLE:
+ * Hardware supports management frame protection (MFP, IEEE 802.11w).
+ *
+ * @IEEE80211_HW_SUPPORTS_STATIC_SMPS:
+ * Hardware supports static spatial multiplexing powersave,
+ * ie. can turn off all but one chain even on HT connections
+ * that should be using more chains.
+ *
+ * @IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS:
+ * Hardware supports dynamic spatial multiplexing powersave,
+ * ie. can turn off all but one chain and then wake the rest
+ * up as required after, for example, rts/cts handshake.
+ *
+ * @IEEE80211_HW_SUPPORTS_UAPSD:
+ * Hardware supports Unscheduled Automatic Power Save Delivery
+ * (U-APSD) in managed mode. The mode is configured with
+ * conf_tx() operation.
+ *
+ * @IEEE80211_HW_REPORTS_TX_ACK_STATUS:
+ * Hardware can provide ack status reports of Tx frames to
+ * the stack.
+ *
+ * @IEEE80211_HW_CONNECTION_MONITOR:
+ * The hardware performs its own connection monitoring, including
+ * periodic keep-alives to the AP and probing the AP on beacon loss.
+ * When this flag is set, signaling beacon-loss will cause an immediate
+ * change to disassociated state.
+ *
+ * @IEEE80211_HW_NEED_DTIM_PERIOD:
+ * This device needs to know the DTIM period for the BSS before
+ * associating.
+ *
+ * @IEEE80211_HW_SUPPORTS_PER_STA_GTK: The device's crypto engine supports
+ * per-station GTKs as used by IBSS RSN or during fast transition. If
+ * the device doesn't support per-station GTKs, but can be asked not
+ * to decrypt group addressed frames, then IBSS RSN support is still
+ * possible but software crypto will be used. Advertise the wiphy flag
+ * only in that case.
+ *
+ * @IEEE80211_HW_AP_LINK_PS: When operating in AP mode the device
+ * autonomously manages the PS status of connected stations. When
+ * this flag is set mac80211 will not trigger PS mode for connected
+ * stations based on the PM bit of incoming frames.
+ * Use ieee80211_start_ps()/ieee8021_end_ps() to manually configure
+ * the PS mode of connected stations.
+ *
+ * @IEEE80211_HW_TX_AMPDU_SETUP_IN_HW: The device handles TX A-MPDU session
+ * setup strictly in HW. mac80211 should not attempt to do this in
+ * software.
+ *
+ * @IEEE80211_HW_SCAN_WHILE_IDLE: The device can do hw scan while
+ * being idle (i.e. mac80211 doesn't have to go idle-off during the
+ * the scan).
+ */
+enum ieee80211_hw_flags {
+ IEEE80211_HW_HAS_RATE_CONTROL = 1<<0,
+ IEEE80211_HW_RX_INCLUDES_FCS = 1<<1,
+ IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING = 1<<2,
+ IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE = 1<<3,
+ IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE = 1<<4,
+ IEEE80211_HW_SIGNAL_UNSPEC = 1<<5,
+ IEEE80211_HW_SIGNAL_DBM = 1<<6,
+ IEEE80211_HW_NEED_DTIM_PERIOD = 1<<7,
+ IEEE80211_HW_SPECTRUM_MGMT = 1<<8,
+ IEEE80211_HW_AMPDU_AGGREGATION = 1<<9,
+ IEEE80211_HW_SUPPORTS_PS = 1<<10,
+ IEEE80211_HW_PS_NULLFUNC_STACK = 1<<11,
+ IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<12,
+ IEEE80211_HW_MFP_CAPABLE = 1<<13,
+ /* reuse bit 14 */
+ IEEE80211_HW_SUPPORTS_STATIC_SMPS = 1<<15,
+ IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS = 1<<16,
+ IEEE80211_HW_SUPPORTS_UAPSD = 1<<17,
+ IEEE80211_HW_REPORTS_TX_ACK_STATUS = 1<<18,
+ IEEE80211_HW_CONNECTION_MONITOR = 1<<19,
+ /* reuse bit 20 */
+ IEEE80211_HW_SUPPORTS_PER_STA_GTK = 1<<21,
+ IEEE80211_HW_AP_LINK_PS = 1<<22,
+ IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23,
+ IEEE80211_HW_SCAN_WHILE_IDLE = 1<<24,
+};
+
+/**
+ * struct ieee80211_hw - hardware information and state
+ *
+ * This structure contains the configuration and hardware
+ * information for an 802.11 PHY.
+ *
+ * @wiphy: This points to the &struct wiphy allocated for this
+ * 802.11 PHY. You must fill in the @perm_addr and @dev
+ * members of this structure using SET_IEEE80211_DEV()
+ * and SET_IEEE80211_PERM_ADDR(). Additionally, all supported
+ * bands (with channels, bitrates) are registered here.
+ *
+ * @conf: &struct ieee80211_conf, device configuration, don't use.
+ *
+ * @priv: pointer to private area that was allocated for driver use
+ * along with this structure.
+ *
+ * @flags: hardware flags, see &enum ieee80211_hw_flags.
+ *
+ * @extra_tx_headroom: headroom to reserve in each transmit skb
+ * for use by the driver (e.g. for transmit headers.)
+ *
+ * @channel_change_time: time (in microseconds) it takes to change channels.
+ *
+ * @max_signal: Maximum value for signal (rssi) in RX information, used
+ * only when @IEEE80211_HW_SIGNAL_UNSPEC or @IEEE80211_HW_SIGNAL_DB
+ *
+ * @max_listen_interval: max listen interval in units of beacon interval
+ * that HW supports
+ *
+ * @queues: number of available hardware transmit queues for
+ * data packets. WMM/QoS requires at least four, these
+ * queues need to have configurable access parameters.
+ *
+ * @rate_control_algorithm: rate control algorithm for this hardware.
+ * If unset (NULL), the default algorithm will be used. Must be
+ * set before calling ieee80211_register_hw().
+ *
+ * @vif_data_size: size (in bytes) of the drv_priv data area
+ * within &struct ieee80211_vif.
+ * @sta_data_size: size (in bytes) of the drv_priv data area
+ * within &struct ieee80211_sta.
+ *
+ * @max_rates: maximum number of alternate rate retry stages the hw
+ * can handle.
+ * @max_report_rates: maximum number of alternate rate retry stages
+ * the hw can report back.
+ * @max_rate_tries: maximum number of tries for each stage
+ *
+ * @napi_weight: weight used for NAPI polling. You must specify an
+ * appropriate value here if a napi_poll operation is provided
+ * by your driver.
+ *
+ * @max_rx_aggregation_subframes: maximum buffer size (number of
+ * sub-frames) to be used for A-MPDU block ack receiver
+ * aggregation.
+ * This is only relevant if the device has restrictions on the
+ * number of subframes, if it relies on mac80211 to do reordering
+ * it shouldn't be set.
+ *
+ * @max_tx_aggregation_subframes: maximum number of subframes in an
+ * aggregate an HT driver will transmit, used by the peer as a
+ * hint to size its reorder buffer.
+ */
+struct ieee80211_hw {
+ struct ieee80211_conf conf;
+ struct wiphy *wiphy;
+ const char *rate_control_algorithm;
+ void *priv;
+ u32 flags;
+ unsigned int extra_tx_headroom;
+ int channel_change_time;
+ int vif_data_size;
+ int sta_data_size;
+ int napi_weight;
+ u16 queues;
+ u16 max_listen_interval;
+ s8 max_signal;
+ u8 max_rates;
+ u8 max_report_rates;
+ u8 max_rate_tries;
+ u8 max_rx_aggregation_subframes;
+ u8 max_tx_aggregation_subframes;
+};
+
+/**
+ * wiphy_to_ieee80211_hw - return a mac80211 driver hw struct from a wiphy
+ *
+ * @wiphy: the &struct wiphy which we want to query
+ *
+ * mac80211 drivers can use this to get to their respective
+ * &struct ieee80211_hw. Drivers wishing to get to their own private
+ * structure can then access it via hw->priv. Note that mac802111 drivers should
+ * not use wiphy_priv() to try to get their private driver structure as this
+ * is already used internally by mac80211.
+ */
+struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy);
+
+/**
+ * SET_IEEE80211_DEV - set device for 802.11 hardware
+ *
+ * @hw: the &struct ieee80211_hw to set the device for
+ * @dev: the &struct device of this 802.11 device
+ */
+static inline void SET_IEEE80211_DEV(struct ieee80211_hw *hw, struct device *dev)
+{
+ set_wiphy_dev(hw->wiphy, dev);
+}
+
+/**
+ * SET_IEEE80211_PERM_ADDR - set the permanent MAC address for 802.11 hardware
+ *
+ * @hw: the &struct ieee80211_hw to set the MAC address for
+ * @addr: the address to set
+ */
+static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, u8 *addr)
+{
+ memcpy(hw->wiphy->perm_addr, addr, ETH_ALEN);
+}
+
+static inline struct ieee80211_rate *
+ieee80211_get_tx_rate(const struct ieee80211_hw *hw,
+ const struct ieee80211_tx_info *c)
+{
+ if (WARN_ON_ONCE(c->control.rates[0].idx < 0))
+ return NULL;
+ return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[0].idx];
+}
+
+static inline struct ieee80211_rate *
+ieee80211_get_rts_cts_rate(const struct ieee80211_hw *hw,
+ const struct ieee80211_tx_info *c)
+{
+ if (c->control.rts_cts_rate_idx < 0)
+ return NULL;
+ return &hw->wiphy->bands[c->band]->bitrates[c->control.rts_cts_rate_idx];
+}
+
+static inline struct ieee80211_rate *
+ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
+ const struct ieee80211_tx_info *c, int idx)
+{
+ if (c->control.rates[idx + 1].idx < 0)
+ return NULL;
+ return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[idx + 1].idx];
+}
+
+/**
+ * ieee80211_free_txskb - free TX skb
+ * @hw: the hardware
+ * @skb: the skb
+ *
+ * Free a transmit skb. Use this funtion when some failure
+ * to transmit happened and thus status cannot be reported.
+ */
+void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
+
+/**
+ * DOC: Hardware crypto acceleration
+ *
+ * mac80211 is capable of taking advantage of many hardware
+ * acceleration designs for encryption and decryption operations.
+ *
+ * The set_key() callback in the &struct ieee80211_ops for a given
+ * device is called to enable hardware acceleration of encryption and
+ * decryption. The callback takes a @sta parameter that will be NULL
+ * for default keys or keys used for transmission only, or point to
+ * the station information for the peer for individual keys.
+ * Multiple transmission keys with the same key index may be used when
+ * VLANs are configured for an access point.
+ *
+ * When transmitting, the TX control data will use the @hw_key_idx
+ * selected by the driver by modifying the &struct ieee80211_key_conf
+ * pointed to by the @key parameter to the set_key() function.
+ *
+ * The set_key() call for the %SET_KEY command should return 0 if
+ * the key is now in use, -%EOPNOTSUPP or -%ENOSPC if it couldn't be
+ * added; if you return 0 then hw_key_idx must be assigned to the
+ * hardware key index, you are free to use the full u8 range.
+ *
+ * When the cmd is %DISABLE_KEY then it must succeed.
+ *
+ * Note that it is permissible to not decrypt a frame even if a key
+ * for it has been uploaded to hardware, the stack will not make any
+ * decision based on whether a key has been uploaded or not but rather
+ * based on the receive flags.
+ *
+ * The &struct ieee80211_key_conf structure pointed to by the @key
+ * parameter is guaranteed to be valid until another call to set_key()
+ * removes it, but it can only be used as a cookie to differentiate
+ * keys.
+ *
+ * In TKIP some HW need to be provided a phase 1 key, for RX decryption
+ * acceleration (i.e. iwlwifi). Those drivers should provide update_tkip_key
+ * handler.
+ * The update_tkip_key() call updates the driver with the new phase 1 key.
+ * This happens every time the iv16 wraps around (every 65536 packets). The
+ * set_key() call will happen only once for each key (unless the AP did
+ * rekeying), it will not include a valid phase 1 key. The valid phase 1 key is
+ * provided by update_tkip_key only. The trigger that makes mac80211 call this
+ * handler is software decryption with wrap around of iv16.
+ */
+
+/**
+ * DOC: Powersave support
+ *
+ * mac80211 has support for various powersave implementations.
+ *
+ * First, it can support hardware that handles all powersaving by itself,
+ * such hardware should simply set the %IEEE80211_HW_SUPPORTS_PS hardware
+ * flag. In that case, it will be told about the desired powersave mode
+ * with the %IEEE80211_CONF_PS flag depending on the association status.
+ * The hardware must take care of sending nullfunc frames when necessary,
+ * i.e. when entering and leaving powersave mode. The hardware is required
+ * to look at the AID in beacons and signal to the AP that it woke up when
+ * it finds traffic directed to it.
+ *
+ * %IEEE80211_CONF_PS flag enabled means that the powersave mode defined in
+ * IEEE 802.11-2007 section 11.2 is enabled. This is not to be confused
+ * with hardware wakeup and sleep states. Driver is responsible for waking
+ * up the hardware before issuing commands to the hardware and putting it
+ * back to sleep at appropriate times.
+ *
+ * When PS is enabled, hardware needs to wakeup for beacons and receive the
+ * buffered multicast/broadcast frames after the beacon. Also it must be
+ * possible to send frames and receive the acknowledment frame.
+ *
+ * Other hardware designs cannot send nullfunc frames by themselves and also
+ * need software support for parsing the TIM bitmap. This is also supported
+ * by mac80211 by combining the %IEEE80211_HW_SUPPORTS_PS and
+ * %IEEE80211_HW_PS_NULLFUNC_STACK flags. The hardware is of course still
+ * required to pass up beacons. The hardware is still required to handle
+ * waking up for multicast traffic; if it cannot the driver must handle that
+ * as best as it can, mac80211 is too slow to do that.
+ *
+ * Dynamic powersave is an extension to normal powersave in which the
+ * hardware stays awake for a user-specified period of time after sending a
+ * frame so that reply frames need not be buffered and therefore delayed to
+ * the next wakeup. It's compromise of getting good enough latency when
+ * there's data traffic and still saving significantly power in idle
+ * periods.
+ *
+ * Dynamic powersave is simply supported by mac80211 enabling and disabling
+ * PS based on traffic. Driver needs to only set %IEEE80211_HW_SUPPORTS_PS
+ * flag and mac80211 will handle everything automatically. Additionally,
+ * hardware having support for the dynamic PS feature may set the
+ * %IEEE80211_HW_SUPPORTS_DYNAMIC_PS flag to indicate that it can support
+ * dynamic PS mode itself. The driver needs to look at the
+ * @dynamic_ps_timeout hardware configuration value and use it that value
+ * whenever %IEEE80211_CONF_PS is set. In this case mac80211 will disable
+ * dynamic PS feature in stack and will just keep %IEEE80211_CONF_PS
+ * enabled whenever user has enabled powersave.
+ *
+ * Some hardware need to toggle a single shared antenna between WLAN and
+ * Bluetooth to facilitate co-existence. These types of hardware set
+ * limitations on the use of host controlled dynamic powersave whenever there
+ * is simultaneous WLAN and Bluetooth traffic. For these types of hardware, the
+ * driver may request temporarily going into full power save, in order to
+ * enable toggling the antenna between BT and WLAN. If the driver requests
+ * disabling dynamic powersave, the @dynamic_ps_timeout value will be
+ * temporarily set to zero until the driver re-enables dynamic powersave.
+ *
+ * Driver informs U-APSD client support by enabling
+ * %IEEE80211_HW_SUPPORTS_UAPSD flag. The mode is configured through the
+ * uapsd paramater in conf_tx() operation. Hardware needs to send the QoS
+ * Nullfunc frames and stay awake until the service period has ended. To
+ * utilize U-APSD, dynamic powersave is disabled for voip AC and all frames
+ * from that AC are transmitted with powersave enabled.
+ *
+ * Note: U-APSD client mode is not yet supported with
+ * %IEEE80211_HW_PS_NULLFUNC_STACK.
+ */
+
+/**
+ * DOC: Beacon filter support
+ *
+ * Some hardware have beacon filter support to reduce host cpu wakeups
+ * which will reduce system power consumption. It usually works so that
+ * the firmware creates a checksum of the beacon but omits all constantly
+ * changing elements (TSF, TIM etc). Whenever the checksum changes the
+ * beacon is forwarded to the host, otherwise it will be just dropped. That
+ * way the host will only receive beacons where some relevant information
+ * (for example ERP protection or WMM settings) have changed.
+ *
+ * Beacon filter support is advertised with the %IEEE80211_VIF_BEACON_FILTER
+ * interface capability. The driver needs to enable beacon filter support
+ * whenever power save is enabled, that is %IEEE80211_CONF_PS is set. When
+ * power save is enabled, the stack will not check for beacon loss and the
+ * driver needs to notify about loss of beacons with ieee80211_beacon_loss().
+ *
+ * The time (or number of beacons missed) until the firmware notifies the
+ * driver of a beacon loss event (which in turn causes the driver to call
+ * ieee80211_beacon_loss()) should be configurable and will be controlled
+ * by mac80211 and the roaming algorithm in the future.
+ *
+ * Since there may be constantly changing information elements that nothing
+ * in the software stack cares about, we will, in the future, have mac80211
+ * tell the driver which information elements are interesting in the sense
+ * that we want to see changes in them. This will include
+ * - a list of information element IDs
+ * - a list of OUIs for the vendor information element
+ *
+ * Ideally, the hardware would filter out any beacons without changes in the
+ * requested elements, but if it cannot support that it may, at the expense
+ * of some efficiency, filter out only a subset. For example, if the device
+ * doesn't support checking for OUIs it should pass up all changes in all
+ * vendor information elements.
+ *
+ * Note that change, for the sake of simplification, also includes information
+ * elements appearing or disappearing from the beacon.
+ *
+ * Some hardware supports an "ignore list" instead, just make sure nothing
+ * that was requested is on the ignore list, and include commonly changing
+ * information element IDs in the ignore list, for example 11 (BSS load) and
+ * the various vendor-assigned IEs with unknown contents (128, 129, 133-136,
+ * 149, 150, 155, 156, 173, 176, 178, 179, 219); for forward compatibility
+ * it could also include some currently unused IDs.
+ *
+ *
+ * In addition to these capabilities, hardware should support notifying the
+ * host of changes in the beacon RSSI. This is relevant to implement roaming
+ * when no traffic is flowing (when traffic is flowing we see the RSSI of
+ * the received data packets). This can consist in notifying the host when
+ * the RSSI changes significantly or when it drops below or rises above
+ * configurable thresholds. In the future these thresholds will also be
+ * configured by mac80211 (which gets them from userspace) to implement
+ * them as the roaming algorithm requires.
+ *
+ * If the hardware cannot implement this, the driver should ask it to
+ * periodically pass beacon frames to the host so that software can do the
+ * signal strength threshold checking.
+ */
+
+/**
+ * DOC: Spatial multiplexing power save
+ *
+ * SMPS (Spatial multiplexing power save) is a mechanism to conserve
+ * power in an 802.11n implementation. For details on the mechanism
+ * and rationale, please refer to 802.11 (as amended by 802.11n-2009)
+ * "11.2.3 SM power save".
+ *
+ * The mac80211 implementation is capable of sending action frames
+ * to update the AP about the station's SMPS mode, and will instruct
+ * the driver to enter the specific mode. It will also announce the
+ * requested SMPS mode during the association handshake. Hardware
+ * support for this feature is required, and can be indicated by
+ * hardware flags.
+ *
+ * The default mode will be "automatic", which nl80211/cfg80211
+ * defines to be dynamic SMPS in (regular) powersave, and SMPS
+ * turned off otherwise.
+ *
+ * To support this feature, the driver must set the appropriate
+ * hardware support flags, and handle the SMPS flag to the config()
+ * operation. It will then with this mechanism be instructed to
+ * enter the requested SMPS mode while associated to an HT AP.
+ */
+
+/**
+ * DOC: Frame filtering
+ *
+ * mac80211 requires to see many management frames for proper
+ * operation, and users may want to see many more frames when
+ * in monitor mode. However, for best CPU usage and power consumption,
+ * having as few frames as possible percolate through the stack is
+ * desirable. Hence, the hardware should filter as much as possible.
+ *
+ * To achieve this, mac80211 uses filter flags (see below) to tell
+ * the driver's configure_filter() function which frames should be
+ * passed to mac80211 and which should be filtered out.
+ *
+ * Before configure_filter() is invoked, the prepare_multicast()
+ * callback is invoked with the parameters @mc_count and @mc_list
+ * for the combined multicast address list of all virtual interfaces.
+ * It's use is optional, and it returns a u64 that is passed to
+ * configure_filter(). Additionally, configure_filter() has the
+ * arguments @changed_flags telling which flags were changed and
+ * @total_flags with the new flag states.
+ *
+ * If your device has no multicast address filters your driver will
+ * need to check both the %FIF_ALLMULTI flag and the @mc_count
+ * parameter to see whether multicast frames should be accepted
+ * or dropped.
+ *
+ * All unsupported flags in @total_flags must be cleared.
+ * Hardware does not support a flag if it is incapable of _passing_
+ * the frame to the stack. Otherwise the driver must ignore
+ * the flag, but not clear it.
+ * You must _only_ clear the flag (announce no support for the
+ * flag to mac80211) if you are not able to pass the packet type
+ * to the stack (so the hardware always filters it).
+ * So for example, you should clear @FIF_CONTROL, if your hardware
+ * always filters control frames. If your hardware always passes
+ * control frames to the kernel and is incapable of filtering them,
+ * you do _not_ clear the @FIF_CONTROL flag.
+ * This rule applies to all other FIF flags as well.
+ */
+
+/**
+ * DOC: AP support for powersaving clients
+ *
+ * In order to implement AP and P2P GO modes, mac80211 has support for
+ * client powersaving, both "legacy" PS (PS-Poll/null data) and uAPSD.
+ * There currently is no support for sAPSD.
+ *
+ * There is one assumption that mac80211 makes, namely that a client
+ * will not poll with PS-Poll and trigger with uAPSD at the same time.
+ * Both are supported, and both can be used by the same client, but
+ * they can't be used concurrently by the same client. This simplifies
+ * the driver code.
+ *
+ * The first thing to keep in mind is that there is a flag for complete
+ * driver implementation: %IEEE80211_HW_AP_LINK_PS. If this flag is set,
+ * mac80211 expects the driver to handle most of the state machine for
+ * powersaving clients and will ignore the PM bit in incoming frames.
+ * Drivers then use ieee80211_sta_ps_transition() to inform mac80211 of
+ * stations' powersave transitions. In this mode, mac80211 also doesn't
+ * handle PS-Poll/uAPSD.
+ *
+ * In the mode without %IEEE80211_HW_AP_LINK_PS, mac80211 will check the
+ * PM bit in incoming frames for client powersave transitions. When a
+ * station goes to sleep, we will stop transmitting to it. There is,
+ * however, a race condition: a station might go to sleep while there is
+ * data buffered on hardware queues. If the device has support for this
+ * it will reject frames, and the driver should give the frames back to
+ * mac80211 with the %IEEE80211_TX_STAT_TX_FILTERED flag set which will
+ * cause mac80211 to retry the frame when the station wakes up. The
+ * driver is also notified of powersave transitions by calling its
+ * @sta_notify callback.
+ *
+ * When the station is asleep, it has three choices: it can wake up,
+ * it can PS-Poll, or it can possibly start a uAPSD service period.
+ * Waking up is implemented by simply transmitting all buffered (and
+ * filtered) frames to the station. This is the easiest case. When
+ * the station sends a PS-Poll or a uAPSD trigger frame, mac80211
+ * will inform the driver of this with the @allow_buffered_frames
+ * callback; this callback is optional. mac80211 will then transmit
+ * the frames as usual and set the %IEEE80211_TX_CTL_NO_PS_BUFFER
+ * on each frame. The last frame in the service period (or the only
+ * response to a PS-Poll) also has %IEEE80211_TX_STATUS_EOSP set to
+ * indicate that it ends the service period; as this frame must have
+ * TX status report it also sets %IEEE80211_TX_CTL_REQ_TX_STATUS.
+ * When TX status is reported for this frame, the service period is
+ * marked has having ended and a new one can be started by the peer.
+ *
+ * Additionally, non-bufferable MMPDUs can also be transmitted by
+ * mac80211 with the %IEEE80211_TX_CTL_NO_PS_BUFFER set in them.
+ *
+ * Another race condition can happen on some devices like iwlwifi
+ * when there are frames queued for the station and it wakes up
+ * or polls; the frames that are already queued could end up being
+ * transmitted first instead, causing reordering and/or wrong
+ * processing of the EOSP. The cause is that allowing frames to be
+ * transmitted to a certain station is out-of-band communication to
+ * the device. To allow this problem to be solved, the driver can
+ * call ieee80211_sta_block_awake() if frames are buffered when it
+ * is notified that the station went to sleep. When all these frames
+ * have been filtered (see above), it must call the function again
+ * to indicate that the station is no longer blocked.
+ *
+ * If the driver buffers frames in the driver for aggregation in any
+ * way, it must use the ieee80211_sta_set_buffered() call when it is
+ * notified of the station going to sleep to inform mac80211 of any
+ * TIDs that have frames buffered. Note that when a station wakes up
+ * this information is reset (hence the requirement to call it when
+ * informed of the station going to sleep). Then, when a service
+ * period starts for any reason, @release_buffered_frames is called
+ * with the number of frames to be released and which TIDs they are
+ * to come from. In this case, the driver is responsible for setting
+ * the EOSP (for uAPSD) and MORE_DATA bits in the released frames,
+ * to help the @more_data paramter is passed to tell the driver if
+ * there is more data on other TIDs -- the TIDs to release frames
+ * from are ignored since mac80211 doesn't know how many frames the
+ * buffers for those TIDs contain.
+ *
+ * If the driver also implement GO mode, where absence periods may
+ * shorten service periods (or abort PS-Poll responses), it must
+ * filter those response frames except in the case of frames that
+ * are buffered in the driver -- those must remain buffered to avoid
+ * reordering. Because it is possible that no frames are released
+ * in this case, the driver must call ieee80211_sta_eosp_irqsafe()
+ * to indicate to mac80211 that the service period ended anyway.
+ *
+ * Finally, if frames from multiple TIDs are released from mac80211
+ * but the driver might reorder them, it must clear & set the flags
+ * appropriately (only the last frame may have %IEEE80211_TX_STATUS_EOSP)
+ * and also take care of the EOSP and MORE_DATA bits in the frame.
+ * The driver may also use ieee80211_sta_eosp_irqsafe() in this case.
+ */
+
+/**
+ * enum ieee80211_filter_flags - hardware filter flags
+ *
+ * These flags determine what the filter in hardware should be
+ * programmed to let through and what should not be passed to the
+ * stack. It is always safe to pass more frames than requested,
+ * but this has negative impact on power consumption.
+ *
+ * @FIF_PROMISC_IN_BSS: promiscuous mode within your BSS,
+ * think of the BSS as your network segment and then this corresponds
+ * to the regular ethernet device promiscuous mode.
+ *
+ * @FIF_ALLMULTI: pass all multicast frames, this is used if requested
+ * by the user or if the hardware is not capable of filtering by
+ * multicast address.
+ *
+ * @FIF_FCSFAIL: pass frames with failed FCS (but you need to set the
+ * %RX_FLAG_FAILED_FCS_CRC for them)
+ *
+ * @FIF_PLCPFAIL: pass frames with failed PLCP CRC (but you need to set
+ * the %RX_FLAG_FAILED_PLCP_CRC for them
+ *
+ * @FIF_BCN_PRBRESP_PROMISC: This flag is set during scanning to indicate
+ * to the hardware that it should not filter beacons or probe responses
+ * by BSSID. Filtering them can greatly reduce the amount of processing
+ * mac80211 needs to do and the amount of CPU wakeups, so you should
+ * honour this flag if possible.
+ *
+ * @FIF_CONTROL: pass control frames (except for PS Poll), if PROMISC_IN_BSS
+ * is not set then only those addressed to this station.
+ *
+ * @FIF_OTHER_BSS: pass frames destined to other BSSes
+ *
+ * @FIF_PSPOLL: pass PS Poll frames, if PROMISC_IN_BSS is not set then only
+ * those addressed to this station.
+ *
+ * @FIF_PROBE_REQ: pass probe request frames
+ */
+enum ieee80211_filter_flags {
+ FIF_PROMISC_IN_BSS = 1<<0,
+ FIF_ALLMULTI = 1<<1,
+ FIF_FCSFAIL = 1<<2,
+ FIF_PLCPFAIL = 1<<3,
+ FIF_BCN_PRBRESP_PROMISC = 1<<4,
+ FIF_CONTROL = 1<<5,
+ FIF_OTHER_BSS = 1<<6,
+ FIF_PSPOLL = 1<<7,
+ FIF_PROBE_REQ = 1<<8,
+};
+
+/**
+ * enum ieee80211_ampdu_mlme_action - A-MPDU actions
+ *
+ * These flags are used with the ampdu_action() callback in
+ * &struct ieee80211_ops to indicate which action is needed.
+ *
+ * Note that drivers MUST be able to deal with a TX aggregation
+ * session being stopped even before they OK'ed starting it by
+ * calling ieee80211_start_tx_ba_cb_irqsafe, because the peer
+ * might receive the addBA frame and send a delBA right away!
+ *
+ * @IEEE80211_AMPDU_RX_START: start Rx aggregation
+ * @IEEE80211_AMPDU_RX_STOP: stop Rx aggregation
+ * @IEEE80211_AMPDU_TX_START: start Tx aggregation
+ * @IEEE80211_AMPDU_TX_STOP: stop Tx aggregation
+ * @IEEE80211_AMPDU_TX_OPERATIONAL: TX aggregation has become operational
+ */
+enum ieee80211_ampdu_mlme_action {
+ IEEE80211_AMPDU_RX_START,
+ IEEE80211_AMPDU_RX_STOP,
+ IEEE80211_AMPDU_TX_START,
+ IEEE80211_AMPDU_TX_STOP,
+ IEEE80211_AMPDU_TX_OPERATIONAL,
+};
+
+/**
+ * enum ieee80211_frame_release_type - frame release reason
+ * @IEEE80211_FRAME_RELEASE_PSPOLL: frame released for PS-Poll
+ * @IEEE80211_FRAME_RELEASE_UAPSD: frame(s) released due to
+ * frame received on trigger-enabled AC
+ */
+enum ieee80211_frame_release_type {
+ IEEE80211_FRAME_RELEASE_PSPOLL,
+ IEEE80211_FRAME_RELEASE_UAPSD,
+};
+
+/**
+ * struct ieee80211_ops - callbacks from mac80211 to the driver
+ *
+ * This structure contains various callbacks that the driver may
+ * handle or, in some cases, must handle, for example to configure
+ * the hardware to a new channel or to transmit a frame.
+ *
+ * @tx: Handler that 802.11 module calls for each transmitted frame.
+ * skb contains the buffer starting from the IEEE 802.11 header.
+ * The low-level driver should send the frame out based on
+ * configuration in the TX control data. This handler should,
+ * preferably, never fail and stop queues appropriately.
+ * This must be implemented if @tx_frags is not.
+ * Must be atomic.
+ *
+ * @tx_frags: Called to transmit multiple fragments of a single MSDU.
+ * This handler must consume all fragments, sending out some of
+ * them only is useless and it can't ask for some of them to be
+ * queued again. If the frame is not fragmented the queue has a
+ * single SKB only. To avoid issues with the networking stack
+ * when TX status is reported the frames should be removed from
+ * the skb queue.
+ * If this is used, the tx_info @vif and @sta pointers will be
+ * invalid -- you must not use them in that case.
+ * This must be implemented if @tx isn't.
+ * Must be atomic.
+ *
+ * @start: Called before the first netdevice attached to the hardware
+ * is enabled. This should turn on the hardware and must turn on
+ * frame reception (for possibly enabled monitor interfaces.)
+ * Returns negative error codes, these may be seen in userspace,
+ * or zero.
+ * When the device is started it should not have a MAC address
+ * to avoid acknowledging frames before a non-monitor device
+ * is added.
+ * Must be implemented and can sleep.
+ *
+ * @stop: Called after last netdevice attached to the hardware
+ * is disabled. This should turn off the hardware (at least
+ * it must turn off frame reception.)
+ * May be called right after add_interface if that rejects
+ * an interface. If you added any work onto the mac80211 workqueue
+ * you should ensure to cancel it on this callback.
+ * Must be implemented and can sleep.
+ *
+ * @suspend: Suspend the device; mac80211 itself will quiesce before and
+ * stop transmitting and doing any other configuration, and then
+ * ask the device to suspend. This is only invoked when WoWLAN is
+ * configured, otherwise the device is deconfigured completely and
+ * reconfigured at resume time.
+ * The driver may also impose special conditions under which it
+ * wants to use the "normal" suspend (deconfigure), say if it only
+ * supports WoWLAN when the device is associated. In this case, it
+ * must return 1 from this function.
+ *
+ * @resume: If WoWLAN was configured, this indicates that mac80211 is
+ * now resuming its operation, after this the device must be fully
+ * functional again. If this returns an error, the only way out is
+ * to also unregister the device. If it returns 1, then mac80211
+ * will also go through the regular complete restart on resume.
+ *
+ * @add_interface: Called when a netdevice attached to the hardware is
+ * enabled. Because it is not called for monitor mode devices, @start
+ * and @stop must be implemented.
+ * The driver should perform any initialization it needs before
+ * the device can be enabled. The initial configuration for the
+ * interface is given in the conf parameter.
+ * The callback may refuse to add an interface by returning a
+ * negative error code (which will be seen in userspace.)
+ * Must be implemented and can sleep.
+ *
+ * @change_interface: Called when a netdevice changes type. This callback
+ * is optional, but only if it is supported can interface types be
+ * switched while the interface is UP. The callback may sleep.
+ * Note that while an interface is being switched, it will not be
+ * found by the interface iteration callbacks.
+ *
+ * @remove_interface: Notifies a driver that an interface is going down.
+ * The @stop callback is called after this if it is the last interface
+ * and no monitor interfaces are present.
+ * When all interfaces are removed, the MAC address in the hardware
+ * must be cleared so the device no longer acknowledges packets,
+ * the mac_addr member of the conf structure is, however, set to the
+ * MAC address of the device going away.
+ * Hence, this callback must be implemented. It can sleep.
+ *
+ * @config: Handler for configuration requests. IEEE 802.11 code calls this
+ * function to change hardware configuration, e.g., channel.
+ * This function should never fail but returns a negative error code
+ * if it does. The callback can sleep.
+ *
+ * @bss_info_changed: Handler for configuration requests related to BSS
+ * parameters that may vary during BSS's lifespan, and may affect low
+ * level driver (e.g. assoc/disassoc status, erp parameters).
+ * This function should not be used if no BSS has been set, unless
+ * for association indication. The @changed parameter indicates which
+ * of the bss parameters has changed when a call is made. The callback
+ * can sleep.
+ *
+ * @prepare_multicast: Prepare for multicast filter configuration.
+ * This callback is optional, and its return value is passed
+ * to configure_filter(). This callback must be atomic.
+ *
+ * @configure_filter: Configure the device's RX filter.
+ * See the section "Frame filtering" for more information.
+ * This callback must be implemented and can sleep.
+ *
+ * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit
+ * must be set or cleared for a given STA. Must be atomic.
+ *
+ * @set_key: See the section "Hardware crypto acceleration"
+ * This callback is only called between add_interface and
+ * remove_interface calls, i.e. while the given virtual interface
+ * is enabled.
+ * Returns a negative error code if the key can't be added.
+ * The callback can sleep.
+ *
+ * @update_tkip_key: See the section "Hardware crypto acceleration"
+ * This callback will be called in the context of Rx. Called for drivers
+ * which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY.
+ * The callback must be atomic.
+ *
+ * @set_rekey_data: If the device supports GTK rekeying, for example while the
+ * host is suspended, it can assign this callback to retrieve the data
+ * necessary to do GTK rekeying, this is the KEK, KCK and replay counter.
+ * After rekeying was done it should (for example during resume) notify
+ * userspace of the new replay counter using ieee80211_gtk_rekey_notify().
+ *
+ * @hw_scan: Ask the hardware to service the scan request, no need to start
+ * the scan state machine in stack. The scan must honour the channel
+ * configuration done by the regulatory agent in the wiphy's
+ * registered bands. The hardware (or the driver) needs to make sure
+ * that power save is disabled.
+ * The @req ie/ie_len members are rewritten by mac80211 to contain the
+ * entire IEs after the SSID, so that drivers need not look at these
+ * at all but just send them after the SSID -- mac80211 includes the
+ * (extended) supported rates and HT information (where applicable).
+ * When the scan finishes, ieee80211_scan_completed() must be called;
+ * note that it also must be called when the scan cannot finish due to
+ * any error unless this callback returned a negative error code.
+ * The callback can sleep.
+ *
+ * @cancel_hw_scan: Ask the low-level tp cancel the active hw scan.
+ * The driver should ask the hardware to cancel the scan (if possible),
+ * but the scan will be completed only after the driver will call
+ * ieee80211_scan_completed().
+ * This callback is needed for wowlan, to prevent enqueueing a new
+ * scan_work after the low-level driver was already suspended.
+ * The callback can sleep.
+ *
+ * @sched_scan_start: Ask the hardware to start scanning repeatedly at
+ * specific intervals. The driver must call the
+ * ieee80211_sched_scan_results() function whenever it finds results.
+ * This process will continue until sched_scan_stop is called.
+ *
+ * @sched_scan_stop: Tell the hardware to stop an ongoing scheduled scan.
+ *
+ * @sw_scan_start: Notifier function that is called just before a software scan
+ * is started. Can be NULL, if the driver doesn't need this notification.
+ * The callback can sleep.
+ *
+ * @sw_scan_complete: Notifier function that is called just after a
+ * software scan finished. Can be NULL, if the driver doesn't need
+ * this notification.
+ * The callback can sleep.
+ *
+ * @get_stats: Return low-level statistics.
+ * Returns zero if statistics are available.
+ * The callback can sleep.
+ *
+ * @get_tkip_seq: If your device implements TKIP encryption in hardware this
+ * callback should be provided to read the TKIP transmit IVs (both IV32
+ * and IV16) for the given key from hardware.
+ * The callback must be atomic.
+ *
+ * @set_frag_threshold: Configuration of fragmentation threshold. Assign this
+ * if the device does fragmentation by itself; if this callback is
+ * implemented then the stack will not do fragmentation.
+ * The callback can sleep.
+ *
+ * @set_rts_threshold: Configuration of RTS threshold (if device needs it)
+ * The callback can sleep.
+ *
+ * @sta_add: Notifies low level driver about addition of an associated station,
+ * AP, IBSS/WDS/mesh peer etc. This callback can sleep.
+ *
+ * @sta_remove: Notifies low level driver about removal of an associated
+ * station, AP, IBSS/WDS/mesh peer etc. This callback can sleep.
+ *
+ * @sta_notify: Notifies low level driver about power state transition of an
+ * associated station, AP, IBSS/WDS/mesh peer etc. For a VIF operating
+ * in AP mode, this callback will not be called when the flag
+ * %IEEE80211_HW_AP_LINK_PS is set. Must be atomic.
+ *
+ * @sta_state: Notifies low level driver about state transition of a
+ * station (which can be the AP, a client, IBSS/WDS/mesh peer etc.)
+ * This callback is mutually exclusive with @sta_add/@sta_remove.
+ * It must not fail for down transitions but may fail for transitions
+ * up the list of states.
+ * The callback can sleep.
+ *
+ * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max),
+ * bursting) for a hardware TX queue.
+ * Returns a negative error code on failure.
+ * The callback can sleep.
+ *
+ * @get_tsf: Get the current TSF timer value from firmware/hardware. Currently,
+ * this is only used for IBSS mode BSSID merging and debugging. Is not a
+ * required function.
+ * The callback can sleep.
+ *
+ * @set_tsf: Set the TSF timer to the specified value in the firmware/hardware.
+ * Currently, this is only used for IBSS mode debugging. Is not a
+ * required function.
+ * The callback can sleep.
+ *
+ * @reset_tsf: Reset the TSF timer and allow firmware/hardware to synchronize
+ * with other STAs in the IBSS. This is only used in IBSS mode. This
+ * function is optional if the firmware/hardware takes full care of
+ * TSF synchronization.
+ * The callback can sleep.
+ *
+ * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us.
+ * This is needed only for IBSS mode and the result of this function is
+ * used to determine whether to reply to Probe Requests.
+ * Returns non-zero if this device sent the last beacon.
+ * The callback can sleep.
+ *
+ * @ampdu_action: Perform a certain A-MPDU action
+ * The RA/TID combination determines the destination and TID we want
+ * the ampdu action to be performed for. The action is defined through
+ * ieee80211_ampdu_mlme_action. Starting sequence number (@ssn)
+ * is the first frame we expect to perform the action on. Notice
+ * that TX/RX_STOP can pass NULL for this parameter.
+ * The @buf_size parameter is only valid when the action is set to
+ * %IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's reorder
+ * buffer size (number of subframes) for this session -- the driver
+ * may neither send aggregates containing more subframes than this
+ * nor send aggregates in a way that lost frames would exceed the
+ * buffer size. If just limiting the aggregate size, this would be
+ * possible with a buf_size of 8:
+ * - TX: 1.....7
+ * - RX: 2....7 (lost frame #1)
+ * - TX: 8..1...
+ * which is invalid since #1 was now re-transmitted well past the
+ * buffer size of 8. Correct ways to retransmit #1 would be:
+ * - TX: 1 or 18 or 81
+ * Even "189" would be wrong since 1 could be lost again.
+ *
+ * Returns a negative error code on failure.
+ * The callback can sleep.
+ *
+ * @get_survey: Return per-channel survey information
+ *
+ * @rfkill_poll: Poll rfkill hardware state. If you need this, you also
+ * need to set wiphy->rfkill_poll to %true before registration,
+ * and need to call wiphy_rfkill_set_hw_state() in the callback.
+ * The callback can sleep.
+ *
+ * @set_coverage_class: Set slot time for given coverage class as specified
+ * in IEEE 802.11-2007 section 17.3.8.6 and modify ACK timeout
+ * accordingly. This callback is not required and may sleep.
+ *
+ * @testmode_cmd: Implement a cfg80211 test mode command.
+ * The callback can sleep.
+ * @testmode_dump: Implement a cfg80211 test mode dump. The callback can sleep.
+ *
+ * @flush: Flush all pending frames from the hardware queue, making sure
+ * that the hardware queues are empty. If the parameter @drop is set
+ * to %true, pending frames may be dropped. The callback can sleep.
+ *
+ * @channel_switch: Drivers that need (or want) to offload the channel
+ * switch operation for CSAs received from the AP may implement this
+ * callback. They must then call ieee80211_chswitch_done() to indicate
+ * completion of the channel switch.
+ *
+ * @napi_poll: Poll Rx queue for incoming data frames.
+ *
+ * @set_antenna: Set antenna configuration (tx_ant, rx_ant) on the device.
+ * Parameters are bitmaps of allowed antennas to use for TX/RX. Drivers may
+ * reject TX/RX mask combinations they cannot support by returning -EINVAL
+ * (also see nl80211.h @NL80211_ATTR_WIPHY_ANTENNA_TX).
+ *
+ * @get_antenna: Get current antenna configuration from device (tx_ant, rx_ant).
+ *
+ * @remain_on_channel: Starts an off-channel period on the given channel, must
+ * call back to ieee80211_ready_on_channel() when on that channel. Note
+ * that normal channel traffic is not stopped as this is intended for hw
+ * offload. Frames to transmit on the off-channel channel are transmitted
+ * normally except for the %IEEE80211_TX_CTL_TX_OFFCHAN flag. When the
+ * duration (which will always be non-zero) expires, the driver must call
+ * ieee80211_remain_on_channel_expired(). This callback may sleep.
+ * @cancel_remain_on_channel: Requests that an ongoing off-channel period is
+ * aborted before it expires. This callback may sleep.
+ *
+ * @set_ringparam: Set tx and rx ring sizes.
+ *
+ * @get_ringparam: Get tx and rx ring current and maximum sizes.
+ *
+ * @tx_frames_pending: Check if there is any pending frame in the hardware
+ * queues before entering power save.
+ *
+ * @set_bitrate_mask: Set a mask of rates to be used for rate control selection
+ * when transmitting a frame. Currently only legacy rates are handled.
+ * The callback can sleep.
+ * @rssi_callback: Notify driver when the average RSSI goes above/below
+ * thresholds that were registered previously. The callback can sleep.
+ *
+ * @release_buffered_frames: Release buffered frames according to the given
+ * parameters. In the case where the driver buffers some frames for
+ * sleeping stations mac80211 will use this callback to tell the driver
+ * to release some frames, either for PS-poll or uAPSD.
+ * Note that if the @more_data paramter is %false the driver must check
+ * if there are more frames on the given TIDs, and if there are more than
+ * the frames being released then it must still set the more-data bit in
+ * the frame. If the @more_data parameter is %true, then of course the
+ * more-data bit must always be set.
+ * The @tids parameter tells the driver which TIDs to release frames
+ * from, for PS-poll it will always have only a single bit set.
+ * In the case this is used for a PS-poll initiated release, the
+ * @num_frames parameter will always be 1 so code can be shared. In
+ * this case the driver must also set %IEEE80211_TX_STATUS_EOSP flag
+ * on the TX status (and must report TX status) so that the PS-poll
+ * period is properly ended. This is used to avoid sending multiple
+ * responses for a retried PS-poll frame.
+ * In the case this is used for uAPSD, the @num_frames parameter may be
+ * bigger than one, but the driver may send fewer frames (it must send
+ * at least one, however). In this case it is also responsible for
+ * setting the EOSP flag in the QoS header of the frames. Also, when the
+ * service period ends, the driver must set %IEEE80211_TX_STATUS_EOSP
+ * on the last frame in the SP. Alternatively, it may call the function
+ * ieee80211_sta_eosp_irqsafe() to inform mac80211 of the end of the SP.
+ * This callback must be atomic.
+ * @allow_buffered_frames: Prepare device to allow the given number of frames
+ * to go out to the given station. The frames will be sent by mac80211
+ * via the usual TX path after this call. The TX information for frames
+ * released will also have the %IEEE80211_TX_CTL_NO_PS_BUFFER flag set
+ * and the last one will also have %IEEE80211_TX_STATUS_EOSP set. In case
+ * frames from multiple TIDs are released and the driver might reorder
+ * them between the TIDs, it must set the %IEEE80211_TX_STATUS_EOSP flag
+ * on the last frame and clear it on all others and also handle the EOSP
+ * bit in the QoS header correctly. Alternatively, it can also call the
+ * ieee80211_sta_eosp_irqsafe() function.
+ * The @tids parameter is a bitmap and tells the driver which TIDs the
+ * frames will be on; it will at most have two bits set.
+ * This callback must be atomic.
+ */
+struct ieee80211_ops {
+ void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
+ void (*tx_frags)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, struct sk_buff_head *skbs);
+ int (*start)(struct ieee80211_hw *hw);
+ void (*stop)(struct ieee80211_hw *hw);
+#ifdef CONFIG_PM
+ int (*suspend)(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
+ int (*resume)(struct ieee80211_hw *hw);
+#endif
+ int (*add_interface)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+ int (*change_interface)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ enum nl80211_iftype new_type, bool p2p);
+ void (*remove_interface)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+ int (*config)(struct ieee80211_hw *hw, u32 changed);
+ void (*bss_info_changed)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info,
+ u32 changed);
+
+ u64 (*prepare_multicast)(struct ieee80211_hw *hw,
+ struct netdev_hw_addr_list *mc_list);
+ void (*configure_filter)(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *total_flags,
+ u64 multicast);
+ int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
+ bool set);
+ int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key);
+ void (*update_tkip_key)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_key_conf *conf,
+ struct ieee80211_sta *sta,
+ u32 iv32, u16 *phase1key);
+ void (*set_rekey_data)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_gtk_rekey_data *data);
+ int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct cfg80211_scan_request *req);
+ void (*cancel_hw_scan)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+ int (*sched_scan_start)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_sched_scan_request *req,
+ struct ieee80211_sched_scan_ies *ies);
+ void (*sched_scan_stop)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+ void (*sw_scan_start)(struct ieee80211_hw *hw);
+ void (*sw_scan_complete)(struct ieee80211_hw *hw);
+ int (*get_stats)(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats);
+ void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx,
+ u32 *iv32, u16 *iv16);
+ int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value);
+ int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value);
+ int (*sta_add)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+ int (*sta_remove)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+ void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ enum sta_notify_cmd, struct ieee80211_sta *sta);
+ int (*sta_state)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ enum ieee80211_sta_state old_state,
+ enum ieee80211_sta_state new_state);
+ int (*conf_tx)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
+ const struct ieee80211_tx_queue_params *params);
+ u64 (*get_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+ void (*set_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ u64 tsf);
+ void (*reset_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+ int (*tx_last_beacon)(struct ieee80211_hw *hw);
+ int (*ampdu_action)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ enum ieee80211_ampdu_mlme_action action,
+ struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+ u8 buf_size);
+ int (*get_survey)(struct ieee80211_hw *hw, int idx,
+ struct survey_info *survey);
+ void (*rfkill_poll)(struct ieee80211_hw *hw);
+ void (*set_coverage_class)(struct ieee80211_hw *hw, u8 coverage_class);
+#ifdef CONFIG_NL80211_TESTMODE
+ int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len);
+ int (*testmode_dump)(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct netlink_callback *cb,
+ void *data, int len);
+#endif
+ void (*flush)(struct ieee80211_hw *hw, bool drop);
+ void (*channel_switch)(struct ieee80211_hw *hw,
+ struct ieee80211_channel_switch *ch_switch);
+ int (*napi_poll)(struct ieee80211_hw *hw, int budget);
+ int (*set_antenna)(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
+ int (*get_antenna)(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
+
+ int (*remain_on_channel)(struct ieee80211_hw *hw,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type,
+ int duration);
+ int (*cancel_remain_on_channel)(struct ieee80211_hw *hw);
+ int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx);
+ void (*get_ringparam)(struct ieee80211_hw *hw,
+ u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
+ bool (*tx_frames_pending)(struct ieee80211_hw *hw);
+ int (*set_bitrate_mask)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ const struct cfg80211_bitrate_mask *mask);
+ void (*rssi_callback)(struct ieee80211_hw *hw,
+ enum ieee80211_rssi_event rssi_event);
+
+ void (*allow_buffered_frames)(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta,
+ u16 tids, int num_frames,
+ enum ieee80211_frame_release_type reason,
+ bool more_data);
+ void (*release_buffered_frames)(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta,
+ u16 tids, int num_frames,
+ enum ieee80211_frame_release_type reason,
+ bool more_data);
+};
+
+/**
+ * ieee80211_alloc_hw - Allocate a new hardware device
+ *
+ * This must be called once for each hardware device. The returned pointer
+ * must be used to refer to this device when calling other functions.
+ * mac80211 allocates a private data area for the driver pointed to by
+ * @priv in &struct ieee80211_hw, the size of this area is given as
+ * @priv_data_len.
+ *
+ * @priv_data_len: length of private data
+ * @ops: callbacks for this device
+ */
+struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
+ const struct ieee80211_ops *ops);
+
+/**
+ * ieee80211_register_hw - Register hardware device
+ *
+ * You must call this function before any other functions in
+ * mac80211. Note that before a hardware can be registered, you
+ * need to fill the contained wiphy's information.
+ *
+ * @hw: the device to register as returned by ieee80211_alloc_hw()
+ */
+int ieee80211_register_hw(struct ieee80211_hw *hw);
+
+/**
+ * struct ieee80211_tpt_blink - throughput blink description
+ * @throughput: throughput in Kbit/sec
+ * @blink_time: blink time in milliseconds
+ * (full cycle, ie. one off + one on period)
+ */
+struct ieee80211_tpt_blink {
+ int throughput;
+ int blink_time;
+};
+
+/**
+ * enum ieee80211_tpt_led_trigger_flags - throughput trigger flags
+ * @IEEE80211_TPT_LEDTRIG_FL_RADIO: enable blinking with radio
+ * @IEEE80211_TPT_LEDTRIG_FL_WORK: enable blinking when working
+ * @IEEE80211_TPT_LEDTRIG_FL_CONNECTED: enable blinking when at least one
+ * interface is connected in some way, including being an AP
+ */
+enum ieee80211_tpt_led_trigger_flags {
+ IEEE80211_TPT_LEDTRIG_FL_RADIO = BIT(0),
+ IEEE80211_TPT_LEDTRIG_FL_WORK = BIT(1),
+ IEEE80211_TPT_LEDTRIG_FL_CONNECTED = BIT(2),
+};
+
+#ifdef CONFIG_MAC80211_LEDS
+extern char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw);
+extern char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw);
+extern char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw);
+extern char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw);
+extern char *__ieee80211_create_tpt_led_trigger(
+ struct ieee80211_hw *hw, unsigned int flags,
+ const struct ieee80211_tpt_blink *blink_table,
+ unsigned int blink_table_len);
+#endif
+/**
+ * ieee80211_get_tx_led_name - get name of TX LED
+ *
+ * mac80211 creates a transmit LED trigger for each wireless hardware
+ * that can be used to drive LEDs if your driver registers a LED device.
+ * This function returns the name (or %NULL if not configured for LEDs)
+ * of the trigger so you can automatically link the LED device.
+ *
+ * @hw: the hardware to get the LED trigger name for
+ */
+static inline char *ieee80211_get_tx_led_name(struct ieee80211_hw *hw)
+{
+#ifdef CONFIG_MAC80211_LEDS
+ return __ieee80211_get_tx_led_name(hw);
+#else
+ return NULL;
+#endif
+}
+
+/**
+ * ieee80211_get_rx_led_name - get name of RX LED
+ *
+ * mac80211 creates a receive LED trigger for each wireless hardware
+ * that can be used to drive LEDs if your driver registers a LED device.
+ * This function returns the name (or %NULL if not configured for LEDs)
+ * of the trigger so you can automatically link the LED device.
+ *
+ * @hw: the hardware to get the LED trigger name for
+ */
+static inline char *ieee80211_get_rx_led_name(struct ieee80211_hw *hw)
+{
+#ifdef CONFIG_MAC80211_LEDS
+ return __ieee80211_get_rx_led_name(hw);
+#else
+ return NULL;
+#endif
+}
+
+/**
+ * ieee80211_get_assoc_led_name - get name of association LED
+ *
+ * mac80211 creates a association LED trigger for each wireless hardware
+ * that can be used to drive LEDs if your driver registers a LED device.
+ * This function returns the name (or %NULL if not configured for LEDs)
+ * of the trigger so you can automatically link the LED device.
+ *
+ * @hw: the hardware to get the LED trigger name for
+ */
+static inline char *ieee80211_get_assoc_led_name(struct ieee80211_hw *hw)
+{
+#ifdef CONFIG_MAC80211_LEDS
+ return __ieee80211_get_assoc_led_name(hw);
+#else
+ return NULL;
+#endif
+}
+
+/**
+ * ieee80211_get_radio_led_name - get name of radio LED
+ *
+ * mac80211 creates a radio change LED trigger for each wireless hardware
+ * that can be used to drive LEDs if your driver registers a LED device.
+ * This function returns the name (or %NULL if not configured for LEDs)
+ * of the trigger so you can automatically link the LED device.
+ *
+ * @hw: the hardware to get the LED trigger name for
+ */
+static inline char *ieee80211_get_radio_led_name(struct ieee80211_hw *hw)
+{
+#ifdef CONFIG_MAC80211_LEDS
+ return __ieee80211_get_radio_led_name(hw);
+#else
+ return NULL;
+#endif
+}
+
+/**
+ * ieee80211_create_tpt_led_trigger - create throughput LED trigger
+ * @hw: the hardware to create the trigger for
+ * @flags: trigger flags, see &enum ieee80211_tpt_led_trigger_flags
+ * @blink_table: the blink table -- needs to be ordered by throughput
+ * @blink_table_len: size of the blink table
+ *
+ * This function returns %NULL (in case of error, or if no LED
+ * triggers are configured) or the name of the new trigger.
+ * This function must be called before ieee80211_register_hw().
+ */
+static inline char *
+ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw, unsigned int flags,
+ const struct ieee80211_tpt_blink *blink_table,
+ unsigned int blink_table_len)
+{
+#ifdef CONFIG_MAC80211_LEDS
+ return __ieee80211_create_tpt_led_trigger(hw, flags, blink_table,
+ blink_table_len);
+#else
+ return NULL;
+#endif
+}
+
+/**
+ * ieee80211_unregister_hw - Unregister a hardware device
+ *
+ * This function instructs mac80211 to free allocated resources
+ * and unregister netdevices from the networking subsystem.
+ *
+ * @hw: the hardware to unregister
+ */
+void ieee80211_unregister_hw(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_free_hw - free hardware descriptor
+ *
+ * This function frees everything that was allocated, including the
+ * private data for the driver. You must call ieee80211_unregister_hw()
+ * before calling this function.
+ *
+ * @hw: the hardware to free
+ */
+void ieee80211_free_hw(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_restart_hw - restart hardware completely
+ *
+ * Call this function when the hardware was restarted for some reason
+ * (hardware error, ...) and the driver is unable to restore its state
+ * by itself. mac80211 assumes that at this point the driver/hardware
+ * is completely uninitialised and stopped, it starts the process by
+ * calling the ->start() operation. The driver will need to reset all
+ * internal state that it has prior to calling this function.
+ *
+ * @hw: the hardware to restart
+ */
+void ieee80211_restart_hw(struct ieee80211_hw *hw);
+
+/** ieee80211_napi_schedule - schedule NAPI poll
+ *
+ * Use this function to schedule NAPI polling on a device.
+ *
+ * @hw: the hardware to start polling
+ */
+void ieee80211_napi_schedule(struct ieee80211_hw *hw);
+
+/** ieee80211_napi_complete - complete NAPI polling
+ *
+ * Use this function to finish NAPI polling on a device.
+ *
+ * @hw: the hardware to stop polling
+ */
+void ieee80211_napi_complete(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_rx - receive frame
+ *
+ * Use this function to hand received frames to mac80211. The receive
+ * buffer in @skb must start with an IEEE 802.11 header. In case of a
+ * paged @skb is used, the driver is recommended to put the ieee80211
+ * header of the frame on the linear part of the @skb to avoid memory
+ * allocation and/or memcpy by the stack.
+ *
+ * This function may not be called in IRQ context. Calls to this function
+ * for a single hardware must be synchronized against each other. Calls to
+ * this function, ieee80211_rx_ni() and ieee80211_rx_irqsafe() may not be
+ * mixed for a single hardware.
+ *
+ * In process context use instead ieee80211_rx_ni().
+ *
+ * @hw: the hardware this frame came in on
+ * @skb: the buffer to receive, owned by mac80211 after this call
+ */
+void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb);
+
+/**
+ * ieee80211_rx_irqsafe - receive frame
+ *
+ * Like ieee80211_rx() but can be called in IRQ context
+ * (internally defers to a tasklet.)
+ *
+ * Calls to this function, ieee80211_rx() or ieee80211_rx_ni() may not
+ * be mixed for a single hardware.
+ *
+ * @hw: the hardware this frame came in on
+ * @skb: the buffer to receive, owned by mac80211 after this call
+ */
+void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb);
+
+/**
+ * ieee80211_rx_ni - receive frame (in process context)
+ *
+ * Like ieee80211_rx() but can be called in process context
+ * (internally disables bottom halves).
+ *
+ * Calls to this function, ieee80211_rx() and ieee80211_rx_irqsafe() may
+ * not be mixed for a single hardware.
+ *
+ * @hw: the hardware this frame came in on
+ * @skb: the buffer to receive, owned by mac80211 after this call
+ */
+static inline void ieee80211_rx_ni(struct ieee80211_hw *hw,
+ struct sk_buff *skb)
+{
+ local_bh_disable();
+ ieee80211_rx(hw, skb);
+ local_bh_enable();
+}
+
+/**
+ * ieee80211_sta_ps_transition - PS transition for connected sta
+ *
+ * When operating in AP mode with the %IEEE80211_HW_AP_LINK_PS
+ * flag set, use this function to inform mac80211 about a connected station
+ * entering/leaving PS mode.
+ *
+ * This function may not be called in IRQ context or with softirqs enabled.
+ *
+ * Calls to this function for a single hardware must be synchronized against
+ * each other.
+ *
+ * The function returns -EINVAL when the requested PS mode is already set.
+ *
+ * @sta: currently connected sta
+ * @start: start or stop PS
+ */
+int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start);
+
+/**
+ * ieee80211_sta_ps_transition_ni - PS transition for connected sta
+ * (in process context)
+ *
+ * Like ieee80211_sta_ps_transition() but can be called in process context
+ * (internally disables bottom halves). Concurrent call restriction still
+ * applies.
+ *
+ * @sta: currently connected sta
+ * @start: start or stop PS
+ */
+static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta,
+ bool start)
+{
+ int ret;
+
+ local_bh_disable();
+ ret = ieee80211_sta_ps_transition(sta, start);
+ local_bh_enable();
+
+ return ret;
+}
+
+/*
+ * The TX headroom reserved by mac80211 for its own tx_status functions.
+ * This is enough for the radiotap header.
+ */
+#define IEEE80211_TX_STATUS_HEADROOM 14
+
+/**
+ * ieee80211_sta_set_buffered - inform mac80211 about driver-buffered frames
+ * @sta: &struct ieee80211_sta pointer for the sleeping station
+ * @tid: the TID that has buffered frames
+ * @buffered: indicates whether or not frames are buffered for this TID
+ *
+ * If a driver buffers frames for a powersave station instead of passing
+ * them back to mac80211 for retransmission, the station may still need
+ * to be told that there are buffered frames via the TIM bit.
+ *
+ * This function informs mac80211 whether or not there are frames that are
+ * buffered in the driver for a given TID; mac80211 can then use this data
+ * to set the TIM bit (NOTE: This may call back into the driver's set_tim
+ * call! Beware of the locking!)
+ *
+ * If all frames are released to the station (due to PS-poll or uAPSD)
+ * then the driver needs to inform mac80211 that there no longer are
+ * frames buffered. However, when the station wakes up mac80211 assumes
+ * that all buffered frames will be transmitted and clears this data,
+ * drivers need to make sure they inform mac80211 about all buffered
+ * frames on the sleep transition (sta_notify() with %STA_NOTIFY_SLEEP).
+ *
+ * Note that technically mac80211 only needs to know this per AC, not per
+ * TID, but since driver buffering will inevitably happen per TID (since
+ * it is related to aggregation) it is easier to make mac80211 map the
+ * TID to the AC as required instead of keeping track in all drivers that
+ * use this API.
+ */
+void ieee80211_sta_set_buffered(struct ieee80211_sta *sta,
+ u8 tid, bool buffered);
+
+/**
+ * ieee80211_tx_status - transmit status callback
+ *
+ * Call this function for all transmitted frames after they have been
+ * transmitted. It is permissible to not call this function for
+ * multicast frames but this can affect statistics.
+ *
+ * This function may not be called in IRQ context. Calls to this function
+ * for a single hardware must be synchronized against each other. Calls
+ * to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe()
+ * may not be mixed for a single hardware.
+ *
+ * @hw: the hardware the frame was transmitted by
+ * @skb: the frame that was transmitted, owned by mac80211 after this call
+ */
+void ieee80211_tx_status(struct ieee80211_hw *hw,
+ struct sk_buff *skb);
+
+/**
+ * ieee80211_tx_status_ni - transmit status callback (in process context)
+ *
+ * Like ieee80211_tx_status() but can be called in process context.
+ *
+ * Calls to this function, ieee80211_tx_status() and
+ * ieee80211_tx_status_irqsafe() may not be mixed
+ * for a single hardware.
+ *
+ * @hw: the hardware the frame was transmitted by
+ * @skb: the frame that was transmitted, owned by mac80211 after this call
+ */
+static inline void ieee80211_tx_status_ni(struct ieee80211_hw *hw,
+ struct sk_buff *skb)
+{
+ local_bh_disable();
+ ieee80211_tx_status(hw, skb);
+ local_bh_enable();
+}
+
+/**
+ * ieee80211_tx_status_irqsafe - IRQ-safe transmit status callback
+ *
+ * Like ieee80211_tx_status() but can be called in IRQ context
+ * (internally defers to a tasklet.)
+ *
+ * Calls to this function, ieee80211_tx_status() and
+ * ieee80211_tx_status_ni() may not be mixed for a single hardware.
+ *
+ * @hw: the hardware the frame was transmitted by
+ * @skb: the frame that was transmitted, owned by mac80211 after this call
+ */
+void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
+ struct sk_buff *skb);
+
+/**
+ * ieee80211_report_low_ack - report non-responding station
+ *
+ * When operating in AP-mode, call this function to report a non-responding
+ * connected STA.
+ *
+ * @sta: the non-responding connected sta
+ * @num_packets: number of packets sent to @sta without a response
+ */
+void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets);
+
+/**
+ * ieee80211_beacon_get_tim - beacon generation function
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @tim_offset: pointer to variable that will receive the TIM IE offset.
+ * Set to 0 if invalid (in non-AP modes).
+ * @tim_length: pointer to variable that will receive the TIM IE length,
+ * (including the ID and length bytes!).
+ * Set to 0 if invalid (in non-AP modes).
+ *
+ * If the driver implements beaconing modes, it must use this function to
+ * obtain the beacon frame/template.
+ *
+ * If the beacon frames are generated by the host system (i.e., not in
+ * hardware/firmware), the driver uses this function to get each beacon
+ * frame from mac80211 -- it is responsible for calling this function
+ * before the beacon is needed (e.g. based on hardware interrupt).
+ *
+ * If the beacon frames are generated by the device, then the driver
+ * must use the returned beacon as the template and change the TIM IE
+ * according to the current DTIM parameters/TIM bitmap.
+ *
+ * The driver is responsible for freeing the returned skb.
+ */
+struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u16 *tim_offset, u16 *tim_length);
+
+/**
+ * ieee80211_beacon_get - beacon generation function
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * See ieee80211_beacon_get_tim().
+ */
+static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ return ieee80211_beacon_get_tim(hw, vif, NULL, NULL);
+}
+
+/**
+ * ieee80211_proberesp_get - retrieve a Probe Response template
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * Creates a Probe Response template which can, for example, be uploaded to
+ * hardware. The destination address should be set by the caller.
+ *
+ * Can only be called in AP mode.
+ */
+struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+
+/**
+ * ieee80211_pspoll_get - retrieve a PS Poll template
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * Creates a PS Poll a template which can, for example, uploaded to
+ * hardware. The template must be updated after association so that correct
+ * AID, BSSID and MAC address is used.
+ *
+ * Note: Caller (or hardware) is responsible for setting the
+ * &IEEE80211_FCTL_PM bit.
+ */
+struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+
+/**
+ * ieee80211_nullfunc_get - retrieve a nullfunc template
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * Creates a Nullfunc template which can, for example, uploaded to
+ * hardware. The template must be updated after association so that correct
+ * BSSID and address is used.
+ *
+ * Note: Caller (or hardware) is responsible for setting the
+ * &IEEE80211_FCTL_PM bit as well as Duration and Sequence Control fields.
+ */
+struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+
+/**
+ * ieee80211_probereq_get - retrieve a Probe Request template
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @ssid: SSID buffer
+ * @ssid_len: length of SSID
+ * @ie: buffer containing all IEs except SSID for the template
+ * @ie_len: length of the IE buffer
+ *
+ * Creates a Probe Request template which can, for example, be uploaded to
+ * hardware.
+ */
+struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ const u8 *ssid, size_t ssid_len,
+ const u8 *ie, size_t ie_len);
+
+/**
+ * ieee80211_rts_get - RTS frame generation function
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @frame: pointer to the frame that is going to be protected by the RTS.
+ * @frame_len: the frame length (in octets).
+ * @frame_txctl: &struct ieee80211_tx_info of the frame.
+ * @rts: The buffer where to store the RTS frame.
+ *
+ * If the RTS frames are generated by the host system (i.e., not in
+ * hardware/firmware), the low-level driver uses this function to receive
+ * the next RTS frame from the 802.11 code. The low-level is responsible
+ * for calling this function before and RTS frame is needed.
+ */
+void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ const void *frame, size_t frame_len,
+ const struct ieee80211_tx_info *frame_txctl,
+ struct ieee80211_rts *rts);
+
+/**
+ * ieee80211_rts_duration - Get the duration field for an RTS frame
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @frame_len: the length of the frame that is going to be protected by the RTS.
+ * @frame_txctl: &struct ieee80211_tx_info of the frame.
+ *
+ * If the RTS is generated in firmware, but the host system must provide
+ * the duration field, the low-level driver uses this function to receive
+ * the duration field value in little-endian byteorder.
+ */
+__le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, size_t frame_len,
+ const struct ieee80211_tx_info *frame_txctl);
+
+/**
+ * ieee80211_ctstoself_get - CTS-to-self frame generation function
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @frame: pointer to the frame that is going to be protected by the CTS-to-self.
+ * @frame_len: the frame length (in octets).
+ * @frame_txctl: &struct ieee80211_tx_info of the frame.
+ * @cts: The buffer where to store the CTS-to-self frame.
+ *
+ * If the CTS-to-self frames are generated by the host system (i.e., not in
+ * hardware/firmware), the low-level driver uses this function to receive
+ * the next CTS-to-self frame from the 802.11 code. The low-level is responsible
+ * for calling this function before and CTS-to-self frame is needed.
+ */
+void ieee80211_ctstoself_get(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ const void *frame, size_t frame_len,
+ const struct ieee80211_tx_info *frame_txctl,
+ struct ieee80211_cts *cts);
+
+/**
+ * ieee80211_ctstoself_duration - Get the duration field for a CTS-to-self frame
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @frame_len: the length of the frame that is going to be protected by the CTS-to-self.
+ * @frame_txctl: &struct ieee80211_tx_info of the frame.
+ *
+ * If the CTS-to-self is generated in firmware, but the host system must provide
+ * the duration field, the low-level driver uses this function to receive
+ * the duration field value in little-endian byteorder.
+ */
+__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ size_t frame_len,
+ const struct ieee80211_tx_info *frame_txctl);
+
+/**
+ * ieee80211_generic_frame_duration - Calculate the duration field for a frame
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @frame_len: the length of the frame.
+ * @rate: the rate at which the frame is going to be transmitted.
+ *
+ * Calculate the duration field of some generic frame, given its
+ * length and transmission rate (in 100kbps).
+ */
+__le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ size_t frame_len,
+ struct ieee80211_rate *rate);
+
+/**
+ * ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * Function for accessing buffered broadcast and multicast frames. If
+ * hardware/firmware does not implement buffering of broadcast/multicast
+ * frames when power saving is used, 802.11 code buffers them in the host
+ * memory. The low-level driver uses this function to fetch next buffered
+ * frame. In most cases, this is used when generating beacon frame. This
+ * function returns a pointer to the next buffered skb or NULL if no more
+ * buffered frames are available.
+ *
+ * Note: buffered frames are returned only after DTIM beacon frame was
+ * generated with ieee80211_beacon_get() and the low-level driver must thus
+ * call ieee80211_beacon_get() first. ieee80211_get_buffered_bc() returns
+ * NULL if the previous generated beacon was not DTIM, so the low-level driver
+ * does not need to check for DTIM beacons separately and should be able to
+ * use common code for all beacons.
+ */
+struct sk_buff *
+ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+
+/**
+ * ieee80211_get_tkip_p1k_iv - get a TKIP phase 1 key for IV32
+ *
+ * This function returns the TKIP phase 1 key for the given IV32.
+ *
+ * @keyconf: the parameter passed with the set key
+ * @iv32: IV32 to get the P1K for
+ * @p1k: a buffer to which the key will be written, as 5 u16 values
+ */
+void ieee80211_get_tkip_p1k_iv(struct ieee80211_key_conf *keyconf,
+ u32 iv32, u16 *p1k);
+
+/**
+ * ieee80211_get_tkip_p1k - get a TKIP phase 1 key
+ *
+ * This function returns the TKIP phase 1 key for the IV32 taken
+ * from the given packet.
+ *
+ * @keyconf: the parameter passed with the set key
+ * @skb: the packet to take the IV32 value from that will be encrypted
+ * with this P1K
+ * @p1k: a buffer to which the key will be written, as 5 u16 values
+ */
+static inline void ieee80211_get_tkip_p1k(struct ieee80211_key_conf *keyconf,
+ struct sk_buff *skb, u16 *p1k)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ const u8 *data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);
+ u32 iv32 = get_unaligned_le32(&data[4]);
+
+ ieee80211_get_tkip_p1k_iv(keyconf, iv32, p1k);
+}
+
+/**
+ * ieee80211_get_tkip_rx_p1k - get a TKIP phase 1 key for RX
+ *
+ * This function returns the TKIP phase 1 key for the given IV32
+ * and transmitter address.
+ *
+ * @keyconf: the parameter passed with the set key
+ * @ta: TA that will be used with the key
+ * @iv32: IV32 to get the P1K for
+ * @p1k: a buffer to which the key will be written, as 5 u16 values
+ */
+void ieee80211_get_tkip_rx_p1k(struct ieee80211_key_conf *keyconf,
+ const u8 *ta, u32 iv32, u16 *p1k);
+
+/**
+ * ieee80211_get_tkip_p2k - get a TKIP phase 2 key
+ *
+ * This function computes the TKIP RC4 key for the IV values
+ * in the packet.
+ *
+ * @keyconf: the parameter passed with the set key
+ * @skb: the packet to take the IV32/IV16 values from that will be
+ * encrypted with this key
+ * @p2k: a buffer to which the key will be written, 16 bytes
+ */
+void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf,
+ struct sk_buff *skb, u8 *p2k);
+
+/**
+ * struct ieee80211_key_seq - key sequence counter
+ *
+ * @tkip: TKIP data, containing IV32 and IV16 in host byte order
+ * @ccmp: PN data, most significant byte first (big endian,
+ * reverse order than in packet)
+ * @aes_cmac: PN data, most significant byte first (big endian,
+ * reverse order than in packet)
+ */
+struct ieee80211_key_seq {
+ union {
+ struct {
+ u32 iv32;
+ u16 iv16;
+ } tkip;
+ struct {
+ u8 pn[6];
+ } ccmp;
+ struct {
+ u8 pn[6];
+ } aes_cmac;
+ };
+};
+
+/**
+ * ieee80211_get_key_tx_seq - get key TX sequence counter
+ *
+ * @keyconf: the parameter passed with the set key
+ * @seq: buffer to receive the sequence data
+ *
+ * This function allows a driver to retrieve the current TX IV/PN
+ * for the given key. It must not be called if IV generation is
+ * offloaded to the device.
+ *
+ * Note that this function may only be called when no TX processing
+ * can be done concurrently, for example when queues are stopped
+ * and the stop has been synchronized.
+ */
+void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf,
+ struct ieee80211_key_seq *seq);
+
+/**
+ * ieee80211_get_key_rx_seq - get key RX sequence counter
+ *
+ * @keyconf: the parameter passed with the set key
+ * @tid: The TID, or -1 for the management frame value (CCMP only);
+ * the value on TID 0 is also used for non-QoS frames. For
+ * CMAC, only TID 0 is valid.
+ * @seq: buffer to receive the sequence data
+ *
+ * This function allows a driver to retrieve the current RX IV/PNs
+ * for the given key. It must not be called if IV checking is done
+ * by the device and not by mac80211.
+ *
+ * Note that this function may only be called when no RX processing
+ * can be done concurrently.
+ */
+void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
+ int tid, struct ieee80211_key_seq *seq);
+
+/**
+ * ieee80211_gtk_rekey_notify - notify userspace supplicant of rekeying
+ * @vif: virtual interface the rekeying was done on
+ * @bssid: The BSSID of the AP, for checking association
+ * @replay_ctr: the new replay counter after GTK rekeying
+ * @gfp: allocation flags
+ */
+void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid,
+ const u8 *replay_ctr, gfp_t gfp);
+
+/**
+ * ieee80211_wake_queue - wake specific queue
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ * @queue: queue number (counted from zero).
+ *
+ * Drivers should use this function instead of netif_wake_queue.
+ */
+void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue);
+
+/**
+ * ieee80211_stop_queue - stop specific queue
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ * @queue: queue number (counted from zero).
+ *
+ * Drivers should use this function instead of netif_stop_queue.
+ */
+void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue);
+
+/**
+ * ieee80211_queue_stopped - test status of the queue
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ * @queue: queue number (counted from zero).
+ *
+ * Drivers should use this function instead of netif_stop_queue.
+ */
+
+int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue);
+
+/**
+ * ieee80211_stop_queues - stop all queues
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ *
+ * Drivers should use this function instead of netif_stop_queue.
+ */
+void ieee80211_stop_queues(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_wake_queues - wake all queues
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ *
+ * Drivers should use this function instead of netif_wake_queue.
+ */
+void ieee80211_wake_queues(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_scan_completed - completed hardware scan
+ *
+ * When hardware scan offload is used (i.e. the hw_scan() callback is
+ * assigned) this function needs to be called by the driver to notify
+ * mac80211 that the scan finished. This function can be called from
+ * any context, including hardirq context.
+ *
+ * @hw: the hardware that finished the scan
+ * @aborted: set to true if scan was aborted
+ */
+void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted);
+
+/**
+ * ieee80211_sched_scan_results - got results from scheduled scan
+ *
+ * When a scheduled scan is running, this function needs to be called by the
+ * driver whenever there are new scan results available.
+ *
+ * @hw: the hardware that is performing scheduled scans
+ */
+void ieee80211_sched_scan_results(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_sched_scan_stopped - inform that the scheduled scan has stopped
+ *
+ * When a scheduled scan is running, this function can be called by
+ * the driver if it needs to stop the scan to perform another task.
+ * Usual scenarios are drivers that cannot continue the scheduled scan
+ * while associating, for instance.
+ *
+ * @hw: the hardware that is performing scheduled scans
+ */
+void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_iterate_active_interfaces - iterate active interfaces
+ *
+ * This function iterates over the interfaces associated with a given
+ * hardware that are currently active and calls the callback for them.
+ * This function allows the iterator function to sleep, when the iterator
+ * function is atomic @ieee80211_iterate_active_interfaces_atomic can
+ * be used.
+ * Does not iterate over a new interface during add_interface()
+ *
+ * @hw: the hardware struct of which the interfaces should be iterated over
+ * @iterator: the iterator function to call
+ * @data: first argument of the iterator function
+ */
+void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw,
+ void (*iterator)(void *data, u8 *mac,
+ struct ieee80211_vif *vif),
+ void *data);
+
+/**
+ * ieee80211_iterate_active_interfaces_atomic - iterate active interfaces
+ *
+ * This function iterates over the interfaces associated with a given
+ * hardware that are currently active and calls the callback for them.
+ * This function requires the iterator callback function to be atomic,
+ * if that is not desired, use @ieee80211_iterate_active_interfaces instead.
+ * Does not iterate over a new interface during add_interface()
+ *
+ * @hw: the hardware struct of which the interfaces should be iterated over
+ * @iterator: the iterator function to call, cannot sleep
+ * @data: first argument of the iterator function
+ */
+void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw,
+ void (*iterator)(void *data,
+ u8 *mac,
+ struct ieee80211_vif *vif),
+ void *data);
+
+/**
+ * ieee80211_queue_work - add work onto the mac80211 workqueue
+ *
+ * Drivers and mac80211 use this to add work onto the mac80211 workqueue.
+ * This helper ensures drivers are not queueing work when they should not be.
+ *
+ * @hw: the hardware struct for the interface we are adding work for
+ * @work: the work we want to add onto the mac80211 workqueue
+ */
+void ieee80211_queue_work(struct ieee80211_hw *hw, struct work_struct *work);
+
+/**
+ * ieee80211_queue_delayed_work - add work onto the mac80211 workqueue
+ *
+ * Drivers and mac80211 use this to queue delayed work onto the mac80211
+ * workqueue.
+ *
+ * @hw: the hardware struct for the interface we are adding work for
+ * @dwork: delayable work to queue onto the mac80211 workqueue
+ * @delay: number of jiffies to wait before queueing
+ */
+void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
+ struct delayed_work *dwork,
+ unsigned long delay);
+
+/**
+ * ieee80211_start_tx_ba_session - Start a tx Block Ack session.
+ * @sta: the station for which to start a BA session
+ * @tid: the TID to BA on.
+ * @timeout: session timeout value (in TUs)
+ *
+ * Return: success if addBA request was sent, failure otherwise
+ *
+ * Although mac80211/low level driver/user space application can estimate
+ * the need to start aggregation on a certain RA/TID, the session level
+ * will be managed by the mac80211.
+ */
+int ieee80211_start_tx_ba_session(struct ieee80211_sta *sta, u16 tid,
+ u16 timeout);
+
+/**
+ * ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate.
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback
+ * @ra: receiver address of the BA session recipient.
+ * @tid: the TID to BA on.
+ *
+ * This function must be called by low level driver once it has
+ * finished with preparations for the BA session. It can be called
+ * from any context.
+ */
+void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, const u8 *ra,
+ u16 tid);
+
+/**
+ * ieee80211_stop_tx_ba_session - Stop a Block Ack session.
+ * @sta: the station whose BA session to stop
+ * @tid: the TID to stop BA.
+ *
+ * Return: negative error if the TID is invalid, or no aggregation active
+ *
+ * Although mac80211/low level driver/user space application can estimate
+ * the need to stop aggregation on a certain RA/TID, the session level
+ * will be managed by the mac80211.
+ */
+int ieee80211_stop_tx_ba_session(struct ieee80211_sta *sta, u16 tid);
+
+/**
+ * ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate.
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback
+ * @ra: receiver address of the BA session recipient.
+ * @tid: the desired TID to BA on.
+ *
+ * This function must be called by low level driver once it has
+ * finished with preparations for the BA session tear down. It
+ * can be called from any context.
+ */
+void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, const u8 *ra,
+ u16 tid);
+
+/**
+ * ieee80211_find_sta - find a station
+ *
+ * @vif: virtual interface to look for station on
+ * @addr: station's address
+ *
+ * This function must be called under RCU lock and the
+ * resulting pointer is only valid under RCU lock as well.
+ */
+struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
+ const u8 *addr);
+
+/**
+ * ieee80211_find_sta_by_ifaddr - find a station on hardware
+ *
+ * @hw: pointer as obtained from ieee80211_alloc_hw()
+ * @addr: remote station's address
+ * @localaddr: local address (vif->sdata->vif.addr). Use NULL for 'any'.
+ *
+ * This function must be called under RCU lock and the
+ * resulting pointer is only valid under RCU lock as well.
+ *
+ * NOTE: You may pass NULL for localaddr, but then you will just get
+ * the first STA that matches the remote address 'addr'.
+ * We can have multiple STA associated with multiple
+ * logical stations (e.g. consider a station connecting to another
+ * BSSID on the same AP hardware without disconnecting first).
+ * In this case, the result of this method with localaddr NULL
+ * is not reliable.
+ *
+ * DO NOT USE THIS FUNCTION with localaddr NULL if at all possible.
+ */
+struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw,
+ const u8 *addr,
+ const u8 *localaddr);
+
+/**
+ * ieee80211_sta_block_awake - block station from waking up
+ * @hw: the hardware
+ * @pubsta: the station
+ * @block: whether to block or unblock
+ *
+ * Some devices require that all frames that are on the queues
+ * for a specific station that went to sleep are flushed before
+ * a poll response or frames after the station woke up can be
+ * delivered to that it. Note that such frames must be rejected
+ * by the driver as filtered, with the appropriate status flag.
+ *
+ * This function allows implementing this mode in a race-free
+ * manner.
+ *
+ * To do this, a driver must keep track of the number of frames
+ * still enqueued for a specific station. If this number is not
+ * zero when the station goes to sleep, the driver must call
+ * this function to force mac80211 to consider the station to
+ * be asleep regardless of the station's actual state. Once the
+ * number of outstanding frames reaches zero, the driver must
+ * call this function again to unblock the station. That will
+ * cause mac80211 to be able to send ps-poll responses, and if
+ * the station queried in the meantime then frames will also
+ * be sent out as a result of this. Additionally, the driver
+ * will be notified that the station woke up some time after
+ * it is unblocked, regardless of whether the station actually
+ * woke up while blocked or not.
+ */
+void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
+ struct ieee80211_sta *pubsta, bool block);
+
+/**
+ * ieee80211_sta_eosp - notify mac80211 about end of SP
+ * @pubsta: the station
+ *
+ * When a device transmits frames in a way that it can't tell
+ * mac80211 in the TX status about the EOSP, it must clear the
+ * %IEEE80211_TX_STATUS_EOSP bit and call this function instead.
+ * This applies for PS-Poll as well as uAPSD.
+ *
+ * Note that there is no non-_irqsafe version right now as
+ * it wasn't needed, but just like _tx_status() and _rx()
+ * must not be mixed in irqsafe/non-irqsafe versions, this
+ * function must not be mixed with those either. Use the
+ * all irqsafe, or all non-irqsafe, don't mix! If you need
+ * the non-irqsafe version of this, you need to add it.
+ */
+void ieee80211_sta_eosp_irqsafe(struct ieee80211_sta *pubsta);
+
+/**
+ * ieee80211_iter_keys - iterate keys programmed into the device
+ * @hw: pointer obtained from ieee80211_alloc_hw()
+ * @vif: virtual interface to iterate, may be %NULL for all
+ * @iter: iterator function that will be called for each key
+ * @iter_data: custom data to pass to the iterator function
+ *
+ * This function can be used to iterate all the keys known to
+ * mac80211, even those that weren't previously programmed into
+ * the device. This is intended for use in WoWLAN if the device
+ * needs reprogramming of the keys during suspend. Note that due
+ * to locking reasons, it is also only safe to call this at few
+ * spots since it must hold the RTNL and be able to sleep.
+ *
+ * The order in which the keys are iterated matches the order
+ * in which they were originally installed and handed to the
+ * set_key callback.
+ */
+void ieee80211_iter_keys(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ void (*iter)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key,
+ void *data),
+ void *iter_data);
+
+/**
+ * ieee80211_ap_probereq_get - retrieve a Probe Request template
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * Creates a Probe Request template which can, for example, be uploaded to
+ * hardware. The template is filled with bssid, ssid and supported rate
+ * information. This function must only be called from within the
+ * .bss_info_changed callback function and only in managed mode. The function
+ * is only useful when the interface is associated, otherwise it will return
+ * NULL.
+ */
+struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+
+/**
+ * ieee80211_beacon_loss - inform hardware does not receive beacons
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * When beacon filtering is enabled with %IEEE80211_VIF_BEACON_FILTER and
+ * %IEEE80211_CONF_PS is set, the driver needs to inform whenever the
+ * hardware is not receiving beacons with this function.
+ */
+void ieee80211_beacon_loss(struct ieee80211_vif *vif);
+
+/**
+ * ieee80211_connection_loss - inform hardware has lost connection to the AP
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * When beacon filtering is enabled with %IEEE80211_VIF_BEACON_FILTER, and
+ * %IEEE80211_CONF_PS and %IEEE80211_HW_CONNECTION_MONITOR are set, the driver
+ * needs to inform if the connection to the AP has been lost.
+ *
+ * This function will cause immediate change to disassociated state,
+ * without connection recovery attempts.
+ */
+void ieee80211_connection_loss(struct ieee80211_vif *vif);
+
+/**
+ * ieee80211_resume_disconnect - disconnect from AP after resume
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * Instructs mac80211 to disconnect from the AP after resume.
+ * Drivers can use this after WoWLAN if they know that the
+ * connection cannot be kept up, for example because keys were
+ * used while the device was asleep but the replay counters or
+ * similar cannot be retrieved from the device during resume.
+ *
+ * Note that due to implementation issues, if the driver uses
+ * the reconfiguration functionality during resume the interface
+ * will still be added as associated first during resume and then
+ * disconnect normally later.
+ *
+ * This function can only be called from the resume callback and
+ * the driver must not be holding any of its own locks while it
+ * calls this function, or at least not any locks it needs in the
+ * key configuration paths (if it supports HW crypto).
+ */
+void ieee80211_resume_disconnect(struct ieee80211_vif *vif);
+
+/**
+ * ieee80211_disable_dyn_ps - force mac80211 to temporarily disable dynamic psm
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * Some hardware require full power save to manage simultaneous BT traffic
+ * on the WLAN frequency. Full PSM is required periodically, whenever there are
+ * burst of BT traffic. The hardware gets information of BT traffic via
+ * hardware co-existence lines, and consequentially requests mac80211 to
+ * (temporarily) enter full psm.
+ * This function will only temporarily disable dynamic PS, not enable PSM if
+ * it was not already enabled.
+ * The driver must make sure to re-enable dynamic PS using
+ * ieee80211_enable_dyn_ps() if the driver has disabled it.
+ *
+ */
+void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif);
+
+/**
+ * ieee80211_enable_dyn_ps - restore dynamic psm after being disabled
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * This function restores dynamic PS after being temporarily disabled via
+ * ieee80211_disable_dyn_ps(). Each ieee80211_disable_dyn_ps() call must
+ * be coupled with an eventual call to this function.
+ *
+ */
+void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif);
+
+/**
+ * ieee80211_cqm_rssi_notify - inform a configured connection quality monitoring
+ * rssi threshold triggered
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @rssi_event: the RSSI trigger event type
+ * @gfp: context flags
+ *
+ * When the %IEEE80211_VIF_SUPPORTS_CQM_RSSI is set, and a connection quality
+ * monitoring is configured with an rssi threshold, the driver will inform
+ * whenever the rssi level reaches the threshold.
+ */
+void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
+ enum nl80211_cqm_rssi_threshold_event rssi_event,
+ gfp_t gfp);
+
+/**
+ * ieee80211_get_operstate - get the operstate of the vif
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * The driver might need to know the operstate of the net_device
+ * (specifically, whether the link is IF_OPER_UP after resume)
+ */
+unsigned char ieee80211_get_operstate(struct ieee80211_vif *vif);
+
+/**
+ * ieee80211_chswitch_done - Complete channel switch process
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @success: make the channel switch successful or not
+ *
+ * Complete the channel switch post-process: set the new operational channel
+ * and wake up the suspended queues.
+ */
+void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success);
+
+/**
+ * ieee80211_request_smps - request SM PS transition
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @smps_mode: new SM PS mode
+ *
+ * This allows the driver to request an SM PS transition in managed
+ * mode. This is useful when the driver has more information than
+ * the stack about possible interference, for example by bluetooth.
+ */
+void ieee80211_request_smps(struct ieee80211_vif *vif,
+ enum ieee80211_smps_mode smps_mode);
+
+/**
+ * ieee80211_key_removed - disable hw acceleration for key
+ * @key_conf: The key hw acceleration should be disabled for
+ *
+ * This allows drivers to indicate that the given key has been
+ * removed from hardware acceleration, due to a new key that
+ * was added. Don't use this if the key can continue to be used
+ * for TX, if the key restriction is on RX only it is permitted
+ * to keep the key for TX only and not call this function.
+ *
+ * Due to locking constraints, it may only be called during
+ * @set_key. This function must be allowed to sleep, and the
+ * key it tries to disable may still be used until it returns.
+ */
+void ieee80211_key_removed(struct ieee80211_key_conf *key_conf);
+
+/**
+ * ieee80211_ready_on_channel - notification of remain-on-channel start
+ * @hw: pointer as obtained from ieee80211_alloc_hw()
+ */
+void ieee80211_ready_on_channel(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_remain_on_channel_expired - remain_on_channel duration expired
+ * @hw: pointer as obtained from ieee80211_alloc_hw()
+ */
+void ieee80211_remain_on_channel_expired(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_stop_rx_ba_session - callback to stop existing BA sessions
+ *
+ * in order not to harm the system performance and user experience, the device
+ * may request not to allow any rx ba session and tear down existing rx ba
+ * sessions based on system constraints such as periodic BT activity that needs
+ * to limit wlan activity (eg.sco or a2dp)."
+ * in such cases, the intention is to limit the duration of the rx ppdu and
+ * therefore prevent the peer device to use a-mpdu aggregation.
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @ba_rx_bitmap: Bit map of open rx ba per tid
+ * @addr: & to bssid mac address
+ */
+void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap,
+ const u8 *addr);
+
+/**
+ * ieee80211_send_bar - send a BlockAckReq frame
+ *
+ * can be used to flush pending frames from the peer's aggregation reorder
+ * buffer.
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @ra: the peer's destination address
+ * @tid: the TID of the aggregation session
+ * @ssn: the new starting sequence number for the receiver
+ */
+void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);
+
+/* Rate control API */
+
+/**
+ * enum rate_control_changed - flags to indicate which parameter changed
+ *
+ * @IEEE80211_RC_HT_CHANGED: The HT parameters of the operating channel have
+ * changed, rate control algorithm can update its internal state if needed.
+ * @IEEE80211_RC_SMPS_CHANGED: The SMPS state of the station changed, the rate
+ * control algorithm needs to adjust accordingly.
+ */
+enum rate_control_changed {
+ IEEE80211_RC_HT_CHANGED = BIT(0),
+ IEEE80211_RC_SMPS_CHANGED = BIT(1),
+};
+
+/**
+ * struct ieee80211_tx_rate_control - rate control information for/from RC algo
+ *
+ * @hw: The hardware the algorithm is invoked for.
+ * @sband: The band this frame is being transmitted on.
+ * @bss_conf: the current BSS configuration
+ * @skb: the skb that will be transmitted, the control information in it needs
+ * to be filled in
+ * @reported_rate: The rate control algorithm can fill this in to indicate
+ * which rate should be reported to userspace as the current rate and
+ * used for rate calculations in the mesh network.
+ * @rts: whether RTS will be used for this frame because it is longer than the
+ * RTS threshold
+ * @short_preamble: whether mac80211 will request short-preamble transmission
+ * if the selected rate supports it
+ * @max_rate_idx: user-requested maximum (legacy) rate
+ * (deprecated; this will be removed once drivers get updated to use
+ * rate_idx_mask)
+ * @rate_idx_mask: user-requested (legacy) rate mask
+ * @rate_idx_mcs_mask: user-requested MCS rate mask
+ * @bss: whether this frame is sent out in AP or IBSS mode
+ */
+struct ieee80211_tx_rate_control {
+ struct ieee80211_hw *hw;
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_bss_conf *bss_conf;
+ struct sk_buff *skb;
+ struct ieee80211_tx_rate reported_rate;
+ bool rts, short_preamble;
+ u8 max_rate_idx;
+ u32 rate_idx_mask;
+ u8 rate_idx_mcs_mask[IEEE80211_HT_MCS_MASK_LEN];
+ bool bss;
+};
+
+struct rate_control_ops {
+ struct module *module;
+ const char *name;
+ void *(*alloc)(struct ieee80211_hw *hw, struct dentry *debugfsdir);
+ void (*free)(void *priv);
+
+ void *(*alloc_sta)(void *priv, struct ieee80211_sta *sta, gfp_t gfp);
+ void (*rate_init)(void *priv, struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta, void *priv_sta);
+ void (*rate_update)(void *priv, struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta,
+ void *priv_sta, u32 changed,
+ enum nl80211_channel_type oper_chan_type);
+ void (*free_sta)(void *priv, struct ieee80211_sta *sta,
+ void *priv_sta);
+
+ void (*tx_status)(void *priv, struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta, void *priv_sta,
+ struct sk_buff *skb);
+ void (*get_rate)(void *priv, struct ieee80211_sta *sta, void *priv_sta,
+ struct ieee80211_tx_rate_control *txrc);
+
+ void (*add_sta_debugfs)(void *priv, void *priv_sta,
+ struct dentry *dir);
+ void (*remove_sta_debugfs)(void *priv, void *priv_sta);
+};
+
+static inline int rate_supported(struct ieee80211_sta *sta,
+ enum ieee80211_band band,
+ int index)
+{
+ return (sta == NULL || sta->supp_rates[band] & BIT(index));
+}
+
+/**
+ * rate_control_send_low - helper for drivers for management/no-ack frames
+ *
+ * Rate control algorithms that agree to use the lowest rate to
+ * send management frames and NO_ACK data with the respective hw
+ * retries should use this in the beginning of their mac80211 get_rate
+ * callback. If true is returned the rate control can simply return.
+ * If false is returned we guarantee that sta and sta and priv_sta is
+ * not null.
+ *
+ * Rate control algorithms wishing to do more intelligent selection of
+ * rate for multicast/broadcast frames may choose to not use this.
+ *
+ * @sta: &struct ieee80211_sta pointer to the target destination. Note
+ * that this may be null.
+ * @priv_sta: private rate control structure. This may be null.
+ * @txrc: rate control information we sholud populate for mac80211.
+ */
+bool rate_control_send_low(struct ieee80211_sta *sta,
+ void *priv_sta,
+ struct ieee80211_tx_rate_control *txrc);
+
+
+static inline s8
+rate_lowest_index(struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta)
+{
+ int i;
+
+ for (i = 0; i < sband->n_bitrates; i++)
+ if (rate_supported(sta, sband->band, i))
+ return i;
+
+ /* warn when we cannot find a rate. */
+ WARN_ON_ONCE(1);
+
+ /* and return 0 (the lowest index) */
+ return 0;
+}
+
+static inline
+bool rate_usable_index_exists(struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta)
+{
+ unsigned int i;
+
+ for (i = 0; i < sband->n_bitrates; i++)
+ if (rate_supported(sta, sband->band, i))
+ return true;
+ return false;
+}
+
+int ieee80211_rate_control_register(struct rate_control_ops *ops);
+void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
+
+static inline bool
+conf_is_ht20(struct ieee80211_conf *conf)
+{
+ return conf->channel_type == NL80211_CHAN_HT20;
+}
+
+static inline bool
+conf_is_ht40_minus(struct ieee80211_conf *conf)
+{
+ return conf->channel_type == NL80211_CHAN_HT40MINUS;
+}
+
+static inline bool
+conf_is_ht40_plus(struct ieee80211_conf *conf)
+{
+ return conf->channel_type == NL80211_CHAN_HT40PLUS;
+}
+
+static inline bool
+conf_is_ht40(struct ieee80211_conf *conf)
+{
+ return conf_is_ht40_minus(conf) || conf_is_ht40_plus(conf);
+}
+
+static inline bool
+conf_is_ht(struct ieee80211_conf *conf)
+{
+ return conf->channel_type != NL80211_CHAN_NO_HT;
+}
+
+static inline enum nl80211_iftype
+ieee80211_iftype_p2p(enum nl80211_iftype type, bool p2p)
+{
+ if (p2p) {
+ switch (type) {
+ case NL80211_IFTYPE_STATION:
+ return NL80211_IFTYPE_P2P_CLIENT;
+ case NL80211_IFTYPE_AP:
+ return NL80211_IFTYPE_P2P_GO;
+ default:
+ break;
+ }
+ }
+ return type;
+}
+
+static inline enum nl80211_iftype
+ieee80211_vif_type_p2p(struct ieee80211_vif *vif)
+{
+ return ieee80211_iftype_p2p(vif->type, vif->p2p);
+}
+
+void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif,
+ int rssi_min_thold,
+ int rssi_max_thold);
+
+void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif);
+
+int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb);
+
+int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif,
+ struct sk_buff *skb);
+#endif /* MAC80211_H */
diff --git a/include/net/mip6.h b/include/net/mip6.h
new file mode 100644
index 00000000..26ba99b5
--- /dev/null
+++ b/include/net/mip6.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C)2003-2006 Helsinki University of Technology
+ * Copyright (C)2003-2006 USAGI/WIDE Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * Authors:
+ * Noriaki TAKAMIYA @USAGI
+ * Masahide NAKAMURA @USAGI
+ * YOSHIFUJI Hideaki @USAGI
+ */
+#ifndef _NET_MIP6_H
+#define _NET_MIP6_H
+
+#include <linux/skbuff.h>
+#include <net/sock.h>
+
+/*
+ * Mobility Header
+ */
+struct ip6_mh {
+ __u8 ip6mh_proto;
+ __u8 ip6mh_hdrlen;
+ __u8 ip6mh_type;
+ __u8 ip6mh_reserved;
+ __u16 ip6mh_cksum;
+ /* Followed by type specific messages */
+ __u8 data[0];
+} __packed;
+
+#define IP6_MH_TYPE_BRR 0 /* Binding Refresh Request */
+#define IP6_MH_TYPE_HOTI 1 /* HOTI Message */
+#define IP6_MH_TYPE_COTI 2 /* COTI Message */
+#define IP6_MH_TYPE_HOT 3 /* HOT Message */
+#define IP6_MH_TYPE_COT 4 /* COT Message */
+#define IP6_MH_TYPE_BU 5 /* Binding Update */
+#define IP6_MH_TYPE_BACK 6 /* Binding ACK */
+#define IP6_MH_TYPE_BERROR 7 /* Binding Error */
+#define IP6_MH_TYPE_MAX IP6_MH_TYPE_BERROR
+
+#endif
diff --git a/include/net/mld.h b/include/net/mld.h
new file mode 100644
index 00000000..467143cd
--- /dev/null
+++ b/include/net/mld.h
@@ -0,0 +1,75 @@
+#ifndef LINUX_MLD_H
+#define LINUX_MLD_H
+
+#include <linux/in6.h>
+#include <linux/icmpv6.h>
+
+/* MLDv1 Query/Report/Done */
+struct mld_msg {
+ struct icmp6hdr mld_hdr;
+ struct in6_addr mld_mca;
+};
+
+#define mld_type mld_hdr.icmp6_type
+#define mld_code mld_hdr.icmp6_code
+#define mld_cksum mld_hdr.icmp6_cksum
+#define mld_maxdelay mld_hdr.icmp6_maxdelay
+#define mld_reserved mld_hdr.icmp6_dataun.un_data16[1]
+
+/* Multicast Listener Discovery version 2 headers */
+/* MLDv2 Report */
+struct mld2_grec {
+ __u8 grec_type;
+ __u8 grec_auxwords;
+ __be16 grec_nsrcs;
+ struct in6_addr grec_mca;
+ struct in6_addr grec_src[0];
+};
+
+struct mld2_report {
+ struct icmp6hdr mld2r_hdr;
+ struct mld2_grec mld2r_grec[0];
+};
+
+#define mld2r_type mld2r_hdr.icmp6_type
+#define mld2r_resv1 mld2r_hdr.icmp6_code
+#define mld2r_cksum mld2r_hdr.icmp6_cksum
+#define mld2r_resv2 mld2r_hdr.icmp6_dataun.un_data16[0]
+#define mld2r_ngrec mld2r_hdr.icmp6_dataun.un_data16[1]
+
+/* MLDv2 Query */
+struct mld2_query {
+ struct icmp6hdr mld2q_hdr;
+ struct in6_addr mld2q_mca;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 mld2q_qrv:3,
+ mld2q_suppress:1,
+ mld2q_resv2:4;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __u8 mld2q_resv2:4,
+ mld2q_suppress:1,
+ mld2q_qrv:3;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+ __u8 mld2q_qqic;
+ __be16 mld2q_nsrcs;
+ struct in6_addr mld2q_srcs[0];
+};
+
+#define mld2q_type mld2q_hdr.icmp6_type
+#define mld2q_code mld2q_hdr.icmp6_code
+#define mld2q_cksum mld2q_hdr.icmp6_cksum
+#define mld2q_mrc mld2q_hdr.icmp6_maxdelay
+#define mld2q_resv1 mld2q_hdr.icmp6_dataun.un_data16[1]
+
+/* Max Response Code */
+#define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value))
+#define MLDV2_EXP(thresh, nbmant, nbexp, value) \
+ ((value) < (thresh) ? (value) : \
+ ((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \
+ (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp))))
+
+#define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value)
+
+#endif
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
new file mode 100644
index 00000000..6f9c25a7
--- /dev/null
+++ b/include/net/ndisc.h
@@ -0,0 +1,183 @@
+#ifndef _NDISC_H
+#define _NDISC_H
+
+/*
+ * ICMP codes for neighbour discovery messages
+ */
+
+#define NDISC_ROUTER_SOLICITATION 133
+#define NDISC_ROUTER_ADVERTISEMENT 134
+#define NDISC_NEIGHBOUR_SOLICITATION 135
+#define NDISC_NEIGHBOUR_ADVERTISEMENT 136
+#define NDISC_REDIRECT 137
+
+/*
+ * Router type: cross-layer information from link-layer to
+ * IPv6 layer reported by certain link types (e.g., RFC4214).
+ */
+#define NDISC_NODETYPE_UNSPEC 0 /* unspecified (default) */
+#define NDISC_NODETYPE_HOST 1 /* host or unauthorized router */
+#define NDISC_NODETYPE_NODEFAULT 2 /* non-default router */
+#define NDISC_NODETYPE_DEFAULT 3 /* default router */
+
+/*
+ * ndisc options
+ */
+
+enum {
+ __ND_OPT_PREFIX_INFO_END = 0,
+ ND_OPT_SOURCE_LL_ADDR = 1, /* RFC2461 */
+ ND_OPT_TARGET_LL_ADDR = 2, /* RFC2461 */
+ ND_OPT_PREFIX_INFO = 3, /* RFC2461 */
+ ND_OPT_REDIRECT_HDR = 4, /* RFC2461 */
+ ND_OPT_MTU = 5, /* RFC2461 */
+ __ND_OPT_ARRAY_MAX,
+ ND_OPT_ROUTE_INFO = 24, /* RFC4191 */
+ ND_OPT_RDNSS = 25, /* RFC5006 */
+ __ND_OPT_MAX
+};
+
+#define MAX_RTR_SOLICITATION_DELAY HZ
+
+#define ND_REACHABLE_TIME (30*HZ)
+#define ND_RETRANS_TIMER HZ
+
+#include <linux/compiler.h>
+#include <linux/icmpv6.h>
+#include <linux/in6.h>
+#include <linux/types.h>
+
+#include <net/neighbour.h>
+
+struct ctl_table;
+struct inet6_dev;
+struct net_device;
+struct net_proto_family;
+struct sk_buff;
+
+extern struct neigh_table nd_tbl;
+
+struct nd_msg {
+ struct icmp6hdr icmph;
+ struct in6_addr target;
+ __u8 opt[0];
+};
+
+struct rs_msg {
+ struct icmp6hdr icmph;
+ __u8 opt[0];
+};
+
+struct ra_msg {
+ struct icmp6hdr icmph;
+ __be32 reachable_time;
+ __be32 retrans_timer;
+};
+
+struct nd_opt_hdr {
+ __u8 nd_opt_type;
+ __u8 nd_opt_len;
+} __packed;
+
+static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, __u32 *hash_rnd)
+{
+ const u32 *p32 = pkey;
+
+ return (((p32[0] ^ dev->ifindex) * hash_rnd[0]) +
+ (p32[1] * hash_rnd[1]) +
+ (p32[2] * hash_rnd[2]) +
+ (p32[3] * hash_rnd[3]));
+}
+
+static inline struct neighbour *__ipv6_neigh_lookup(struct neigh_table *tbl, struct net_device *dev, const void *pkey)
+{
+ struct neigh_hash_table *nht;
+ const u32 *p32 = pkey;
+ struct neighbour *n;
+ u32 hash_val;
+
+ rcu_read_lock_bh();
+ nht = rcu_dereference_bh(tbl->nht);
+ hash_val = ndisc_hashfn(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
+ for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
+ n != NULL;
+ n = rcu_dereference_bh(n->next)) {
+ u32 *n32 = (u32 *) n->primary_key;
+ if (n->dev == dev &&
+ ((n32[0] ^ p32[0]) | (n32[1] ^ p32[1]) |
+ (n32[2] ^ p32[2]) | (n32[3] ^ p32[3])) == 0) {
+ if (!atomic_inc_not_zero(&n->refcnt))
+ n = NULL;
+ break;
+ }
+ }
+ rcu_read_unlock_bh();
+
+ return n;
+}
+
+extern int ndisc_init(void);
+
+extern void ndisc_cleanup(void);
+
+extern int ndisc_rcv(struct sk_buff *skb);
+
+extern void ndisc_send_ns(struct net_device *dev,
+ struct neighbour *neigh,
+ const struct in6_addr *solicit,
+ const struct in6_addr *daddr,
+ const struct in6_addr *saddr);
+
+extern void ndisc_send_rs(struct net_device *dev,
+ const struct in6_addr *saddr,
+ const struct in6_addr *daddr);
+
+extern void ndisc_send_redirect(struct sk_buff *skb,
+ const struct in6_addr *target);
+
+extern int ndisc_mc_map(const struct in6_addr *addr, char *buf,
+ struct net_device *dev, int dir);
+
+extern struct sk_buff *ndisc_build_skb(struct net_device *dev,
+ const struct in6_addr *daddr,
+ const struct in6_addr *saddr,
+ struct icmp6hdr *icmp6h,
+ const struct in6_addr *target,
+ int llinfo);
+
+extern void ndisc_send_skb(struct sk_buff *skb,
+ struct net_device *dev,
+ struct neighbour *neigh,
+ const struct in6_addr *daddr,
+ const struct in6_addr *saddr,
+ struct icmp6hdr *icmp6h);
+
+
+
+/*
+ * IGMP
+ */
+extern int igmp6_init(void);
+
+extern void igmp6_cleanup(void);
+
+extern int igmp6_event_query(struct sk_buff *skb);
+
+extern int igmp6_event_report(struct sk_buff *skb);
+
+
+#ifdef CONFIG_SYSCTL
+extern int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl,
+ int write,
+ void __user *buffer,
+ size_t *lenp,
+ loff_t *ppos);
+int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen);
+#endif
+
+extern void inet6_ifinfo_notify(int event,
+ struct inet6_dev *idev);
+
+#endif
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
new file mode 100644
index 00000000..34c996f4
--- /dev/null
+++ b/include/net/neighbour.h
@@ -0,0 +1,407 @@
+#ifndef _NET_NEIGHBOUR_H
+#define _NET_NEIGHBOUR_H
+
+#include <linux/neighbour.h>
+
+/*
+ * Generic neighbour manipulation
+ *
+ * Authors:
+ * Pedro Roque <roque@di.fc.ul.pt>
+ * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
+ *
+ * Changes:
+ *
+ * Harald Welte: <laforge@gnumonks.org>
+ * - Add neighbour cache statistics like rtstat
+ */
+
+#include <linux/atomic.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rcupdate.h>
+#include <linux/seq_file.h>
+
+#include <linux/err.h>
+#include <linux/sysctl.h>
+#include <linux/workqueue.h>
+#include <net/rtnetlink.h>
+
+/*
+ * NUD stands for "neighbor unreachability detection"
+ */
+
+#define NUD_IN_TIMER (NUD_INCOMPLETE|NUD_REACHABLE|NUD_DELAY|NUD_PROBE)
+#define NUD_VALID (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE|NUD_PROBE|NUD_STALE|NUD_DELAY)
+#define NUD_CONNECTED (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE)
+
+struct neighbour;
+
+struct neigh_parms {
+#ifdef CONFIG_NET_NS
+ struct net *net;
+#endif
+ struct net_device *dev;
+ struct neigh_parms *next;
+ int (*neigh_setup)(struct neighbour *);
+ void (*neigh_cleanup)(struct neighbour *);
+ struct neigh_table *tbl;
+
+ void *sysctl_table;
+
+ int dead;
+ atomic_t refcnt;
+ struct rcu_head rcu_head;
+
+ int base_reachable_time;
+ int retrans_time;
+ int gc_staletime;
+ int reachable_time;
+ int delay_probe_time;
+
+ int queue_len_bytes;
+ int ucast_probes;
+ int app_probes;
+ int mcast_probes;
+ int anycast_delay;
+ int proxy_delay;
+ int proxy_qlen;
+ int locktime;
+};
+
+struct neigh_statistics {
+ unsigned long allocs; /* number of allocated neighs */
+ unsigned long destroys; /* number of destroyed neighs */
+ unsigned long hash_grows; /* number of hash resizes */
+
+ unsigned long res_failed; /* number of failed resolutions */
+
+ unsigned long lookups; /* number of lookups */
+ unsigned long hits; /* number of hits (among lookups) */
+
+ unsigned long rcv_probes_mcast; /* number of received mcast ipv6 */
+ unsigned long rcv_probes_ucast; /* number of received ucast ipv6 */
+
+ unsigned long periodic_gc_runs; /* number of periodic GC runs */
+ unsigned long forced_gc_runs; /* number of forced GC runs */
+
+ unsigned long unres_discards; /* number of unresolved drops */
+};
+
+#define NEIGH_CACHE_STAT_INC(tbl, field) this_cpu_inc((tbl)->stats->field)
+
+struct neighbour {
+ struct neighbour __rcu *next;
+ struct neigh_table *tbl;
+ struct neigh_parms *parms;
+ unsigned long confirmed;
+ unsigned long updated;
+ rwlock_t lock;
+ atomic_t refcnt;
+ struct sk_buff_head arp_queue;
+ unsigned int arp_queue_len_bytes;
+ struct timer_list timer;
+ unsigned long used;
+ atomic_t probes;
+ __u8 flags;
+ __u8 nud_state;
+ __u8 type;
+ __u8 dead;
+ seqlock_t ha_lock;
+ unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
+ struct hh_cache hh;
+ int (*output)(struct neighbour *, struct sk_buff *);
+ const struct neigh_ops *ops;
+ struct rcu_head rcu;
+ struct net_device *dev;
+ u8 primary_key[0];
+};
+
+struct neigh_ops {
+ int family;
+ void (*solicit)(struct neighbour *, struct sk_buff *);
+ void (*error_report)(struct neighbour *, struct sk_buff *);
+ int (*output)(struct neighbour *, struct sk_buff *);
+ int (*connected_output)(struct neighbour *, struct sk_buff *);
+};
+
+struct pneigh_entry {
+ struct pneigh_entry *next;
+#ifdef CONFIG_NET_NS
+ struct net *net;
+#endif
+ struct net_device *dev;
+ u8 flags;
+ u8 key[0];
+};
+
+/*
+ * neighbour table manipulation
+ */
+
+#define NEIGH_NUM_HASH_RND 4
+
+struct neigh_hash_table {
+ struct neighbour __rcu **hash_buckets;
+ unsigned int hash_shift;
+ __u32 hash_rnd[NEIGH_NUM_HASH_RND];
+ struct rcu_head rcu;
+};
+
+
+struct neigh_table {
+ struct neigh_table *next;
+ int family;
+ int entry_size;
+ int key_len;
+ __u32 (*hash)(const void *pkey,
+ const struct net_device *dev,
+ __u32 *hash_rnd);
+ int (*constructor)(struct neighbour *);
+ int (*pconstructor)(struct pneigh_entry *);
+ void (*pdestructor)(struct pneigh_entry *);
+ void (*proxy_redo)(struct sk_buff *skb);
+ char *id;
+ struct neigh_parms parms;
+ /* HACK. gc_* should follow parms without a gap! */
+ int gc_interval;
+ int gc_thresh1;
+ int gc_thresh2;
+ int gc_thresh3;
+ unsigned long last_flush;
+ struct delayed_work gc_work;
+ struct timer_list proxy_timer;
+ struct sk_buff_head proxy_queue;
+ atomic_t entries;
+ rwlock_t lock;
+ unsigned long last_rand;
+ struct neigh_statistics __percpu *stats;
+ struct neigh_hash_table __rcu *nht;
+ struct pneigh_entry **phash_buckets;
+};
+
+#define NEIGH_PRIV_ALIGN sizeof(long long)
+
+static inline void *neighbour_priv(const struct neighbour *n)
+{
+ return (char *)n + ALIGN(sizeof(*n) + n->tbl->key_len, NEIGH_PRIV_ALIGN);
+}
+
+/* flags for neigh_update() */
+#define NEIGH_UPDATE_F_OVERRIDE 0x00000001
+#define NEIGH_UPDATE_F_WEAK_OVERRIDE 0x00000002
+#define NEIGH_UPDATE_F_OVERRIDE_ISROUTER 0x00000004
+#define NEIGH_UPDATE_F_ISROUTER 0x40000000
+#define NEIGH_UPDATE_F_ADMIN 0x80000000
+
+extern void neigh_table_init(struct neigh_table *tbl);
+extern void neigh_table_init_no_netlink(struct neigh_table *tbl);
+extern int neigh_table_clear(struct neigh_table *tbl);
+extern struct neighbour * neigh_lookup(struct neigh_table *tbl,
+ const void *pkey,
+ struct net_device *dev);
+extern struct neighbour * neigh_lookup_nodev(struct neigh_table *tbl,
+ struct net *net,
+ const void *pkey);
+extern struct neighbour * neigh_create(struct neigh_table *tbl,
+ const void *pkey,
+ struct net_device *dev);
+extern void neigh_destroy(struct neighbour *neigh);
+extern int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb);
+extern int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
+ u32 flags);
+extern void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
+extern int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
+extern int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb);
+extern int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb);
+extern int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb);
+extern int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb);
+extern struct neighbour *neigh_event_ns(struct neigh_table *tbl,
+ u8 *lladdr, void *saddr,
+ struct net_device *dev);
+
+extern struct neigh_parms *neigh_parms_alloc(struct net_device *dev, struct neigh_table *tbl);
+extern void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms);
+
+static inline
+struct net *neigh_parms_net(const struct neigh_parms *parms)
+{
+ return read_pnet(&parms->net);
+}
+
+extern unsigned long neigh_rand_reach_time(unsigned long base);
+
+extern void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
+ struct sk_buff *skb);
+extern struct pneigh_entry *pneigh_lookup(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev, int creat);
+extern struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
+ struct net *net,
+ const void *key,
+ struct net_device *dev);
+extern int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev);
+
+static inline
+struct net *pneigh_net(const struct pneigh_entry *pneigh)
+{
+ return read_pnet(&pneigh->net);
+}
+
+extern void neigh_app_ns(struct neighbour *n);
+extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie);
+extern void __neigh_for_each_release(struct neigh_table *tbl, int (*cb)(struct neighbour *));
+extern void pneigh_for_each(struct neigh_table *tbl, void (*cb)(struct pneigh_entry *));
+
+struct neigh_seq_state {
+ struct seq_net_private p;
+ struct neigh_table *tbl;
+ struct neigh_hash_table *nht;
+ void *(*neigh_sub_iter)(struct neigh_seq_state *state,
+ struct neighbour *n, loff_t *pos);
+ unsigned int bucket;
+ unsigned int flags;
+#define NEIGH_SEQ_NEIGH_ONLY 0x00000001
+#define NEIGH_SEQ_IS_PNEIGH 0x00000002
+#define NEIGH_SEQ_SKIP_NOARP 0x00000004
+};
+extern void *neigh_seq_start(struct seq_file *, loff_t *, struct neigh_table *, unsigned int);
+extern void *neigh_seq_next(struct seq_file *, void *, loff_t *);
+extern void neigh_seq_stop(struct seq_file *, void *);
+
+extern int neigh_sysctl_register(struct net_device *dev,
+ struct neigh_parms *p,
+ char *p_name,
+ proc_handler *proc_handler);
+extern void neigh_sysctl_unregister(struct neigh_parms *p);
+
+static inline void __neigh_parms_put(struct neigh_parms *parms)
+{
+ atomic_dec(&parms->refcnt);
+}
+
+static inline struct neigh_parms *neigh_parms_clone(struct neigh_parms *parms)
+{
+ atomic_inc(&parms->refcnt);
+ return parms;
+}
+
+/*
+ * Neighbour references
+ */
+
+static inline void neigh_release(struct neighbour *neigh)
+{
+ if (atomic_dec_and_test(&neigh->refcnt))
+ neigh_destroy(neigh);
+}
+
+static inline struct neighbour * neigh_clone(struct neighbour *neigh)
+{
+ if (neigh)
+ atomic_inc(&neigh->refcnt);
+ return neigh;
+}
+
+#define neigh_hold(n) atomic_inc(&(n)->refcnt)
+
+static inline void neigh_confirm(struct neighbour *neigh)
+{
+ if (neigh)
+ neigh->confirmed = jiffies;
+}
+
+static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
+{
+ unsigned long now = jiffies;
+
+ if (neigh->used != now)
+ neigh->used = now;
+ if (!(neigh->nud_state&(NUD_CONNECTED|NUD_DELAY|NUD_PROBE)))
+ return __neigh_event_send(neigh, skb);
+ return 0;
+}
+
+#ifdef CONFIG_BRIDGE_NETFILTER
+static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb)
+{
+ unsigned seq, hh_alen;
+
+ do {
+ seq = read_seqbegin(&hh->hh_lock);
+ hh_alen = HH_DATA_ALIGN(ETH_HLEN);
+ memcpy(skb->data - hh_alen, hh->hh_data, ETH_ALEN + hh_alen - ETH_HLEN);
+ } while (read_seqretry(&hh->hh_lock, seq));
+ return 0;
+}
+#endif
+
+static inline int neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb)
+{
+ unsigned seq;
+ int hh_len;
+
+ do {
+ int hh_alen;
+
+ seq = read_seqbegin(&hh->hh_lock);
+ hh_len = hh->hh_len;
+ hh_alen = HH_DATA_ALIGN(hh_len);
+ memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
+ } while (read_seqretry(&hh->hh_lock, seq));
+
+ skb_push(skb, hh_len);
+ return dev_queue_xmit(skb);
+}
+
+static inline int neigh_output(struct neighbour *n, struct sk_buff *skb)
+{
+ struct hh_cache *hh = &n->hh;
+ if ((n->nud_state & NUD_CONNECTED) && hh->hh_len)
+ return neigh_hh_output(hh, skb);
+ else
+ return n->output(n, skb);
+}
+
+static inline struct neighbour *
+__neigh_lookup(struct neigh_table *tbl, const void *pkey, struct net_device *dev, int creat)
+{
+ struct neighbour *n = neigh_lookup(tbl, pkey, dev);
+
+ if (n || !creat)
+ return n;
+
+ n = neigh_create(tbl, pkey, dev);
+ return IS_ERR(n) ? NULL : n;
+}
+
+static inline struct neighbour *
+__neigh_lookup_errno(struct neigh_table *tbl, const void *pkey,
+ struct net_device *dev)
+{
+ struct neighbour *n = neigh_lookup(tbl, pkey, dev);
+
+ if (n)
+ return n;
+
+ return neigh_create(tbl, pkey, dev);
+}
+
+struct neighbour_cb {
+ unsigned long sched_next;
+ unsigned int flags;
+};
+
+#define LOCALLY_ENQUEUED 0x1
+
+#define NEIGH_CB(skb) ((struct neighbour_cb *)(skb)->cb)
+
+static inline void neigh_ha_snapshot(char *dst, const struct neighbour *n,
+ const struct net_device *dev)
+{
+ unsigned int seq;
+
+ do {
+ seq = read_seqbegin(&n->ha_lock);
+ memcpy(dst, n->ha, dev->addr_len);
+ } while (read_seqretry(&n->ha_lock, seq));
+}
+#endif
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
new file mode 100644
index 00000000..ee547c14
--- /dev/null
+++ b/include/net/net_namespace.h
@@ -0,0 +1,292 @@
+/*
+ * Operations on the network namespace
+ */
+#ifndef __NET_NET_NAMESPACE_H
+#define __NET_NET_NAMESPACE_H
+
+#include <linux/atomic.h>
+#include <linux/workqueue.h>
+#include <linux/list.h>
+#include <linux/sysctl.h>
+
+#include <net/netns/core.h>
+#include <net/netns/mib.h>
+#include <net/netns/unix.h>
+#include <net/netns/packet.h>
+#include <net/netns/ipv4.h>
+#include <net/netns/ipv6.h>
+#include <net/netns/dccp.h>
+#include <net/netns/x_tables.h>
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#include <net/netns/conntrack.h>
+#endif
+#include <net/netns/xfrm.h>
+
+struct proc_dir_entry;
+struct net_device;
+struct sock;
+struct ctl_table_header;
+struct net_generic;
+struct sock;
+struct netns_ipvs;
+
+
+#define NETDEV_HASHBITS 8
+#define NETDEV_HASHENTRIES (1 << NETDEV_HASHBITS)
+
+struct net {
+ atomic_t passive; /* To decided when the network
+ * namespace should be freed.
+ */
+ atomic_t count; /* To decided when the network
+ * namespace should be shut down.
+ */
+#ifdef NETNS_REFCNT_DEBUG
+ atomic_t use_count; /* To track references we
+ * destroy on demand
+ */
+#endif
+ spinlock_t rules_mod_lock;
+
+ struct list_head list; /* list of network namespaces */
+ struct list_head cleanup_list; /* namespaces on death row */
+ struct list_head exit_list; /* Use only net_mutex */
+
+ struct proc_dir_entry *proc_net;
+ struct proc_dir_entry *proc_net_stat;
+
+#ifdef CONFIG_SYSCTL
+ struct ctl_table_set sysctls;
+#endif
+
+ struct sock *rtnl; /* rtnetlink socket */
+ struct sock *genl_sock;
+
+ struct list_head dev_base_head;
+ struct hlist_head *dev_name_head;
+ struct hlist_head *dev_index_head;
+ unsigned int dev_base_seq; /* protected by rtnl_mutex */
+
+ /* core fib_rules */
+ struct list_head rules_ops;
+
+
+ struct net_device *loopback_dev; /* The loopback */
+ struct netns_core core;
+ struct netns_mib mib;
+ struct netns_packet packet;
+ struct netns_unix unx;
+ struct netns_ipv4 ipv4;
+#if IS_ENABLED(CONFIG_IPV6)
+ struct netns_ipv6 ipv6;
+#endif
+#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
+ struct netns_dccp dccp;
+#endif
+#ifdef CONFIG_NETFILTER
+ struct netns_xt xt;
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+ struct netns_ct ct;
+#endif
+ struct sock *nfnl;
+ struct sock *nfnl_stash;
+#endif
+#ifdef CONFIG_WEXT_CORE
+ struct sk_buff_head wext_nlevents;
+#endif
+ struct net_generic __rcu *gen;
+
+ /* Note : following structs are cache line aligned */
+#ifdef CONFIG_XFRM
+ struct netns_xfrm xfrm;
+#endif
+ struct netns_ipvs *ipvs;
+};
+
+
+#include <linux/seq_file_net.h>
+
+/* Init's network namespace */
+extern struct net init_net;
+
+#ifdef CONFIG_NET
+extern struct net *copy_net_ns(unsigned long flags, struct net *net_ns);
+
+#else /* CONFIG_NET */
+static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns)
+{
+ /* There is nothing to copy so this is a noop */
+ return net_ns;
+}
+#endif /* CONFIG_NET */
+
+
+extern struct list_head net_namespace_list;
+
+extern struct net *get_net_ns_by_pid(pid_t pid);
+extern struct net *get_net_ns_by_fd(int pid);
+
+#ifdef CONFIG_NET_NS
+extern void __put_net(struct net *net);
+
+static inline struct net *get_net(struct net *net)
+{
+ atomic_inc(&net->count);
+ return net;
+}
+
+static inline struct net *maybe_get_net(struct net *net)
+{
+ /* Used when we know struct net exists but we
+ * aren't guaranteed a previous reference count
+ * exists. If the reference count is zero this
+ * function fails and returns NULL.
+ */
+ if (!atomic_inc_not_zero(&net->count))
+ net = NULL;
+ return net;
+}
+
+static inline void put_net(struct net *net)
+{
+ if (atomic_dec_and_test(&net->count))
+ __put_net(net);
+}
+
+static inline
+int net_eq(const struct net *net1, const struct net *net2)
+{
+ return net1 == net2;
+}
+
+extern void net_drop_ns(void *);
+
+#else
+
+static inline struct net *get_net(struct net *net)
+{
+ return net;
+}
+
+static inline void put_net(struct net *net)
+{
+}
+
+static inline struct net *maybe_get_net(struct net *net)
+{
+ return net;
+}
+
+static inline
+int net_eq(const struct net *net1, const struct net *net2)
+{
+ return 1;
+}
+
+#define net_drop_ns NULL
+#endif
+
+
+#ifdef NETNS_REFCNT_DEBUG
+static inline struct net *hold_net(struct net *net)
+{
+ if (net)
+ atomic_inc(&net->use_count);
+ return net;
+}
+
+static inline void release_net(struct net *net)
+{
+ if (net)
+ atomic_dec(&net->use_count);
+}
+#else
+static inline struct net *hold_net(struct net *net)
+{
+ return net;
+}
+
+static inline void release_net(struct net *net)
+{
+}
+#endif
+
+#ifdef CONFIG_NET_NS
+
+static inline void write_pnet(struct net **pnet, struct net *net)
+{
+ *pnet = net;
+}
+
+static inline struct net *read_pnet(struct net * const *pnet)
+{
+ return *pnet;
+}
+
+#else
+
+#define write_pnet(pnet, net) do { (void)(net);} while (0)
+#define read_pnet(pnet) (&init_net)
+
+#endif
+
+#define for_each_net(VAR) \
+ list_for_each_entry(VAR, &net_namespace_list, list)
+
+#define for_each_net_rcu(VAR) \
+ list_for_each_entry_rcu(VAR, &net_namespace_list, list)
+
+#ifdef CONFIG_NET_NS
+#define __net_init
+#define __net_exit
+#define __net_initdata
+#else
+#define __net_init __init
+#define __net_exit __exit_refok
+#define __net_initdata __initdata
+#endif
+
+struct pernet_operations {
+ struct list_head list;
+ int (*init)(struct net *net);
+ void (*exit)(struct net *net);
+ void (*exit_batch)(struct list_head *net_exit_list);
+ int *id;
+ size_t size;
+};
+
+/*
+ * Use these carefully. If you implement a network device and it
+ * needs per network namespace operations use device pernet operations,
+ * otherwise use pernet subsys operations.
+ *
+ * Network interfaces need to be removed from a dying netns _before_
+ * subsys notifiers can be called, as most of the network code cleanup
+ * (which is done from subsys notifiers) runs with the assumption that
+ * dev_remove_pack has been called so no new packets will arrive during
+ * and after the cleanup functions have been called. dev_remove_pack
+ * is not per namespace so instead the guarantee of no more packets
+ * arriving in a network namespace is provided by ensuring that all
+ * network devices and all sockets have left the network namespace
+ * before the cleanup methods are called.
+ *
+ * For the longest time the ipv4 icmp code was registered as a pernet
+ * device which caused kernel oops, and panics during network
+ * namespace cleanup. So please don't get this wrong.
+ */
+extern int register_pernet_subsys(struct pernet_operations *);
+extern void unregister_pernet_subsys(struct pernet_operations *);
+extern int register_pernet_device(struct pernet_operations *);
+extern void unregister_pernet_device(struct pernet_operations *);
+
+struct ctl_path;
+struct ctl_table;
+struct ctl_table_header;
+
+extern struct ctl_table_header *register_net_sysctl_table(struct net *net,
+ const struct ctl_path *path, struct ctl_table *table);
+extern struct ctl_table_header *register_net_sysctl_rotable(
+ const struct ctl_path *path, struct ctl_table *table);
+extern void unregister_net_sysctl_table(struct ctl_table_header *header);
+
+#endif /* __NET_NET_NAMESPACE_H */
diff --git a/include/net/net_ratelimit.h b/include/net/net_ratelimit.h
new file mode 100644
index 00000000..7727b424
--- /dev/null
+++ b/include/net/net_ratelimit.h
@@ -0,0 +1,8 @@
+#ifndef _LINUX_NET_RATELIMIT_H
+#define _LINUX_NET_RATELIMIT_H
+
+#include <linux/ratelimit.h>
+
+extern struct ratelimit_state net_ratelimit_state;
+
+#endif /* _LINUX_NET_RATELIMIT_H */
diff --git a/include/net/netdma.h b/include/net/netdma.h
new file mode 100644
index 00000000..8ba8ce28
--- /dev/null
+++ b/include/net/netdma.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+#ifndef NETDMA_H
+#define NETDMA_H
+#ifdef CONFIG_NET_DMA
+#include <linux/dmaengine.h>
+#include <linux/skbuff.h>
+
+int dma_skb_copy_datagram_iovec(struct dma_chan* chan,
+ struct sk_buff *skb, int offset, struct iovec *to,
+ size_t len, struct dma_pinned_list *pinned_list);
+
+#endif /* CONFIG_NET_DMA */
+#endif /* NETDMA_H */
diff --git a/include/net/netevent.h b/include/net/netevent.h
new file mode 100644
index 00000000..086f8a5b
--- /dev/null
+++ b/include/net/netevent.h
@@ -0,0 +1,30 @@
+#ifndef _NET_EVENT_H
+#define _NET_EVENT_H
+
+/*
+ * Generic netevent notifiers
+ *
+ * Authors:
+ * Tom Tucker <tom@opengridcomputing.com>
+ * Steve Wise <swise@opengridcomputing.com>
+ *
+ * Changes:
+ */
+
+struct dst_entry;
+
+struct netevent_redirect {
+ struct dst_entry *old;
+ struct dst_entry *new;
+};
+
+enum netevent_notif_type {
+ NETEVENT_NEIGH_UPDATE = 1, /* arg is struct neighbour ptr */
+ NETEVENT_REDIRECT, /* arg is struct netevent_redirect ptr */
+};
+
+extern int register_netevent_notifier(struct notifier_block *nb);
+extern int unregister_netevent_notifier(struct notifier_block *nb);
+extern int call_netevent_notifiers(unsigned long val, void *v);
+
+#endif
diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
new file mode 100644
index 00000000..7573d52a
--- /dev/null
+++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
@@ -0,0 +1,24 @@
+/*
+ * IPv4 support for nf_conntrack.
+ *
+ * 23 Mar 2004: Yasuyuki Kozakai @ USAGI <yasuyuki.kozakai@toshiba.co.jp>
+ * - move L3 protocol dependent part from include/linux/netfilter_ipv4/
+ * ip_conntarck.h
+ */
+
+#ifndef _NF_CONNTRACK_IPV4_H
+#define _NF_CONNTRACK_IPV4_H
+
+
+extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4;
+
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp;
+
+extern int nf_conntrack_ipv4_compat_init(void);
+extern void nf_conntrack_ipv4_compat_fini(void);
+
+extern void need_ipv4_conntrack(void);
+
+#endif /*_NF_CONNTRACK_IPV4_H*/
diff --git a/include/net/netfilter/ipv4/nf_defrag_ipv4.h b/include/net/netfilter/ipv4/nf_defrag_ipv4.h
new file mode 100644
index 00000000..6b00ea38
--- /dev/null
+++ b/include/net/netfilter/ipv4/nf_defrag_ipv4.h
@@ -0,0 +1,6 @@
+#ifndef _NF_DEFRAG_IPV4_H
+#define _NF_DEFRAG_IPV4_H
+
+extern void nf_defrag_ipv4_enable(void);
+
+#endif /* _NF_DEFRAG_IPV4_H */
diff --git a/include/net/netfilter/ipv6/nf_conntrack_icmpv6.h b/include/net/netfilter/ipv6/nf_conntrack_icmpv6.h
new file mode 100644
index 00000000..67edd50a
--- /dev/null
+++ b/include/net/netfilter/ipv6/nf_conntrack_icmpv6.h
@@ -0,0 +1,20 @@
+/*
+ * ICMPv6 tracking.
+ *
+ * 21 Apl 2004: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
+ * - separated from nf_conntrack_icmp.h
+ *
+ * Derived from include/linux/netfiter_ipv4/ip_conntrack_icmp.h
+ */
+
+#ifndef _NF_CONNTRACK_ICMPV6_H
+#define _NF_CONNTRACK_ICMPV6_H
+
+#ifndef ICMPV6_NI_QUERY
+#define ICMPV6_NI_QUERY 139
+#endif
+#ifndef ICMPV6_NI_REPLY
+#define ICMPV6_NI_REPLY 140
+#endif
+
+#endif /* _NF_CONNTRACK_ICMPV6_H */
diff --git a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
new file mode 100644
index 00000000..a4c99368
--- /dev/null
+++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
@@ -0,0 +1,13 @@
+#ifndef _NF_CONNTRACK_IPV6_H
+#define _NF_CONNTRACK_IPV6_H
+
+extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
+
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6;
+
+#include <linux/sysctl.h>
+extern struct ctl_table nf_ct_ipv6_sysctl_table[];
+
+#endif /* _NF_CONNTRACK_IPV6_H*/
diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
new file mode 100644
index 00000000..fd79c9a1
--- /dev/null
+++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
@@ -0,0 +1,16 @@
+#ifndef _NF_DEFRAG_IPV6_H
+#define _NF_DEFRAG_IPV6_H
+
+extern void nf_defrag_ipv6_enable(void);
+
+extern int nf_ct_frag6_init(void);
+extern void nf_ct_frag6_cleanup(void);
+extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user);
+extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
+ struct net_device *in,
+ struct net_device *out,
+ int (*okfn)(struct sk_buff *));
+
+struct inet_frags_ctl;
+
+#endif /* _NF_DEFRAG_IPV6_H */
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
new file mode 100644
index 00000000..ab86036b
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack.h
@@ -0,0 +1,336 @@
+/*
+ * Connection state tracking for netfilter. This is separated from,
+ * but required by, the (future) NAT layer; it can also be used by an iptables
+ * extension.
+ *
+ * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
+ * - generalize L3 protocol dependent part.
+ *
+ * Derived from include/linux/netfiter_ipv4/ip_conntrack.h
+ */
+
+#ifndef _NF_CONNTRACK_H
+#define _NF_CONNTRACK_H
+
+#include <linux/netfilter/nf_conntrack_common.h>
+
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+#include <linux/atomic.h>
+
+#include <linux/netfilter/nf_conntrack_tcp.h>
+#include <linux/netfilter/nf_conntrack_dccp.h>
+#include <linux/netfilter/nf_conntrack_sctp.h>
+#include <linux/netfilter/nf_conntrack_proto_gre.h>
+#include <net/netfilter/ipv6/nf_conntrack_icmpv6.h>
+
+#include <net/netfilter/nf_conntrack_tuple.h>
+
+/* per conntrack: protocol private data */
+union nf_conntrack_proto {
+ /* insert conntrack proto private data here */
+ struct nf_ct_dccp dccp;
+ struct ip_ct_sctp sctp;
+ struct ip_ct_tcp tcp;
+ struct nf_ct_gre gre;
+};
+
+union nf_conntrack_expect_proto {
+ /* insert expect proto private data here */
+};
+
+/* Add protocol helper include file here */
+#include <linux/netfilter/nf_conntrack_ftp.h>
+#include <linux/netfilter/nf_conntrack_pptp.h>
+#include <linux/netfilter/nf_conntrack_h323.h>
+#include <linux/netfilter/nf_conntrack_sane.h>
+#include <linux/netfilter/nf_conntrack_sip.h>
+
+/* per conntrack: application helper private data */
+union nf_conntrack_help {
+ /* insert conntrack helper private data (master) here */
+#if defined(CONFIG_NF_CONNTRACK_FTP) || defined(CONFIG_NF_CONNTRACK_FTP_MODULE)
+ struct nf_ct_ftp_master ct_ftp_info;
+#endif
+#if defined(CONFIG_NF_CONNTRACK_PPTP) || \
+ defined(CONFIG_NF_CONNTRACK_PPTP_MODULE)
+ struct nf_ct_pptp_master ct_pptp_info;
+#endif
+#if defined(CONFIG_NF_CONNTRACK_H323) || \
+ defined(CONFIG_NF_CONNTRACK_H323_MODULE)
+ struct nf_ct_h323_master ct_h323_info;
+#endif
+#if defined(CONFIG_NF_CONNTRACK_SANE) || \
+ defined(CONFIG_NF_CONNTRACK_SANE_MODULE)
+ struct nf_ct_sane_master ct_sane_info;
+#endif
+#if defined(CONFIG_NF_CONNTRACK_SIP) || defined(CONFIG_NF_CONNTRACK_SIP_MODULE)
+ struct nf_ct_sip_master ct_sip_info;
+#endif
+};
+
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/timer.h>
+
+#ifdef CONFIG_NETFILTER_DEBUG
+#define NF_CT_ASSERT(x) WARN_ON(!(x))
+#else
+#define NF_CT_ASSERT(x)
+#endif
+
+struct nf_conntrack_helper;
+
+/* Must be kept in sync with the classes defined by helpers */
+#define NF_CT_MAX_EXPECT_CLASSES 4
+
+/* nf_conn feature for connections that have a helper */
+struct nf_conn_help {
+ /* Helper. if any */
+ struct nf_conntrack_helper __rcu *helper;
+
+ union nf_conntrack_help help;
+
+ struct hlist_head expectations;
+
+ /* Current number of expected connections */
+ u8 expecting[NF_CT_MAX_EXPECT_CLASSES];
+};
+
+#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
+#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
+
+struct nf_conn {
+ /* Usage count in here is 1 for hash table/destruct timer, 1 per skb,
+ plus 1 for any connection(s) we are `master' for */
+ struct nf_conntrack ct_general;
+
+ spinlock_t lock;
+
+ /* XXX should I move this to the tail ? - Y.K */
+ /* These are my tuples; original and reply */
+ struct nf_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
+
+ /* Have we seen traffic both ways yet? (bitset) */
+ unsigned long status;
+
+ /* If we were expected by an expectation, this will be it */
+ struct nf_conn *master;
+
+ /* Timer function; drops refcnt when it goes off. */
+ struct timer_list timeout;
+
+#if defined(CONFIG_NF_CONNTRACK_MARK)
+ u_int32_t mark;
+#endif
+
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+ u_int32_t secmark;
+#endif
+
+ /* Extensions */
+ struct nf_ct_ext *ext;
+#ifdef CONFIG_NET_NS
+ struct net *ct_net;
+#endif
+
+ /* Storage reserved for other modules, must be the last member */
+ union nf_conntrack_proto proto;
+};
+
+static inline struct nf_conn *
+nf_ct_tuplehash_to_ctrack(const struct nf_conntrack_tuple_hash *hash)
+{
+ return container_of(hash, struct nf_conn,
+ tuplehash[hash->tuple.dst.dir]);
+}
+
+static inline u_int16_t nf_ct_l3num(const struct nf_conn *ct)
+{
+ return ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+}
+
+static inline u_int8_t nf_ct_protonum(const struct nf_conn *ct)
+{
+ return ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
+}
+
+#define nf_ct_tuple(ct, dir) (&(ct)->tuplehash[dir].tuple)
+
+/* get master conntrack via master expectation */
+#define master_ct(conntr) (conntr->master)
+
+extern struct net init_net;
+
+static inline struct net *nf_ct_net(const struct nf_conn *ct)
+{
+ return read_pnet(&ct->ct_net);
+}
+
+/* Alter reply tuple (maybe alter helper). */
+extern void
+nf_conntrack_alter_reply(struct nf_conn *ct,
+ const struct nf_conntrack_tuple *newreply);
+
+/* Is this tuple taken? (ignoring any belonging to the given
+ conntrack). */
+extern int
+nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple,
+ const struct nf_conn *ignored_conntrack);
+
+/* Return conntrack_info and tuple hash for given skb. */
+static inline struct nf_conn *
+nf_ct_get(const struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
+{
+ *ctinfo = skb->nfctinfo;
+ return (struct nf_conn *)skb->nfct;
+}
+
+/* decrement reference count on a conntrack */
+static inline void nf_ct_put(struct nf_conn *ct)
+{
+ NF_CT_ASSERT(ct);
+ nf_conntrack_put(&ct->ct_general);
+}
+
+/* Protocol module loading */
+extern int nf_ct_l3proto_try_module_get(unsigned short l3proto);
+extern void nf_ct_l3proto_module_put(unsigned short l3proto);
+
+/*
+ * Allocate a hashtable of hlist_head (if nulls == 0),
+ * or hlist_nulls_head (if nulls == 1)
+ */
+extern void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls);
+
+extern void nf_ct_free_hashtable(void *hash, unsigned int size);
+
+extern struct nf_conntrack_tuple_hash *
+__nf_conntrack_find(struct net *net, u16 zone,
+ const struct nf_conntrack_tuple *tuple);
+
+extern int nf_conntrack_hash_check_insert(struct nf_conn *ct);
+extern void nf_ct_delete_from_lists(struct nf_conn *ct);
+extern void nf_ct_insert_dying_list(struct nf_conn *ct);
+
+extern void nf_conntrack_flush_report(struct net *net, u32 pid, int report);
+
+extern bool nf_ct_get_tuplepr(const struct sk_buff *skb,
+ unsigned int nhoff, u_int16_t l3num,
+ struct nf_conntrack_tuple *tuple);
+extern bool nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
+ const struct nf_conntrack_tuple *orig);
+
+extern void __nf_ct_refresh_acct(struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ const struct sk_buff *skb,
+ unsigned long extra_jiffies,
+ int do_acct);
+
+/* Refresh conntrack for this many jiffies and do accounting */
+static inline void nf_ct_refresh_acct(struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ const struct sk_buff *skb,
+ unsigned long extra_jiffies)
+{
+ __nf_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies, 1);
+}
+
+/* Refresh conntrack for this many jiffies */
+static inline void nf_ct_refresh(struct nf_conn *ct,
+ const struct sk_buff *skb,
+ unsigned long extra_jiffies)
+{
+ __nf_ct_refresh_acct(ct, 0, skb, extra_jiffies, 0);
+}
+
+extern bool __nf_ct_kill_acct(struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ const struct sk_buff *skb,
+ int do_acct);
+
+/* kill conntrack and do accounting */
+static inline bool nf_ct_kill_acct(struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ const struct sk_buff *skb)
+{
+ return __nf_ct_kill_acct(ct, ctinfo, skb, 1);
+}
+
+/* kill conntrack without accounting */
+static inline bool nf_ct_kill(struct nf_conn *ct)
+{
+ return __nf_ct_kill_acct(ct, 0, NULL, 0);
+}
+
+/* These are for NAT. Icky. */
+extern s16 (*nf_ct_nat_offset)(const struct nf_conn *ct,
+ enum ip_conntrack_dir dir,
+ u32 seq);
+
+/* Fake conntrack entry for untracked connections */
+DECLARE_PER_CPU(struct nf_conn, nf_conntrack_untracked);
+static inline struct nf_conn *nf_ct_untracked_get(void)
+{
+ return &__raw_get_cpu_var(nf_conntrack_untracked);
+}
+extern void nf_ct_untracked_status_or(unsigned long bits);
+
+/* Iterate over all conntracks: if iter returns true, it's deleted. */
+extern void
+nf_ct_iterate_cleanup(struct net *net, int (*iter)(struct nf_conn *i, void *data), void *data);
+extern void nf_conntrack_free(struct nf_conn *ct);
+extern struct nf_conn *
+nf_conntrack_alloc(struct net *net, u16 zone,
+ const struct nf_conntrack_tuple *orig,
+ const struct nf_conntrack_tuple *repl,
+ gfp_t gfp);
+
+static inline int nf_ct_is_template(const struct nf_conn *ct)
+{
+ return test_bit(IPS_TEMPLATE_BIT, &ct->status);
+}
+
+/* It's confirmed if it is, or has been in the hash table. */
+static inline int nf_ct_is_confirmed(struct nf_conn *ct)
+{
+ return test_bit(IPS_CONFIRMED_BIT, &ct->status);
+}
+
+static inline int nf_ct_is_dying(struct nf_conn *ct)
+{
+ return test_bit(IPS_DYING_BIT, &ct->status);
+}
+
+static inline int nf_ct_is_untracked(const struct nf_conn *ct)
+{
+ return test_bit(IPS_UNTRACKED_BIT, &ct->status);
+}
+
+/* Packet is received from loopback */
+static inline bool nf_is_loopback_packet(const struct sk_buff *skb)
+{
+ return skb->dev && skb->skb_iif && skb->dev->flags & IFF_LOOPBACK;
+}
+
+struct kernel_param;
+
+extern int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp);
+extern unsigned int nf_conntrack_htable_size;
+extern unsigned int nf_conntrack_max;
+extern unsigned int nf_conntrack_hash_rnd;
+void init_nf_conntrack_hash_rnd(void);
+
+#define NF_CT_STAT_INC(net, count) \
+ __this_cpu_inc((net)->ct.stat->count)
+#define NF_CT_STAT_INC_ATOMIC(net, count) \
+do { \
+ local_bh_disable(); \
+ __this_cpu_inc((net)->ct.stat->count); \
+ local_bh_enable(); \
+} while (0)
+
+#define MODULE_ALIAS_NFCT_HELPER(helper) \
+ MODULE_ALIAS("nfct-helper-" helper)
+
+#endif /* _NF_CONNTRACK_H */
diff --git a/include/net/netfilter/nf_conntrack_acct.h b/include/net/netfilter/nf_conntrack_acct.h
new file mode 100644
index 00000000..463ae8e1
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_acct.h
@@ -0,0 +1,63 @@
+/*
+ * (C) 2008 Krzysztof Piotr Oledzki <ole@ans.pl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _NF_CONNTRACK_ACCT_H
+#define _NF_CONNTRACK_ACCT_H
+#include <net/net_namespace.h>
+#include <linux/netfilter/nf_conntrack_common.h>
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+
+struct nf_conn_counter {
+ atomic64_t packets;
+ atomic64_t bytes;
+};
+
+static inline
+struct nf_conn_counter *nf_conn_acct_find(const struct nf_conn *ct)
+{
+ return nf_ct_ext_find(ct, NF_CT_EXT_ACCT);
+}
+
+static inline
+struct nf_conn_counter *nf_ct_acct_ext_add(struct nf_conn *ct, gfp_t gfp)
+{
+ struct net *net = nf_ct_net(ct);
+ struct nf_conn_counter *acct;
+
+ if (!net->ct.sysctl_acct)
+ return NULL;
+
+ acct = nf_ct_ext_add(ct, NF_CT_EXT_ACCT, gfp);
+ if (!acct)
+ pr_debug("failed to add accounting extension area");
+
+
+ return acct;
+};
+
+extern unsigned int
+seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir);
+
+/* Check if connection tracking accounting is enabled */
+static inline bool nf_ct_acct_enabled(struct net *net)
+{
+ return net->ct.sysctl_acct != 0;
+}
+
+/* Enable/disable connection tracking accounting */
+static inline void nf_ct_set_acct(struct net *net, bool enable)
+{
+ net->ct.sysctl_acct = enable;
+}
+
+extern int nf_conntrack_acct_init(struct net *net);
+extern void nf_conntrack_acct_fini(struct net *net);
+
+#endif /* _NF_CONNTRACK_ACCT_H */
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
new file mode 100644
index 00000000..aced0851
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -0,0 +1,79 @@
+/*
+ * This header is used to share core functionality between the
+ * standalone connection tracking module, and the compatibility layer's use
+ * of connection tracking.
+ *
+ * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
+ * - generalize L3 protocol dependent part.
+ *
+ * Derived from include/linux/netfiter_ipv4/ip_conntrack_core.h
+ */
+
+#ifndef _NF_CONNTRACK_CORE_H
+#define _NF_CONNTRACK_CORE_H
+
+#include <linux/netfilter.h>
+#include <net/netfilter/nf_conntrack_l3proto.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
+
+/* This header is used to share core functionality between the
+ standalone connection tracking module, and the compatibility layer's use
+ of connection tracking. */
+extern unsigned int nf_conntrack_in(struct net *net,
+ u_int8_t pf,
+ unsigned int hooknum,
+ struct sk_buff *skb);
+
+extern int nf_conntrack_init(struct net *net);
+extern void nf_conntrack_cleanup(struct net *net);
+
+extern int nf_conntrack_proto_init(void);
+extern void nf_conntrack_proto_fini(void);
+
+extern bool
+nf_ct_get_tuple(const struct sk_buff *skb,
+ unsigned int nhoff,
+ unsigned int dataoff,
+ u_int16_t l3num,
+ u_int8_t protonum,
+ struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_l3proto *l3proto,
+ const struct nf_conntrack_l4proto *l4proto);
+
+extern bool
+nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
+ const struct nf_conntrack_tuple *orig,
+ const struct nf_conntrack_l3proto *l3proto,
+ const struct nf_conntrack_l4proto *l4proto);
+
+/* Find a connection corresponding to a tuple. */
+extern struct nf_conntrack_tuple_hash *
+nf_conntrack_find_get(struct net *net, u16 zone,
+ const struct nf_conntrack_tuple *tuple);
+
+extern int __nf_conntrack_confirm(struct sk_buff *skb);
+
+/* Confirm a connection: returns NF_DROP if packet must be dropped. */
+static inline int nf_conntrack_confirm(struct sk_buff *skb)
+{
+ struct nf_conn *ct = (struct nf_conn *)skb->nfct;
+ int ret = NF_ACCEPT;
+
+ if (ct && !nf_ct_is_untracked(ct)) {
+ if (!nf_ct_is_confirmed(ct))
+ ret = __nf_conntrack_confirm(skb);
+ if (likely(ret == NF_ACCEPT))
+ nf_ct_deliver_cached_events(ct);
+ }
+ return ret;
+}
+
+int
+print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_l3proto *l3proto,
+ const struct nf_conntrack_l4proto *proto);
+
+extern spinlock_t nf_conntrack_lock ;
+
+#endif /* _NF_CONNTRACK_CORE_H */
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
new file mode 100644
index 00000000..a88fb693
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -0,0 +1,245 @@
+/*
+ * connection tracking event cache.
+ */
+
+#ifndef _NF_CONNTRACK_ECACHE_H
+#define _NF_CONNTRACK_ECACHE_H
+#include <net/netfilter/nf_conntrack.h>
+
+#include <net/net_namespace.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <linux/netfilter/nf_conntrack_common.h>
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+
+struct nf_conntrack_ecache {
+ unsigned long cache; /* bitops want long */
+ unsigned long missed; /* missed events */
+ u16 ctmask; /* bitmask of ct events to be delivered */
+ u16 expmask; /* bitmask of expect events to be delivered */
+ u32 pid; /* netlink pid of destroyer */
+};
+
+static inline struct nf_conntrack_ecache *
+nf_ct_ecache_find(const struct nf_conn *ct)
+{
+#ifdef CONFIG_NF_CONNTRACK_EVENTS
+ return nf_ct_ext_find(ct, NF_CT_EXT_ECACHE);
+#else
+ return NULL;
+#endif
+}
+
+static inline struct nf_conntrack_ecache *
+nf_ct_ecache_ext_add(struct nf_conn *ct, u16 ctmask, u16 expmask, gfp_t gfp)
+{
+#ifdef CONFIG_NF_CONNTRACK_EVENTS
+ struct net *net = nf_ct_net(ct);
+ struct nf_conntrack_ecache *e;
+
+ if (!ctmask && !expmask && net->ct.sysctl_events) {
+ ctmask = ~0;
+ expmask = ~0;
+ }
+ if (!ctmask && !expmask)
+ return NULL;
+
+ e = nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp);
+ if (e) {
+ e->ctmask = ctmask;
+ e->expmask = expmask;
+ }
+ return e;
+#else
+ return NULL;
+#endif
+};
+
+#ifdef CONFIG_NF_CONNTRACK_EVENTS
+/* This structure is passed to event handler */
+struct nf_ct_event {
+ struct nf_conn *ct;
+ u32 pid;
+ int report;
+};
+
+struct nf_ct_event_notifier {
+ int (*fcn)(unsigned int events, struct nf_ct_event *item);
+};
+
+extern int nf_conntrack_register_notifier(struct net *net, struct nf_ct_event_notifier *nb);
+extern void nf_conntrack_unregister_notifier(struct net *net, struct nf_ct_event_notifier *nb);
+
+extern void nf_ct_deliver_cached_events(struct nf_conn *ct);
+
+static inline void
+nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
+{
+ struct net *net = nf_ct_net(ct);
+ struct nf_conntrack_ecache *e;
+
+ if (net->ct.nf_conntrack_event_cb == NULL)
+ return;
+
+ e = nf_ct_ecache_find(ct);
+ if (e == NULL)
+ return;
+
+ set_bit(event, &e->cache);
+}
+
+static inline int
+nf_conntrack_eventmask_report(unsigned int eventmask,
+ struct nf_conn *ct,
+ u32 pid,
+ int report)
+{
+ int ret = 0;
+ struct net *net = nf_ct_net(ct);
+ struct nf_ct_event_notifier *notify;
+ struct nf_conntrack_ecache *e;
+
+ rcu_read_lock();
+ notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
+ if (notify == NULL)
+ goto out_unlock;
+
+ e = nf_ct_ecache_find(ct);
+ if (e == NULL)
+ goto out_unlock;
+
+ if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) {
+ struct nf_ct_event item = {
+ .ct = ct,
+ .pid = e->pid ? e->pid : pid,
+ .report = report
+ };
+ /* This is a resent of a destroy event? If so, skip missed */
+ unsigned long missed = e->pid ? 0 : e->missed;
+
+ if (!((eventmask | missed) & e->ctmask))
+ goto out_unlock;
+
+ ret = notify->fcn(eventmask | missed, &item);
+ if (unlikely(ret < 0 || missed)) {
+ spin_lock_bh(&ct->lock);
+ if (ret < 0) {
+ /* This is a destroy event that has been
+ * triggered by a process, we store the PID
+ * to include it in the retransmission. */
+ if (eventmask & (1 << IPCT_DESTROY) &&
+ e->pid == 0 && pid != 0)
+ e->pid = pid;
+ else
+ e->missed |= eventmask;
+ } else
+ e->missed &= ~missed;
+ spin_unlock_bh(&ct->lock);
+ }
+ }
+out_unlock:
+ rcu_read_unlock();
+ return ret;
+}
+
+static inline int
+nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct,
+ u32 pid, int report)
+{
+ return nf_conntrack_eventmask_report(1 << event, ct, pid, report);
+}
+
+static inline int
+nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct)
+{
+ return nf_conntrack_eventmask_report(1 << event, ct, 0, 0);
+}
+
+struct nf_exp_event {
+ struct nf_conntrack_expect *exp;
+ u32 pid;
+ int report;
+};
+
+struct nf_exp_event_notifier {
+ int (*fcn)(unsigned int events, struct nf_exp_event *item);
+};
+
+extern int nf_ct_expect_register_notifier(struct net *net, struct nf_exp_event_notifier *nb);
+extern void nf_ct_expect_unregister_notifier(struct net *net, struct nf_exp_event_notifier *nb);
+
+static inline void
+nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
+ struct nf_conntrack_expect *exp,
+ u32 pid,
+ int report)
+{
+ struct net *net = nf_ct_exp_net(exp);
+ struct nf_exp_event_notifier *notify;
+ struct nf_conntrack_ecache *e;
+
+ rcu_read_lock();
+ notify = rcu_dereference(net->ct.nf_expect_event_cb);
+ if (notify == NULL)
+ goto out_unlock;
+
+ e = nf_ct_ecache_find(exp->master);
+ if (e == NULL)
+ goto out_unlock;
+
+ if (e->expmask & (1 << event)) {
+ struct nf_exp_event item = {
+ .exp = exp,
+ .pid = pid,
+ .report = report
+ };
+ notify->fcn(1 << event, &item);
+ }
+out_unlock:
+ rcu_read_unlock();
+}
+
+static inline void
+nf_ct_expect_event(enum ip_conntrack_expect_events event,
+ struct nf_conntrack_expect *exp)
+{
+ nf_ct_expect_event_report(event, exp, 0, 0);
+}
+
+extern int nf_conntrack_ecache_init(struct net *net);
+extern void nf_conntrack_ecache_fini(struct net *net);
+
+#else /* CONFIG_NF_CONNTRACK_EVENTS */
+
+static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
+ struct nf_conn *ct) {}
+static inline int nf_conntrack_eventmask_report(unsigned int eventmask,
+ struct nf_conn *ct,
+ u32 pid,
+ int report) { return 0; }
+static inline int nf_conntrack_event(enum ip_conntrack_events event,
+ struct nf_conn *ct) { return 0; }
+static inline int nf_conntrack_event_report(enum ip_conntrack_events event,
+ struct nf_conn *ct,
+ u32 pid,
+ int report) { return 0; }
+static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {}
+static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event,
+ struct nf_conntrack_expect *exp) {}
+static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e,
+ struct nf_conntrack_expect *exp,
+ u32 pid,
+ int report) {}
+
+static inline int nf_conntrack_ecache_init(struct net *net)
+{
+ return 0;
+}
+
+static inline void nf_conntrack_ecache_fini(struct net *net)
+{
+}
+#endif /* CONFIG_NF_CONNTRACK_EVENTS */
+
+#endif /*_NF_CONNTRACK_ECACHE_H*/
+
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
new file mode 100644
index 00000000..4619caad
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -0,0 +1,111 @@
+/*
+ * connection tracking expectations.
+ */
+
+#ifndef _NF_CONNTRACK_EXPECT_H
+#define _NF_CONNTRACK_EXPECT_H
+#include <net/netfilter/nf_conntrack.h>
+
+extern unsigned int nf_ct_expect_hsize;
+extern unsigned int nf_ct_expect_max;
+
+struct nf_conntrack_expect {
+ /* Conntrack expectation list member */
+ struct hlist_node lnode;
+
+ /* Hash member */
+ struct hlist_node hnode;
+
+ /* We expect this tuple, with the following mask */
+ struct nf_conntrack_tuple tuple;
+ struct nf_conntrack_tuple_mask mask;
+
+ /* Function to call after setup and insertion */
+ void (*expectfn)(struct nf_conn *new,
+ struct nf_conntrack_expect *this);
+
+ /* Helper to assign to new connection */
+ struct nf_conntrack_helper *helper;
+
+ /* The conntrack of the master connection */
+ struct nf_conn *master;
+
+ /* Timer function; deletes the expectation. */
+ struct timer_list timeout;
+
+ /* Usage count. */
+ atomic_t use;
+
+ /* Flags */
+ unsigned int flags;
+
+ /* Expectation class */
+ unsigned int class;
+
+#ifdef CONFIG_NF_NAT_NEEDED
+ __be32 saved_ip;
+ /* This is the original per-proto part, used to map the
+ * expected connection the way the recipient expects. */
+ union nf_conntrack_man_proto saved_proto;
+ /* Direction relative to the master connection. */
+ enum ip_conntrack_dir dir;
+#endif
+
+ struct rcu_head rcu;
+};
+
+static inline struct net *nf_ct_exp_net(struct nf_conntrack_expect *exp)
+{
+ return nf_ct_net(exp->master);
+}
+
+struct nf_conntrack_expect_policy {
+ unsigned int max_expected;
+ unsigned int timeout;
+ const char *name;
+};
+
+#define NF_CT_EXPECT_CLASS_DEFAULT 0
+
+int nf_conntrack_expect_init(struct net *net);
+void nf_conntrack_expect_fini(struct net *net);
+
+struct nf_conntrack_expect *
+__nf_ct_expect_find(struct net *net, u16 zone,
+ const struct nf_conntrack_tuple *tuple);
+
+struct nf_conntrack_expect *
+nf_ct_expect_find_get(struct net *net, u16 zone,
+ const struct nf_conntrack_tuple *tuple);
+
+struct nf_conntrack_expect *
+nf_ct_find_expectation(struct net *net, u16 zone,
+ const struct nf_conntrack_tuple *tuple);
+
+void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
+ u32 pid, int report);
+static inline void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
+{
+ nf_ct_unlink_expect_report(exp, 0, 0);
+}
+
+void nf_ct_remove_expectations(struct nf_conn *ct);
+void nf_ct_unexpect_related(struct nf_conntrack_expect *exp);
+
+/* Allocate space for an expectation: this is mandatory before calling
+ nf_ct_expect_related. You will have to call put afterwards. */
+struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me);
+void nf_ct_expect_init(struct nf_conntrack_expect *, unsigned int, u_int8_t,
+ const union nf_inet_addr *,
+ const union nf_inet_addr *,
+ u_int8_t, const __be16 *, const __be16 *);
+void nf_ct_expect_put(struct nf_conntrack_expect *exp);
+int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
+ u32 pid, int report);
+static inline int nf_ct_expect_related(struct nf_conntrack_expect *expect)
+{
+ return nf_ct_expect_related_report(expect, 0, 0);
+}
+
+#endif /*_NF_CONNTRACK_EXPECT_H*/
+
diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h
new file mode 100644
index 00000000..96755c37
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_extend.h
@@ -0,0 +1,110 @@
+#ifndef _NF_CONNTRACK_EXTEND_H
+#define _NF_CONNTRACK_EXTEND_H
+
+#include <linux/slab.h>
+
+#include <net/netfilter/nf_conntrack.h>
+
+enum nf_ct_ext_id {
+ NF_CT_EXT_HELPER,
+#if defined(CONFIG_NF_NAT) || defined(CONFIG_NF_NAT_MODULE)
+ NF_CT_EXT_NAT,
+#endif
+ NF_CT_EXT_ACCT,
+#ifdef CONFIG_NF_CONNTRACK_EVENTS
+ NF_CT_EXT_ECACHE,
+#endif
+#ifdef CONFIG_NF_CONNTRACK_ZONES
+ NF_CT_EXT_ZONE,
+#endif
+#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
+ NF_CT_EXT_TSTAMP,
+#endif
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+ NF_CT_EXT_TIMEOUT,
+#endif
+ NF_CT_EXT_NUM,
+};
+
+#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help
+#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat
+#define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter
+#define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache
+#define NF_CT_EXT_ZONE_TYPE struct nf_conntrack_zone
+#define NF_CT_EXT_TSTAMP_TYPE struct nf_conn_tstamp
+#define NF_CT_EXT_TIMEOUT_TYPE struct nf_conn_timeout
+
+/* Extensions: optional stuff which isn't permanently in struct. */
+struct nf_ct_ext {
+ struct rcu_head rcu;
+ u8 offset[NF_CT_EXT_NUM];
+ u8 len;
+ char data[0];
+};
+
+static inline bool __nf_ct_ext_exist(const struct nf_ct_ext *ext, u8 id)
+{
+ return !!ext->offset[id];
+}
+
+static inline bool nf_ct_ext_exist(const struct nf_conn *ct, u8 id)
+{
+ return (ct->ext && __nf_ct_ext_exist(ct->ext, id));
+}
+
+static inline void *__nf_ct_ext_find(const struct nf_conn *ct, u8 id)
+{
+ if (!nf_ct_ext_exist(ct, id))
+ return NULL;
+
+ return (void *)ct->ext + ct->ext->offset[id];
+}
+#define nf_ct_ext_find(ext, id) \
+ ((id##_TYPE *)__nf_ct_ext_find((ext), (id)))
+
+/* Destroy all relationships */
+extern void __nf_ct_ext_destroy(struct nf_conn *ct);
+static inline void nf_ct_ext_destroy(struct nf_conn *ct)
+{
+ if (ct->ext)
+ __nf_ct_ext_destroy(ct);
+}
+
+/* Free operation. If you want to free a object referred from private area,
+ * please implement __nf_ct_ext_free() and call it.
+ */
+static inline void nf_ct_ext_free(struct nf_conn *ct)
+{
+ if (ct->ext)
+ kfree(ct->ext);
+}
+
+/* Add this type, returns pointer to data or NULL. */
+void *
+__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp);
+#define nf_ct_ext_add(ct, id, gfp) \
+ ((id##_TYPE *)__nf_ct_ext_add((ct), (id), (gfp)))
+
+#define NF_CT_EXT_F_PREALLOC 0x0001
+
+struct nf_ct_ext_type {
+ /* Destroys relationships (can be NULL). */
+ void (*destroy)(struct nf_conn *ct);
+ /* Called when realloacted (can be NULL).
+ Contents has already been moved. */
+ void (*move)(void *new, void *old);
+
+ enum nf_ct_ext_id id;
+
+ unsigned int flags;
+
+ /* Length and min alignment. */
+ u8 len;
+ u8 align;
+ /* initial size of nf_ct_ext. */
+ u8 alloc_size;
+};
+
+int nf_ct_extend_register(struct nf_ct_ext_type *type);
+void nf_ct_extend_unregister(struct nf_ct_ext_type *type);
+#endif /* _NF_CONNTRACK_EXTEND_H */
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
new file mode 100644
index 00000000..5767dc24
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -0,0 +1,85 @@
+/*
+ * connection tracking helpers.
+ *
+ * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
+ * - generalize L3 protocol dependent part.
+ *
+ * Derived from include/linux/netfiter_ipv4/ip_conntrack_helper.h
+ */
+
+#ifndef _NF_CONNTRACK_HELPER_H
+#define _NF_CONNTRACK_HELPER_H
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+
+struct module;
+
+#define NF_CT_HELPER_NAME_LEN 16
+
+struct nf_conntrack_helper {
+ struct hlist_node hnode; /* Internal use. */
+
+ const char *name; /* name of the module */
+ struct module *me; /* pointer to self */
+ const struct nf_conntrack_expect_policy *expect_policy;
+
+ /* Tuple of things we will help (compared against server response) */
+ struct nf_conntrack_tuple tuple;
+
+ /* Function to call when data passes; return verdict, or -1 to
+ invalidate. */
+ int (*help)(struct sk_buff *skb,
+ unsigned int protoff,
+ struct nf_conn *ct,
+ enum ip_conntrack_info conntrackinfo);
+
+ void (*destroy)(struct nf_conn *ct);
+
+ int (*to_nlattr)(struct sk_buff *skb, const struct nf_conn *ct);
+ unsigned int expect_class_max;
+};
+
+extern struct nf_conntrack_helper *
+__nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum);
+
+extern struct nf_conntrack_helper *
+nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum);
+
+extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
+extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
+
+extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp);
+
+extern int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
+ gfp_t flags);
+
+extern void nf_ct_helper_destroy(struct nf_conn *ct);
+
+static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
+{
+ return nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
+}
+
+extern int nf_conntrack_helper_init(void);
+extern void nf_conntrack_helper_fini(void);
+
+extern int nf_conntrack_broadcast_help(struct sk_buff *skb,
+ unsigned int protoff,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int timeout);
+
+struct nf_ct_helper_expectfn {
+ struct list_head head;
+ const char *name;
+ void (*expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp);
+};
+
+void nf_ct_helper_expectfn_register(struct nf_ct_helper_expectfn *n);
+void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n);
+struct nf_ct_helper_expectfn *
+nf_ct_helper_expectfn_find_by_name(const char *name);
+struct nf_ct_helper_expectfn *
+nf_ct_helper_expectfn_find_by_symbol(const void *symbol);
+
+#endif /*_NF_CONNTRACK_HELPER_H*/
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
new file mode 100644
index 00000000..e8010f44
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C)2003,2004 USAGI/WIDE Project
+ *
+ * Header for use in defining a given L3 protocol for connection tracking.
+ *
+ * Author:
+ * Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
+ *
+ * Derived from include/netfilter_ipv4/ip_conntrack_protocol.h
+ */
+
+#ifndef _NF_CONNTRACK_L3PROTO_H
+#define _NF_CONNTRACK_L3PROTO_H
+#include <linux/netlink.h>
+#include <net/netlink.h>
+#include <linux/seq_file.h>
+#include <net/netfilter/nf_conntrack.h>
+
+struct nf_conntrack_l3proto {
+ /* L3 Protocol Family number. ex) PF_INET */
+ u_int16_t l3proto;
+
+ /* Protocol name */
+ const char *name;
+
+ /*
+ * Try to fill in the third arg: nhoff is offset of l3 proto
+ * hdr. Return true if possible.
+ */
+ bool (*pkt_to_tuple)(const struct sk_buff *skb, unsigned int nhoff,
+ struct nf_conntrack_tuple *tuple);
+
+ /*
+ * Invert the per-proto part of the tuple: ie. turn xmit into reply.
+ * Some packets can't be inverted: return 0 in that case.
+ */
+ bool (*invert_tuple)(struct nf_conntrack_tuple *inverse,
+ const struct nf_conntrack_tuple *orig);
+
+ /* Print out the per-protocol part of the tuple. */
+ int (*print_tuple)(struct seq_file *s,
+ const struct nf_conntrack_tuple *);
+
+ /*
+ * Called before tracking.
+ * *dataoff: offset of protocol header (TCP, UDP,...) in skb
+ * *protonum: protocol number
+ */
+ int (*get_l4proto)(const struct sk_buff *skb, unsigned int nhoff,
+ unsigned int *dataoff, u_int8_t *protonum);
+
+ int (*tuple_to_nlattr)(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *t);
+
+ /*
+ * Calculate size of tuple nlattr
+ */
+ int (*nlattr_tuple_size)(void);
+
+ int (*nlattr_to_tuple)(struct nlattr *tb[],
+ struct nf_conntrack_tuple *t);
+ const struct nla_policy *nla_policy;
+
+ size_t nla_size;
+
+#ifdef CONFIG_SYSCTL
+ struct ctl_table_header *ctl_table_header;
+ struct ctl_path *ctl_table_path;
+ struct ctl_table *ctl_table;
+#endif /* CONFIG_SYSCTL */
+
+ /* Module (if any) which this is connected to. */
+ struct module *me;
+};
+
+extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX];
+
+/* Protocol registration. */
+extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto);
+extern void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto);
+extern struct nf_conntrack_l3proto *nf_ct_l3proto_find_get(u_int16_t l3proto);
+extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p);
+
+/* Existing built-in protocols */
+extern struct nf_conntrack_l3proto nf_conntrack_l3proto_generic;
+
+static inline struct nf_conntrack_l3proto *
+__nf_ct_l3proto_find(u_int16_t l3proto)
+{
+ if (unlikely(l3proto >= AF_MAX))
+ return &nf_conntrack_l3proto_generic;
+ return rcu_dereference(nf_ct_l3protos[l3proto]);
+}
+
+#endif /*_NF_CONNTRACK_L3PROTO_H*/
diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
new file mode 100644
index 00000000..3b572bb2
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -0,0 +1,152 @@
+/*
+ * Header for use in defining a given L4 protocol for connection tracking.
+ *
+ * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
+ * - generalized L3 protocol dependent part.
+ *
+ * Derived from include/linux/netfiter_ipv4/ip_conntrack_protcol.h
+ */
+
+#ifndef _NF_CONNTRACK_L4PROTO_H
+#define _NF_CONNTRACK_L4PROTO_H
+#include <linux/netlink.h>
+#include <net/netlink.h>
+#include <net/netfilter/nf_conntrack.h>
+
+struct seq_file;
+
+struct nf_conntrack_l4proto {
+ /* L3 Protocol number. */
+ u_int16_t l3proto;
+
+ /* L4 Protocol number. */
+ u_int8_t l4proto;
+
+ /* Try to fill in the third arg: dataoff is offset past network protocol
+ hdr. Return true if possible. */
+ bool (*pkt_to_tuple)(const struct sk_buff *skb, unsigned int dataoff,
+ struct nf_conntrack_tuple *tuple);
+
+ /* Invert the per-proto part of the tuple: ie. turn xmit into reply.
+ * Some packets can't be inverted: return 0 in that case.
+ */
+ bool (*invert_tuple)(struct nf_conntrack_tuple *inverse,
+ const struct nf_conntrack_tuple *orig);
+
+ /* Returns verdict for packet, or -1 for invalid. */
+ int (*packet)(struct nf_conn *ct,
+ const struct sk_buff *skb,
+ unsigned int dataoff,
+ enum ip_conntrack_info ctinfo,
+ u_int8_t pf,
+ unsigned int hooknum,
+ unsigned int *timeouts);
+
+ /* Called when a new connection for this protocol found;
+ * returns TRUE if it's OK. If so, packet() called next. */
+ bool (*new)(struct nf_conn *ct, const struct sk_buff *skb,
+ unsigned int dataoff, unsigned int *timeouts);
+
+ /* Called when a conntrack entry is destroyed */
+ void (*destroy)(struct nf_conn *ct);
+
+ int (*error)(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
+ unsigned int dataoff, enum ip_conntrack_info *ctinfo,
+ u_int8_t pf, unsigned int hooknum);
+
+ /* Print out the per-protocol part of the tuple. Return like seq_* */
+ int (*print_tuple)(struct seq_file *s,
+ const struct nf_conntrack_tuple *);
+
+ /* Print out the private part of the conntrack. */
+ int (*print_conntrack)(struct seq_file *s, struct nf_conn *);
+
+ /* Return the array of timeouts for this protocol. */
+ unsigned int *(*get_timeouts)(struct net *net);
+
+ /* convert protoinfo to nfnetink attributes */
+ int (*to_nlattr)(struct sk_buff *skb, struct nlattr *nla,
+ struct nf_conn *ct);
+ /* Calculate protoinfo nlattr size */
+ int (*nlattr_size)(void);
+
+ /* convert nfnetlink attributes to protoinfo */
+ int (*from_nlattr)(struct nlattr *tb[], struct nf_conn *ct);
+
+ int (*tuple_to_nlattr)(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *t);
+ /* Calculate tuple nlattr size */
+ int (*nlattr_tuple_size)(void);
+ int (*nlattr_to_tuple)(struct nlattr *tb[],
+ struct nf_conntrack_tuple *t);
+ const struct nla_policy *nla_policy;
+
+ size_t nla_size;
+
+#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
+ struct {
+ size_t obj_size;
+ int (*nlattr_to_obj)(struct nlattr *tb[], void *data);
+ int (*obj_to_nlattr)(struct sk_buff *skb, const void *data);
+
+ unsigned int nlattr_max;
+ const struct nla_policy *nla_policy;
+ } ctnl_timeout;
+#endif
+
+#ifdef CONFIG_SYSCTL
+ struct ctl_table_header **ctl_table_header;
+ struct ctl_table *ctl_table;
+ unsigned int *ctl_table_users;
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ struct ctl_table_header *ctl_compat_table_header;
+ struct ctl_table *ctl_compat_table;
+#endif
+#endif
+ /* Protocol name */
+ const char *name;
+
+ /* Module (if any) which this is connected to. */
+ struct module *me;
+};
+
+/* Existing built-in generic protocol */
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_generic;
+
+#define MAX_NF_CT_PROTO 256
+
+extern struct nf_conntrack_l4proto *
+__nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto);
+
+extern struct nf_conntrack_l4proto *
+nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t l4proto);
+extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p);
+
+/* Protocol registration. */
+extern int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *proto);
+extern void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto);
+
+/* Generic netlink helpers */
+extern int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *tuple);
+extern int nf_ct_port_nlattr_to_tuple(struct nlattr *tb[],
+ struct nf_conntrack_tuple *t);
+extern int nf_ct_port_nlattr_tuple_size(void);
+extern const struct nla_policy nf_ct_port_nla_policy[];
+
+#ifdef CONFIG_SYSCTL
+#ifdef DEBUG_INVALID_PACKETS
+#define LOG_INVALID(net, proto) \
+ ((net)->ct.sysctl_log_invalid == (proto) || \
+ (net)->ct.sysctl_log_invalid == IPPROTO_RAW)
+#else
+#define LOG_INVALID(net, proto) \
+ (((net)->ct.sysctl_log_invalid == (proto) || \
+ (net)->ct.sysctl_log_invalid == IPPROTO_RAW) \
+ && net_ratelimit())
+#endif
+#else
+static inline int LOG_INVALID(struct net *net, int proto) { return 0; }
+#endif /* CONFIG_SYSCTL */
+
+#endif /*_NF_CONNTRACK_PROTOCOL_H*/
diff --git a/include/net/netfilter/nf_conntrack_timeout.h b/include/net/netfilter/nf_conntrack_timeout.h
new file mode 100644
index 00000000..34ec89f8
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_timeout.h
@@ -0,0 +1,78 @@
+#ifndef _NF_CONNTRACK_TIMEOUT_H
+#define _NF_CONNTRACK_TIMEOUT_H
+
+#include <net/net_namespace.h>
+#include <linux/netfilter/nf_conntrack_common.h>
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+
+#define CTNL_TIMEOUT_NAME_MAX 32
+
+struct ctnl_timeout {
+ struct list_head head;
+ struct rcu_head rcu_head;
+ atomic_t refcnt;
+ char name[CTNL_TIMEOUT_NAME_MAX];
+ __u16 l3num;
+ struct nf_conntrack_l4proto *l4proto;
+ char data[0];
+};
+
+struct nf_conn_timeout {
+ struct ctnl_timeout *timeout;
+};
+
+#define NF_CT_TIMEOUT_EXT_DATA(__t) (unsigned int *) &((__t)->timeout->data)
+
+static inline
+struct nf_conn_timeout *nf_ct_timeout_find(const struct nf_conn *ct)
+{
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+ return nf_ct_ext_find(ct, NF_CT_EXT_TIMEOUT);
+#else
+ return NULL;
+#endif
+}
+
+static inline
+struct nf_conn_timeout *nf_ct_timeout_ext_add(struct nf_conn *ct,
+ struct ctnl_timeout *timeout,
+ gfp_t gfp)
+{
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+ struct nf_conn_timeout *timeout_ext;
+
+ timeout_ext = nf_ct_ext_add(ct, NF_CT_EXT_TIMEOUT, gfp);
+ if (timeout_ext == NULL)
+ return NULL;
+
+ timeout_ext->timeout = timeout;
+
+ return timeout_ext;
+#else
+ return NULL;
+#endif
+};
+
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+extern int nf_conntrack_timeout_init(struct net *net);
+extern void nf_conntrack_timeout_fini(struct net *net);
+#else
+static inline int nf_conntrack_timeout_init(struct net *net)
+{
+ return 0;
+}
+
+static inline void nf_conntrack_timeout_fini(struct net *net)
+{
+ return;
+}
+#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
+
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+extern struct ctnl_timeout *(*nf_ct_timeout_find_get_hook)(const char *name);
+extern void (*nf_ct_timeout_put_hook)(struct ctnl_timeout *timeout);
+#endif
+
+#endif /* _NF_CONNTRACK_TIMEOUT_H */
diff --git a/include/net/netfilter/nf_conntrack_timestamp.h b/include/net/netfilter/nf_conntrack_timestamp.h
new file mode 100644
index 00000000..fc9c82b1
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_timestamp.h
@@ -0,0 +1,65 @@
+#ifndef _NF_CONNTRACK_TSTAMP_H
+#define _NF_CONNTRACK_TSTAMP_H
+
+#include <net/net_namespace.h>
+#include <linux/netfilter/nf_conntrack_common.h>
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+
+struct nf_conn_tstamp {
+ u_int64_t start;
+ u_int64_t stop;
+};
+
+static inline
+struct nf_conn_tstamp *nf_conn_tstamp_find(const struct nf_conn *ct)
+{
+#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
+ return nf_ct_ext_find(ct, NF_CT_EXT_TSTAMP);
+#else
+ return NULL;
+#endif
+}
+
+static inline
+struct nf_conn_tstamp *nf_ct_tstamp_ext_add(struct nf_conn *ct, gfp_t gfp)
+{
+#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
+ struct net *net = nf_ct_net(ct);
+
+ if (!net->ct.sysctl_tstamp)
+ return NULL;
+
+ return nf_ct_ext_add(ct, NF_CT_EXT_TSTAMP, gfp);
+#else
+ return NULL;
+#endif
+};
+
+static inline bool nf_ct_tstamp_enabled(struct net *net)
+{
+ return net->ct.sysctl_tstamp != 0;
+}
+
+static inline void nf_ct_set_tstamp(struct net *net, bool enable)
+{
+ net->ct.sysctl_tstamp = enable;
+}
+
+#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
+extern int nf_conntrack_tstamp_init(struct net *net);
+extern void nf_conntrack_tstamp_fini(struct net *net);
+#else
+static inline int nf_conntrack_tstamp_init(struct net *net)
+{
+ return 0;
+}
+
+static inline void nf_conntrack_tstamp_fini(struct net *net)
+{
+ return;
+}
+#endif /* CONFIG_NF_CONNTRACK_TIMESTAMP */
+
+#endif /* _NF_CONNTRACK_TSTAMP_H */
diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h
new file mode 100644
index 00000000..aea3f822
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_tuple.h
@@ -0,0 +1,186 @@
+/*
+ * Definitions and Declarations for tuple.
+ *
+ * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
+ * - generalize L3 protocol dependent part.
+ *
+ * Derived from include/linux/netfiter_ipv4/ip_conntrack_tuple.h
+ */
+
+#ifndef _NF_CONNTRACK_TUPLE_H
+#define _NF_CONNTRACK_TUPLE_H
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+#include <linux/list_nulls.h>
+
+/* A `tuple' is a structure containing the information to uniquely
+ identify a connection. ie. if two packets have the same tuple, they
+ are in the same connection; if not, they are not.
+
+ We divide the structure along "manipulatable" and
+ "non-manipulatable" lines, for the benefit of the NAT code.
+*/
+
+#define NF_CT_TUPLE_L3SIZE ARRAY_SIZE(((union nf_inet_addr *)NULL)->all)
+
+/* The manipulable part of the tuple. */
+struct nf_conntrack_man {
+ union nf_inet_addr u3;
+ union nf_conntrack_man_proto u;
+ /* Layer 3 protocol */
+ u_int16_t l3num;
+};
+
+/* This contains the information to distinguish a connection. */
+struct nf_conntrack_tuple {
+ struct nf_conntrack_man src;
+
+ /* These are the parts of the tuple which are fixed. */
+ struct {
+ union nf_inet_addr u3;
+ union {
+ /* Add other protocols here. */
+ __be16 all;
+
+ struct {
+ __be16 port;
+ } tcp;
+ struct {
+ __be16 port;
+ } udp;
+ struct {
+ u_int8_t type, code;
+ } icmp;
+ struct {
+ __be16 port;
+ } dccp;
+ struct {
+ __be16 port;
+ } sctp;
+ struct {
+ __be16 key;
+ } gre;
+ } u;
+
+ /* The protocol. */
+ u_int8_t protonum;
+
+ /* The direction (for tuplehash) */
+ u_int8_t dir;
+ } dst;
+};
+
+struct nf_conntrack_tuple_mask {
+ struct {
+ union nf_inet_addr u3;
+ union nf_conntrack_man_proto u;
+ } src;
+};
+
+static inline void nf_ct_dump_tuple_ip(const struct nf_conntrack_tuple *t)
+{
+#ifdef DEBUG
+ printk("tuple %p: %u %pI4:%hu -> %pI4:%hu\n",
+ t, t->dst.protonum,
+ &t->src.u3.ip, ntohs(t->src.u.all),
+ &t->dst.u3.ip, ntohs(t->dst.u.all));
+#endif
+}
+
+static inline void nf_ct_dump_tuple_ipv6(const struct nf_conntrack_tuple *t)
+{
+#ifdef DEBUG
+ printk("tuple %p: %u %pI6 %hu -> %pI6 %hu\n",
+ t, t->dst.protonum,
+ t->src.u3.all, ntohs(t->src.u.all),
+ t->dst.u3.all, ntohs(t->dst.u.all));
+#endif
+}
+
+static inline void nf_ct_dump_tuple(const struct nf_conntrack_tuple *t)
+{
+ switch (t->src.l3num) {
+ case AF_INET:
+ nf_ct_dump_tuple_ip(t);
+ break;
+ case AF_INET6:
+ nf_ct_dump_tuple_ipv6(t);
+ break;
+ }
+}
+
+/* If we're the first tuple, it's the original dir. */
+#define NF_CT_DIRECTION(h) \
+ ((enum ip_conntrack_dir)(h)->tuple.dst.dir)
+
+/* Connections have two entries in the hash table: one for each way */
+struct nf_conntrack_tuple_hash {
+ struct hlist_nulls_node hnnode;
+ struct nf_conntrack_tuple tuple;
+};
+
+static inline bool __nf_ct_tuple_src_equal(const struct nf_conntrack_tuple *t1,
+ const struct nf_conntrack_tuple *t2)
+{
+ return (nf_inet_addr_cmp(&t1->src.u3, &t2->src.u3) &&
+ t1->src.u.all == t2->src.u.all &&
+ t1->src.l3num == t2->src.l3num);
+}
+
+static inline bool __nf_ct_tuple_dst_equal(const struct nf_conntrack_tuple *t1,
+ const struct nf_conntrack_tuple *t2)
+{
+ return (nf_inet_addr_cmp(&t1->dst.u3, &t2->dst.u3) &&
+ t1->dst.u.all == t2->dst.u.all &&
+ t1->dst.protonum == t2->dst.protonum);
+}
+
+static inline bool nf_ct_tuple_equal(const struct nf_conntrack_tuple *t1,
+ const struct nf_conntrack_tuple *t2)
+{
+ return __nf_ct_tuple_src_equal(t1, t2) &&
+ __nf_ct_tuple_dst_equal(t1, t2);
+}
+
+static inline bool
+nf_ct_tuple_mask_equal(const struct nf_conntrack_tuple_mask *m1,
+ const struct nf_conntrack_tuple_mask *m2)
+{
+ return (nf_inet_addr_cmp(&m1->src.u3, &m2->src.u3) &&
+ m1->src.u.all == m2->src.u.all);
+}
+
+static inline bool
+nf_ct_tuple_src_mask_cmp(const struct nf_conntrack_tuple *t1,
+ const struct nf_conntrack_tuple *t2,
+ const struct nf_conntrack_tuple_mask *mask)
+{
+ int count;
+
+ for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++) {
+ if ((t1->src.u3.all[count] ^ t2->src.u3.all[count]) &
+ mask->src.u3.all[count])
+ return false;
+ }
+
+ if ((t1->src.u.all ^ t2->src.u.all) & mask->src.u.all)
+ return false;
+
+ if (t1->src.l3num != t2->src.l3num ||
+ t1->dst.protonum != t2->dst.protonum)
+ return false;
+
+ return true;
+}
+
+static inline bool
+nf_ct_tuple_mask_cmp(const struct nf_conntrack_tuple *t,
+ const struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_tuple_mask *mask)
+{
+ return nf_ct_tuple_src_mask_cmp(t, tuple, mask) &&
+ __nf_ct_tuple_dst_equal(t, tuple);
+}
+
+#endif /* _NF_CONNTRACK_TUPLE_H */
diff --git a/include/net/netfilter/nf_conntrack_zones.h b/include/net/netfilter/nf_conntrack_zones.h
new file mode 100644
index 00000000..034efe8d
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_zones.h
@@ -0,0 +1,25 @@
+#ifndef _NF_CONNTRACK_ZONES_H
+#define _NF_CONNTRACK_ZONES_H
+
+#define NF_CT_DEFAULT_ZONE 0
+
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#include <net/netfilter/nf_conntrack_extend.h>
+
+struct nf_conntrack_zone {
+ u16 id;
+};
+
+static inline u16 nf_ct_zone(const struct nf_conn *ct)
+{
+#ifdef CONFIG_NF_CONNTRACK_ZONES
+ struct nf_conntrack_zone *nf_ct_zone;
+ nf_ct_zone = nf_ct_ext_find(ct, NF_CT_EXT_ZONE);
+ if (nf_ct_zone)
+ return nf_ct_zone->id;
+#endif
+ return NF_CT_DEFAULT_ZONE;
+}
+
+#endif /* CONFIG_NF_CONNTRACK || CONFIG_NF_CONNTRACK_MODULE */
+#endif /* _NF_CONNTRACK_ZONES_H */
diff --git a/include/net/netfilter/nf_log.h b/include/net/netfilter/nf_log.h
new file mode 100644
index 00000000..e991bd0a
--- /dev/null
+++ b/include/net/netfilter/nf_log.h
@@ -0,0 +1,65 @@
+#ifndef _NF_LOG_H
+#define _NF_LOG_H
+
+#include <linux/netfilter.h>
+
+/* those NF_LOG_* defines and struct nf_loginfo are legacy definitios that will
+ * disappear once iptables is replaced with pkttables. Please DO NOT use them
+ * for any new code! */
+#define NF_LOG_TCPSEQ 0x01 /* Log TCP sequence numbers */
+#define NF_LOG_TCPOPT 0x02 /* Log TCP options */
+#define NF_LOG_IPOPT 0x04 /* Log IP options */
+#define NF_LOG_UID 0x08 /* Log UID owning local socket */
+#define NF_LOG_MASK 0x0f
+
+#define NF_LOG_TYPE_LOG 0x01
+#define NF_LOG_TYPE_ULOG 0x02
+
+struct nf_loginfo {
+ u_int8_t type;
+ union {
+ struct {
+ u_int32_t copy_len;
+ u_int16_t group;
+ u_int16_t qthreshold;
+ } ulog;
+ struct {
+ u_int8_t level;
+ u_int8_t logflags;
+ } log;
+ } u;
+};
+
+typedef void nf_logfn(u_int8_t pf,
+ unsigned int hooknum,
+ const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct nf_loginfo *li,
+ const char *prefix);
+
+struct nf_logger {
+ struct module *me;
+ nf_logfn *logfn;
+ char *name;
+ struct list_head list[NFPROTO_NUMPROTO];
+};
+
+/* Function to register/unregister log function. */
+int nf_log_register(u_int8_t pf, struct nf_logger *logger);
+void nf_log_unregister(struct nf_logger *logger);
+
+int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger);
+void nf_log_unbind_pf(u_int8_t pf);
+
+/* Calls the registered backend logging function */
+__printf(7, 8)
+void nf_log_packet(u_int8_t pf,
+ unsigned int hooknum,
+ const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct nf_loginfo *li,
+ const char *fmt, ...);
+
+#endif /* _NF_LOG_H */
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h
new file mode 100644
index 00000000..b4de990b
--- /dev/null
+++ b/include/net/netfilter/nf_nat.h
@@ -0,0 +1,69 @@
+#ifndef _NF_NAT_H
+#define _NF_NAT_H
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter/nf_nat.h>
+#include <net/netfilter/nf_conntrack_tuple.h>
+
+enum nf_nat_manip_type {
+ NF_NAT_MANIP_SRC,
+ NF_NAT_MANIP_DST
+};
+
+/* SRC manip occurs POST_ROUTING or LOCAL_IN */
+#define HOOK2MANIP(hooknum) ((hooknum) != NF_INET_POST_ROUTING && \
+ (hooknum) != NF_INET_LOCAL_IN)
+
+/* NAT sequence number modifications */
+struct nf_nat_seq {
+ /* position of the last TCP sequence number modification (if any) */
+ u_int32_t correction_pos;
+
+ /* sequence number offset before and after last modification */
+ int16_t offset_before, offset_after;
+};
+
+#include <linux/list.h>
+#include <linux/netfilter/nf_conntrack_pptp.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+
+/* per conntrack: nat application helper private data */
+union nf_conntrack_nat_help {
+ /* insert nat helper private data here */
+#if defined(CONFIG_NF_NAT_PPTP) || defined(CONFIG_NF_NAT_PPTP_MODULE)
+ struct nf_nat_pptp nat_pptp_info;
+#endif
+};
+
+struct nf_conn;
+
+/* The structure embedded in the conntrack structure. */
+struct nf_conn_nat {
+ struct hlist_node bysource;
+ struct nf_nat_seq seq[IP_CT_DIR_MAX];
+ struct nf_conn *ct;
+ union nf_conntrack_nat_help help;
+#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
+ defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
+ int masq_index;
+#endif
+};
+
+/* Set up the info structure to map into this range. */
+extern unsigned int nf_nat_setup_info(struct nf_conn *ct,
+ const struct nf_nat_ipv4_range *range,
+ enum nf_nat_manip_type maniptype);
+
+/* Is this tuple already taken? (not by us)*/
+extern int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
+ const struct nf_conn *ignored_conntrack);
+
+static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
+{
+#if defined(CONFIG_NF_NAT) || defined(CONFIG_NF_NAT_MODULE)
+ return nf_ct_ext_find(ct, NF_CT_EXT_NAT);
+#else
+ return NULL;
+#endif
+}
+
+#endif
diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h
new file mode 100644
index 00000000..b13d8d18
--- /dev/null
+++ b/include/net/netfilter/nf_nat_core.h
@@ -0,0 +1,36 @@
+#ifndef _NF_NAT_CORE_H
+#define _NF_NAT_CORE_H
+#include <linux/list.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_nat.h>
+
+/* This header used to share core functionality between the standalone
+ NAT module, and the compatibility layer's use of NAT for masquerading. */
+
+extern unsigned int nf_nat_packet(struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int hooknum,
+ struct sk_buff *skb);
+
+extern int nf_nat_icmp_reply_translation(struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int hooknum,
+ struct sk_buff *skb);
+
+static inline int nf_nat_initialized(struct nf_conn *ct,
+ enum nf_nat_manip_type manip)
+{
+ if (manip == NF_NAT_MANIP_SRC)
+ return ct->status & IPS_SRC_NAT_DONE;
+ else
+ return ct->status & IPS_DST_NAT_DONE;
+}
+
+struct nlattr;
+
+extern int
+(*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct,
+ enum nf_nat_manip_type manip,
+ const struct nlattr *attr);
+
+#endif /* _NF_NAT_CORE_H */
diff --git a/include/net/netfilter/nf_nat_helper.h b/include/net/netfilter/nf_nat_helper.h
new file mode 100644
index 00000000..02bb6c29
--- /dev/null
+++ b/include/net/netfilter/nf_nat_helper.h
@@ -0,0 +1,57 @@
+#ifndef _NF_NAT_HELPER_H
+#define _NF_NAT_HELPER_H
+/* NAT protocol helper routines. */
+
+#include <net/netfilter/nf_conntrack.h>
+
+struct sk_buff;
+
+/* These return true or false. */
+extern int __nf_nat_mangle_tcp_packet(struct sk_buff *skb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int match_offset,
+ unsigned int match_len,
+ const char *rep_buffer,
+ unsigned int rep_len, bool adjust);
+
+static inline int nf_nat_mangle_tcp_packet(struct sk_buff *skb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int match_offset,
+ unsigned int match_len,
+ const char *rep_buffer,
+ unsigned int rep_len)
+{
+ return __nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
+ match_offset, match_len,
+ rep_buffer, rep_len, true);
+}
+
+extern int nf_nat_mangle_udp_packet(struct sk_buff *skb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int match_offset,
+ unsigned int match_len,
+ const char *rep_buffer,
+ unsigned int rep_len);
+
+extern void nf_nat_set_seq_adjust(struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ __be32 seq, s16 off);
+extern int nf_nat_seq_adjust(struct sk_buff *skb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo);
+extern int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo);
+
+/* Setup NAT on this expected conntrack so it follows master, but goes
+ * to port ct->master->saved_proto. */
+extern void nf_nat_follow_master(struct nf_conn *ct,
+ struct nf_conntrack_expect *this);
+
+extern s16 nf_nat_get_offset(const struct nf_conn *ct,
+ enum ip_conntrack_dir dir,
+ u32 seq);
+#endif
diff --git a/include/net/netfilter/nf_nat_protocol.h b/include/net/netfilter/nf_nat_protocol.h
new file mode 100644
index 00000000..7b0b5116
--- /dev/null
+++ b/include/net/netfilter/nf_nat_protocol.h
@@ -0,0 +1,67 @@
+/* Header for use in defining a given protocol. */
+#ifndef _NF_NAT_PROTOCOL_H
+#define _NF_NAT_PROTOCOL_H
+#include <net/netfilter/nf_nat.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
+
+struct nf_nat_ipv4_range;
+
+struct nf_nat_protocol {
+ /* Protocol number. */
+ unsigned int protonum;
+
+ /* Translate a packet to the target according to manip type.
+ Return true if succeeded. */
+ bool (*manip_pkt)(struct sk_buff *skb,
+ unsigned int iphdroff,
+ const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype);
+
+ /* Is the manipable part of the tuple between min and max incl? */
+ bool (*in_range)(const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype,
+ const union nf_conntrack_man_proto *min,
+ const union nf_conntrack_man_proto *max);
+
+ /* Alter the per-proto part of the tuple (depending on
+ maniptype), to give a unique tuple in the given range if
+ possible. Per-protocol part of tuple is initialized to the
+ incoming packet. */
+ void (*unique_tuple)(struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_ipv4_range *range,
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *ct);
+
+ int (*nlattr_to_range)(struct nlattr *tb[],
+ struct nf_nat_ipv4_range *range);
+};
+
+/* Protocol registration. */
+extern int nf_nat_protocol_register(const struct nf_nat_protocol *proto);
+extern void nf_nat_protocol_unregister(const struct nf_nat_protocol *proto);
+
+/* Built-in protocols. */
+extern const struct nf_nat_protocol nf_nat_protocol_tcp;
+extern const struct nf_nat_protocol nf_nat_protocol_udp;
+extern const struct nf_nat_protocol nf_nat_protocol_icmp;
+extern const struct nf_nat_protocol nf_nat_unknown_protocol;
+
+extern int init_protocols(void) __init;
+extern void cleanup_protocols(void);
+extern const struct nf_nat_protocol *find_nat_proto(u_int16_t protonum);
+
+extern bool nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype,
+ const union nf_conntrack_man_proto *min,
+ const union nf_conntrack_man_proto *max);
+
+extern void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_ipv4_range *range,
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *ct,
+ u_int16_t *rover);
+
+extern int nf_nat_proto_nlattr_to_range(struct nlattr *tb[],
+ struct nf_nat_ipv4_range *range);
+
+#endif /*_NF_NAT_PROTO_H*/
diff --git a/include/net/netfilter/nf_nat_rule.h b/include/net/netfilter/nf_nat_rule.h
new file mode 100644
index 00000000..2890bdc4
--- /dev/null
+++ b/include/net/netfilter/nf_nat_rule.h
@@ -0,0 +1,15 @@
+#ifndef _NF_NAT_RULE_H
+#define _NF_NAT_RULE_H
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_nat.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+extern int nf_nat_rule_init(void) __init;
+extern void nf_nat_rule_cleanup(void);
+extern int nf_nat_rule_find(struct sk_buff *skb,
+ unsigned int hooknum,
+ const struct net_device *in,
+ const struct net_device *out,
+ struct nf_conn *ct);
+
+#endif /* _NF_NAT_RULE_H */
diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h
new file mode 100644
index 00000000..252fd101
--- /dev/null
+++ b/include/net/netfilter/nf_queue.h
@@ -0,0 +1,34 @@
+#ifndef _NF_QUEUE_H
+#define _NF_QUEUE_H
+
+/* Each queued (to userspace) skbuff has one of these. */
+struct nf_queue_entry {
+ struct list_head list;
+ struct sk_buff *skb;
+ unsigned int id;
+
+ struct nf_hook_ops *elem;
+ u_int8_t pf;
+ unsigned int hook;
+ struct net_device *indev;
+ struct net_device *outdev;
+ int (*okfn)(struct sk_buff *);
+};
+
+#define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry))
+
+/* Packet queuing */
+struct nf_queue_handler {
+ int (*outfn)(struct nf_queue_entry *entry,
+ unsigned int queuenum);
+ char *name;
+};
+
+extern int nf_register_queue_handler(u_int8_t pf,
+ const struct nf_queue_handler *qh);
+extern int nf_unregister_queue_handler(u_int8_t pf,
+ const struct nf_queue_handler *qh);
+extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh);
+extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
+
+#endif /* _NF_QUEUE_H */
diff --git a/include/net/netfilter/nf_tproxy_core.h b/include/net/netfilter/nf_tproxy_core.h
new file mode 100644
index 00000000..75ca9291
--- /dev/null
+++ b/include/net/netfilter/nf_tproxy_core.h
@@ -0,0 +1,208 @@
+#ifndef _NF_TPROXY_CORE_H
+#define _NF_TPROXY_CORE_H
+
+#include <linux/types.h>
+#include <linux/in.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/inet_hashtables.h>
+#include <net/inet6_hashtables.h>
+#include <net/tcp.h>
+
+#define NFT_LOOKUP_ANY 0
+#define NFT_LOOKUP_LISTENER 1
+#define NFT_LOOKUP_ESTABLISHED 2
+
+/* look up and get a reference to a matching socket */
+
+
+/* This function is used by the 'TPROXY' target and the 'socket'
+ * match. The following lookups are supported:
+ *
+ * Explicit TProxy target rule
+ * ===========================
+ *
+ * This is used when the user wants to intercept a connection matching
+ * an explicit iptables rule. In this case the sockets are assumed
+ * matching in preference order:
+ *
+ * - match: if there's a fully established connection matching the
+ * _packet_ tuple, it is returned, assuming the redirection
+ * already took place and we process a packet belonging to an
+ * established connection
+ *
+ * - match: if there's a listening socket matching the redirection
+ * (e.g. on-port & on-ip of the connection), it is returned,
+ * regardless if it was bound to 0.0.0.0 or an explicit
+ * address. The reasoning is that if there's an explicit rule, it
+ * does not really matter if the listener is bound to an interface
+ * or to 0. The user already stated that he wants redirection
+ * (since he added the rule).
+ *
+ * "socket" match based redirection (no specific rule)
+ * ===================================================
+ *
+ * There are connections with dynamic endpoints (e.g. FTP data
+ * connection) that the user is unable to add explicit rules
+ * for. These are taken care of by a generic "socket" rule. It is
+ * assumed that the proxy application is trusted to open such
+ * connections without explicit iptables rule (except of course the
+ * generic 'socket' rule). In this case the following sockets are
+ * matched in preference order:
+ *
+ * - match: if there's a fully established connection matching the
+ * _packet_ tuple
+ *
+ * - match: if there's a non-zero bound listener (possibly with a
+ * non-local address) We don't accept zero-bound listeners, since
+ * then local services could intercept traffic going through the
+ * box.
+ *
+ * Please note that there's an overlap between what a TPROXY target
+ * and a socket match will match. Normally if you have both rules the
+ * "socket" match will be the first one, effectively all packets
+ * belonging to established connections going through that one.
+ */
+static inline struct sock *
+nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
+ const __be32 saddr, const __be32 daddr,
+ const __be16 sport, const __be16 dport,
+ const struct net_device *in, int lookup_type)
+{
+ struct sock *sk;
+
+ /* look up socket */
+ switch (protocol) {
+ case IPPROTO_TCP:
+ switch (lookup_type) {
+ case NFT_LOOKUP_ANY:
+ sk = __inet_lookup(net, &tcp_hashinfo,
+ saddr, sport, daddr, dport,
+ in->ifindex);
+ break;
+ case NFT_LOOKUP_LISTENER:
+ sk = inet_lookup_listener(net, &tcp_hashinfo,
+ daddr, dport,
+ in->ifindex);
+
+ /* NOTE: we return listeners even if bound to
+ * 0.0.0.0, those are filtered out in
+ * xt_socket, since xt_TPROXY needs 0 bound
+ * listeners too */
+
+ break;
+ case NFT_LOOKUP_ESTABLISHED:
+ sk = inet_lookup_established(net, &tcp_hashinfo,
+ saddr, sport, daddr, dport,
+ in->ifindex);
+ break;
+ default:
+ WARN_ON(1);
+ sk = NULL;
+ break;
+ }
+ break;
+ case IPPROTO_UDP:
+ sk = udp4_lib_lookup(net, saddr, sport, daddr, dport,
+ in->ifindex);
+ if (sk && lookup_type != NFT_LOOKUP_ANY) {
+ int connected = (sk->sk_state == TCP_ESTABLISHED);
+ int wildcard = (inet_sk(sk)->inet_rcv_saddr == 0);
+
+ /* NOTE: we return listeners even if bound to
+ * 0.0.0.0, those are filtered out in
+ * xt_socket, since xt_TPROXY needs 0 bound
+ * listeners too */
+ if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) ||
+ (lookup_type == NFT_LOOKUP_LISTENER && connected)) {
+ sock_put(sk);
+ sk = NULL;
+ }
+ }
+ break;
+ default:
+ WARN_ON(1);
+ sk = NULL;
+ }
+
+ pr_debug("tproxy socket lookup: proto %u %08x:%u -> %08x:%u, lookup type: %d, sock %p\n",
+ protocol, ntohl(saddr), ntohs(sport), ntohl(daddr), ntohs(dport), lookup_type, sk);
+
+ return sk;
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+static inline struct sock *
+nf_tproxy_get_sock_v6(struct net *net, const u8 protocol,
+ const struct in6_addr *saddr, const struct in6_addr *daddr,
+ const __be16 sport, const __be16 dport,
+ const struct net_device *in, int lookup_type)
+{
+ struct sock *sk;
+
+ /* look up socket */
+ switch (protocol) {
+ case IPPROTO_TCP:
+ switch (lookup_type) {
+ case NFT_LOOKUP_ANY:
+ sk = inet6_lookup(net, &tcp_hashinfo,
+ saddr, sport, daddr, dport,
+ in->ifindex);
+ break;
+ case NFT_LOOKUP_LISTENER:
+ sk = inet6_lookup_listener(net, &tcp_hashinfo,
+ daddr, ntohs(dport),
+ in->ifindex);
+
+ /* NOTE: we return listeners even if bound to
+ * 0.0.0.0, those are filtered out in
+ * xt_socket, since xt_TPROXY needs 0 bound
+ * listeners too */
+
+ break;
+ case NFT_LOOKUP_ESTABLISHED:
+ sk = __inet6_lookup_established(net, &tcp_hashinfo,
+ saddr, sport, daddr, ntohs(dport),
+ in->ifindex);
+ break;
+ default:
+ WARN_ON(1);
+ sk = NULL;
+ break;
+ }
+ break;
+ case IPPROTO_UDP:
+ sk = udp6_lib_lookup(net, saddr, sport, daddr, dport,
+ in->ifindex);
+ if (sk && lookup_type != NFT_LOOKUP_ANY) {
+ int connected = (sk->sk_state == TCP_ESTABLISHED);
+ int wildcard = ipv6_addr_any(&inet6_sk(sk)->rcv_saddr);
+
+ /* NOTE: we return listeners even if bound to
+ * 0.0.0.0, those are filtered out in
+ * xt_socket, since xt_TPROXY needs 0 bound
+ * listeners too */
+ if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) ||
+ (lookup_type == NFT_LOOKUP_LISTENER && connected)) {
+ sock_put(sk);
+ sk = NULL;
+ }
+ }
+ break;
+ default:
+ WARN_ON(1);
+ sk = NULL;
+ }
+
+ pr_debug("tproxy socket lookup: proto %u %pI6:%u -> %pI6:%u, lookup type: %d, sock %p\n",
+ protocol, saddr, ntohs(sport), daddr, ntohs(dport), lookup_type, sk);
+
+ return sk;
+}
+#endif
+
+/* assign a socket to the skb -- consumes sk */
+void
+nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk);
+
+#endif
diff --git a/include/net/netfilter/nfnetlink_log.h b/include/net/netfilter/nfnetlink_log.h
new file mode 100644
index 00000000..e2dec42c
--- /dev/null
+++ b/include/net/netfilter/nfnetlink_log.h
@@ -0,0 +1,16 @@
+#ifndef _KER_NFNETLINK_LOG_H
+#define _KER_NFNETLINK_LOG_H
+
+void
+nfulnl_log_packet(u_int8_t pf,
+ unsigned int hooknum,
+ const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct nf_loginfo *li_user,
+ const char *prefix);
+
+#define NFULNL_COPY_DISABLED 0xff
+
+#endif /* _KER_NFNETLINK_LOG_H */
+
diff --git a/include/net/netfilter/xt_log.h b/include/net/netfilter/xt_log.h
new file mode 100644
index 00000000..9d9756cc
--- /dev/null
+++ b/include/net/netfilter/xt_log.h
@@ -0,0 +1,54 @@
+#define S_SIZE (1024 - (sizeof(unsigned int) + 1))
+
+struct sbuff {
+ unsigned int count;
+ char buf[S_SIZE + 1];
+};
+static struct sbuff emergency, *emergency_ptr = &emergency;
+
+static __printf(2, 3) int sb_add(struct sbuff *m, const char *f, ...)
+{
+ va_list args;
+ int len;
+
+ if (likely(m->count < S_SIZE)) {
+ va_start(args, f);
+ len = vsnprintf(m->buf + m->count, S_SIZE - m->count, f, args);
+ va_end(args);
+ if (likely(m->count + len < S_SIZE)) {
+ m->count += len;
+ return 0;
+ }
+ }
+ m->count = S_SIZE;
+ printk_once(KERN_ERR KBUILD_MODNAME " please increase S_SIZE\n");
+ return -1;
+}
+
+static struct sbuff *sb_open(void)
+{
+ struct sbuff *m = kmalloc(sizeof(*m), GFP_ATOMIC);
+
+ if (unlikely(!m)) {
+ local_bh_disable();
+ do {
+ m = xchg(&emergency_ptr, NULL);
+ } while (!m);
+ }
+ m->count = 0;
+ return m;
+}
+
+static void sb_close(struct sbuff *m)
+{
+ m->buf[m->count] = 0;
+ printk("%s\n", m->buf);
+
+ if (likely(m != &emergency))
+ kfree(m);
+ else {
+ emergency_ptr = m;
+ local_bh_enable();
+ }
+}
+
diff --git a/include/net/netfilter/xt_rateest.h b/include/net/netfilter/xt_rateest.h
new file mode 100644
index 00000000..5a2978d1
--- /dev/null
+++ b/include/net/netfilter/xt_rateest.h
@@ -0,0 +1,22 @@
+#ifndef _XT_RATEEST_H
+#define _XT_RATEEST_H
+
+struct xt_rateest {
+ /* keep lock and bstats on same cache line to speedup xt_rateest_tg() */
+ struct gnet_stats_basic_packed bstats;
+ spinlock_t lock;
+ /* keep rstats and lock on same cache line to speedup xt_rateest_mt() */
+ struct gnet_stats_rate_est rstats;
+
+ /* following fields not accessed in hot path */
+ struct hlist_node list;
+ char name[IFNAMSIZ];
+ unsigned int refcnt;
+ struct gnet_estimator params;
+ struct rcu_head rcu;
+};
+
+extern struct xt_rateest *xt_rateest_lookup(const char *name);
+extern void xt_rateest_put(struct xt_rateest *est);
+
+#endif /* _XT_RATEEST_H */
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
new file mode 100644
index 00000000..f6744097
--- /dev/null
+++ b/include/net/netlabel.h
@@ -0,0 +1,590 @@
+/*
+ * NetLabel System
+ *
+ * The NetLabel system manages static and dynamic label mappings for network
+ * protocols such as CIPSO and RIPSO.
+ *
+ * Author: Paul Moore <paul@paul-moore.com>
+ *
+ */
+
+/*
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _NETLABEL_H
+#define _NETLABEL_H
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/net.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <net/netlink.h>
+#include <net/request_sock.h>
+#include <linux/atomic.h>
+
+struct cipso_v4_doi;
+
+/*
+ * NetLabel - A management interface for maintaining network packet label
+ * mapping tables for explicit packet labling protocols.
+ *
+ * Network protocols such as CIPSO and RIPSO require a label translation layer
+ * to convert the label on the packet into something meaningful on the host
+ * machine. In the current Linux implementation these mapping tables live
+ * inside the kernel; NetLabel provides a mechanism for user space applications
+ * to manage these mapping tables.
+ *
+ * NetLabel makes use of the Generic NETLINK mechanism as a transport layer to
+ * send messages between kernel and user space. The general format of a
+ * NetLabel message is shown below:
+ *
+ * +-----------------+-------------------+--------- --- -- -
+ * | struct nlmsghdr | struct genlmsghdr | payload
+ * +-----------------+-------------------+--------- --- -- -
+ *
+ * The 'nlmsghdr' and 'genlmsghdr' structs should be dealt with like normal.
+ * The payload is dependent on the subsystem specified in the
+ * 'nlmsghdr->nlmsg_type' and should be defined below, supporting functions
+ * should be defined in the corresponding net/netlabel/netlabel_<subsys>.h|c
+ * file. All of the fields in the NetLabel payload are NETLINK attributes, see
+ * the include/net/netlink.h file for more information on NETLINK attributes.
+ *
+ */
+
+/*
+ * NetLabel NETLINK protocol
+ */
+
+/* NetLabel NETLINK protocol version
+ * 1: initial version
+ * 2: added static labels for unlabeled connections
+ * 3: network selectors added to the NetLabel/LSM domain mapping and the
+ * CIPSO_V4_MAP_LOCAL CIPSO mapping was added
+ */
+#define NETLBL_PROTO_VERSION 3
+
+/* NetLabel NETLINK types/families */
+#define NETLBL_NLTYPE_NONE 0
+#define NETLBL_NLTYPE_MGMT 1
+#define NETLBL_NLTYPE_MGMT_NAME "NLBL_MGMT"
+#define NETLBL_NLTYPE_RIPSO 2
+#define NETLBL_NLTYPE_RIPSO_NAME "NLBL_RIPSO"
+#define NETLBL_NLTYPE_CIPSOV4 3
+#define NETLBL_NLTYPE_CIPSOV4_NAME "NLBL_CIPSOv4"
+#define NETLBL_NLTYPE_CIPSOV6 4
+#define NETLBL_NLTYPE_CIPSOV6_NAME "NLBL_CIPSOv6"
+#define NETLBL_NLTYPE_UNLABELED 5
+#define NETLBL_NLTYPE_UNLABELED_NAME "NLBL_UNLBL"
+#define NETLBL_NLTYPE_ADDRSELECT 6
+#define NETLBL_NLTYPE_ADDRSELECT_NAME "NLBL_ADRSEL"
+
+/*
+ * NetLabel - Kernel API for accessing the network packet label mappings.
+ *
+ * The following functions are provided for use by other kernel modules,
+ * specifically kernel LSM modules, to provide a consistent, transparent API
+ * for dealing with explicit packet labeling protocols such as CIPSO and
+ * RIPSO. The functions defined here are implemented in the
+ * net/netlabel/netlabel_kapi.c file.
+ *
+ */
+
+/* NetLabel audit information */
+struct netlbl_audit {
+ u32 secid;
+ uid_t loginuid;
+ u32 sessionid;
+};
+
+/*
+ * LSM security attributes
+ */
+
+/**
+ * struct netlbl_lsm_cache - NetLabel LSM security attribute cache
+ * @refcount: atomic reference counter
+ * @free: LSM supplied function to free the cache data
+ * @data: LSM supplied cache data
+ *
+ * Description:
+ * This structure is provided for LSMs which wish to make use of the NetLabel
+ * caching mechanism to store LSM specific data/attributes in the NetLabel
+ * cache. If the LSM has to perform a lot of translation from the NetLabel
+ * security attributes into it's own internal representation then the cache
+ * mechanism can provide a way to eliminate some or all of that translation
+ * overhead on a cache hit.
+ *
+ */
+struct netlbl_lsm_cache {
+ atomic_t refcount;
+ void (*free) (const void *data);
+ void *data;
+};
+
+/**
+ * struct netlbl_lsm_secattr_catmap - NetLabel LSM secattr category bitmap
+ * @startbit: the value of the lowest order bit in the bitmap
+ * @bitmap: the category bitmap
+ * @next: pointer to the next bitmap "node" or NULL
+ *
+ * Description:
+ * This structure is used to represent category bitmaps. Due to the large
+ * number of categories supported by most labeling protocols it is not
+ * practical to transfer a full bitmap internally so NetLabel adopts a sparse
+ * bitmap structure modeled after SELinux's ebitmap structure.
+ * The catmap bitmap field MUST be a power of two in length and large
+ * enough to hold at least 240 bits. Special care (i.e. check the code!)
+ * should be used when changing these values as the LSM implementation
+ * probably has functions which rely on the sizes of these types to speed
+ * processing.
+ *
+ */
+#define NETLBL_CATMAP_MAPTYPE u64
+#define NETLBL_CATMAP_MAPCNT 4
+#define NETLBL_CATMAP_MAPSIZE (sizeof(NETLBL_CATMAP_MAPTYPE) * 8)
+#define NETLBL_CATMAP_SIZE (NETLBL_CATMAP_MAPSIZE * \
+ NETLBL_CATMAP_MAPCNT)
+#define NETLBL_CATMAP_BIT (NETLBL_CATMAP_MAPTYPE)0x01
+struct netlbl_lsm_secattr_catmap {
+ u32 startbit;
+ NETLBL_CATMAP_MAPTYPE bitmap[NETLBL_CATMAP_MAPCNT];
+ struct netlbl_lsm_secattr_catmap *next;
+};
+
+/**
+ * struct netlbl_lsm_secattr - NetLabel LSM security attributes
+ * @flags: indicate structure attributes, see NETLBL_SECATTR_*
+ * @type: indicate the NLTYPE of the attributes
+ * @domain: the NetLabel LSM domain
+ * @cache: NetLabel LSM specific cache
+ * @attr.mls: MLS sensitivity label
+ * @attr.mls.cat: MLS category bitmap
+ * @attr.mls.lvl: MLS sensitivity level
+ * @attr.secid: LSM specific secid token
+ *
+ * Description:
+ * This structure is used to pass security attributes between NetLabel and the
+ * LSM modules. The flags field is used to specify which fields within the
+ * struct are valid and valid values can be created by bitwise OR'ing the
+ * NETLBL_SECATTR_* defines. The domain field is typically set by the LSM to
+ * specify domain specific configuration settings and is not usually used by
+ * NetLabel itself when returning security attributes to the LSM.
+ *
+ */
+struct netlbl_lsm_secattr {
+ u32 flags;
+ /* bitmap values for 'flags' */
+#define NETLBL_SECATTR_NONE 0x00000000
+#define NETLBL_SECATTR_DOMAIN 0x00000001
+#define NETLBL_SECATTR_DOMAIN_CPY (NETLBL_SECATTR_DOMAIN | \
+ NETLBL_SECATTR_FREE_DOMAIN)
+#define NETLBL_SECATTR_CACHE 0x00000002
+#define NETLBL_SECATTR_MLS_LVL 0x00000004
+#define NETLBL_SECATTR_MLS_CAT 0x00000008
+#define NETLBL_SECATTR_SECID 0x00000010
+ /* bitmap meta-values for 'flags' */
+#define NETLBL_SECATTR_FREE_DOMAIN 0x01000000
+#define NETLBL_SECATTR_CACHEABLE (NETLBL_SECATTR_MLS_LVL | \
+ NETLBL_SECATTR_MLS_CAT | \
+ NETLBL_SECATTR_SECID)
+ u32 type;
+ char *domain;
+ struct netlbl_lsm_cache *cache;
+ struct {
+ struct {
+ struct netlbl_lsm_secattr_catmap *cat;
+ u32 lvl;
+ } mls;
+ u32 secid;
+ } attr;
+};
+
+/*
+ * LSM security attribute operations (inline)
+ */
+
+/**
+ * netlbl_secattr_cache_alloc - Allocate and initialize a secattr cache
+ * @flags: the memory allocation flags
+ *
+ * Description:
+ * Allocate and initialize a netlbl_lsm_cache structure. Returns a pointer
+ * on success, NULL on failure.
+ *
+ */
+static inline struct netlbl_lsm_cache *netlbl_secattr_cache_alloc(gfp_t flags)
+{
+ struct netlbl_lsm_cache *cache;
+
+ cache = kzalloc(sizeof(*cache), flags);
+ if (cache)
+ atomic_set(&cache->refcount, 1);
+ return cache;
+}
+
+/**
+ * netlbl_secattr_cache_free - Frees a netlbl_lsm_cache struct
+ * @cache: the struct to free
+ *
+ * Description:
+ * Frees @secattr including all of the internal buffers.
+ *
+ */
+static inline void netlbl_secattr_cache_free(struct netlbl_lsm_cache *cache)
+{
+ if (!atomic_dec_and_test(&cache->refcount))
+ return;
+
+ if (cache->free)
+ cache->free(cache->data);
+ kfree(cache);
+}
+
+/**
+ * netlbl_secattr_catmap_alloc - Allocate a LSM secattr catmap
+ * @flags: memory allocation flags
+ *
+ * Description:
+ * Allocate memory for a LSM secattr catmap, returns a pointer on success, NULL
+ * on failure.
+ *
+ */
+static inline struct netlbl_lsm_secattr_catmap *netlbl_secattr_catmap_alloc(
+ gfp_t flags)
+{
+ return kzalloc(sizeof(struct netlbl_lsm_secattr_catmap), flags);
+}
+
+/**
+ * netlbl_secattr_catmap_free - Free a LSM secattr catmap
+ * @catmap: the category bitmap
+ *
+ * Description:
+ * Free a LSM secattr catmap.
+ *
+ */
+static inline void netlbl_secattr_catmap_free(
+ struct netlbl_lsm_secattr_catmap *catmap)
+{
+ struct netlbl_lsm_secattr_catmap *iter;
+
+ do {
+ iter = catmap;
+ catmap = catmap->next;
+ kfree(iter);
+ } while (catmap);
+}
+
+/**
+ * netlbl_secattr_init - Initialize a netlbl_lsm_secattr struct
+ * @secattr: the struct to initialize
+ *
+ * Description:
+ * Initialize an already allocated netlbl_lsm_secattr struct.
+ *
+ */
+static inline void netlbl_secattr_init(struct netlbl_lsm_secattr *secattr)
+{
+ memset(secattr, 0, sizeof(*secattr));
+}
+
+/**
+ * netlbl_secattr_destroy - Clears a netlbl_lsm_secattr struct
+ * @secattr: the struct to clear
+ *
+ * Description:
+ * Destroys the @secattr struct, including freeing all of the internal buffers.
+ * The struct must be reset with a call to netlbl_secattr_init() before reuse.
+ *
+ */
+static inline void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr)
+{
+ if (secattr->flags & NETLBL_SECATTR_FREE_DOMAIN)
+ kfree(secattr->domain);
+ if (secattr->flags & NETLBL_SECATTR_CACHE)
+ netlbl_secattr_cache_free(secattr->cache);
+ if (secattr->flags & NETLBL_SECATTR_MLS_CAT)
+ netlbl_secattr_catmap_free(secattr->attr.mls.cat);
+}
+
+/**
+ * netlbl_secattr_alloc - Allocate and initialize a netlbl_lsm_secattr struct
+ * @flags: the memory allocation flags
+ *
+ * Description:
+ * Allocate and initialize a netlbl_lsm_secattr struct. Returns a valid
+ * pointer on success, or NULL on failure.
+ *
+ */
+static inline struct netlbl_lsm_secattr *netlbl_secattr_alloc(gfp_t flags)
+{
+ return kzalloc(sizeof(struct netlbl_lsm_secattr), flags);
+}
+
+/**
+ * netlbl_secattr_free - Frees a netlbl_lsm_secattr struct
+ * @secattr: the struct to free
+ *
+ * Description:
+ * Frees @secattr including all of the internal buffers.
+ *
+ */
+static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr)
+{
+ netlbl_secattr_destroy(secattr);
+ kfree(secattr);
+}
+
+#ifdef CONFIG_NETLABEL
+/*
+ * LSM configuration operations
+ */
+int netlbl_cfg_map_del(const char *domain,
+ u16 family,
+ const void *addr,
+ const void *mask,
+ struct netlbl_audit *audit_info);
+int netlbl_cfg_unlbl_map_add(const char *domain,
+ u16 family,
+ const void *addr,
+ const void *mask,
+ struct netlbl_audit *audit_info);
+int netlbl_cfg_unlbl_static_add(struct net *net,
+ const char *dev_name,
+ const void *addr,
+ const void *mask,
+ u16 family,
+ u32 secid,
+ struct netlbl_audit *audit_info);
+int netlbl_cfg_unlbl_static_del(struct net *net,
+ const char *dev_name,
+ const void *addr,
+ const void *mask,
+ u16 family,
+ struct netlbl_audit *audit_info);
+int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
+ struct netlbl_audit *audit_info);
+void netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info);
+int netlbl_cfg_cipsov4_map_add(u32 doi,
+ const char *domain,
+ const struct in_addr *addr,
+ const struct in_addr *mask,
+ struct netlbl_audit *audit_info);
+/*
+ * LSM security attribute operations
+ */
+int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap,
+ u32 offset);
+int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
+ u32 offset);
+int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap,
+ u32 bit,
+ gfp_t flags);
+int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
+ u32 start,
+ u32 end,
+ gfp_t flags);
+
+/*
+ * LSM protocol operations (NetLabel LSM/kernel API)
+ */
+int netlbl_enabled(void);
+int netlbl_sock_setattr(struct sock *sk,
+ u16 family,
+ const struct netlbl_lsm_secattr *secattr);
+void netlbl_sock_delattr(struct sock *sk);
+int netlbl_sock_getattr(struct sock *sk,
+ struct netlbl_lsm_secattr *secattr);
+int netlbl_conn_setattr(struct sock *sk,
+ struct sockaddr *addr,
+ const struct netlbl_lsm_secattr *secattr);
+int netlbl_req_setattr(struct request_sock *req,
+ const struct netlbl_lsm_secattr *secattr);
+void netlbl_req_delattr(struct request_sock *req);
+int netlbl_skbuff_setattr(struct sk_buff *skb,
+ u16 family,
+ const struct netlbl_lsm_secattr *secattr);
+int netlbl_skbuff_getattr(const struct sk_buff *skb,
+ u16 family,
+ struct netlbl_lsm_secattr *secattr);
+void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway);
+
+/*
+ * LSM label mapping cache operations
+ */
+void netlbl_cache_invalidate(void);
+int netlbl_cache_add(const struct sk_buff *skb,
+ const struct netlbl_lsm_secattr *secattr);
+
+/*
+ * Protocol engine operations
+ */
+struct audit_buffer *netlbl_audit_start(int type,
+ struct netlbl_audit *audit_info);
+#else
+static inline int netlbl_cfg_map_del(const char *domain,
+ u16 family,
+ const void *addr,
+ const void *mask,
+ struct netlbl_audit *audit_info)
+{
+ return -ENOSYS;
+}
+static inline int netlbl_cfg_unlbl_map_add(const char *domain,
+ u16 family,
+ void *addr,
+ void *mask,
+ struct netlbl_audit *audit_info)
+{
+ return -ENOSYS;
+}
+static inline int netlbl_cfg_unlbl_static_add(struct net *net,
+ const char *dev_name,
+ const void *addr,
+ const void *mask,
+ u16 family,
+ u32 secid,
+ struct netlbl_audit *audit_info)
+{
+ return -ENOSYS;
+}
+static inline int netlbl_cfg_unlbl_static_del(struct net *net,
+ const char *dev_name,
+ const void *addr,
+ const void *mask,
+ u16 family,
+ struct netlbl_audit *audit_info)
+{
+ return -ENOSYS;
+}
+static inline int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
+ struct netlbl_audit *audit_info)
+{
+ return -ENOSYS;
+}
+static inline void netlbl_cfg_cipsov4_del(u32 doi,
+ struct netlbl_audit *audit_info)
+{
+ return;
+}
+static inline int netlbl_cfg_cipsov4_map_add(u32 doi,
+ const char *domain,
+ const struct in_addr *addr,
+ const struct in_addr *mask,
+ struct netlbl_audit *audit_info)
+{
+ return -ENOSYS;
+}
+static inline int netlbl_secattr_catmap_walk(
+ struct netlbl_lsm_secattr_catmap *catmap,
+ u32 offset)
+{
+ return -ENOENT;
+}
+static inline int netlbl_secattr_catmap_walk_rng(
+ struct netlbl_lsm_secattr_catmap *catmap,
+ u32 offset)
+{
+ return -ENOENT;
+}
+static inline int netlbl_secattr_catmap_setbit(
+ struct netlbl_lsm_secattr_catmap *catmap,
+ u32 bit,
+ gfp_t flags)
+{
+ return 0;
+}
+static inline int netlbl_secattr_catmap_setrng(
+ struct netlbl_lsm_secattr_catmap *catmap,
+ u32 start,
+ u32 end,
+ gfp_t flags)
+{
+ return 0;
+}
+static inline int netlbl_enabled(void)
+{
+ return 0;
+}
+static inline int netlbl_sock_setattr(struct sock *sk,
+ u16 family,
+ const struct netlbl_lsm_secattr *secattr)
+{
+ return -ENOSYS;
+}
+static inline void netlbl_sock_delattr(struct sock *sk)
+{
+}
+static inline int netlbl_sock_getattr(struct sock *sk,
+ struct netlbl_lsm_secattr *secattr)
+{
+ return -ENOSYS;
+}
+static inline int netlbl_conn_setattr(struct sock *sk,
+ struct sockaddr *addr,
+ const struct netlbl_lsm_secattr *secattr)
+{
+ return -ENOSYS;
+}
+static inline int netlbl_req_setattr(struct request_sock *req,
+ const struct netlbl_lsm_secattr *secattr)
+{
+ return -ENOSYS;
+}
+static inline void netlbl_req_delattr(struct request_sock *req)
+{
+ return;
+}
+static inline int netlbl_skbuff_setattr(struct sk_buff *skb,
+ u16 family,
+ const struct netlbl_lsm_secattr *secattr)
+{
+ return -ENOSYS;
+}
+static inline int netlbl_skbuff_getattr(const struct sk_buff *skb,
+ u16 family,
+ struct netlbl_lsm_secattr *secattr)
+{
+ return -ENOSYS;
+}
+static inline void netlbl_skbuff_err(struct sk_buff *skb,
+ int error,
+ int gateway)
+{
+ return;
+}
+static inline void netlbl_cache_invalidate(void)
+{
+ return;
+}
+static inline int netlbl_cache_add(const struct sk_buff *skb,
+ const struct netlbl_lsm_secattr *secattr)
+{
+ return 0;
+}
+static inline struct audit_buffer *netlbl_audit_start(int type,
+ struct netlbl_audit *audit_info)
+{
+ return NULL;
+}
+#endif /* CONFIG_NETLABEL */
+
+#endif /* _NETLABEL_H */
diff --git a/include/net/netlink.h b/include/net/netlink.h
new file mode 100644
index 00000000..f394fe5d
--- /dev/null
+++ b/include/net/netlink.h
@@ -0,0 +1,1072 @@
+#ifndef __NET_NETLINK_H
+#define __NET_NETLINK_H
+
+#include <linux/types.h>
+#include <linux/netlink.h>
+#include <linux/jiffies.h>
+
+/* ========================================================================
+ * Netlink Messages and Attributes Interface (As Seen On TV)
+ * ------------------------------------------------------------------------
+ * Messages Interface
+ * ------------------------------------------------------------------------
+ *
+ * Message Format:
+ * <--- nlmsg_total_size(payload) --->
+ * <-- nlmsg_msg_size(payload) ->
+ * +----------+- - -+-------------+- - -+-------- - -
+ * | nlmsghdr | Pad | Payload | Pad | nlmsghdr
+ * +----------+- - -+-------------+- - -+-------- - -
+ * nlmsg_data(nlh)---^ ^
+ * nlmsg_next(nlh)-----------------------+
+ *
+ * Payload Format:
+ * <---------------------- nlmsg_len(nlh) --------------------->
+ * <------ hdrlen ------> <- nlmsg_attrlen(nlh, hdrlen) ->
+ * +----------------------+- - -+--------------------------------+
+ * | Family Header | Pad | Attributes |
+ * +----------------------+- - -+--------------------------------+
+ * nlmsg_attrdata(nlh, hdrlen)---^
+ *
+ * Data Structures:
+ * struct nlmsghdr netlink message header
+ *
+ * Message Construction:
+ * nlmsg_new() create a new netlink message
+ * nlmsg_put() add a netlink message to an skb
+ * nlmsg_put_answer() callback based nlmsg_put()
+ * nlmsg_end() finalize netlink message
+ * nlmsg_get_pos() return current position in message
+ * nlmsg_trim() trim part of message
+ * nlmsg_cancel() cancel message construction
+ * nlmsg_free() free a netlink message
+ *
+ * Message Sending:
+ * nlmsg_multicast() multicast message to several groups
+ * nlmsg_unicast() unicast a message to a single socket
+ * nlmsg_notify() send notification message
+ *
+ * Message Length Calculations:
+ * nlmsg_msg_size(payload) length of message w/o padding
+ * nlmsg_total_size(payload) length of message w/ padding
+ * nlmsg_padlen(payload) length of padding at tail
+ *
+ * Message Payload Access:
+ * nlmsg_data(nlh) head of message payload
+ * nlmsg_len(nlh) length of message payload
+ * nlmsg_attrdata(nlh, hdrlen) head of attributes data
+ * nlmsg_attrlen(nlh, hdrlen) length of attributes data
+ *
+ * Message Parsing:
+ * nlmsg_ok(nlh, remaining) does nlh fit into remaining bytes?
+ * nlmsg_next(nlh, remaining) get next netlink message
+ * nlmsg_parse() parse attributes of a message
+ * nlmsg_find_attr() find an attribute in a message
+ * nlmsg_for_each_msg() loop over all messages
+ * nlmsg_validate() validate netlink message incl. attrs
+ * nlmsg_for_each_attr() loop over all attributes
+ *
+ * Misc:
+ * nlmsg_report() report back to application?
+ *
+ * ------------------------------------------------------------------------
+ * Attributes Interface
+ * ------------------------------------------------------------------------
+ *
+ * Attribute Format:
+ * <------- nla_total_size(payload) ------->
+ * <---- nla_attr_size(payload) ----->
+ * +----------+- - -+- - - - - - - - - +- - -+-------- - -
+ * | Header | Pad | Payload | Pad | Header
+ * +----------+- - -+- - - - - - - - - +- - -+-------- - -
+ * <- nla_len(nla) -> ^
+ * nla_data(nla)----^ |
+ * nla_next(nla)-----------------------------'
+ *
+ * Data Structures:
+ * struct nlattr netlink attribute header
+ *
+ * Attribute Construction:
+ * nla_reserve(skb, type, len) reserve room for an attribute
+ * nla_reserve_nohdr(skb, len) reserve room for an attribute w/o hdr
+ * nla_put(skb, type, len, data) add attribute to skb
+ * nla_put_nohdr(skb, len, data) add attribute w/o hdr
+ * nla_append(skb, len, data) append data to skb
+ *
+ * Attribute Construction for Basic Types:
+ * nla_put_u8(skb, type, value) add u8 attribute to skb
+ * nla_put_u16(skb, type, value) add u16 attribute to skb
+ * nla_put_u32(skb, type, value) add u32 attribute to skb
+ * nla_put_u64(skb, type, value) add u64 attribute to skb
+ * nla_put_string(skb, type, str) add string attribute to skb
+ * nla_put_flag(skb, type) add flag attribute to skb
+ * nla_put_msecs(skb, type, jiffies) add msecs attribute to skb
+ *
+ * Exceptions Based Attribute Construction:
+ * NLA_PUT(skb, type, len, data) add attribute to skb
+ * NLA_PUT_U8(skb, type, value) add u8 attribute to skb
+ * NLA_PUT_U16(skb, type, value) add u16 attribute to skb
+ * NLA_PUT_U32(skb, type, value) add u32 attribute to skb
+ * NLA_PUT_U64(skb, type, value) add u64 attribute to skb
+ * NLA_PUT_STRING(skb, type, str) add string attribute to skb
+ * NLA_PUT_FLAG(skb, type) add flag attribute to skb
+ * NLA_PUT_MSECS(skb, type, jiffies) add msecs attribute to skb
+ *
+ * The meaning of these functions is equal to their lower case
+ * variants but they jump to the label nla_put_failure in case
+ * of a failure.
+ *
+ * Nested Attributes Construction:
+ * nla_nest_start(skb, type) start a nested attribute
+ * nla_nest_end(skb, nla) finalize a nested attribute
+ * nla_nest_cancel(skb, nla) cancel nested attribute construction
+ *
+ * Attribute Length Calculations:
+ * nla_attr_size(payload) length of attribute w/o padding
+ * nla_total_size(payload) length of attribute w/ padding
+ * nla_padlen(payload) length of padding
+ *
+ * Attribute Payload Access:
+ * nla_data(nla) head of attribute payload
+ * nla_len(nla) length of attribute payload
+ *
+ * Attribute Payload Access for Basic Types:
+ * nla_get_u8(nla) get payload for a u8 attribute
+ * nla_get_u16(nla) get payload for a u16 attribute
+ * nla_get_u32(nla) get payload for a u32 attribute
+ * nla_get_u64(nla) get payload for a u64 attribute
+ * nla_get_flag(nla) return 1 if flag is true
+ * nla_get_msecs(nla) get payload for a msecs attribute
+ *
+ * Attribute Misc:
+ * nla_memcpy(dest, nla, count) copy attribute into memory
+ * nla_memcmp(nla, data, size) compare attribute with memory area
+ * nla_strlcpy(dst, nla, size) copy attribute to a sized string
+ * nla_strcmp(nla, str) compare attribute with string
+ *
+ * Attribute Parsing:
+ * nla_ok(nla, remaining) does nla fit into remaining bytes?
+ * nla_next(nla, remaining) get next netlink attribute
+ * nla_validate() validate a stream of attributes
+ * nla_validate_nested() validate a stream of nested attributes
+ * nla_find() find attribute in stream of attributes
+ * nla_find_nested() find attribute in nested attributes
+ * nla_parse() parse and validate stream of attrs
+ * nla_parse_nested() parse nested attribuets
+ * nla_for_each_attr() loop over all attributes
+ * nla_for_each_nested() loop over the nested attributes
+ *=========================================================================
+ */
+
+ /**
+ * Standard attribute types to specify validation policy
+ */
+enum {
+ NLA_UNSPEC,
+ NLA_U8,
+ NLA_U16,
+ NLA_U32,
+ NLA_U64,
+ NLA_STRING,
+ NLA_FLAG,
+ NLA_MSECS,
+ NLA_NESTED,
+ NLA_NESTED_COMPAT,
+ NLA_NUL_STRING,
+ NLA_BINARY,
+ __NLA_TYPE_MAX,
+};
+
+#define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1)
+
+/**
+ * struct nla_policy - attribute validation policy
+ * @type: Type of attribute or NLA_UNSPEC
+ * @len: Type specific length of payload
+ *
+ * Policies are defined as arrays of this struct, the array must be
+ * accessible by attribute type up to the highest identifier to be expected.
+ *
+ * Meaning of `len' field:
+ * NLA_STRING Maximum length of string
+ * NLA_NUL_STRING Maximum length of string (excluding NUL)
+ * NLA_FLAG Unused
+ * NLA_BINARY Maximum length of attribute payload
+ * NLA_NESTED Don't use `len' field -- length verification is
+ * done by checking len of nested header (or empty)
+ * NLA_NESTED_COMPAT Minimum length of structure payload
+ * NLA_U8, NLA_U16,
+ * NLA_U32, NLA_U64,
+ * NLA_MSECS Leaving the length field zero will verify the
+ * given type fits, using it verifies minimum length
+ * just like "All other"
+ * All other Minimum length of attribute payload
+ *
+ * Example:
+ * static const struct nla_policy my_policy[ATTR_MAX+1] = {
+ * [ATTR_FOO] = { .type = NLA_U16 },
+ * [ATTR_BAR] = { .type = NLA_STRING, .len = BARSIZ },
+ * [ATTR_BAZ] = { .len = sizeof(struct mystruct) },
+ * };
+ */
+struct nla_policy {
+ u16 type;
+ u16 len;
+};
+
+/**
+ * struct nl_info - netlink source information
+ * @nlh: Netlink message header of original request
+ * @pid: Netlink PID of requesting application
+ */
+struct nl_info {
+ struct nlmsghdr *nlh;
+ struct net *nl_net;
+ u32 pid;
+};
+
+extern int netlink_rcv_skb(struct sk_buff *skb,
+ int (*cb)(struct sk_buff *,
+ struct nlmsghdr *));
+extern int nlmsg_notify(struct sock *sk, struct sk_buff *skb,
+ u32 pid, unsigned int group, int report,
+ gfp_t flags);
+
+extern int nla_validate(const struct nlattr *head,
+ int len, int maxtype,
+ const struct nla_policy *policy);
+extern int nla_parse(struct nlattr **tb, int maxtype,
+ const struct nlattr *head, int len,
+ const struct nla_policy *policy);
+extern int nla_policy_len(const struct nla_policy *, int);
+extern struct nlattr * nla_find(const struct nlattr *head,
+ int len, int attrtype);
+extern size_t nla_strlcpy(char *dst, const struct nlattr *nla,
+ size_t dstsize);
+extern int nla_memcpy(void *dest, const struct nlattr *src, int count);
+extern int nla_memcmp(const struct nlattr *nla, const void *data,
+ size_t size);
+extern int nla_strcmp(const struct nlattr *nla, const char *str);
+extern struct nlattr * __nla_reserve(struct sk_buff *skb, int attrtype,
+ int attrlen);
+extern void * __nla_reserve_nohdr(struct sk_buff *skb, int attrlen);
+extern struct nlattr * nla_reserve(struct sk_buff *skb, int attrtype,
+ int attrlen);
+extern void * nla_reserve_nohdr(struct sk_buff *skb, int attrlen);
+extern void __nla_put(struct sk_buff *skb, int attrtype,
+ int attrlen, const void *data);
+extern void __nla_put_nohdr(struct sk_buff *skb, int attrlen,
+ const void *data);
+extern int nla_put(struct sk_buff *skb, int attrtype,
+ int attrlen, const void *data);
+extern int nla_put_nohdr(struct sk_buff *skb, int attrlen,
+ const void *data);
+extern int nla_append(struct sk_buff *skb, int attrlen,
+ const void *data);
+
+/**************************************************************************
+ * Netlink Messages
+ **************************************************************************/
+
+/**
+ * nlmsg_msg_size - length of netlink message not including padding
+ * @payload: length of message payload
+ */
+static inline int nlmsg_msg_size(int payload)
+{
+ return NLMSG_HDRLEN + payload;
+}
+
+/**
+ * nlmsg_total_size - length of netlink message including padding
+ * @payload: length of message payload
+ */
+static inline int nlmsg_total_size(int payload)
+{
+ return NLMSG_ALIGN(nlmsg_msg_size(payload));
+}
+
+/**
+ * nlmsg_padlen - length of padding at the message's tail
+ * @payload: length of message payload
+ */
+static inline int nlmsg_padlen(int payload)
+{
+ return nlmsg_total_size(payload) - nlmsg_msg_size(payload);
+}
+
+/**
+ * nlmsg_data - head of message payload
+ * @nlh: netlink message header
+ */
+static inline void *nlmsg_data(const struct nlmsghdr *nlh)
+{
+ return (unsigned char *) nlh + NLMSG_HDRLEN;
+}
+
+/**
+ * nlmsg_len - length of message payload
+ * @nlh: netlink message header
+ */
+static inline int nlmsg_len(const struct nlmsghdr *nlh)
+{
+ return nlh->nlmsg_len - NLMSG_HDRLEN;
+}
+
+/**
+ * nlmsg_attrdata - head of attributes data
+ * @nlh: netlink message header
+ * @hdrlen: length of family specific header
+ */
+static inline struct nlattr *nlmsg_attrdata(const struct nlmsghdr *nlh,
+ int hdrlen)
+{
+ unsigned char *data = nlmsg_data(nlh);
+ return (struct nlattr *) (data + NLMSG_ALIGN(hdrlen));
+}
+
+/**
+ * nlmsg_attrlen - length of attributes data
+ * @nlh: netlink message header
+ * @hdrlen: length of family specific header
+ */
+static inline int nlmsg_attrlen(const struct nlmsghdr *nlh, int hdrlen)
+{
+ return nlmsg_len(nlh) - NLMSG_ALIGN(hdrlen);
+}
+
+/**
+ * nlmsg_ok - check if the netlink message fits into the remaining bytes
+ * @nlh: netlink message header
+ * @remaining: number of bytes remaining in message stream
+ */
+static inline int nlmsg_ok(const struct nlmsghdr *nlh, int remaining)
+{
+ return (remaining >= (int) sizeof(struct nlmsghdr) &&
+ nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
+ nlh->nlmsg_len <= remaining);
+}
+
+/**
+ * nlmsg_next - next netlink message in message stream
+ * @nlh: netlink message header
+ * @remaining: number of bytes remaining in message stream
+ *
+ * Returns the next netlink message in the message stream and
+ * decrements remaining by the size of the current message.
+ */
+static inline struct nlmsghdr *
+nlmsg_next(const struct nlmsghdr *nlh, int *remaining)
+{
+ int totlen = NLMSG_ALIGN(nlh->nlmsg_len);
+
+ *remaining -= totlen;
+
+ return (struct nlmsghdr *) ((unsigned char *) nlh + totlen);
+}
+
+/**
+ * nlmsg_parse - parse attributes of a netlink message
+ * @nlh: netlink message header
+ * @hdrlen: length of family specific header
+ * @tb: destination array with maxtype+1 elements
+ * @maxtype: maximum attribute type to be expected
+ * @policy: validation policy
+ *
+ * See nla_parse()
+ */
+static inline int nlmsg_parse(const struct nlmsghdr *nlh, int hdrlen,
+ struct nlattr *tb[], int maxtype,
+ const struct nla_policy *policy)
+{
+ if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
+ return -EINVAL;
+
+ return nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen),
+ nlmsg_attrlen(nlh, hdrlen), policy);
+}
+
+/**
+ * nlmsg_find_attr - find a specific attribute in a netlink message
+ * @nlh: netlink message header
+ * @hdrlen: length of familiy specific header
+ * @attrtype: type of attribute to look for
+ *
+ * Returns the first attribute which matches the specified type.
+ */
+static inline struct nlattr *nlmsg_find_attr(const struct nlmsghdr *nlh,
+ int hdrlen, int attrtype)
+{
+ return nla_find(nlmsg_attrdata(nlh, hdrlen),
+ nlmsg_attrlen(nlh, hdrlen), attrtype);
+}
+
+/**
+ * nlmsg_validate - validate a netlink message including attributes
+ * @nlh: netlinket message header
+ * @hdrlen: length of familiy specific header
+ * @maxtype: maximum attribute type to be expected
+ * @policy: validation policy
+ */
+static inline int nlmsg_validate(const struct nlmsghdr *nlh,
+ int hdrlen, int maxtype,
+ const struct nla_policy *policy)
+{
+ if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
+ return -EINVAL;
+
+ return nla_validate(nlmsg_attrdata(nlh, hdrlen),
+ nlmsg_attrlen(nlh, hdrlen), maxtype, policy);
+}
+
+/**
+ * nlmsg_report - need to report back to application?
+ * @nlh: netlink message header
+ *
+ * Returns 1 if a report back to the application is requested.
+ */
+static inline int nlmsg_report(const struct nlmsghdr *nlh)
+{
+ return !!(nlh->nlmsg_flags & NLM_F_ECHO);
+}
+
+/**
+ * nlmsg_for_each_attr - iterate over a stream of attributes
+ * @pos: loop counter, set to current attribute
+ * @nlh: netlink message header
+ * @hdrlen: length of familiy specific header
+ * @rem: initialized to len, holds bytes currently remaining in stream
+ */
+#define nlmsg_for_each_attr(pos, nlh, hdrlen, rem) \
+ nla_for_each_attr(pos, nlmsg_attrdata(nlh, hdrlen), \
+ nlmsg_attrlen(nlh, hdrlen), rem)
+
+/**
+ * nlmsg_put - Add a new netlink message to an skb
+ * @skb: socket buffer to store message in
+ * @pid: netlink process id
+ * @seq: sequence number of message
+ * @type: message type
+ * @payload: length of message payload
+ * @flags: message flags
+ *
+ * Returns NULL if the tailroom of the skb is insufficient to store
+ * the message header and payload.
+ */
+static inline struct nlmsghdr *nlmsg_put(struct sk_buff *skb, u32 pid, u32 seq,
+ int type, int payload, int flags)
+{
+ if (unlikely(skb_tailroom(skb) < nlmsg_total_size(payload)))
+ return NULL;
+
+ return __nlmsg_put(skb, pid, seq, type, payload, flags);
+}
+
+/**
+ * nlmsg_put_answer - Add a new callback based netlink message to an skb
+ * @skb: socket buffer to store message in
+ * @cb: netlink callback
+ * @type: message type
+ * @payload: length of message payload
+ * @flags: message flags
+ *
+ * Returns NULL if the tailroom of the skb is insufficient to store
+ * the message header and payload.
+ */
+static inline struct nlmsghdr *nlmsg_put_answer(struct sk_buff *skb,
+ struct netlink_callback *cb,
+ int type, int payload,
+ int flags)
+{
+ return nlmsg_put(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
+ type, payload, flags);
+}
+
+/**
+ * nlmsg_new - Allocate a new netlink message
+ * @payload: size of the message payload
+ * @flags: the type of memory to allocate.
+ *
+ * Use NLMSG_DEFAULT_SIZE if the size of the payload isn't known
+ * and a good default is needed.
+ */
+static inline struct sk_buff *nlmsg_new(size_t payload, gfp_t flags)
+{
+ return alloc_skb(nlmsg_total_size(payload), flags);
+}
+
+/**
+ * nlmsg_end - Finalize a netlink message
+ * @skb: socket buffer the message is stored in
+ * @nlh: netlink message header
+ *
+ * Corrects the netlink message header to include the appeneded
+ * attributes. Only necessary if attributes have been added to
+ * the message.
+ *
+ * Returns the total data length of the skb.
+ */
+static inline int nlmsg_end(struct sk_buff *skb, struct nlmsghdr *nlh)
+{
+ nlh->nlmsg_len = skb_tail_pointer(skb) - (unsigned char *)nlh;
+
+ return skb->len;
+}
+
+/**
+ * nlmsg_get_pos - return current position in netlink message
+ * @skb: socket buffer the message is stored in
+ *
+ * Returns a pointer to the current tail of the message.
+ */
+static inline void *nlmsg_get_pos(struct sk_buff *skb)
+{
+ return skb_tail_pointer(skb);
+}
+
+/**
+ * nlmsg_trim - Trim message to a mark
+ * @skb: socket buffer the message is stored in
+ * @mark: mark to trim to
+ *
+ * Trims the message to the provided mark.
+ */
+static inline void nlmsg_trim(struct sk_buff *skb, const void *mark)
+{
+ if (mark)
+ skb_trim(skb, (unsigned char *) mark - skb->data);
+}
+
+/**
+ * nlmsg_cancel - Cancel construction of a netlink message
+ * @skb: socket buffer the message is stored in
+ * @nlh: netlink message header
+ *
+ * Removes the complete netlink message including all
+ * attributes from the socket buffer again.
+ */
+static inline void nlmsg_cancel(struct sk_buff *skb, struct nlmsghdr *nlh)
+{
+ nlmsg_trim(skb, nlh);
+}
+
+/**
+ * nlmsg_free - free a netlink message
+ * @skb: socket buffer of netlink message
+ */
+static inline void nlmsg_free(struct sk_buff *skb)
+{
+ kfree_skb(skb);
+}
+
+/**
+ * nlmsg_multicast - multicast a netlink message
+ * @sk: netlink socket to spread messages to
+ * @skb: netlink message as socket buffer
+ * @pid: own netlink pid to avoid sending to yourself
+ * @group: multicast group id
+ * @flags: allocation flags
+ */
+static inline int nlmsg_multicast(struct sock *sk, struct sk_buff *skb,
+ u32 pid, unsigned int group, gfp_t flags)
+{
+ int err;
+
+ NETLINK_CB(skb).dst_group = group;
+
+ err = netlink_broadcast(sk, skb, pid, group, flags);
+ if (err > 0)
+ err = 0;
+
+ return err;
+}
+
+/**
+ * nlmsg_unicast - unicast a netlink message
+ * @sk: netlink socket to spread message to
+ * @skb: netlink message as socket buffer
+ * @pid: netlink pid of the destination socket
+ */
+static inline int nlmsg_unicast(struct sock *sk, struct sk_buff *skb, u32 pid)
+{
+ int err;
+
+ err = netlink_unicast(sk, skb, pid, MSG_DONTWAIT);
+ if (err > 0)
+ err = 0;
+
+ return err;
+}
+
+/**
+ * nlmsg_for_each_msg - iterate over a stream of messages
+ * @pos: loop counter, set to current message
+ * @head: head of message stream
+ * @len: length of message stream
+ * @rem: initialized to len, holds bytes currently remaining in stream
+ */
+#define nlmsg_for_each_msg(pos, head, len, rem) \
+ for (pos = head, rem = len; \
+ nlmsg_ok(pos, rem); \
+ pos = nlmsg_next(pos, &(rem)))
+
+/**
+ * nl_dump_check_consistent - check if sequence is consistent and advertise if not
+ * @cb: netlink callback structure that stores the sequence number
+ * @nlh: netlink message header to write the flag to
+ *
+ * This function checks if the sequence (generation) number changed during dump
+ * and if it did, advertises it in the netlink message header.
+ *
+ * The correct way to use it is to set cb->seq to the generation counter when
+ * all locks for dumping have been acquired, and then call this function for
+ * each message that is generated.
+ *
+ * Note that due to initialisation concerns, 0 is an invalid sequence number
+ * and must not be used by code that uses this functionality.
+ */
+static inline void
+nl_dump_check_consistent(struct netlink_callback *cb,
+ struct nlmsghdr *nlh)
+{
+ if (cb->prev_seq && cb->seq != cb->prev_seq)
+ nlh->nlmsg_flags |= NLM_F_DUMP_INTR;
+ cb->prev_seq = cb->seq;
+}
+
+/**************************************************************************
+ * Netlink Attributes
+ **************************************************************************/
+
+/**
+ * nla_attr_size - length of attribute not including padding
+ * @payload: length of payload
+ */
+static inline int nla_attr_size(int payload)
+{
+ return NLA_HDRLEN + payload;
+}
+
+/**
+ * nla_total_size - total length of attribute including padding
+ * @payload: length of payload
+ */
+static inline int nla_total_size(int payload)
+{
+ return NLA_ALIGN(nla_attr_size(payload));
+}
+
+/**
+ * nla_padlen - length of padding at the tail of attribute
+ * @payload: length of payload
+ */
+static inline int nla_padlen(int payload)
+{
+ return nla_total_size(payload) - nla_attr_size(payload);
+}
+
+/**
+ * nla_type - attribute type
+ * @nla: netlink attribute
+ */
+static inline int nla_type(const struct nlattr *nla)
+{
+ return nla->nla_type & NLA_TYPE_MASK;
+}
+
+/**
+ * nla_data - head of payload
+ * @nla: netlink attribute
+ */
+static inline void *nla_data(const struct nlattr *nla)
+{
+ return (char *) nla + NLA_HDRLEN;
+}
+
+/**
+ * nla_len - length of payload
+ * @nla: netlink attribute
+ */
+static inline int nla_len(const struct nlattr *nla)
+{
+ return nla->nla_len - NLA_HDRLEN;
+}
+
+/**
+ * nla_ok - check if the netlink attribute fits into the remaining bytes
+ * @nla: netlink attribute
+ * @remaining: number of bytes remaining in attribute stream
+ */
+static inline int nla_ok(const struct nlattr *nla, int remaining)
+{
+ return remaining >= (int) sizeof(*nla) &&
+ nla->nla_len >= sizeof(*nla) &&
+ nla->nla_len <= remaining;
+}
+
+/**
+ * nla_next - next netlink attribute in attribute stream
+ * @nla: netlink attribute
+ * @remaining: number of bytes remaining in attribute stream
+ *
+ * Returns the next netlink attribute in the attribute stream and
+ * decrements remaining by the size of the current attribute.
+ */
+static inline struct nlattr *nla_next(const struct nlattr *nla, int *remaining)
+{
+ int totlen = NLA_ALIGN(nla->nla_len);
+
+ *remaining -= totlen;
+ return (struct nlattr *) ((char *) nla + totlen);
+}
+
+/**
+ * nla_find_nested - find attribute in a set of nested attributes
+ * @nla: attribute containing the nested attributes
+ * @attrtype: type of attribute to look for
+ *
+ * Returns the first attribute which matches the specified type.
+ */
+static inline struct nlattr *
+nla_find_nested(const struct nlattr *nla, int attrtype)
+{
+ return nla_find(nla_data(nla), nla_len(nla), attrtype);
+}
+
+/**
+ * nla_parse_nested - parse nested attributes
+ * @tb: destination array with maxtype+1 elements
+ * @maxtype: maximum attribute type to be expected
+ * @nla: attribute containing the nested attributes
+ * @policy: validation policy
+ *
+ * See nla_parse()
+ */
+static inline int nla_parse_nested(struct nlattr *tb[], int maxtype,
+ const struct nlattr *nla,
+ const struct nla_policy *policy)
+{
+ return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
+}
+
+/**
+ * nla_put_u8 - Add a u8 netlink attribute to a socket buffer
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ * @value: numeric value
+ */
+static inline int nla_put_u8(struct sk_buff *skb, int attrtype, u8 value)
+{
+ return nla_put(skb, attrtype, sizeof(u8), &value);
+}
+
+/**
+ * nla_put_u16 - Add a u16 netlink attribute to a socket buffer
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ * @value: numeric value
+ */
+static inline int nla_put_u16(struct sk_buff *skb, int attrtype, u16 value)
+{
+ return nla_put(skb, attrtype, sizeof(u16), &value);
+}
+
+/**
+ * nla_put_u32 - Add a u32 netlink attribute to a socket buffer
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ * @value: numeric value
+ */
+static inline int nla_put_u32(struct sk_buff *skb, int attrtype, u32 value)
+{
+ return nla_put(skb, attrtype, sizeof(u32), &value);
+}
+
+/**
+ * nla_put_64 - Add a u64 netlink attribute to a socket buffer
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ * @value: numeric value
+ */
+static inline int nla_put_u64(struct sk_buff *skb, int attrtype, u64 value)
+{
+ return nla_put(skb, attrtype, sizeof(u64), &value);
+}
+
+/**
+ * nla_put_string - Add a string netlink attribute to a socket buffer
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ * @str: NUL terminated string
+ */
+static inline int nla_put_string(struct sk_buff *skb, int attrtype,
+ const char *str)
+{
+ return nla_put(skb, attrtype, strlen(str) + 1, str);
+}
+
+/**
+ * nla_put_flag - Add a flag netlink attribute to a socket buffer
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ */
+static inline int nla_put_flag(struct sk_buff *skb, int attrtype)
+{
+ return nla_put(skb, attrtype, 0, NULL);
+}
+
+/**
+ * nla_put_msecs - Add a msecs netlink attribute to a socket buffer
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ * @jiffies: number of msecs in jiffies
+ */
+static inline int nla_put_msecs(struct sk_buff *skb, int attrtype,
+ unsigned long jiffies)
+{
+ u64 tmp = jiffies_to_msecs(jiffies);
+ return nla_put(skb, attrtype, sizeof(u64), &tmp);
+}
+
+#define NLA_PUT(skb, attrtype, attrlen, data) \
+ do { \
+ if (unlikely(nla_put(skb, attrtype, attrlen, data) < 0)) \
+ goto nla_put_failure; \
+ } while(0)
+
+#define NLA_PUT_TYPE(skb, type, attrtype, value) \
+ do { \
+ type __tmp = value; \
+ NLA_PUT(skb, attrtype, sizeof(type), &__tmp); \
+ } while(0)
+
+#define NLA_PUT_U8(skb, attrtype, value) \
+ NLA_PUT_TYPE(skb, u8, attrtype, value)
+
+#define NLA_PUT_U16(skb, attrtype, value) \
+ NLA_PUT_TYPE(skb, u16, attrtype, value)
+
+#define NLA_PUT_LE16(skb, attrtype, value) \
+ NLA_PUT_TYPE(skb, __le16, attrtype, value)
+
+#define NLA_PUT_BE16(skb, attrtype, value) \
+ NLA_PUT_TYPE(skb, __be16, attrtype, value)
+
+#define NLA_PUT_NET16(skb, attrtype, value) \
+ NLA_PUT_BE16(skb, attrtype | NLA_F_NET_BYTEORDER, value)
+
+#define NLA_PUT_U32(skb, attrtype, value) \
+ NLA_PUT_TYPE(skb, u32, attrtype, value)
+
+#define NLA_PUT_BE32(skb, attrtype, value) \
+ NLA_PUT_TYPE(skb, __be32, attrtype, value)
+
+#define NLA_PUT_NET32(skb, attrtype, value) \
+ NLA_PUT_BE32(skb, attrtype | NLA_F_NET_BYTEORDER, value)
+
+#define NLA_PUT_U64(skb, attrtype, value) \
+ NLA_PUT_TYPE(skb, u64, attrtype, value)
+
+#define NLA_PUT_BE64(skb, attrtype, value) \
+ NLA_PUT_TYPE(skb, __be64, attrtype, value)
+
+#define NLA_PUT_NET64(skb, attrtype, value) \
+ NLA_PUT_BE64(skb, attrtype | NLA_F_NET_BYTEORDER, value)
+
+#define NLA_PUT_STRING(skb, attrtype, value) \
+ NLA_PUT(skb, attrtype, strlen(value) + 1, value)
+
+#define NLA_PUT_FLAG(skb, attrtype) \
+ NLA_PUT(skb, attrtype, 0, NULL)
+
+#define NLA_PUT_MSECS(skb, attrtype, jiffies) \
+ NLA_PUT_U64(skb, attrtype, jiffies_to_msecs(jiffies))
+
+/**
+ * nla_get_u32 - return payload of u32 attribute
+ * @nla: u32 netlink attribute
+ */
+static inline u32 nla_get_u32(const struct nlattr *nla)
+{
+ return *(u32 *) nla_data(nla);
+}
+
+/**
+ * nla_get_be32 - return payload of __be32 attribute
+ * @nla: __be32 netlink attribute
+ */
+static inline __be32 nla_get_be32(const struct nlattr *nla)
+{
+ return *(__be32 *) nla_data(nla);
+}
+
+/**
+ * nla_get_u16 - return payload of u16 attribute
+ * @nla: u16 netlink attribute
+ */
+static inline u16 nla_get_u16(const struct nlattr *nla)
+{
+ return *(u16 *) nla_data(nla);
+}
+
+/**
+ * nla_get_be16 - return payload of __be16 attribute
+ * @nla: __be16 netlink attribute
+ */
+static inline __be16 nla_get_be16(const struct nlattr *nla)
+{
+ return *(__be16 *) nla_data(nla);
+}
+
+/**
+ * nla_get_le16 - return payload of __le16 attribute
+ * @nla: __le16 netlink attribute
+ */
+static inline __le16 nla_get_le16(const struct nlattr *nla)
+{
+ return *(__le16 *) nla_data(nla);
+}
+
+/**
+ * nla_get_u8 - return payload of u8 attribute
+ * @nla: u8 netlink attribute
+ */
+static inline u8 nla_get_u8(const struct nlattr *nla)
+{
+ return *(u8 *) nla_data(nla);
+}
+
+/**
+ * nla_get_u64 - return payload of u64 attribute
+ * @nla: u64 netlink attribute
+ */
+static inline u64 nla_get_u64(const struct nlattr *nla)
+{
+ u64 tmp;
+
+ nla_memcpy(&tmp, nla, sizeof(tmp));
+
+ return tmp;
+}
+
+/**
+ * nla_get_be64 - return payload of __be64 attribute
+ * @nla: __be64 netlink attribute
+ */
+static inline __be64 nla_get_be64(const struct nlattr *nla)
+{
+ __be64 tmp;
+
+ nla_memcpy(&tmp, nla, sizeof(tmp));
+
+ return tmp;
+}
+
+/**
+ * nla_get_flag - return payload of flag attribute
+ * @nla: flag netlink attribute
+ */
+static inline int nla_get_flag(const struct nlattr *nla)
+{
+ return !!nla;
+}
+
+/**
+ * nla_get_msecs - return payload of msecs attribute
+ * @nla: msecs netlink attribute
+ *
+ * Returns the number of milliseconds in jiffies.
+ */
+static inline unsigned long nla_get_msecs(const struct nlattr *nla)
+{
+ u64 msecs = nla_get_u64(nla);
+
+ return msecs_to_jiffies((unsigned long) msecs);
+}
+
+/**
+ * nla_nest_start - Start a new level of nested attributes
+ * @skb: socket buffer to add attributes to
+ * @attrtype: attribute type of container
+ *
+ * Returns the container attribute
+ */
+static inline struct nlattr *nla_nest_start(struct sk_buff *skb, int attrtype)
+{
+ struct nlattr *start = (struct nlattr *)skb_tail_pointer(skb);
+
+ if (nla_put(skb, attrtype, 0, NULL) < 0)
+ return NULL;
+
+ return start;
+}
+
+/**
+ * nla_nest_end - Finalize nesting of attributes
+ * @skb: socket buffer the attributes are stored in
+ * @start: container attribute
+ *
+ * Corrects the container attribute header to include the all
+ * appeneded attributes.
+ *
+ * Returns the total data length of the skb.
+ */
+static inline int nla_nest_end(struct sk_buff *skb, struct nlattr *start)
+{
+ start->nla_len = skb_tail_pointer(skb) - (unsigned char *)start;
+ return skb->len;
+}
+
+/**
+ * nla_nest_cancel - Cancel nesting of attributes
+ * @skb: socket buffer the message is stored in
+ * @start: container attribute
+ *
+ * Removes the container attribute and including all nested
+ * attributes. Returns -EMSGSIZE
+ */
+static inline void nla_nest_cancel(struct sk_buff *skb, struct nlattr *start)
+{
+ nlmsg_trim(skb, start);
+}
+
+/**
+ * nla_validate_nested - Validate a stream of nested attributes
+ * @start: container attribute
+ * @maxtype: maximum attribute type to be expected
+ * @policy: validation policy
+ *
+ * Validates all attributes in the nested attribute stream against the
+ * specified policy. Attributes with a type exceeding maxtype will be
+ * ignored. See documenation of struct nla_policy for more details.
+ *
+ * Returns 0 on success or a negative error code.
+ */
+static inline int nla_validate_nested(const struct nlattr *start, int maxtype,
+ const struct nla_policy *policy)
+{
+ return nla_validate(nla_data(start), nla_len(start), maxtype, policy);
+}
+
+/**
+ * nla_for_each_attr - iterate over a stream of attributes
+ * @pos: loop counter, set to current attribute
+ * @head: head of attribute stream
+ * @len: length of attribute stream
+ * @rem: initialized to len, holds bytes currently remaining in stream
+ */
+#define nla_for_each_attr(pos, head, len, rem) \
+ for (pos = head, rem = len; \
+ nla_ok(pos, rem); \
+ pos = nla_next(pos, &(rem)))
+
+/**
+ * nla_for_each_nested - iterate over nested attributes
+ * @pos: loop counter, set to current attribute
+ * @nla: attribute containing the nested attributes
+ * @rem: initialized to len, holds bytes currently remaining in stream
+ */
+#define nla_for_each_nested(pos, nla, rem) \
+ nla_for_each_attr(pos, nla_data(nla), nla_len(nla), rem)
+
+#endif
diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h
new file mode 100644
index 00000000..7a911eca
--- /dev/null
+++ b/include/net/netns/conntrack.h
@@ -0,0 +1,37 @@
+#ifndef __NETNS_CONNTRACK_H
+#define __NETNS_CONNTRACK_H
+
+#include <linux/list.h>
+#include <linux/list_nulls.h>
+#include <linux/atomic.h>
+
+struct ctl_table_header;
+struct nf_conntrack_ecache;
+
+struct netns_ct {
+ atomic_t count;
+ unsigned int expect_count;
+ unsigned int htable_size;
+ struct kmem_cache *nf_conntrack_cachep;
+ struct hlist_nulls_head *hash;
+ struct hlist_head *expect_hash;
+ struct hlist_nulls_head unconfirmed;
+ struct hlist_nulls_head dying;
+ struct ip_conntrack_stat __percpu *stat;
+ struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb;
+ struct nf_exp_event_notifier __rcu *nf_expect_event_cb;
+ int sysctl_events;
+ unsigned int sysctl_events_retry_timeout;
+ int sysctl_acct;
+ int sysctl_tstamp;
+ int sysctl_checksum;
+ unsigned int sysctl_log_invalid; /* Log invalid packets */
+#ifdef CONFIG_SYSCTL
+ struct ctl_table_header *sysctl_header;
+ struct ctl_table_header *acct_sysctl_header;
+ struct ctl_table_header *tstamp_sysctl_header;
+ struct ctl_table_header *event_sysctl_header;
+#endif
+ char *slabname;
+};
+#endif
diff --git a/include/net/netns/core.h b/include/net/netns/core.h
new file mode 100644
index 00000000..78eb1ff7
--- /dev/null
+++ b/include/net/netns/core.h
@@ -0,0 +1,16 @@
+#ifndef __NETNS_CORE_H__
+#define __NETNS_CORE_H__
+
+struct ctl_table_header;
+struct prot_inuse;
+
+struct netns_core {
+ /* core sysctls */
+ struct ctl_table_header *sysctl_hdr;
+
+ int sysctl_somaxconn;
+
+ struct prot_inuse __percpu *inuse;
+};
+
+#endif
diff --git a/include/net/netns/dccp.h b/include/net/netns/dccp.h
new file mode 100644
index 00000000..98d2a7ce
--- /dev/null
+++ b/include/net/netns/dccp.h
@@ -0,0 +1,11 @@
+#ifndef __NETNS_DCCP_H__
+#define __NETNS_DCCP_H__
+
+struct sock;
+
+struct netns_dccp {
+ struct sock *v4_ctl_sk;
+ struct sock *v6_ctl_sk;
+};
+
+#endif
diff --git a/include/net/netns/generic.h b/include/net/netns/generic.h
new file mode 100644
index 00000000..0931618c
--- /dev/null
+++ b/include/net/netns/generic.h
@@ -0,0 +1,48 @@
+/*
+ * generic net pointers
+ */
+
+#ifndef __NET_GENERIC_H__
+#define __NET_GENERIC_H__
+
+#include <linux/bug.h>
+#include <linux/rcupdate.h>
+
+/*
+ * Generic net pointers are to be used by modules to put some private
+ * stuff on the struct net without explicit struct net modification
+ *
+ * The rules are simple:
+ * 1. set pernet_operations->id. After register_pernet_device you
+ * will have the id of your private pointer.
+ * 2. set pernet_operations->size to have the code allocate and free
+ * a private structure pointed to from struct net.
+ * 3. do not change this pointer while the net is alive;
+ * 4. do not try to have any private reference on the net_generic object.
+ *
+ * After accomplishing all of the above, the private pointer can be
+ * accessed with the net_generic() call.
+ */
+
+struct net_generic {
+ unsigned int len;
+ struct rcu_head rcu;
+
+ void *ptr[0];
+};
+
+static inline void *net_generic(const struct net *net, int id)
+{
+ struct net_generic *ng;
+ void *ptr;
+
+ rcu_read_lock();
+ ng = rcu_dereference(net->gen);
+ BUG_ON(id == 0 || id > ng->len);
+ ptr = ng->ptr[id - 1];
+ rcu_read_unlock();
+
+ BUG_ON(!ptr);
+ return ptr;
+}
+#endif
diff --git a/include/net/netns/hash.h b/include/net/netns/hash.h
new file mode 100644
index 00000000..548d78f2
--- /dev/null
+++ b/include/net/netns/hash.h
@@ -0,0 +1,21 @@
+#ifndef __NET_NS_HASH_H__
+#define __NET_NS_HASH_H__
+
+#include <asm/cache.h>
+
+struct net;
+
+static inline unsigned net_hash_mix(struct net *net)
+{
+#ifdef CONFIG_NET_NS
+ /*
+ * shift this right to eliminate bits, that are
+ * always zeroed
+ */
+
+ return (unsigned)(((unsigned long)net) >> L1_CACHE_SHIFT);
+#else
+ return 0;
+#endif
+}
+#endif
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
new file mode 100644
index 00000000..bbd023a1
--- /dev/null
+++ b/include/net/netns/ipv4.h
@@ -0,0 +1,72 @@
+/*
+ * ipv4 in net namespaces
+ */
+
+#ifndef __NETNS_IPV4_H__
+#define __NETNS_IPV4_H__
+
+#include <net/inet_frag.h>
+
+struct ctl_table_header;
+struct ipv4_devconf;
+struct fib_rules_ops;
+struct hlist_head;
+struct sock;
+
+struct netns_ipv4 {
+#ifdef CONFIG_SYSCTL
+ struct ctl_table_header *forw_hdr;
+ struct ctl_table_header *frags_hdr;
+ struct ctl_table_header *ipv4_hdr;
+ struct ctl_table_header *route_hdr;
+#endif
+ struct ipv4_devconf *devconf_all;
+ struct ipv4_devconf *devconf_dflt;
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+ struct fib_rules_ops *rules_ops;
+#endif
+ struct hlist_head *fib_table_hash;
+ struct sock *fibnl;
+
+ struct sock **icmp_sk;
+ struct sock *tcp_sock;
+
+ struct netns_frags frags;
+#ifdef CONFIG_NETFILTER
+ struct xt_table *iptable_filter;
+ struct xt_table *iptable_mangle;
+ struct xt_table *iptable_raw;
+ struct xt_table *arptable_filter;
+#ifdef CONFIG_SECURITY
+ struct xt_table *iptable_security;
+#endif
+ struct xt_table *nat_table;
+ struct hlist_head *nat_bysource;
+ unsigned int nat_htable_size;
+#endif
+
+ int sysctl_icmp_echo_ignore_all;
+ int sysctl_icmp_echo_ignore_broadcasts;
+ int sysctl_icmp_ignore_bogus_error_responses;
+ int sysctl_icmp_ratelimit;
+ int sysctl_icmp_ratemask;
+ int sysctl_icmp_errors_use_inbound_ifaddr;
+ int sysctl_rt_cache_rebuild_count;
+ int current_rt_cache_rebuild_count;
+
+ unsigned int sysctl_ping_group_range[2];
+ long sysctl_tcp_mem[3];
+
+ atomic_t rt_genid;
+ atomic_t dev_addr_genid;
+
+#ifdef CONFIG_IP_MROUTE
+#ifndef CONFIG_IP_MROUTE_MULTIPLE_TABLES
+ struct mr_table *mrt;
+#else
+ struct list_head mr_tables;
+ struct fib_rules_ops *mr_rules_ops;
+#endif
+#endif
+};
+#endif
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
new file mode 100644
index 00000000..81abfcb2
--- /dev/null
+++ b/include/net/netns/ipv6.h
@@ -0,0 +1,70 @@
+/*
+ * ipv6 in net namespaces
+ */
+
+#include <net/inet_frag.h>
+
+#ifndef __NETNS_IPV6_H__
+#define __NETNS_IPV6_H__
+#include <net/dst_ops.h>
+
+struct ctl_table_header;
+
+struct netns_sysctl_ipv6 {
+#ifdef CONFIG_SYSCTL
+ struct ctl_table_header *table;
+ struct ctl_table_header *frags_hdr;
+#endif
+ int bindv6only;
+ int flush_delay;
+ int ip6_rt_max_size;
+ int ip6_rt_gc_min_interval;
+ int ip6_rt_gc_timeout;
+ int ip6_rt_gc_interval;
+ int ip6_rt_gc_elasticity;
+ int ip6_rt_mtu_expires;
+ int ip6_rt_min_advmss;
+ int icmpv6_time;
+};
+
+struct netns_ipv6 {
+ struct netns_sysctl_ipv6 sysctl;
+ struct ipv6_devconf *devconf_all;
+ struct ipv6_devconf *devconf_dflt;
+ struct netns_frags frags;
+#ifdef CONFIG_NETFILTER
+ struct xt_table *ip6table_filter;
+ struct xt_table *ip6table_mangle;
+ struct xt_table *ip6table_raw;
+#ifdef CONFIG_SECURITY
+ struct xt_table *ip6table_security;
+#endif
+#endif
+ struct rt6_info *ip6_null_entry;
+ struct rt6_statistics *rt6_stats;
+ struct timer_list ip6_fib_timer;
+ struct hlist_head *fib_table_hash;
+ struct fib6_table *fib6_main_tbl;
+ struct dst_ops ip6_dst_ops;
+ unsigned int ip6_rt_gc_expire;
+ unsigned long ip6_rt_last_gc;
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+ struct rt6_info *ip6_prohibit_entry;
+ struct rt6_info *ip6_blk_hole_entry;
+ struct fib6_table *fib6_local_tbl;
+ struct fib_rules_ops *fib6_rules_ops;
+#endif
+ struct sock **icmp_sk;
+ struct sock *ndisc_sk;
+ struct sock *tcp_sk;
+ struct sock *igmp_sk;
+#ifdef CONFIG_IPV6_MROUTE
+#ifndef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
+ struct mr6_table *mrt6;
+#else
+ struct list_head mr6_tables;
+ struct fib_rules_ops *mr6_rules_ops;
+#endif
+#endif
+};
+#endif
diff --git a/include/net/netns/mib.h b/include/net/netns/mib.h
new file mode 100644
index 00000000..d542a4b2
--- /dev/null
+++ b/include/net/netns/mib.h
@@ -0,0 +1,28 @@
+#ifndef __NETNS_MIB_H__
+#define __NETNS_MIB_H__
+
+#include <net/snmp.h>
+
+struct netns_mib {
+ DEFINE_SNMP_STAT(struct tcp_mib, tcp_statistics);
+ DEFINE_SNMP_STAT(struct ipstats_mib, ip_statistics);
+ DEFINE_SNMP_STAT(struct linux_mib, net_statistics);
+ DEFINE_SNMP_STAT(struct udp_mib, udp_statistics);
+ DEFINE_SNMP_STAT(struct udp_mib, udplite_statistics);
+ DEFINE_SNMP_STAT(struct icmp_mib, icmp_statistics);
+ DEFINE_SNMP_STAT_ATOMIC(struct icmpmsg_mib, icmpmsg_statistics);
+
+#if IS_ENABLED(CONFIG_IPV6)
+ struct proc_dir_entry *proc_net_devsnmp6;
+ DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6);
+ DEFINE_SNMP_STAT(struct udp_mib, udplite_stats_in6);
+ DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics);
+ DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
+ DEFINE_SNMP_STAT_ATOMIC(struct icmpv6msg_mib, icmpv6msg_statistics);
+#endif
+#ifdef CONFIG_XFRM_STATISTICS
+ DEFINE_SNMP_STAT(struct linux_xfrm_mib, xfrm_statistics);
+#endif
+};
+
+#endif
diff --git a/include/net/netns/packet.h b/include/net/netns/packet.h
new file mode 100644
index 00000000..cb4e894c
--- /dev/null
+++ b/include/net/netns/packet.h
@@ -0,0 +1,15 @@
+/*
+ * Packet network namespace
+ */
+#ifndef __NETNS_PACKET_H__
+#define __NETNS_PACKET_H__
+
+#include <linux/rculist.h>
+#include <linux/spinlock.h>
+
+struct netns_packet {
+ spinlock_t sklist_lock;
+ struct hlist_head sklist;
+};
+
+#endif /* __NETNS_PACKET_H__ */
diff --git a/include/net/netns/unix.h b/include/net/netns/unix.h
new file mode 100644
index 00000000..284649d4
--- /dev/null
+++ b/include/net/netns/unix.h
@@ -0,0 +1,13 @@
+/*
+ * Unix network namespace
+ */
+#ifndef __NETNS_UNIX_H__
+#define __NETNS_UNIX_H__
+
+struct ctl_table_header;
+struct netns_unix {
+ int sysctl_max_dgram_qlen;
+ struct ctl_table_header *ctl;
+};
+
+#endif /* __NETNS_UNIX_H__ */
diff --git a/include/net/netns/x_tables.h b/include/net/netns/x_tables.h
new file mode 100644
index 00000000..591db7d6
--- /dev/null
+++ b/include/net/netns/x_tables.h
@@ -0,0 +1,18 @@
+#ifndef __NETNS_X_TABLES_H
+#define __NETNS_X_TABLES_H
+
+#include <linux/list.h>
+#include <linux/netfilter.h>
+
+struct ebt_table;
+
+struct netns_xt {
+ struct list_head tables[NFPROTO_NUMPROTO];
+#if defined(CONFIG_BRIDGE_NF_EBTABLES) || \
+ defined(CONFIG_BRIDGE_NF_EBTABLES_MODULE)
+ struct ebt_table *broute_table;
+ struct ebt_table *frame_filter;
+ struct ebt_table *frame_nat;
+#endif
+};
+#endif
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
new file mode 100644
index 00000000..5299e69a
--- /dev/null
+++ b/include/net/netns/xfrm.h
@@ -0,0 +1,64 @@
+#ifndef __NETNS_XFRM_H
+#define __NETNS_XFRM_H
+
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+#include <linux/xfrm.h>
+#include <net/dst_ops.h>
+
+struct ctl_table_header;
+
+struct xfrm_policy_hash {
+ struct hlist_head *table;
+ unsigned int hmask;
+};
+
+struct netns_xfrm {
+ struct list_head state_all;
+ /*
+ * Hash table to find appropriate SA towards given target (endpoint of
+ * tunnel or destination of transport mode) allowed by selector.
+ *
+ * Main use is finding SA after policy selected tunnel or transport
+ * mode. Also, it can be used by ah/esp icmp error handler to find
+ * offending SA.
+ */
+ struct hlist_head *state_bydst;
+ struct hlist_head *state_bysrc;
+ struct hlist_head *state_byspi;
+ unsigned int state_hmask;
+ unsigned int state_num;
+ struct work_struct state_hash_work;
+ struct hlist_head state_gc_list;
+ struct work_struct state_gc_work;
+
+ wait_queue_head_t km_waitq;
+
+ struct list_head policy_all;
+ struct hlist_head *policy_byidx;
+ unsigned int policy_idx_hmask;
+ struct hlist_head policy_inexact[XFRM_POLICY_MAX * 2];
+ struct xfrm_policy_hash policy_bydst[XFRM_POLICY_MAX * 2];
+ unsigned int policy_count[XFRM_POLICY_MAX * 2];
+ struct work_struct policy_hash_work;
+
+
+ struct sock *nlsk;
+ struct sock *nlsk_stash;
+
+ u32 sysctl_aevent_etime;
+ u32 sysctl_aevent_rseqth;
+ int sysctl_larval_drop;
+ u32 sysctl_acq_expires;
+#ifdef CONFIG_SYSCTL
+ struct ctl_table_header *sysctl_hdr;
+#endif
+
+ struct dst_ops xfrm4_dst_ops;
+#if IS_ENABLED(CONFIG_IPV6)
+ struct dst_ops xfrm6_dst_ops;
+#endif
+};
+
+#endif
diff --git a/include/net/netprio_cgroup.h b/include/net/netprio_cgroup.h
new file mode 100644
index 00000000..d58fdec4
--- /dev/null
+++ b/include/net/netprio_cgroup.h
@@ -0,0 +1,88 @@
+/*
+ * netprio_cgroup.h Control Group Priority set
+ *
+ *
+ * Authors: Neil Horman <nhorman@tuxdriver.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#ifndef _NETPRIO_CGROUP_H
+#define _NETPRIO_CGROUP_H
+#include <linux/cgroup.h>
+#include <linux/hardirq.h>
+#include <linux/rcupdate.h>
+
+
+struct netprio_map {
+ struct rcu_head rcu;
+ u32 priomap_len;
+ u32 priomap[];
+};
+
+#ifdef CONFIG_CGROUPS
+
+struct cgroup_netprio_state {
+ struct cgroup_subsys_state css;
+ u32 prioidx;
+};
+
+#ifndef CONFIG_NETPRIO_CGROUP
+extern int net_prio_subsys_id;
+#endif
+
+extern void sock_update_netprioidx(struct sock *sk);
+
+#if IS_BUILTIN(CONFIG_NETPRIO_CGROUP)
+
+static inline u32 task_netprioidx(struct task_struct *p)
+{
+ struct cgroup_netprio_state *state;
+ u32 idx;
+
+ rcu_read_lock();
+ state = container_of(task_subsys_state(p, net_prio_subsys_id),
+ struct cgroup_netprio_state, css);
+ idx = state->prioidx;
+ rcu_read_unlock();
+ return idx;
+}
+
+#elif IS_MODULE(CONFIG_NETPRIO_CGROUP)
+
+static inline u32 task_netprioidx(struct task_struct *p)
+{
+ struct cgroup_netprio_state *state;
+ int subsys_id;
+ u32 idx = 0;
+
+ rcu_read_lock();
+ subsys_id = rcu_dereference_index_check(net_prio_subsys_id,
+ rcu_read_lock_held());
+ if (subsys_id >= 0) {
+ state = container_of(task_subsys_state(p, subsys_id),
+ struct cgroup_netprio_state, css);
+ idx = state->prioidx;
+ }
+ rcu_read_unlock();
+ return idx;
+}
+
+#else
+
+static inline u32 task_netprioidx(struct task_struct *p)
+{
+ return 0;
+}
+
+#endif /* CONFIG_NETPRIO_CGROUP */
+
+#else
+#define sock_update_netprioidx(sk)
+#endif
+
+#endif /* _NET_CLS_CGROUP_H */
diff --git a/include/net/netrom.h b/include/net/netrom.h
new file mode 100644
index 00000000..f0793c1c
--- /dev/null
+++ b/include/net/netrom.h
@@ -0,0 +1,270 @@
+/*
+ * Declarations of NET/ROM type objects.
+ *
+ * Jonathan Naylor G4KLX 9/4/95
+ */
+
+#ifndef _NETROM_H
+#define _NETROM_H
+
+#include <linux/netrom.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <net/sock.h>
+
+#define NR_NETWORK_LEN 15
+#define NR_TRANSPORT_LEN 5
+
+#define NR_PROTO_IP 0x0C
+
+#define NR_PROTOEXT 0x00
+#define NR_CONNREQ 0x01
+#define NR_CONNACK 0x02
+#define NR_DISCREQ 0x03
+#define NR_DISCACK 0x04
+#define NR_INFO 0x05
+#define NR_INFOACK 0x06
+#define NR_RESET 0x07
+
+#define NR_CHOKE_FLAG 0x80
+#define NR_NAK_FLAG 0x40
+#define NR_MORE_FLAG 0x20
+
+/* Define Link State constants. */
+enum {
+ NR_STATE_0,
+ NR_STATE_1,
+ NR_STATE_2,
+ NR_STATE_3
+};
+
+#define NR_COND_ACK_PENDING 0x01
+#define NR_COND_REJECT 0x02
+#define NR_COND_PEER_RX_BUSY 0x04
+#define NR_COND_OWN_RX_BUSY 0x08
+
+#define NR_DEFAULT_T1 120000 /* Outstanding frames - 120 seconds */
+#define NR_DEFAULT_T2 5000 /* Response delay - 5 seconds */
+#define NR_DEFAULT_N2 3 /* Number of Retries - 3 */
+#define NR_DEFAULT_T4 180000 /* Busy Delay - 180 seconds */
+#define NR_DEFAULT_IDLE 0 /* No Activity Timeout - none */
+#define NR_DEFAULT_WINDOW 4 /* Default Window Size - 4 */
+#define NR_DEFAULT_OBS 6 /* Default Obsolescence Count - 6 */
+#define NR_DEFAULT_QUAL 10 /* Default Neighbour Quality - 10 */
+#define NR_DEFAULT_TTL 16 /* Default Time To Live - 16 */
+#define NR_DEFAULT_ROUTING 1 /* Is routing enabled ? */
+#define NR_DEFAULT_FAILS 2 /* Link fails until route fails */
+#define NR_DEFAULT_RESET 0 /* Sent / accept reset cmds? */
+
+#define NR_MODULUS 256
+#define NR_MAX_WINDOW_SIZE 127 /* Maximum Window Allowable - 127 */
+#define NR_MAX_PACKET_SIZE 236 /* Maximum Packet Length - 236 */
+
+struct nr_sock {
+ struct sock sock;
+ ax25_address user_addr, source_addr, dest_addr;
+ struct net_device *device;
+ unsigned char my_index, my_id;
+ unsigned char your_index, your_id;
+ unsigned char state, condition, bpqext, window;
+ unsigned short vs, vr, va, vl;
+ unsigned char n2, n2count;
+ unsigned long t1, t2, t4, idle;
+ unsigned short fraglen;
+ struct timer_list t1timer;
+ struct timer_list t2timer;
+ struct timer_list t4timer;
+ struct timer_list idletimer;
+ struct sk_buff_head ack_queue;
+ struct sk_buff_head reseq_queue;
+ struct sk_buff_head frag_queue;
+};
+
+#define nr_sk(sk) ((struct nr_sock *)(sk))
+
+struct nr_neigh {
+ struct hlist_node neigh_node;
+ ax25_address callsign;
+ ax25_digi *digipeat;
+ ax25_cb *ax25;
+ struct net_device *dev;
+ unsigned char quality;
+ unsigned char locked;
+ unsigned short count;
+ unsigned int number;
+ unsigned char failed;
+ atomic_t refcount;
+};
+
+struct nr_route {
+ unsigned char quality;
+ unsigned char obs_count;
+ struct nr_neigh *neighbour;
+};
+
+struct nr_node {
+ struct hlist_node node_node;
+ ax25_address callsign;
+ char mnemonic[7];
+ unsigned char which;
+ unsigned char count;
+ struct nr_route routes[3];
+ atomic_t refcount;
+ spinlock_t node_lock;
+};
+
+/*********************************************************************
+ * nr_node & nr_neigh lists, refcounting and locking
+ *********************************************************************/
+
+#define nr_node_hold(__nr_node) \
+ atomic_inc(&((__nr_node)->refcount))
+
+static __inline__ void nr_node_put(struct nr_node *nr_node)
+{
+ if (atomic_dec_and_test(&nr_node->refcount)) {
+ kfree(nr_node);
+ }
+}
+
+#define nr_neigh_hold(__nr_neigh) \
+ atomic_inc(&((__nr_neigh)->refcount))
+
+static __inline__ void nr_neigh_put(struct nr_neigh *nr_neigh)
+{
+ if (atomic_dec_and_test(&nr_neigh->refcount)) {
+ if (nr_neigh->ax25)
+ ax25_cb_put(nr_neigh->ax25);
+ kfree(nr_neigh->digipeat);
+ kfree(nr_neigh);
+ }
+}
+
+/* nr_node_lock and nr_node_unlock also hold/put the node's refcounter.
+ */
+static __inline__ void nr_node_lock(struct nr_node *nr_node)
+{
+ nr_node_hold(nr_node);
+ spin_lock_bh(&nr_node->node_lock);
+}
+
+static __inline__ void nr_node_unlock(struct nr_node *nr_node)
+{
+ spin_unlock_bh(&nr_node->node_lock);
+ nr_node_put(nr_node);
+}
+
+#define nr_neigh_for_each(__nr_neigh, node, list) \
+ hlist_for_each_entry(__nr_neigh, node, list, neigh_node)
+
+#define nr_neigh_for_each_safe(__nr_neigh, node, node2, list) \
+ hlist_for_each_entry_safe(__nr_neigh, node, node2, list, neigh_node)
+
+#define nr_node_for_each(__nr_node, node, list) \
+ hlist_for_each_entry(__nr_node, node, list, node_node)
+
+#define nr_node_for_each_safe(__nr_node, node, node2, list) \
+ hlist_for_each_entry_safe(__nr_node, node, node2, list, node_node)
+
+
+/*********************************************************************/
+
+/* af_netrom.c */
+extern int sysctl_netrom_default_path_quality;
+extern int sysctl_netrom_obsolescence_count_initialiser;
+extern int sysctl_netrom_network_ttl_initialiser;
+extern int sysctl_netrom_transport_timeout;
+extern int sysctl_netrom_transport_maximum_tries;
+extern int sysctl_netrom_transport_acknowledge_delay;
+extern int sysctl_netrom_transport_busy_delay;
+extern int sysctl_netrom_transport_requested_window_size;
+extern int sysctl_netrom_transport_no_activity_timeout;
+extern int sysctl_netrom_routing_control;
+extern int sysctl_netrom_link_fails_count;
+extern int sysctl_netrom_reset_circuit;
+
+extern int nr_rx_frame(struct sk_buff *, struct net_device *);
+extern void nr_destroy_socket(struct sock *);
+
+/* nr_dev.c */
+extern int nr_rx_ip(struct sk_buff *, struct net_device *);
+extern void nr_setup(struct net_device *);
+
+/* nr_in.c */
+extern int nr_process_rx_frame(struct sock *, struct sk_buff *);
+
+/* nr_loopback.c */
+extern void nr_loopback_init(void);
+extern void nr_loopback_clear(void);
+extern int nr_loopback_queue(struct sk_buff *);
+
+/* nr_out.c */
+extern void nr_output(struct sock *, struct sk_buff *);
+extern void nr_send_nak_frame(struct sock *);
+extern void nr_kick(struct sock *);
+extern void nr_transmit_buffer(struct sock *, struct sk_buff *);
+extern void nr_establish_data_link(struct sock *);
+extern void nr_enquiry_response(struct sock *);
+extern void nr_check_iframes_acked(struct sock *, unsigned short);
+
+/* nr_route.c */
+extern void nr_rt_device_down(struct net_device *);
+extern struct net_device *nr_dev_first(void);
+extern struct net_device *nr_dev_get(ax25_address *);
+extern int nr_rt_ioctl(unsigned int, void __user *);
+extern void nr_link_failed(ax25_cb *, int);
+extern int nr_route_frame(struct sk_buff *, ax25_cb *);
+extern const struct file_operations nr_nodes_fops;
+extern const struct file_operations nr_neigh_fops;
+extern void nr_rt_free(void);
+
+/* nr_subr.c */
+extern void nr_clear_queues(struct sock *);
+extern void nr_frames_acked(struct sock *, unsigned short);
+extern void nr_requeue_frames(struct sock *);
+extern int nr_validate_nr(struct sock *, unsigned short);
+extern int nr_in_rx_window(struct sock *, unsigned short);
+extern void nr_write_internal(struct sock *, int);
+
+extern void __nr_transmit_reply(struct sk_buff *skb, int mine,
+ unsigned char cmdflags);
+
+/*
+ * This routine is called when a Connect Acknowledge with the Choke Flag
+ * set is needed to refuse a connection.
+ */
+#define nr_transmit_refusal(skb, mine) \
+do { \
+ __nr_transmit_reply((skb), (mine), NR_CONNACK | NR_CHOKE_FLAG); \
+} while (0)
+
+/*
+ * This routine is called when we don't have a circuit matching an incoming
+ * NET/ROM packet. This is an G8PZT Xrouter extension.
+ */
+#define nr_transmit_reset(skb, mine) \
+do { \
+ __nr_transmit_reply((skb), (mine), NR_RESET); \
+} while (0)
+
+extern void nr_disconnect(struct sock *, int);
+
+/* nr_timer.c */
+extern void nr_init_timers(struct sock *sk);
+extern void nr_start_heartbeat(struct sock *);
+extern void nr_start_t1timer(struct sock *);
+extern void nr_start_t2timer(struct sock *);
+extern void nr_start_t4timer(struct sock *);
+extern void nr_start_idletimer(struct sock *);
+extern void nr_stop_heartbeat(struct sock *);
+extern void nr_stop_t1timer(struct sock *);
+extern void nr_stop_t2timer(struct sock *);
+extern void nr_stop_t4timer(struct sock *);
+extern void nr_stop_idletimer(struct sock *);
+extern int nr_t1timer_running(struct sock *);
+
+/* sysctl_net_netrom.c */
+extern void nr_register_sysctl(void);
+extern void nr_unregister_sysctl(void);
+
+#endif
diff --git a/include/net/nexthop.h b/include/net/nexthop.h
new file mode 100644
index 00000000..3334dbfa
--- /dev/null
+++ b/include/net/nexthop.h
@@ -0,0 +1,33 @@
+#ifndef __NET_NEXTHOP_H
+#define __NET_NEXTHOP_H
+
+#include <linux/rtnetlink.h>
+#include <net/netlink.h>
+
+static inline int rtnh_ok(const struct rtnexthop *rtnh, int remaining)
+{
+ return remaining >= sizeof(*rtnh) &&
+ rtnh->rtnh_len >= sizeof(*rtnh) &&
+ rtnh->rtnh_len <= remaining;
+}
+
+static inline struct rtnexthop *rtnh_next(const struct rtnexthop *rtnh,
+ int *remaining)
+{
+ int totlen = NLA_ALIGN(rtnh->rtnh_len);
+
+ *remaining -= totlen;
+ return (struct rtnexthop *) ((char *) rtnh + totlen);
+}
+
+static inline struct nlattr *rtnh_attrs(const struct rtnexthop *rtnh)
+{
+ return (struct nlattr *) ((char *) rtnh + NLA_ALIGN(sizeof(*rtnh)));
+}
+
+static inline int rtnh_attrlen(const struct rtnexthop *rtnh)
+{
+ return rtnh->rtnh_len - NLA_ALIGN(sizeof(*rtnh));
+}
+
+#endif
diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h
new file mode 100644
index 00000000..276094b9
--- /dev/null
+++ b/include/net/nfc/nci.h
@@ -0,0 +1,364 @@
+/*
+ * The NFC Controller Interface is the communication protocol between an
+ * NFC Controller (NFCC) and a Device Host (DH).
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * Written by Ilan Elias <ilane@ti.com>
+ *
+ * Acknowledgements:
+ * This file is based on hci.h, which was written
+ * by Maxim Krasnyansky.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __NCI_H
+#define __NCI_H
+
+/* NCI constants */
+#define NCI_MAX_NUM_MAPPING_CONFIGS 10
+#define NCI_MAX_NUM_RF_CONFIGS 10
+#define NCI_MAX_NUM_CONN 10
+
+/* NCI Status Codes */
+#define NCI_STATUS_OK 0x00
+#define NCI_STATUS_REJECTED 0x01
+#define NCI_STATUS_RF_FRAME_CORRUPTED 0x02
+#define NCI_STATUS_FAILED 0x03
+#define NCI_STATUS_NOT_INITIALIZED 0x04
+#define NCI_STATUS_SYNTAX_ERROR 0x05
+#define NCI_STATUS_SEMANTIC_ERROR 0x06
+#define NCI_STATUS_UNKNOWN_GID 0x07
+#define NCI_STATUS_UNKNOWN_OID 0x08
+#define NCI_STATUS_INVALID_PARAM 0x09
+#define NCI_STATUS_MESSAGE_SIZE_EXCEEDED 0x0a
+/* Discovery Specific Status Codes */
+#define NCI_STATUS_DISCOVERY_ALREADY_STARTED 0xa0
+#define NCI_STATUS_DISCOVERY_TARGET_ACTIVATION_FAILED 0xa1
+#define NCI_STATUS_DISCOVERY_TEAR_DOWN 0xa2
+/* RF Interface Specific Status Codes */
+#define NCI_STATUS_RF_TRANSMISSION_ERROR 0xb0
+#define NCI_STATUS_RF_PROTOCOL_ERROR 0xb1
+#define NCI_STATUS_RF_TIMEOUT_ERROR 0xb2
+/* NFCEE Interface Specific Status Codes */
+#define NCI_STATUS_NFCEE_INTERFACE_ACTIVATION_FAILED 0xc0
+#define NCI_STATUS_NFCEE_TRANSMISSION_ERROR 0xc1
+#define NCI_STATUS_NFCEE_PROTOCOL_ERROR 0xc2
+#define NCI_STATUS_NFCEE_TIMEOUT_ERROR 0xc3
+
+/* NCI RF Technology and Mode */
+#define NCI_NFC_A_PASSIVE_POLL_MODE 0x00
+#define NCI_NFC_B_PASSIVE_POLL_MODE 0x01
+#define NCI_NFC_F_PASSIVE_POLL_MODE 0x02
+#define NCI_NFC_A_ACTIVE_POLL_MODE 0x03
+#define NCI_NFC_F_ACTIVE_POLL_MODE 0x05
+#define NCI_NFC_15693_PASSIVE_POLL_MODE 0x06
+#define NCI_NFC_A_PASSIVE_LISTEN_MODE 0x80
+#define NCI_NFC_B_PASSIVE_LISTEN_MODE 0x81
+#define NCI_NFC_F_PASSIVE_LISTEN_MODE 0x82
+#define NCI_NFC_A_ACTIVE_LISTEN_MODE 0x83
+#define NCI_NFC_F_ACTIVE_LISTEN_MODE 0x85
+#define NCI_NFC_15693_PASSIVE_LISTEN_MODE 0x86
+
+/* NCI RF Technologies */
+#define NCI_NFC_RF_TECHNOLOGY_A 0x00
+#define NCI_NFC_RF_TECHNOLOGY_B 0x01
+#define NCI_NFC_RF_TECHNOLOGY_F 0x02
+#define NCI_NFC_RF_TECHNOLOGY_15693 0x03
+
+/* NCI Bit Rates */
+#define NCI_NFC_BIT_RATE_106 0x00
+#define NCI_NFC_BIT_RATE_212 0x01
+#define NCI_NFC_BIT_RATE_424 0x02
+#define NCI_NFC_BIT_RATE_848 0x03
+#define NCI_NFC_BIT_RATE_1695 0x04
+#define NCI_NFC_BIT_RATE_3390 0x05
+#define NCI_NFC_BIT_RATE_6780 0x06
+
+/* NCI RF Protocols */
+#define NCI_RF_PROTOCOL_UNKNOWN 0x00
+#define NCI_RF_PROTOCOL_T1T 0x01
+#define NCI_RF_PROTOCOL_T2T 0x02
+#define NCI_RF_PROTOCOL_T3T 0x03
+#define NCI_RF_PROTOCOL_ISO_DEP 0x04
+#define NCI_RF_PROTOCOL_NFC_DEP 0x05
+
+/* NCI RF Interfaces */
+#define NCI_RF_INTERFACE_NFCEE_DIRECT 0x00
+#define NCI_RF_INTERFACE_FRAME 0x01
+#define NCI_RF_INTERFACE_ISO_DEP 0x02
+#define NCI_RF_INTERFACE_NFC_DEP 0x03
+
+/* NCI Reset types */
+#define NCI_RESET_TYPE_KEEP_CONFIG 0x00
+#define NCI_RESET_TYPE_RESET_CONFIG 0x01
+
+/* NCI Static RF connection ID */
+#define NCI_STATIC_RF_CONN_ID 0x00
+
+/* NCI Data Flow Control */
+#define NCI_DATA_FLOW_CONTROL_NOT_USED 0xff
+
+/* NCI RF_DISCOVER_MAP_CMD modes */
+#define NCI_DISC_MAP_MODE_POLL 0x01
+#define NCI_DISC_MAP_MODE_LISTEN 0x02
+
+/* NCI Discover Notification Type */
+#define NCI_DISCOVER_NTF_TYPE_LAST 0x00
+#define NCI_DISCOVER_NTF_TYPE_LAST_NFCC 0x01
+#define NCI_DISCOVER_NTF_TYPE_MORE 0x02
+
+/* NCI Deactivation Type */
+#define NCI_DEACTIVATE_TYPE_IDLE_MODE 0x00
+#define NCI_DEACTIVATE_TYPE_SLEEP_MODE 0x01
+#define NCI_DEACTIVATE_TYPE_SLEEP_AF_MODE 0x02
+#define NCI_DEACTIVATE_TYPE_DISCOVERY 0x03
+
+/* Message Type (MT) */
+#define NCI_MT_DATA_PKT 0x00
+#define NCI_MT_CMD_PKT 0x01
+#define NCI_MT_RSP_PKT 0x02
+#define NCI_MT_NTF_PKT 0x03
+
+#define nci_mt(hdr) (((hdr)[0]>>5)&0x07)
+#define nci_mt_set(hdr, mt) ((hdr)[0] |= (__u8)(((mt)&0x07)<<5))
+
+/* Packet Boundary Flag (PBF) */
+#define NCI_PBF_LAST 0x00
+#define NCI_PBF_CONT 0x01
+
+#define nci_pbf(hdr) (__u8)(((hdr)[0]>>4)&0x01)
+#define nci_pbf_set(hdr, pbf) ((hdr)[0] |= (__u8)(((pbf)&0x01)<<4))
+
+/* Control Opcode manipulation */
+#define nci_opcode_pack(gid, oid) (__u16)((((__u16)((gid)&0x0f))<<8)|\
+ ((__u16)((oid)&0x3f)))
+#define nci_opcode(hdr) nci_opcode_pack(hdr[0], hdr[1])
+#define nci_opcode_gid(op) (__u8)(((op)&0x0f00)>>8)
+#define nci_opcode_oid(op) (__u8)((op)&0x003f)
+
+/* Payload Length */
+#define nci_plen(hdr) (__u8)((hdr)[2])
+
+/* Connection ID */
+#define nci_conn_id(hdr) (__u8)(((hdr)[0])&0x0f)
+
+/* GID values */
+#define NCI_GID_CORE 0x0
+#define NCI_GID_RF_MGMT 0x1
+#define NCI_GID_NFCEE_MGMT 0x2
+#define NCI_GID_PROPRIETARY 0xf
+
+/* ---- NCI Packet structures ---- */
+#define NCI_CTRL_HDR_SIZE 3
+#define NCI_DATA_HDR_SIZE 3
+
+struct nci_ctrl_hdr {
+ __u8 gid; /* MT & PBF & GID */
+ __u8 oid;
+ __u8 plen;
+} __packed;
+
+struct nci_data_hdr {
+ __u8 conn_id; /* MT & PBF & ConnID */
+ __u8 rfu;
+ __u8 plen;
+} __packed;
+
+/* ------------------------ */
+/* ----- NCI Commands ---- */
+/* ------------------------ */
+#define NCI_OP_CORE_RESET_CMD nci_opcode_pack(NCI_GID_CORE, 0x00)
+struct nci_core_reset_cmd {
+ __u8 reset_type;
+} __packed;
+
+#define NCI_OP_CORE_INIT_CMD nci_opcode_pack(NCI_GID_CORE, 0x01)
+
+#define NCI_OP_RF_DISCOVER_MAP_CMD nci_opcode_pack(NCI_GID_RF_MGMT, 0x00)
+struct disc_map_config {
+ __u8 rf_protocol;
+ __u8 mode;
+ __u8 rf_interface;
+} __packed;
+
+struct nci_rf_disc_map_cmd {
+ __u8 num_mapping_configs;
+ struct disc_map_config mapping_configs
+ [NCI_MAX_NUM_MAPPING_CONFIGS];
+} __packed;
+
+#define NCI_OP_RF_DISCOVER_CMD nci_opcode_pack(NCI_GID_RF_MGMT, 0x03)
+struct disc_config {
+ __u8 rf_tech_and_mode;
+ __u8 frequency;
+} __packed;
+
+struct nci_rf_disc_cmd {
+ __u8 num_disc_configs;
+ struct disc_config disc_configs[NCI_MAX_NUM_RF_CONFIGS];
+} __packed;
+
+#define NCI_OP_RF_DISCOVER_SELECT_CMD nci_opcode_pack(NCI_GID_RF_MGMT, 0x04)
+struct nci_rf_discover_select_cmd {
+ __u8 rf_discovery_id;
+ __u8 rf_protocol;
+ __u8 rf_interface;
+} __packed;
+
+#define NCI_OP_RF_DEACTIVATE_CMD nci_opcode_pack(NCI_GID_RF_MGMT, 0x06)
+struct nci_rf_deactivate_cmd {
+ __u8 type;
+} __packed;
+
+/* ----------------------- */
+/* ---- NCI Responses ---- */
+/* ----------------------- */
+#define NCI_OP_CORE_RESET_RSP nci_opcode_pack(NCI_GID_CORE, 0x00)
+struct nci_core_reset_rsp {
+ __u8 status;
+ __u8 nci_ver;
+ __u8 config_status;
+} __packed;
+
+#define NCI_OP_CORE_INIT_RSP nci_opcode_pack(NCI_GID_CORE, 0x01)
+struct nci_core_init_rsp_1 {
+ __u8 status;
+ __le32 nfcc_features;
+ __u8 num_supported_rf_interfaces;
+ __u8 supported_rf_interfaces[0]; /* variable size array */
+ /* continuted in nci_core_init_rsp_2 */
+} __packed;
+
+struct nci_core_init_rsp_2 {
+ __u8 max_logical_connections;
+ __le16 max_routing_table_size;
+ __u8 max_ctrl_pkt_payload_len;
+ __le16 max_size_for_large_params;
+ __u8 manufact_id;
+ __le32 manufact_specific_info;
+} __packed;
+
+#define NCI_OP_RF_DISCOVER_MAP_RSP nci_opcode_pack(NCI_GID_RF_MGMT, 0x00)
+
+#define NCI_OP_RF_DISCOVER_RSP nci_opcode_pack(NCI_GID_RF_MGMT, 0x03)
+
+#define NCI_OP_RF_DISCOVER_SELECT_RSP nci_opcode_pack(NCI_GID_RF_MGMT, 0x04)
+
+#define NCI_OP_RF_DEACTIVATE_RSP nci_opcode_pack(NCI_GID_RF_MGMT, 0x06)
+
+/* --------------------------- */
+/* ---- NCI Notifications ---- */
+/* --------------------------- */
+#define NCI_OP_CORE_CONN_CREDITS_NTF nci_opcode_pack(NCI_GID_CORE, 0x06)
+struct conn_credit_entry {
+ __u8 conn_id;
+ __u8 credits;
+} __packed;
+
+struct nci_core_conn_credit_ntf {
+ __u8 num_entries;
+ struct conn_credit_entry conn_entries[NCI_MAX_NUM_CONN];
+} __packed;
+
+#define NCI_OP_CORE_GENERIC_ERROR_NTF nci_opcode_pack(NCI_GID_CORE, 0x07)
+
+#define NCI_OP_CORE_INTF_ERROR_NTF nci_opcode_pack(NCI_GID_CORE, 0x08)
+struct nci_core_intf_error_ntf {
+ __u8 status;
+ __u8 conn_id;
+} __packed;
+
+#define NCI_OP_RF_DISCOVER_NTF nci_opcode_pack(NCI_GID_RF_MGMT, 0x03)
+struct rf_tech_specific_params_nfca_poll {
+ __u16 sens_res;
+ __u8 nfcid1_len; /* 0, 4, 7, or 10 Bytes */
+ __u8 nfcid1[10];
+ __u8 sel_res_len; /* 0 or 1 Bytes */
+ __u8 sel_res;
+} __packed;
+
+struct rf_tech_specific_params_nfcb_poll {
+ __u8 sensb_res_len;
+ __u8 sensb_res[12]; /* 11 or 12 Bytes */
+} __packed;
+
+struct rf_tech_specific_params_nfcf_poll {
+ __u8 bit_rate;
+ __u8 sensf_res_len;
+ __u8 sensf_res[18]; /* 16 or 18 Bytes */
+} __packed;
+
+struct nci_rf_discover_ntf {
+ __u8 rf_discovery_id;
+ __u8 rf_protocol;
+ __u8 rf_tech_and_mode;
+ __u8 rf_tech_specific_params_len;
+
+ union {
+ struct rf_tech_specific_params_nfca_poll nfca_poll;
+ struct rf_tech_specific_params_nfcb_poll nfcb_poll;
+ struct rf_tech_specific_params_nfcf_poll nfcf_poll;
+ } rf_tech_specific_params;
+
+ __u8 ntf_type;
+} __packed;
+
+#define NCI_OP_RF_INTF_ACTIVATED_NTF nci_opcode_pack(NCI_GID_RF_MGMT, 0x05)
+struct activation_params_nfca_poll_iso_dep {
+ __u8 rats_res_len;
+ __u8 rats_res[20];
+};
+
+struct activation_params_nfcb_poll_iso_dep {
+ __u8 attrib_res_len;
+ __u8 attrib_res[50];
+};
+
+struct nci_rf_intf_activated_ntf {
+ __u8 rf_discovery_id;
+ __u8 rf_interface;
+ __u8 rf_protocol;
+ __u8 activation_rf_tech_and_mode;
+ __u8 max_data_pkt_payload_size;
+ __u8 initial_num_credits;
+ __u8 rf_tech_specific_params_len;
+
+ union {
+ struct rf_tech_specific_params_nfca_poll nfca_poll;
+ struct rf_tech_specific_params_nfcb_poll nfcb_poll;
+ struct rf_tech_specific_params_nfcf_poll nfcf_poll;
+ } rf_tech_specific_params;
+
+ __u8 data_exch_rf_tech_and_mode;
+ __u8 data_exch_tx_bit_rate;
+ __u8 data_exch_rx_bit_rate;
+ __u8 activation_params_len;
+
+ union {
+ struct activation_params_nfca_poll_iso_dep nfca_poll_iso_dep;
+ struct activation_params_nfcb_poll_iso_dep nfcb_poll_iso_dep;
+ } activation_params;
+
+} __packed;
+
+#define NCI_OP_RF_DEACTIVATE_NTF nci_opcode_pack(NCI_GID_RF_MGMT, 0x06)
+struct nci_rf_deactivate_ntf {
+ __u8 type;
+ __u8 reason;
+} __packed;
+
+#endif /* __NCI_H */
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
new file mode 100644
index 00000000..feba7402
--- /dev/null
+++ b/include/net/nfc/nci_core.h
@@ -0,0 +1,199 @@
+/*
+ * The NFC Controller Interface is the communication protocol between an
+ * NFC Controller (NFCC) and a Device Host (DH).
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * Written by Ilan Elias <ilane@ti.com>
+ *
+ * Acknowledgements:
+ * This file is based on hci_core.h, which was written
+ * by Maxim Krasnyansky.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __NCI_CORE_H
+#define __NCI_CORE_H
+
+#include <linux/interrupt.h>
+#include <linux/skbuff.h>
+
+#include <net/nfc/nfc.h>
+#include <net/nfc/nci.h>
+
+/* NCI device flags */
+enum nci_flag {
+ NCI_INIT,
+ NCI_UP,
+ NCI_DATA_EXCHANGE,
+ NCI_DATA_EXCHANGE_TO,
+};
+
+/* NCI device states */
+enum nci_state {
+ NCI_IDLE,
+ NCI_DISCOVERY,
+ NCI_W4_ALL_DISCOVERIES,
+ NCI_W4_HOST_SELECT,
+ NCI_POLL_ACTIVE,
+};
+
+/* NCI timeouts */
+#define NCI_RESET_TIMEOUT 5000
+#define NCI_INIT_TIMEOUT 5000
+#define NCI_RF_DISC_TIMEOUT 5000
+#define NCI_RF_DISC_SELECT_TIMEOUT 5000
+#define NCI_RF_DEACTIVATE_TIMEOUT 30000
+#define NCI_CMD_TIMEOUT 5000
+#define NCI_DATA_TIMEOUT 700
+
+struct nci_dev;
+
+struct nci_ops {
+ int (*open)(struct nci_dev *ndev);
+ int (*close)(struct nci_dev *ndev);
+ int (*send)(struct sk_buff *skb);
+};
+
+#define NCI_MAX_SUPPORTED_RF_INTERFACES 4
+#define NCI_MAX_DISCOVERED_TARGETS 10
+
+/* NCI Core structures */
+struct nci_dev {
+ struct nfc_dev *nfc_dev;
+ struct nci_ops *ops;
+
+ int tx_headroom;
+ int tx_tailroom;
+
+ atomic_t state;
+ unsigned long flags;
+
+ atomic_t cmd_cnt;
+ atomic_t credits_cnt;
+
+ struct timer_list cmd_timer;
+ struct timer_list data_timer;
+
+ struct workqueue_struct *cmd_wq;
+ struct work_struct cmd_work;
+
+ struct workqueue_struct *rx_wq;
+ struct work_struct rx_work;
+
+ struct workqueue_struct *tx_wq;
+ struct work_struct tx_work;
+
+ struct sk_buff_head cmd_q;
+ struct sk_buff_head rx_q;
+ struct sk_buff_head tx_q;
+
+ struct mutex req_lock;
+ struct completion req_completion;
+ __u32 req_status;
+ __u32 req_result;
+
+ void *driver_data;
+
+ __u32 poll_prots;
+ __u32 target_active_prot;
+
+ struct nfc_target targets[NCI_MAX_DISCOVERED_TARGETS];
+ int n_targets;
+
+ /* received during NCI_OP_CORE_RESET_RSP */
+ __u8 nci_ver;
+
+ /* received during NCI_OP_CORE_INIT_RSP */
+ __u32 nfcc_features;
+ __u8 num_supported_rf_interfaces;
+ __u8 supported_rf_interfaces
+ [NCI_MAX_SUPPORTED_RF_INTERFACES];
+ __u8 max_logical_connections;
+ __u16 max_routing_table_size;
+ __u8 max_ctrl_pkt_payload_len;
+ __u16 max_size_for_large_params;
+ __u8 manufact_id;
+ __u32 manufact_specific_info;
+
+ /* received during NCI_OP_RF_INTF_ACTIVATED_NTF */
+ __u8 max_data_pkt_payload_size;
+ __u8 initial_num_credits;
+
+ /* stored during nci_data_exchange */
+ data_exchange_cb_t data_exchange_cb;
+ void *data_exchange_cb_context;
+ struct sk_buff *rx_data_reassembly;
+};
+
+/* ----- NCI Devices ----- */
+struct nci_dev *nci_allocate_device(struct nci_ops *ops,
+ __u32 supported_protocols,
+ int tx_headroom,
+ int tx_tailroom);
+void nci_free_device(struct nci_dev *ndev);
+int nci_register_device(struct nci_dev *ndev);
+void nci_unregister_device(struct nci_dev *ndev);
+int nci_recv_frame(struct sk_buff *skb);
+
+static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev,
+ unsigned int len,
+ gfp_t how)
+{
+ struct sk_buff *skb;
+
+ skb = alloc_skb(len + ndev->tx_headroom + ndev->tx_tailroom, how);
+ if (skb)
+ skb_reserve(skb, ndev->tx_headroom);
+
+ return skb;
+}
+
+static inline void nci_set_parent_dev(struct nci_dev *ndev, struct device *dev)
+{
+ nfc_set_parent_dev(ndev->nfc_dev, dev);
+}
+
+static inline void nci_set_drvdata(struct nci_dev *ndev, void *data)
+{
+ ndev->driver_data = data;
+}
+
+static inline void *nci_get_drvdata(struct nci_dev *ndev)
+{
+ return ndev->driver_data;
+}
+
+void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb);
+void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb);
+void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb);
+int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload);
+int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb);
+void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb,
+ int err);
+void nci_clear_target_list(struct nci_dev *ndev);
+
+/* ----- NCI requests ----- */
+#define NCI_REQ_DONE 0
+#define NCI_REQ_PEND 1
+#define NCI_REQ_CANCELED 2
+
+void nci_req_complete(struct nci_dev *ndev, int result);
+
+/* ----- NCI status code ----- */
+int nci_to_errno(__u8 code);
+
+#endif /* __NCI_CORE_H */
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
new file mode 100644
index 00000000..bac070bf
--- /dev/null
+++ b/include/net/nfc/nfc.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2011 Instituto Nokia de Tecnologia
+ *
+ * Authors:
+ * Lauro Ramos Venancio <lauro.venancio@openbossa.org>
+ * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __NET_NFC_H
+#define __NET_NFC_H
+
+#include <linux/nfc.h>
+#include <linux/device.h>
+#include <linux/skbuff.h>
+
+#define nfc_dev_info(dev, fmt, arg...) dev_info((dev), "NFC: " fmt "\n", ## arg)
+#define nfc_dev_err(dev, fmt, arg...) dev_err((dev), "NFC: " fmt "\n", ## arg)
+#define nfc_dev_dbg(dev, fmt, arg...) dev_dbg((dev), fmt "\n", ## arg)
+
+struct nfc_dev;
+
+/**
+ * data_exchange_cb_t - Definition of nfc_data_exchange callback
+ *
+ * @context: nfc_data_exchange cb_context parameter
+ * @skb: response data
+ * @err: If an error has occurred during data exchange, it is the
+ * error number. Zero means no error.
+ *
+ * When a rx or tx package is lost or corrupted or the target gets out
+ * of the operating field, err is -EIO.
+ */
+typedef void (*data_exchange_cb_t)(void *context, struct sk_buff *skb,
+ int err);
+
+struct nfc_ops {
+ int (*dev_up)(struct nfc_dev *dev);
+ int (*dev_down)(struct nfc_dev *dev);
+ int (*start_poll)(struct nfc_dev *dev, u32 protocols);
+ void (*stop_poll)(struct nfc_dev *dev);
+ int (*dep_link_up)(struct nfc_dev *dev, int target_idx, u8 comm_mode,
+ u8 *gb, size_t gb_len);
+ int (*dep_link_down)(struct nfc_dev *dev);
+ int (*activate_target)(struct nfc_dev *dev, u32 target_idx,
+ u32 protocol);
+ void (*deactivate_target)(struct nfc_dev *dev, u32 target_idx);
+ int (*data_exchange)(struct nfc_dev *dev, u32 target_idx,
+ struct sk_buff *skb, data_exchange_cb_t cb,
+ void *cb_context);
+};
+
+#define NFC_TARGET_IDX_ANY -1
+#define NFC_MAX_GT_LEN 48
+
+struct nfc_target {
+ u32 idx;
+ u32 supported_protocols;
+ u16 sens_res;
+ u8 sel_res;
+ u8 nfcid1_len;
+ u8 nfcid1[NFC_NFCID1_MAXSIZE];
+ u8 sensb_res_len;
+ u8 sensb_res[NFC_SENSB_RES_MAXSIZE];
+ u8 sensf_res_len;
+ u8 sensf_res[NFC_SENSF_RES_MAXSIZE];
+};
+
+struct nfc_genl_data {
+ u32 poll_req_pid;
+ struct mutex genl_data_mutex;
+};
+
+struct nfc_dev {
+ unsigned idx;
+ struct nfc_target *targets;
+ int n_targets;
+ int targets_generation;
+ spinlock_t targets_lock;
+ struct device dev;
+ bool dev_up;
+ bool polling;
+ bool remote_activated;
+ bool dep_link_up;
+ u32 dep_rf_mode;
+ struct nfc_genl_data genl_data;
+ u32 supported_protocols;
+
+ int tx_headroom;
+ int tx_tailroom;
+
+ struct nfc_ops *ops;
+};
+#define to_nfc_dev(_dev) container_of(_dev, struct nfc_dev, dev)
+
+extern struct class nfc_class;
+
+struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
+ u32 supported_protocols,
+ int tx_headroom,
+ int tx_tailroom);
+
+/**
+ * nfc_free_device - free nfc device
+ *
+ * @dev: The nfc device to free
+ */
+static inline void nfc_free_device(struct nfc_dev *dev)
+{
+ put_device(&dev->dev);
+}
+
+int nfc_register_device(struct nfc_dev *dev);
+
+void nfc_unregister_device(struct nfc_dev *dev);
+
+/**
+ * nfc_set_parent_dev - set the parent device
+ *
+ * @nfc_dev: The nfc device whose parent is being set
+ * @dev: The parent device
+ */
+static inline void nfc_set_parent_dev(struct nfc_dev *nfc_dev,
+ struct device *dev)
+{
+ nfc_dev->dev.parent = dev;
+}
+
+/**
+ * nfc_set_drvdata - set driver specifc data
+ *
+ * @dev: The nfc device
+ * @data: Pointer to driver specifc data
+ */
+static inline void nfc_set_drvdata(struct nfc_dev *dev, void *data)
+{
+ dev_set_drvdata(&dev->dev, data);
+}
+
+/**
+ * nfc_get_drvdata - get driver specifc data
+ *
+ * @dev: The nfc device
+ */
+static inline void *nfc_get_drvdata(struct nfc_dev *dev)
+{
+ return dev_get_drvdata(&dev->dev);
+}
+
+/**
+ * nfc_device_name - get the nfc device name
+ *
+ * @dev: The nfc device whose name to return
+ */
+static inline const char *nfc_device_name(struct nfc_dev *dev)
+{
+ return dev_name(&dev->dev);
+}
+
+struct sk_buff *nfc_alloc_send_skb(struct nfc_dev *dev, struct sock *sk,
+ unsigned int flags, unsigned int size,
+ unsigned int *err);
+struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp);
+
+int nfc_set_remote_general_bytes(struct nfc_dev *dev,
+ u8 *gt, u8 gt_len);
+
+int nfc_targets_found(struct nfc_dev *dev,
+ struct nfc_target *targets, int ntargets);
+
+int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
+ u8 comm_mode, u8 rf_mode);
+
+#endif /* __NET_NFC_H */
diff --git a/include/net/nl802154.h b/include/net/nl802154.h
new file mode 100644
index 00000000..99d2ba1c
--- /dev/null
+++ b/include/net/nl802154.h
@@ -0,0 +1,126 @@
+/*
+ * nl802154.h
+ *
+ * Copyright (C) 2007, 2008, 2009 Siemens AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef IEEE802154_NL_H
+#define IEEE802154_NL_H
+
+struct net_device;
+struct ieee802154_addr;
+
+/**
+ * ieee802154_nl_assoc_indic - Notify userland of an association request.
+ * @dev: The network device on which this association request was
+ * received.
+ * @addr: The address of the device requesting association.
+ * @cap: The capability information field from the device.
+ *
+ * This informs a userland coordinator of a device requesting to
+ * associate with the PAN controlled by the coordinator.
+ *
+ * Note: This is in section 7.3.1 of the IEEE 802.15.4-2006 document.
+ */
+int ieee802154_nl_assoc_indic(struct net_device *dev,
+ struct ieee802154_addr *addr, u8 cap);
+
+/**
+ * ieee802154_nl_assoc_confirm - Notify userland of association.
+ * @dev: The device which has completed association.
+ * @short_addr: The short address assigned to the device.
+ * @status: The status of the association.
+ *
+ * Inform userland of the result of an association request. If the
+ * association request included asking the coordinator to allocate
+ * a short address then it is returned in @short_addr.
+ *
+ * Note: This is in section 7.3.2 of the IEEE 802.15.4 document.
+ */
+int ieee802154_nl_assoc_confirm(struct net_device *dev,
+ u16 short_addr, u8 status);
+
+/**
+ * ieee802154_nl_disassoc_indic - Notify userland of disassociation.
+ * @dev: The device on which disassociation was indicated.
+ * @addr: The device which is disassociating.
+ * @reason: The reason for the disassociation.
+ *
+ * Inform userland that a device has disassociated from the network.
+ *
+ * Note: This is in section 7.3.3 of the IEEE 802.15.4 document.
+ */
+int ieee802154_nl_disassoc_indic(struct net_device *dev,
+ struct ieee802154_addr *addr, u8 reason);
+
+/**
+ * ieee802154_nl_disassoc_confirm - Notify userland of disassociation
+ * completion.
+ * @dev: The device on which disassociation was ordered.
+ * @status: The result of the disassociation.
+ *
+ * Inform userland of the result of requesting that a device
+ * disassociate, or the result of requesting that we disassociate from
+ * a PAN managed by another coordinator.
+ *
+ * Note: This is in section 7.1.4.3 of the IEEE 802.15.4 document.
+ */
+int ieee802154_nl_disassoc_confirm(struct net_device *dev,
+ u8 status);
+
+/**
+ * ieee802154_nl_scan_confirm - Notify userland of completion of scan.
+ * @dev: The device which was instructed to scan.
+ * @status: The status of the scan operation.
+ * @scan_type: What type of scan was performed.
+ * @unscanned: Any channels that the device was unable to scan.
+ * @edl: The energy levels (if a passive scan).
+ *
+ *
+ * Note: This is in section 7.1.11 of the IEEE 802.15.4 document.
+ * Note: This API does not permit the return of an active scan result.
+ */
+int ieee802154_nl_scan_confirm(struct net_device *dev,
+ u8 status, u8 scan_type, u32 unscanned, u8 page,
+ u8 *edl/*, struct list_head *pan_desc_list */);
+
+/**
+ * ieee802154_nl_beacon_indic - Notify userland of a received beacon.
+ * @dev: The device on which a beacon was received.
+ * @panid: The PAN of the coordinator.
+ * @coord_addr: The short address of the coordinator on that PAN.
+ *
+ * Note: This is in section 7.1.5 of the IEEE 802.15.4 document.
+ * Note: This API does not provide extended information such as what
+ * channel the PAN is on or what the LQI of the beacon frame was on
+ * receipt.
+ * Note: This API cannot indicate a beacon frame for a coordinator
+ * operating in long addressing mode.
+ */
+int ieee802154_nl_beacon_indic(struct net_device *dev, u16 panid,
+ u16 coord_addr);
+
+/**
+ * ieee802154_nl_start_confirm - Notify userland of completion of start.
+ * @dev: The device which was instructed to scan.
+ * @status: The status of the scan operation.
+ *
+ * Note: This is in section 7.1.14 of the IEEE 802.15.4 document.
+ */
+int ieee802154_nl_start_confirm(struct net_device *dev, u8 status);
+
+#endif
diff --git a/include/net/p8022.h b/include/net/p8022.h
new file mode 100644
index 00000000..42e9fac5
--- /dev/null
+++ b/include/net/p8022.h
@@ -0,0 +1,13 @@
+#ifndef _NET_P8022_H
+#define _NET_P8022_H
+extern struct datalink_proto *
+ register_8022_client(unsigned char type,
+ int (*func)(struct sk_buff *skb,
+ struct net_device *dev,
+ struct packet_type *pt,
+ struct net_device *orig_dev));
+extern void unregister_8022_client(struct datalink_proto *proto);
+
+extern struct datalink_proto *make_8023_client(void);
+extern void destroy_8023_client(struct datalink_proto *dl);
+#endif
diff --git a/include/net/phonet/gprs.h b/include/net/phonet/gprs.h
new file mode 100644
index 00000000..928daf59
--- /dev/null
+++ b/include/net/phonet/gprs.h
@@ -0,0 +1,38 @@
+/*
+ * File: pep_gprs.h
+ *
+ * GPRS over Phonet pipe end point socket
+ *
+ * Copyright (C) 2008 Nokia Corporation.
+ *
+ * Author: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef NET_PHONET_GPRS_H
+#define NET_PHONET_GPRS_H
+
+struct sock;
+struct sk_buff;
+
+int pep_writeable(struct sock *sk);
+int pep_write(struct sock *sk, struct sk_buff *skb);
+struct sk_buff *pep_read(struct sock *sk);
+
+int gprs_attach(struct sock *sk);
+void gprs_detach(struct sock *sk);
+
+#endif
diff --git a/include/net/phonet/pep.h b/include/net/phonet/pep.h
new file mode 100644
index 00000000..b669fe6d
--- /dev/null
+++ b/include/net/phonet/pep.h
@@ -0,0 +1,168 @@
+/*
+ * File: pep.h
+ *
+ * Phonet Pipe End Point sockets definitions
+ *
+ * Copyright (C) 2008 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef NET_PHONET_PEP_H
+#define NET_PHONET_PEP_H
+
+struct pep_sock {
+ struct pn_sock pn_sk;
+
+ /* XXX: union-ify listening vs connected stuff ? */
+ /* Listening socket stuff: */
+ struct hlist_head hlist;
+
+ /* Connected socket stuff: */
+ struct sock *listener;
+ struct sk_buff_head ctrlreq_queue;
+#define PNPIPE_CTRLREQ_MAX 10
+ atomic_t tx_credits;
+ int ifindex;
+ u16 peer_type; /* peer type/subtype */
+ u8 pipe_handle;
+
+ u8 rx_credits;
+ u8 rx_fc; /* RX flow control */
+ u8 tx_fc; /* TX flow control */
+ u8 init_enable; /* auto-enable at creation */
+ u8 aligned;
+};
+
+static inline struct pep_sock *pep_sk(struct sock *sk)
+{
+ return (struct pep_sock *)sk;
+}
+
+extern const struct proto_ops phonet_stream_ops;
+
+/* Pipe protocol definitions */
+struct pnpipehdr {
+ u8 utid; /* transaction ID */
+ u8 message_id;
+ u8 pipe_handle;
+ union {
+ u8 state_after_connect; /* connect request */
+ u8 state_after_reset; /* reset request */
+ u8 error_code; /* any response */
+ u8 pep_type; /* status indication */
+ u8 data[1];
+ };
+};
+#define other_pep_type data[1]
+
+static inline struct pnpipehdr *pnp_hdr(struct sk_buff *skb)
+{
+ return (struct pnpipehdr *)skb_transport_header(skb);
+}
+
+#define MAX_PNPIPE_HEADER (MAX_PHONET_HEADER + 4)
+
+enum {
+ PNS_PIPE_CREATE_REQ = 0x00,
+ PNS_PIPE_CREATE_RESP,
+ PNS_PIPE_REMOVE_REQ,
+ PNS_PIPE_REMOVE_RESP,
+
+ PNS_PIPE_DATA = 0x20,
+ PNS_PIPE_ALIGNED_DATA,
+
+ PNS_PEP_CONNECT_REQ = 0x40,
+ PNS_PEP_CONNECT_RESP,
+ PNS_PEP_DISCONNECT_REQ,
+ PNS_PEP_DISCONNECT_RESP,
+ PNS_PEP_RESET_REQ,
+ PNS_PEP_RESET_RESP,
+ PNS_PEP_ENABLE_REQ,
+ PNS_PEP_ENABLE_RESP,
+ PNS_PEP_CTRL_REQ,
+ PNS_PEP_CTRL_RESP,
+ PNS_PEP_DISABLE_REQ = 0x4C,
+ PNS_PEP_DISABLE_RESP,
+
+ PNS_PEP_STATUS_IND = 0x60,
+ PNS_PIPE_CREATED_IND,
+ PNS_PIPE_RESET_IND = 0x63,
+ PNS_PIPE_ENABLED_IND,
+ PNS_PIPE_REDIRECTED_IND,
+ PNS_PIPE_DISABLED_IND = 0x66,
+};
+
+#define PN_PIPE_INVALID_HANDLE 0xff
+#define PN_PEP_TYPE_COMMON 0x00
+
+/* Phonet pipe status indication */
+enum {
+ PN_PEP_IND_FLOW_CONTROL,
+ PN_PEP_IND_ID_MCFC_GRANT_CREDITS,
+};
+
+/* Phonet pipe error codes */
+enum {
+ PN_PIPE_NO_ERROR,
+ PN_PIPE_ERR_INVALID_PARAM,
+ PN_PIPE_ERR_INVALID_HANDLE,
+ PN_PIPE_ERR_INVALID_CTRL_ID,
+ PN_PIPE_ERR_NOT_ALLOWED,
+ PN_PIPE_ERR_PEP_IN_USE,
+ PN_PIPE_ERR_OVERLOAD,
+ PN_PIPE_ERR_DEV_DISCONNECTED,
+ PN_PIPE_ERR_TIMEOUT,
+ PN_PIPE_ERR_ALL_PIPES_IN_USE,
+ PN_PIPE_ERR_GENERAL,
+ PN_PIPE_ERR_NOT_SUPPORTED,
+};
+
+/* Phonet pipe states */
+enum {
+ PN_PIPE_DISABLE,
+ PN_PIPE_ENABLE,
+};
+
+/* Phonet pipe sub-block types */
+enum {
+ PN_PIPE_SB_CREATE_REQ_PEP_SUB_TYPE,
+ PN_PIPE_SB_CONNECT_REQ_PEP_SUB_TYPE,
+ PN_PIPE_SB_REDIRECT_REQ_PEP_SUB_TYPE,
+ PN_PIPE_SB_NEGOTIATED_FC,
+ PN_PIPE_SB_REQUIRED_FC_TX,
+ PN_PIPE_SB_PREFERRED_FC_RX,
+ PN_PIPE_SB_ALIGNED_DATA,
+};
+
+/* Phonet pipe flow control models */
+enum {
+ PN_NO_FLOW_CONTROL,
+ PN_LEGACY_FLOW_CONTROL,
+ PN_ONE_CREDIT_FLOW_CONTROL,
+ PN_MULTI_CREDIT_FLOW_CONTROL,
+ PN_MAX_FLOW_CONTROL,
+};
+
+#define pn_flow_safe(fc) ((fc) >> 1)
+
+/* Phonet pipe flow control states */
+enum {
+ PEP_IND_EMPTY,
+ PEP_IND_BUSY,
+ PEP_IND_READY,
+};
+
+#endif
diff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h
new file mode 100644
index 00000000..68e50975
--- /dev/null
+++ b/include/net/phonet/phonet.h
@@ -0,0 +1,119 @@
+/*
+ * File: af_phonet.h
+ *
+ * Phonet sockets kernel definitions
+ *
+ * Copyright (C) 2008 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef AF_PHONET_H
+#define AF_PHONET_H
+
+/*
+ * The lower layers may not require more space, ever. Make sure it's
+ * enough.
+ */
+#define MAX_PHONET_HEADER (8 + MAX_HEADER)
+
+/*
+ * Every Phonet* socket has this structure first in its
+ * protocol-specific structure under name c.
+ */
+struct pn_sock {
+ struct sock sk;
+ u16 sobject;
+ u16 dobject;
+ u8 resource;
+};
+
+static inline struct pn_sock *pn_sk(struct sock *sk)
+{
+ return (struct pn_sock *)sk;
+}
+
+extern const struct proto_ops phonet_dgram_ops;
+
+void pn_sock_init(void);
+struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *sa);
+void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb);
+void phonet_get_local_port_range(int *min, int *max);
+void pn_sock_hash(struct sock *sk);
+void pn_sock_unhash(struct sock *sk);
+int pn_sock_get_port(struct sock *sk, unsigned short sport);
+
+struct sock *pn_find_sock_by_res(struct net *net, u8 res);
+int pn_sock_bind_res(struct sock *sock, u8 res);
+int pn_sock_unbind_res(struct sock *sk, u8 res);
+void pn_sock_unbind_all_res(struct sock *sk);
+
+int pn_skb_send(struct sock *sk, struct sk_buff *skb,
+ const struct sockaddr_pn *target);
+
+static inline struct phonethdr *pn_hdr(struct sk_buff *skb)
+{
+ return (struct phonethdr *)skb_network_header(skb);
+}
+
+static inline struct phonetmsg *pn_msg(struct sk_buff *skb)
+{
+ return (struct phonetmsg *)skb_transport_header(skb);
+}
+
+/*
+ * Get the other party's sockaddr from received skb. The skb begins
+ * with a Phonet header.
+ */
+static inline
+void pn_skb_get_src_sockaddr(struct sk_buff *skb, struct sockaddr_pn *sa)
+{
+ struct phonethdr *ph = pn_hdr(skb);
+ u16 obj = pn_object(ph->pn_sdev, ph->pn_sobj);
+
+ sa->spn_family = AF_PHONET;
+ pn_sockaddr_set_object(sa, obj);
+ pn_sockaddr_set_resource(sa, ph->pn_res);
+ memset(sa->spn_zero, 0, sizeof(sa->spn_zero));
+}
+
+static inline
+void pn_skb_get_dst_sockaddr(struct sk_buff *skb, struct sockaddr_pn *sa)
+{
+ struct phonethdr *ph = pn_hdr(skb);
+ u16 obj = pn_object(ph->pn_rdev, ph->pn_robj);
+
+ sa->spn_family = AF_PHONET;
+ pn_sockaddr_set_object(sa, obj);
+ pn_sockaddr_set_resource(sa, ph->pn_res);
+ memset(sa->spn_zero, 0, sizeof(sa->spn_zero));
+}
+
+/* Protocols in Phonet protocol family. */
+struct phonet_protocol {
+ const struct proto_ops *ops;
+ struct proto *prot;
+ int sock_type;
+};
+
+int phonet_proto_register(unsigned int protocol, struct phonet_protocol *pp);
+void phonet_proto_unregister(unsigned int protocol, struct phonet_protocol *pp);
+
+int phonet_sysctl_init(void);
+void phonet_sysctl_exit(void);
+int isi_register(void);
+void isi_unregister(void);
+
+#endif
diff --git a/include/net/phonet/pn_dev.h b/include/net/phonet/pn_dev.h
new file mode 100644
index 00000000..8639de57
--- /dev/null
+++ b/include/net/phonet/pn_dev.h
@@ -0,0 +1,62 @@
+/*
+ * File: pn_dev.h
+ *
+ * Phonet network device
+ *
+ * Copyright (C) 2008 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef PN_DEV_H
+#define PN_DEV_H
+
+struct phonet_device_list {
+ struct list_head list;
+ struct mutex lock;
+};
+
+struct phonet_device_list *phonet_device_list(struct net *net);
+
+struct phonet_device {
+ struct list_head list;
+ struct net_device *netdev;
+ DECLARE_BITMAP(addrs, 64);
+ struct rcu_head rcu;
+};
+
+int phonet_device_init(void);
+void phonet_device_exit(void);
+int phonet_netlink_register(void);
+struct net_device *phonet_device_get(struct net *net);
+
+int phonet_address_add(struct net_device *dev, u8 addr);
+int phonet_address_del(struct net_device *dev, u8 addr);
+u8 phonet_address_get(struct net_device *dev, u8 addr);
+int phonet_address_lookup(struct net *net, u8 addr);
+void phonet_address_notify(int event, struct net_device *dev, u8 addr);
+
+int phonet_route_add(struct net_device *dev, u8 daddr);
+int phonet_route_del(struct net_device *dev, u8 daddr);
+void rtm_phonet_notify(int event, struct net_device *dev, u8 dst);
+struct net_device *phonet_route_get_rcu(struct net *net, u8 daddr);
+struct net_device *phonet_route_output(struct net *net, u8 daddr);
+
+#define PN_NO_ADDR 0xff
+
+extern const struct file_operations pn_sock_seq_fops;
+extern const struct file_operations pn_res_seq_fops;
+
+#endif
diff --git a/include/net/ping.h b/include/net/ping.h
new file mode 100644
index 00000000..b1717ae9
--- /dev/null
+++ b/include/net/ping.h
@@ -0,0 +1,99 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the "ping" module.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _PING_H
+#define _PING_H
+
+#include <net/icmp.h>
+#include <net/netns/hash.h>
+
+/* PING_HTABLE_SIZE must be power of 2 */
+#define PING_HTABLE_SIZE 64
+#define PING_HTABLE_MASK (PING_HTABLE_SIZE-1)
+
+#define ping_portaddr_for_each_entry(__sk, node, list) \
+ hlist_nulls_for_each_entry(__sk, node, list, sk_nulls_node)
+
+/*
+ * gid_t is either uint or ushort. We want to pass it to
+ * proc_dointvec_minmax(), so it must not be larger than MAX_INT
+ */
+#define GID_T_MAX (((gid_t)~0U) >> 1)
+
+/* Compatibility glue so we can support IPv6 when it's compiled as a module */
+struct pingv6_ops {
+ int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len);
+ int (*datagram_recv_ctl)(struct sock *sk, struct msghdr *msg,
+ struct sk_buff *skb);
+ int (*icmpv6_err_convert)(u8 type, u8 code, int *err);
+ void (*ipv6_icmp_error)(struct sock *sk, struct sk_buff *skb, int err,
+ __be16 port, u32 info, u8 *payload);
+ int (*ipv6_chk_addr)(struct net *net, const struct in6_addr *addr,
+ struct net_device *dev, int strict);
+};
+
+struct ping_table {
+ struct hlist_nulls_head hash[PING_HTABLE_SIZE];
+ rwlock_t lock;
+};
+
+struct ping_iter_state {
+ struct seq_net_private p;
+ int bucket;
+};
+
+extern struct proto ping_prot;
+extern struct ping_table ping_table;
+#if IS_ENABLED(CONFIG_IPV6)
+extern struct pingv6_ops pingv6_ops;
+#endif
+
+struct pingfakehdr {
+ struct icmphdr icmph;
+ struct iovec *iov;
+ sa_family_t family;
+ __wsum wcheck;
+};
+
+int ping_get_port(struct sock *sk, unsigned short ident);
+void ping_hash(struct sock *sk);
+void ping_unhash(struct sock *sk);
+
+int ping_init_sock(struct sock *sk);
+void ping_close(struct sock *sk, long timeout);
+int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len);
+void ping_err(struct sk_buff *skb, int offset, u32 info);
+void ping_v4_err(struct sk_buff *skb, u32 info);
+int ping_getfrag(void *from, char *to, int offset, int fraglen, int odd,
+ struct sk_buff *);
+
+int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ size_t len, int noblock, int flags, int *addr_len);
+int ping_common_sendmsg(int family, struct msghdr *msg, size_t len,
+ void *user_icmph, size_t icmph_len);
+int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ size_t len);
+int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ size_t len);
+int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
+void ping_rcv(struct sk_buff *skb);
+
+#ifdef CONFIG_PROC_FS
+extern int __init ping_proc_init(void);
+extern void ping_proc_exit(void);
+#endif
+
+void __init ping_init(void);
+int __init pingv6_init(void);
+void pingv6_exit(void);
+
+#endif /* _PING_H */
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
new file mode 100644
index 00000000..9fcc680a
--- /dev/null
+++ b/include/net/pkt_cls.h
@@ -0,0 +1,359 @@
+#ifndef __NET_PKT_CLS_H
+#define __NET_PKT_CLS_H
+
+#include <linux/pkt_cls.h>
+#include <net/sch_generic.h>
+#include <net/act_api.h>
+
+/* Basic packet classifier frontend definitions. */
+
+struct tcf_walker {
+ int stop;
+ int skip;
+ int count;
+ int (*fn)(struct tcf_proto *, unsigned long node, struct tcf_walker *);
+};
+
+extern int register_tcf_proto_ops(struct tcf_proto_ops *ops);
+extern int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
+
+static inline unsigned long
+__cls_set_class(unsigned long *clp, unsigned long cl)
+{
+ unsigned long old_cl;
+
+ old_cl = *clp;
+ *clp = cl;
+ return old_cl;
+}
+
+static inline unsigned long
+cls_set_class(struct tcf_proto *tp, unsigned long *clp,
+ unsigned long cl)
+{
+ unsigned long old_cl;
+
+ tcf_tree_lock(tp);
+ old_cl = __cls_set_class(clp, cl);
+ tcf_tree_unlock(tp);
+
+ return old_cl;
+}
+
+static inline void
+tcf_bind_filter(struct tcf_proto *tp, struct tcf_result *r, unsigned long base)
+{
+ unsigned long cl;
+
+ cl = tp->q->ops->cl_ops->bind_tcf(tp->q, base, r->classid);
+ cl = cls_set_class(tp, &r->class, cl);
+ if (cl)
+ tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
+}
+
+static inline void
+tcf_unbind_filter(struct tcf_proto *tp, struct tcf_result *r)
+{
+ unsigned long cl;
+
+ if ((cl = __cls_set_class(&r->class, 0)) != 0)
+ tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
+}
+
+struct tcf_exts {
+#ifdef CONFIG_NET_CLS_ACT
+ struct tc_action *action;
+#endif
+};
+
+/* Map to export classifier specific extension TLV types to the
+ * generic extensions API. Unsupported extensions must be set to 0.
+ */
+struct tcf_ext_map {
+ int action;
+ int police;
+};
+
+/**
+ * tcf_exts_is_predicative - check if a predicative extension is present
+ * @exts: tc filter extensions handle
+ *
+ * Returns 1 if a predicative extension is present, i.e. an extension which
+ * might cause further actions and thus overrule the regular tcf_result.
+ */
+static inline int
+tcf_exts_is_predicative(struct tcf_exts *exts)
+{
+#ifdef CONFIG_NET_CLS_ACT
+ return !!exts->action;
+#else
+ return 0;
+#endif
+}
+
+/**
+ * tcf_exts_is_available - check if at least one extension is present
+ * @exts: tc filter extensions handle
+ *
+ * Returns 1 if at least one extension is present.
+ */
+static inline int
+tcf_exts_is_available(struct tcf_exts *exts)
+{
+ /* All non-predicative extensions must be added here. */
+ return tcf_exts_is_predicative(exts);
+}
+
+/**
+ * tcf_exts_exec - execute tc filter extensions
+ * @skb: socket buffer
+ * @exts: tc filter extensions handle
+ * @res: desired result
+ *
+ * Executes all configured extensions. Returns 0 on a normal execution,
+ * a negative number if the filter must be considered unmatched or
+ * a positive action code (TC_ACT_*) which must be returned to the
+ * underlying layer.
+ */
+static inline int
+tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts,
+ struct tcf_result *res)
+{
+#ifdef CONFIG_NET_CLS_ACT
+ if (exts->action)
+ return tcf_action_exec(skb, exts->action, res);
+#endif
+ return 0;
+}
+
+extern int tcf_exts_validate(struct tcf_proto *tp, struct nlattr **tb,
+ struct nlattr *rate_tlv, struct tcf_exts *exts,
+ const struct tcf_ext_map *map);
+extern void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts);
+extern void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
+ struct tcf_exts *src);
+extern int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts,
+ const struct tcf_ext_map *map);
+extern int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts,
+ const struct tcf_ext_map *map);
+
+/**
+ * struct tcf_pkt_info - packet information
+ */
+struct tcf_pkt_info {
+ unsigned char * ptr;
+ int nexthdr;
+};
+
+#ifdef CONFIG_NET_EMATCH
+
+struct tcf_ematch_ops;
+
+/**
+ * struct tcf_ematch - extended match (ematch)
+ *
+ * @matchid: identifier to allow userspace to reidentify a match
+ * @flags: flags specifying attributes and the relation to other matches
+ * @ops: the operations lookup table of the corresponding ematch module
+ * @datalen: length of the ematch specific configuration data
+ * @data: ematch specific data
+ */
+struct tcf_ematch {
+ struct tcf_ematch_ops * ops;
+ unsigned long data;
+ unsigned int datalen;
+ u16 matchid;
+ u16 flags;
+};
+
+static inline int tcf_em_is_container(struct tcf_ematch *em)
+{
+ return !em->ops;
+}
+
+static inline int tcf_em_is_simple(struct tcf_ematch *em)
+{
+ return em->flags & TCF_EM_SIMPLE;
+}
+
+static inline int tcf_em_is_inverted(struct tcf_ematch *em)
+{
+ return em->flags & TCF_EM_INVERT;
+}
+
+static inline int tcf_em_last_match(struct tcf_ematch *em)
+{
+ return (em->flags & TCF_EM_REL_MASK) == TCF_EM_REL_END;
+}
+
+static inline int tcf_em_early_end(struct tcf_ematch *em, int result)
+{
+ if (tcf_em_last_match(em))
+ return 1;
+
+ if (result == 0 && em->flags & TCF_EM_REL_AND)
+ return 1;
+
+ if (result != 0 && em->flags & TCF_EM_REL_OR)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * struct tcf_ematch_tree - ematch tree handle
+ *
+ * @hdr: ematch tree header supplied by userspace
+ * @matches: array of ematches
+ */
+struct tcf_ematch_tree {
+ struct tcf_ematch_tree_hdr hdr;
+ struct tcf_ematch * matches;
+
+};
+
+/**
+ * struct tcf_ematch_ops - ematch module operations
+ *
+ * @kind: identifier (kind) of this ematch module
+ * @datalen: length of expected configuration data (optional)
+ * @change: called during validation (optional)
+ * @match: called during ematch tree evaluation, must return 1/0
+ * @destroy: called during destroyage (optional)
+ * @dump: called during dumping process (optional)
+ * @owner: owner, must be set to THIS_MODULE
+ * @link: link to previous/next ematch module (internal use)
+ */
+struct tcf_ematch_ops {
+ int kind;
+ int datalen;
+ int (*change)(struct tcf_proto *, void *,
+ int, struct tcf_ematch *);
+ int (*match)(struct sk_buff *, struct tcf_ematch *,
+ struct tcf_pkt_info *);
+ void (*destroy)(struct tcf_proto *,
+ struct tcf_ematch *);
+ int (*dump)(struct sk_buff *, struct tcf_ematch *);
+ struct module *owner;
+ struct list_head link;
+};
+
+extern int tcf_em_register(struct tcf_ematch_ops *);
+extern void tcf_em_unregister(struct tcf_ematch_ops *);
+extern int tcf_em_tree_validate(struct tcf_proto *, struct nlattr *,
+ struct tcf_ematch_tree *);
+extern void tcf_em_tree_destroy(struct tcf_proto *, struct tcf_ematch_tree *);
+extern int tcf_em_tree_dump(struct sk_buff *, struct tcf_ematch_tree *, int);
+extern int __tcf_em_tree_match(struct sk_buff *, struct tcf_ematch_tree *,
+ struct tcf_pkt_info *);
+
+/**
+ * tcf_em_tree_change - replace ematch tree of a running classifier
+ *
+ * @tp: classifier kind handle
+ * @dst: destination ematch tree variable
+ * @src: source ematch tree (temporary tree from tcf_em_tree_validate)
+ *
+ * This functions replaces the ematch tree in @dst with the ematch
+ * tree in @src. The classifier in charge of the ematch tree may be
+ * running.
+ */
+static inline void tcf_em_tree_change(struct tcf_proto *tp,
+ struct tcf_ematch_tree *dst,
+ struct tcf_ematch_tree *src)
+{
+ tcf_tree_lock(tp);
+ memcpy(dst, src, sizeof(*dst));
+ tcf_tree_unlock(tp);
+}
+
+/**
+ * tcf_em_tree_match - evaulate an ematch tree
+ *
+ * @skb: socket buffer of the packet in question
+ * @tree: ematch tree to be used for evaluation
+ * @info: packet information examined by classifier
+ *
+ * This function matches @skb against the ematch tree in @tree by going
+ * through all ematches respecting their logic relations returning
+ * as soon as the result is obvious.
+ *
+ * Returns 1 if the ematch tree as-one matches, no ematches are configured
+ * or ematch is not enabled in the kernel, otherwise 0 is returned.
+ */
+static inline int tcf_em_tree_match(struct sk_buff *skb,
+ struct tcf_ematch_tree *tree,
+ struct tcf_pkt_info *info)
+{
+ if (tree->hdr.nmatches)
+ return __tcf_em_tree_match(skb, tree, info);
+ else
+ return 1;
+}
+
+#define MODULE_ALIAS_TCF_EMATCH(kind) MODULE_ALIAS("ematch-kind-" __stringify(kind))
+
+#else /* CONFIG_NET_EMATCH */
+
+struct tcf_ematch_tree {
+};
+
+#define tcf_em_tree_validate(tp, tb, t) ((void)(t), 0)
+#define tcf_em_tree_destroy(tp, t) do { (void)(t); } while(0)
+#define tcf_em_tree_dump(skb, t, tlv) (0)
+#define tcf_em_tree_change(tp, dst, src) do { } while(0)
+#define tcf_em_tree_match(skb, t, info) ((void)(info), 1)
+
+#endif /* CONFIG_NET_EMATCH */
+
+static inline unsigned char * tcf_get_base_ptr(struct sk_buff *skb, int layer)
+{
+ switch (layer) {
+ case TCF_LAYER_LINK:
+ return skb->data;
+ case TCF_LAYER_NETWORK:
+ return skb_network_header(skb);
+ case TCF_LAYER_TRANSPORT:
+ return skb_transport_header(skb);
+ }
+
+ return NULL;
+}
+
+static inline int tcf_valid_offset(const struct sk_buff *skb,
+ const unsigned char *ptr, const int len)
+{
+ return likely((ptr + len) <= skb_tail_pointer(skb) &&
+ ptr >= skb->head &&
+ (ptr <= (ptr + len)));
+}
+
+#ifdef CONFIG_NET_CLS_IND
+#include <net/net_namespace.h>
+
+static inline int
+tcf_change_indev(struct tcf_proto *tp, char *indev, struct nlattr *indev_tlv)
+{
+ if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ)
+ return -EINVAL;
+ return 0;
+}
+
+static inline int
+tcf_match_indev(struct sk_buff *skb, char *indev)
+{
+ struct net_device *dev;
+
+ if (indev[0]) {
+ if (!skb->skb_iif)
+ return 0;
+ dev = __dev_get_by_index(dev_net(skb->dev), skb->skb_iif);
+ if (!dev || strcmp(indev, dev->name))
+ return 0;
+ }
+
+ return 1;
+}
+#endif /* CONFIG_NET_CLS_IND */
+
+#endif
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
new file mode 100644
index 00000000..fffdc603
--- /dev/null
+++ b/include/net/pkt_sched.h
@@ -0,0 +1,115 @@
+#ifndef __NET_PKT_SCHED_H
+#define __NET_PKT_SCHED_H
+
+#include <linux/jiffies.h>
+#include <linux/ktime.h>
+#include <net/sch_generic.h>
+
+struct qdisc_walker {
+ int stop;
+ int skip;
+ int count;
+ int (*fn)(struct Qdisc *, unsigned long cl, struct qdisc_walker *);
+};
+
+#define QDISC_ALIGNTO 64
+#define QDISC_ALIGN(len) (((len) + QDISC_ALIGNTO-1) & ~(QDISC_ALIGNTO-1))
+
+static inline void *qdisc_priv(struct Qdisc *q)
+{
+ return (char *) q + QDISC_ALIGN(sizeof(struct Qdisc));
+}
+
+/*
+ Timer resolution MUST BE < 10% of min_schedulable_packet_size/bandwidth
+
+ Normal IP packet size ~ 512byte, hence:
+
+ 0.5Kbyte/1Mbyte/sec = 0.5msec, so that we need 50usec timer for
+ 10Mbit ethernet.
+
+ 10msec resolution -> <50Kbit/sec.
+
+ The result: [34]86 is not good choice for QoS router :-(
+
+ The things are not so bad, because we may use artificial
+ clock evaluated by integration of network data flow
+ in the most critical places.
+ */
+
+typedef u64 psched_time_t;
+typedef long psched_tdiff_t;
+
+/* Avoid doing 64 bit divide */
+#define PSCHED_SHIFT 6
+#define PSCHED_TICKS2NS(x) ((s64)(x) << PSCHED_SHIFT)
+#define PSCHED_NS2TICKS(x) ((x) >> PSCHED_SHIFT)
+
+#define PSCHED_TICKS_PER_SEC PSCHED_NS2TICKS(NSEC_PER_SEC)
+#define PSCHED_PASTPERFECT 0
+
+static inline psched_time_t psched_get_time(void)
+{
+ return PSCHED_NS2TICKS(ktime_to_ns(ktime_get()));
+}
+
+static inline psched_tdiff_t
+psched_tdiff_bounded(psched_time_t tv1, psched_time_t tv2, psched_time_t bound)
+{
+ return min(tv1 - tv2, bound);
+}
+
+struct qdisc_watchdog {
+ struct hrtimer timer;
+ struct Qdisc *qdisc;
+};
+
+extern void qdisc_watchdog_init(struct qdisc_watchdog *wd, struct Qdisc *qdisc);
+extern void qdisc_watchdog_schedule(struct qdisc_watchdog *wd,
+ psched_time_t expires);
+extern void qdisc_watchdog_cancel(struct qdisc_watchdog *wd);
+
+extern struct Qdisc_ops pfifo_qdisc_ops;
+extern struct Qdisc_ops bfifo_qdisc_ops;
+extern struct Qdisc_ops pfifo_head_drop_qdisc_ops;
+
+extern int fifo_set_limit(struct Qdisc *q, unsigned int limit);
+extern struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops,
+ unsigned int limit);
+
+extern int register_qdisc(struct Qdisc_ops *qops);
+extern int unregister_qdisc(struct Qdisc_ops *qops);
+extern void qdisc_list_del(struct Qdisc *q);
+extern struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle);
+extern struct Qdisc *qdisc_lookup_class(struct net_device *dev, u32 handle);
+extern struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r,
+ struct nlattr *tab);
+extern void qdisc_put_rtab(struct qdisc_rate_table *tab);
+extern void qdisc_put_stab(struct qdisc_size_table *tab);
+extern void qdisc_warn_nonwc(char *txt, struct Qdisc *qdisc);
+extern int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
+ struct net_device *dev, struct netdev_queue *txq,
+ spinlock_t *root_lock);
+
+extern void __qdisc_run(struct Qdisc *q);
+
+static inline void qdisc_run(struct Qdisc *q)
+{
+ if (qdisc_run_begin(q))
+ __qdisc_run(q);
+}
+
+extern int tc_classify_compat(struct sk_buff *skb, const struct tcf_proto *tp,
+ struct tcf_result *res);
+extern int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp,
+ struct tcf_result *res);
+
+/* Calculate maximal size of packet seen by hard_start_xmit
+ routine of this device.
+ */
+static inline unsigned psched_mtu(const struct net_device *dev)
+{
+ return dev->mtu + dev->hard_header_len;
+}
+
+#endif
diff --git a/include/net/protocol.h b/include/net/protocol.h
new file mode 100644
index 00000000..875f4895
--- /dev/null
+++ b/include/net/protocol.h
@@ -0,0 +1,110 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the protocol dispatcher.
+ *
+ * Version: @(#)protocol.h 1.0.2 05/07/93
+ *
+ * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Changes:
+ * Alan Cox : Added a name field and a frag handler
+ * field for later.
+ * Alan Cox : Cleaned up, and sorted types.
+ * Pedro Roque : inet6 protocols
+ */
+
+#ifndef _PROTOCOL_H
+#define _PROTOCOL_H
+
+#include <linux/in6.h>
+#if IS_ENABLED(CONFIG_IPV6)
+#include <linux/ipv6.h>
+#endif
+
+#define MAX_INET_PROTOS 256 /* Must be a power of 2 */
+
+
+/* This is used to register protocols. */
+struct net_protocol {
+ int (*handler)(struct sk_buff *skb);
+ void (*err_handler)(struct sk_buff *skb, u32 info);
+ int (*gso_send_check)(struct sk_buff *skb);
+ struct sk_buff *(*gso_segment)(struct sk_buff *skb,
+ netdev_features_t features);
+ struct sk_buff **(*gro_receive)(struct sk_buff **head,
+ struct sk_buff *skb);
+ int (*gro_complete)(struct sk_buff *skb);
+ unsigned int no_policy:1,
+ netns_ok:1;
+};
+
+#if IS_ENABLED(CONFIG_IPV6)
+struct inet6_protocol {
+ int (*handler)(struct sk_buff *skb);
+
+ void (*err_handler)(struct sk_buff *skb,
+ struct inet6_skb_parm *opt,
+ u8 type, u8 code, int offset,
+ __be32 info);
+
+ int (*gso_send_check)(struct sk_buff *skb);
+ struct sk_buff *(*gso_segment)(struct sk_buff *skb,
+ netdev_features_t features);
+ struct sk_buff **(*gro_receive)(struct sk_buff **head,
+ struct sk_buff *skb);
+ int (*gro_complete)(struct sk_buff *skb);
+
+ unsigned int flags; /* INET6_PROTO_xxx */
+};
+
+#define INET6_PROTO_NOPOLICY 0x1
+#define INET6_PROTO_FINAL 0x2
+/* This should be set for any extension header which is compatible with GSO. */
+#define INET6_PROTO_GSO_EXTHDR 0x4
+#endif
+
+/* This is used to register socket interfaces for IP protocols. */
+struct inet_protosw {
+ struct list_head list;
+
+ /* These two fields form the lookup key. */
+ unsigned short type; /* This is the 2nd argument to socket(2). */
+ unsigned short protocol; /* This is the L4 protocol number. */
+
+ struct proto *prot;
+ const struct proto_ops *ops;
+
+ char no_check; /* checksum on rcv/xmit/none? */
+ unsigned char flags; /* See INET_PROTOSW_* below. */
+};
+#define INET_PROTOSW_REUSE 0x01 /* Are ports automatically reusable? */
+#define INET_PROTOSW_PERMANENT 0x02 /* Permanent protocols are unremovable. */
+#define INET_PROTOSW_ICSK 0x04 /* Is this an inet_connection_sock? */
+
+extern const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS];
+
+#if IS_ENABLED(CONFIG_IPV6)
+extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS];
+#endif
+
+extern int inet_add_protocol(const struct net_protocol *prot, unsigned char num);
+extern int inet_del_protocol(const struct net_protocol *prot, unsigned char num);
+extern void inet_register_protosw(struct inet_protosw *p);
+extern void inet_unregister_protosw(struct inet_protosw *p);
+
+#if IS_ENABLED(CONFIG_IPV6)
+extern int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char num);
+extern int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char num);
+extern int inet6_register_protosw(struct inet_protosw *p);
+extern void inet6_unregister_protosw(struct inet_protosw *p);
+#endif
+
+#endif /* _PROTOCOL_H */
diff --git a/include/net/psnap.h b/include/net/psnap.h
new file mode 100644
index 00000000..fe456c29
--- /dev/null
+++ b/include/net/psnap.h
@@ -0,0 +1,11 @@
+#ifndef _NET_PSNAP_H
+#define _NET_PSNAP_H
+
+extern struct datalink_proto *
+register_snap_client(const unsigned char *desc,
+ int (*rcvfunc)(struct sk_buff *, struct net_device *,
+ struct packet_type *,
+ struct net_device *orig_dev));
+extern void unregister_snap_client(struct datalink_proto *proto);
+
+#endif
diff --git a/include/net/raw.h b/include/net/raw.h
new file mode 100644
index 00000000..42ce6fe7
--- /dev/null
+++ b/include/net/raw.h
@@ -0,0 +1,75 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the RAW-IP module.
+ *
+ * Version: @(#)raw.h 1.0.2 05/07/93
+ *
+ * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _RAW_H
+#define _RAW_H
+
+
+#include <net/protocol.h>
+#include <linux/icmp.h>
+
+extern struct proto raw_prot;
+
+void raw_icmp_error(struct sk_buff *, int, u32);
+int raw_local_deliver(struct sk_buff *, int);
+
+extern int raw_rcv(struct sock *, struct sk_buff *);
+
+#define RAW_HTABLE_SIZE MAX_INET_PROTOS
+
+struct raw_hashinfo {
+ rwlock_t lock;
+ struct hlist_head ht[RAW_HTABLE_SIZE];
+};
+
+#ifdef CONFIG_PROC_FS
+extern int raw_proc_init(void);
+extern void raw_proc_exit(void);
+
+struct raw_iter_state {
+ struct seq_net_private p;
+ int bucket;
+ struct raw_hashinfo *h;
+};
+
+static inline struct raw_iter_state *raw_seq_private(struct seq_file *seq)
+{
+ return seq->private;
+}
+void *raw_seq_start(struct seq_file *seq, loff_t *pos);
+void *raw_seq_next(struct seq_file *seq, void *v, loff_t *pos);
+void raw_seq_stop(struct seq_file *seq, void *v);
+int raw_seq_open(struct inode *ino, struct file *file,
+ struct raw_hashinfo *h, const struct seq_operations *ops);
+
+#endif
+
+void raw_hash_sk(struct sock *sk);
+void raw_unhash_sk(struct sock *sk);
+
+struct raw_sock {
+ /* inet_sock has to be the first member */
+ struct inet_sock inet;
+ struct icmp_filter filter;
+ u32 ipmr_table;
+};
+
+static inline struct raw_sock *raw_sk(const struct sock *sk)
+{
+ return (struct raw_sock *)sk;
+}
+
+#endif /* _RAW_H */
diff --git a/include/net/rawv6.h b/include/net/rawv6.h
new file mode 100644
index 00000000..cf757723
--- /dev/null
+++ b/include/net/rawv6.h
@@ -0,0 +1,20 @@
+#ifndef _NET_RAWV6_H
+#define _NET_RAWV6_H
+
+#include <net/protocol.h>
+
+void raw6_icmp_error(struct sk_buff *, int nexthdr,
+ u8 type, u8 code, int inner_offset, __be32);
+int raw6_local_deliver(struct sk_buff *, int);
+
+extern int rawv6_rcv(struct sock *sk,
+ struct sk_buff *skb);
+
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+int rawv6_mh_filter_register(int (*filter)(struct sock *sock,
+ struct sk_buff *skb));
+int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock,
+ struct sk_buff *skb));
+#endif
+
+#endif
diff --git a/include/net/red.h b/include/net/red.h
new file mode 100644
index 00000000..ef46058d
--- /dev/null
+++ b/include/net/red.h
@@ -0,0 +1,405 @@
+#ifndef __NET_SCHED_RED_H
+#define __NET_SCHED_RED_H
+
+#include <linux/types.h>
+#include <linux/bug.h>
+#include <net/pkt_sched.h>
+#include <net/inet_ecn.h>
+#include <net/dsfield.h>
+#include <linux/reciprocal_div.h>
+
+/* Random Early Detection (RED) algorithm.
+ =======================================
+
+ Source: Sally Floyd and Van Jacobson, "Random Early Detection Gateways
+ for Congestion Avoidance", 1993, IEEE/ACM Transactions on Networking.
+
+ This file codes a "divisionless" version of RED algorithm
+ as written down in Fig.17 of the paper.
+
+ Short description.
+ ------------------
+
+ When a new packet arrives we calculate the average queue length:
+
+ avg = (1-W)*avg + W*current_queue_len,
+
+ W is the filter time constant (chosen as 2^(-Wlog)), it controls
+ the inertia of the algorithm. To allow larger bursts, W should be
+ decreased.
+
+ if (avg > th_max) -> packet marked (dropped).
+ if (avg < th_min) -> packet passes.
+ if (th_min < avg < th_max) we calculate probability:
+
+ Pb = max_P * (avg - th_min)/(th_max-th_min)
+
+ and mark (drop) packet with this probability.
+ Pb changes from 0 (at avg==th_min) to max_P (avg==th_max).
+ max_P should be small (not 1), usually 0.01..0.02 is good value.
+
+ max_P is chosen as a number, so that max_P/(th_max-th_min)
+ is a negative power of two in order arithmetics to contain
+ only shifts.
+
+
+ Parameters, settable by user:
+ -----------------------------
+
+ qth_min - bytes (should be < qth_max/2)
+ qth_max - bytes (should be at least 2*qth_min and less limit)
+ Wlog - bits (<32) log(1/W).
+ Plog - bits (<32)
+
+ Plog is related to max_P by formula:
+
+ max_P = (qth_max-qth_min)/2^Plog;
+
+ F.e. if qth_max=128K and qth_min=32K, then Plog=22
+ corresponds to max_P=0.02
+
+ Scell_log
+ Stab
+
+ Lookup table for log((1-W)^(t/t_ave).
+
+
+ NOTES:
+
+ Upper bound on W.
+ -----------------
+
+ If you want to allow bursts of L packets of size S,
+ you should choose W:
+
+ L + 1 - th_min/S < (1-(1-W)^L)/W
+
+ th_min/S = 32 th_min/S = 4
+
+ log(W) L
+ -1 33
+ -2 35
+ -3 39
+ -4 46
+ -5 57
+ -6 75
+ -7 101
+ -8 135
+ -9 190
+ etc.
+ */
+
+/*
+ * Adaptative RED : An Algorithm for Increasing the Robustness of RED's AQM
+ * (Sally FLoyd, Ramakrishna Gummadi, and Scott Shenker) August 2001
+ *
+ * Every 500 ms:
+ * if (avg > target and max_p <= 0.5)
+ * increase max_p : max_p += alpha;
+ * else if (avg < target and max_p >= 0.01)
+ * decrease max_p : max_p *= beta;
+ *
+ * target :[qth_min + 0.4*(qth_min - qth_max),
+ * qth_min + 0.6*(qth_min - qth_max)].
+ * alpha : min(0.01, max_p / 4)
+ * beta : 0.9
+ * max_P is a Q0.32 fixed point number (with 32 bits mantissa)
+ * max_P between 0.01 and 0.5 (1% - 50%) [ Its no longer a negative power of two ]
+ */
+#define RED_ONE_PERCENT ((u32)DIV_ROUND_CLOSEST(1ULL<<32, 100))
+
+#define MAX_P_MIN (1 * RED_ONE_PERCENT)
+#define MAX_P_MAX (50 * RED_ONE_PERCENT)
+#define MAX_P_ALPHA(val) min(MAX_P_MIN, val / 4)
+
+#define RED_STAB_SIZE 256
+#define RED_STAB_MASK (RED_STAB_SIZE - 1)
+
+struct red_stats {
+ u32 prob_drop; /* Early probability drops */
+ u32 prob_mark; /* Early probability marks */
+ u32 forced_drop; /* Forced drops, qavg > max_thresh */
+ u32 forced_mark; /* Forced marks, qavg > max_thresh */
+ u32 pdrop; /* Drops due to queue limits */
+ u32 other; /* Drops due to drop() calls */
+};
+
+struct red_parms {
+ /* Parameters */
+ u32 qth_min; /* Min avg length threshold: Wlog scaled */
+ u32 qth_max; /* Max avg length threshold: Wlog scaled */
+ u32 Scell_max;
+ u32 max_P; /* probability, [0 .. 1.0] 32 scaled */
+ u32 max_P_reciprocal; /* reciprocal_value(max_P / qth_delta) */
+ u32 qth_delta; /* max_th - min_th */
+ u32 target_min; /* min_th + 0.4*(max_th - min_th) */
+ u32 target_max; /* min_th + 0.6*(max_th - min_th) */
+ u8 Scell_log;
+ u8 Wlog; /* log(W) */
+ u8 Plog; /* random number bits */
+ u8 Stab[RED_STAB_SIZE];
+};
+
+struct red_vars {
+ /* Variables */
+ int qcount; /* Number of packets since last random
+ number generation */
+ u32 qR; /* Cached random number */
+
+ unsigned long qavg; /* Average queue length: Wlog scaled */
+ ktime_t qidlestart; /* Start of current idle period */
+};
+
+static inline u32 red_maxp(u8 Plog)
+{
+ return Plog < 32 ? (~0U >> Plog) : ~0U;
+}
+
+static inline void red_set_vars(struct red_vars *v)
+{
+ /* Reset average queue length, the value is strictly bound
+ * to the parameters below, reseting hurts a bit but leaving
+ * it might result in an unreasonable qavg for a while. --TGR
+ */
+ v->qavg = 0;
+
+ v->qcount = -1;
+}
+
+static inline void red_set_parms(struct red_parms *p,
+ u32 qth_min, u32 qth_max, u8 Wlog, u8 Plog,
+ u8 Scell_log, u8 *stab, u32 max_P)
+{
+ int delta = qth_max - qth_min;
+ u32 max_p_delta;
+
+ p->qth_min = qth_min << Wlog;
+ p->qth_max = qth_max << Wlog;
+ p->Wlog = Wlog;
+ p->Plog = Plog;
+ if (delta < 0)
+ delta = 1;
+ p->qth_delta = delta;
+ if (!max_P) {
+ max_P = red_maxp(Plog);
+ max_P *= delta; /* max_P = (qth_max - qth_min)/2^Plog */
+ }
+ p->max_P = max_P;
+ max_p_delta = max_P / delta;
+ max_p_delta = max(max_p_delta, 1U);
+ p->max_P_reciprocal = reciprocal_value(max_p_delta);
+
+ /* RED Adaptative target :
+ * [min_th + 0.4*(min_th - max_th),
+ * min_th + 0.6*(min_th - max_th)].
+ */
+ delta /= 5;
+ p->target_min = qth_min + 2*delta;
+ p->target_max = qth_min + 3*delta;
+
+ p->Scell_log = Scell_log;
+ p->Scell_max = (255 << Scell_log);
+
+ if (stab)
+ memcpy(p->Stab, stab, sizeof(p->Stab));
+}
+
+static inline int red_is_idling(const struct red_vars *v)
+{
+ return v->qidlestart.tv64 != 0;
+}
+
+static inline void red_start_of_idle_period(struct red_vars *v)
+{
+ v->qidlestart = ktime_get();
+}
+
+static inline void red_end_of_idle_period(struct red_vars *v)
+{
+ v->qidlestart.tv64 = 0;
+}
+
+static inline void red_restart(struct red_vars *v)
+{
+ red_end_of_idle_period(v);
+ v->qavg = 0;
+ v->qcount = -1;
+}
+
+static inline unsigned long red_calc_qavg_from_idle_time(const struct red_parms *p,
+ const struct red_vars *v)
+{
+ s64 delta = ktime_us_delta(ktime_get(), v->qidlestart);
+ long us_idle = min_t(s64, delta, p->Scell_max);
+ int shift;
+
+ /*
+ * The problem: ideally, average length queue recalcultion should
+ * be done over constant clock intervals. This is too expensive, so
+ * that the calculation is driven by outgoing packets.
+ * When the queue is idle we have to model this clock by hand.
+ *
+ * SF+VJ proposed to "generate":
+ *
+ * m = idletime / (average_pkt_size / bandwidth)
+ *
+ * dummy packets as a burst after idle time, i.e.
+ *
+ * v->qavg *= (1-W)^m
+ *
+ * This is an apparently overcomplicated solution (f.e. we have to
+ * precompute a table to make this calculation in reasonable time)
+ * I believe that a simpler model may be used here,
+ * but it is field for experiments.
+ */
+
+ shift = p->Stab[(us_idle >> p->Scell_log) & RED_STAB_MASK];
+
+ if (shift)
+ return v->qavg >> shift;
+ else {
+ /* Approximate initial part of exponent with linear function:
+ *
+ * (1-W)^m ~= 1-mW + ...
+ *
+ * Seems, it is the best solution to
+ * problem of too coarse exponent tabulation.
+ */
+ us_idle = (v->qavg * (u64)us_idle) >> p->Scell_log;
+
+ if (us_idle < (v->qavg >> 1))
+ return v->qavg - us_idle;
+ else
+ return v->qavg >> 1;
+ }
+}
+
+static inline unsigned long red_calc_qavg_no_idle_time(const struct red_parms *p,
+ const struct red_vars *v,
+ unsigned int backlog)
+{
+ /*
+ * NOTE: v->qavg is fixed point number with point at Wlog.
+ * The formula below is equvalent to floating point
+ * version:
+ *
+ * qavg = qavg*(1-W) + backlog*W;
+ *
+ * --ANK (980924)
+ */
+ return v->qavg + (backlog - (v->qavg >> p->Wlog));
+}
+
+static inline unsigned long red_calc_qavg(const struct red_parms *p,
+ const struct red_vars *v,
+ unsigned int backlog)
+{
+ if (!red_is_idling(v))
+ return red_calc_qavg_no_idle_time(p, v, backlog);
+ else
+ return red_calc_qavg_from_idle_time(p, v);
+}
+
+
+static inline u32 red_random(const struct red_parms *p)
+{
+ return reciprocal_divide(net_random(), p->max_P_reciprocal);
+}
+
+static inline int red_mark_probability(const struct red_parms *p,
+ const struct red_vars *v,
+ unsigned long qavg)
+{
+ /* The formula used below causes questions.
+
+ OK. qR is random number in the interval
+ (0..1/max_P)*(qth_max-qth_min)
+ i.e. 0..(2^Plog). If we used floating point
+ arithmetics, it would be: (2^Plog)*rnd_num,
+ where rnd_num is less 1.
+
+ Taking into account, that qavg have fixed
+ point at Wlog, two lines
+ below have the following floating point equivalent:
+
+ max_P*(qavg - qth_min)/(qth_max-qth_min) < rnd/qcount
+
+ Any questions? --ANK (980924)
+ */
+ return !(((qavg - p->qth_min) >> p->Wlog) * v->qcount < v->qR);
+}
+
+enum {
+ RED_BELOW_MIN_THRESH,
+ RED_BETWEEN_TRESH,
+ RED_ABOVE_MAX_TRESH,
+};
+
+static inline int red_cmp_thresh(const struct red_parms *p, unsigned long qavg)
+{
+ if (qavg < p->qth_min)
+ return RED_BELOW_MIN_THRESH;
+ else if (qavg >= p->qth_max)
+ return RED_ABOVE_MAX_TRESH;
+ else
+ return RED_BETWEEN_TRESH;
+}
+
+enum {
+ RED_DONT_MARK,
+ RED_PROB_MARK,
+ RED_HARD_MARK,
+};
+
+static inline int red_action(const struct red_parms *p,
+ struct red_vars *v,
+ unsigned long qavg)
+{
+ switch (red_cmp_thresh(p, qavg)) {
+ case RED_BELOW_MIN_THRESH:
+ v->qcount = -1;
+ return RED_DONT_MARK;
+
+ case RED_BETWEEN_TRESH:
+ if (++v->qcount) {
+ if (red_mark_probability(p, v, qavg)) {
+ v->qcount = 0;
+ v->qR = red_random(p);
+ return RED_PROB_MARK;
+ }
+ } else
+ v->qR = red_random(p);
+
+ return RED_DONT_MARK;
+
+ case RED_ABOVE_MAX_TRESH:
+ v->qcount = -1;
+ return RED_HARD_MARK;
+ }
+
+ BUG();
+ return RED_DONT_MARK;
+}
+
+static inline void red_adaptative_algo(struct red_parms *p, struct red_vars *v)
+{
+ unsigned long qavg;
+ u32 max_p_delta;
+
+ qavg = v->qavg;
+ if (red_is_idling(v))
+ qavg = red_calc_qavg_from_idle_time(p, v);
+
+ /* v->qavg is fixed point number with point at Wlog */
+ qavg >>= p->Wlog;
+
+ if (qavg > p->target_max && p->max_P <= MAX_P_MAX)
+ p->max_P += MAX_P_ALPHA(p->max_P); /* maxp = maxp + alpha */
+ else if (qavg < p->target_min && p->max_P >= MAX_P_MIN)
+ p->max_P = (p->max_P/10)*9; /* maxp = maxp * Beta */
+
+ max_p_delta = DIV_ROUND_CLOSEST(p->max_P, p->qth_delta);
+ max_p_delta = max(max_p_delta, 1U);
+ p->max_P_reciprocal = reciprocal_value(max_p_delta);
+}
+#endif
diff --git a/include/net/regulatory.h b/include/net/regulatory.h
new file mode 100644
index 00000000..a5f79933
--- /dev/null
+++ b/include/net/regulatory.h
@@ -0,0 +1,122 @@
+#ifndef __NET_REGULATORY_H
+#define __NET_REGULATORY_H
+/*
+ * regulatory support structures
+ *
+ * Copyright 2008-2009 Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+/**
+ * enum environment_cap - Environment parsed from country IE
+ * @ENVIRON_ANY: indicates country IE applies to both indoor and
+ * outdoor operation.
+ * @ENVIRON_INDOOR: indicates country IE applies only to indoor operation
+ * @ENVIRON_OUTDOOR: indicates country IE applies only to outdoor operation
+ */
+enum environment_cap {
+ ENVIRON_ANY,
+ ENVIRON_INDOOR,
+ ENVIRON_OUTDOOR,
+};
+
+/**
+ * struct regulatory_request - used to keep track of regulatory requests
+ *
+ * @wiphy_idx: this is set if this request's initiator is
+ * %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This
+ * can be used by the wireless core to deal with conflicts
+ * and potentially inform users of which devices specifically
+ * cased the conflicts.
+ * @initiator: indicates who sent this request, could be any of
+ * of those set in nl80211_reg_initiator (%NL80211_REGDOM_SET_BY_*)
+ * @alpha2: the ISO / IEC 3166 alpha2 country code of the requested
+ * regulatory domain. We have a few special codes:
+ * 00 - World regulatory domain
+ * 99 - built by driver but a specific alpha2 cannot be determined
+ * 98 - result of an intersection between two regulatory domains
+ * 97 - regulatory domain has not yet been configured
+ * @dfs_region: If CRDA responded with a regulatory domain that requires
+ * DFS master operation on a known DFS region (NL80211_DFS_*),
+ * dfs_region represents that region. Drivers can use this and the
+ * @alpha2 to adjust their device's DFS parameters as required.
+ * @intersect: indicates whether the wireless core should intersect
+ * the requested regulatory domain with the presently set regulatory
+ * domain.
+ * @processed: indicates whether or not this requests has already been
+ * processed. When the last request is processed it means that the
+ * currently regulatory domain set on cfg80211 is updated from
+ * CRDA and can be used by other regulatory requests. When a
+ * the last request is not yet processed we must yield until it
+ * is processed before processing any new requests.
+ * @country_ie_checksum: checksum of the last processed and accepted
+ * country IE
+ * @country_ie_env: lets us know if the AP is telling us we are outdoor,
+ * indoor, or if it doesn't matter
+ * @list: used to insert into the reg_requests_list linked list
+ */
+struct regulatory_request {
+ int wiphy_idx;
+ enum nl80211_reg_initiator initiator;
+ char alpha2[2];
+ u8 dfs_region;
+ bool intersect;
+ bool processed;
+ enum environment_cap country_ie_env;
+ struct list_head list;
+};
+
+struct ieee80211_freq_range {
+ u32 start_freq_khz;
+ u32 end_freq_khz;
+ u32 max_bandwidth_khz;
+};
+
+struct ieee80211_power_rule {
+ u32 max_antenna_gain;
+ u32 max_eirp;
+};
+
+struct ieee80211_reg_rule {
+ struct ieee80211_freq_range freq_range;
+ struct ieee80211_power_rule power_rule;
+ u32 flags;
+};
+
+struct ieee80211_regdomain {
+ u32 n_reg_rules;
+ char alpha2[2];
+ u8 dfs_region;
+ struct ieee80211_reg_rule reg_rules[];
+};
+
+#define MHZ_TO_KHZ(freq) ((freq) * 1000)
+#define KHZ_TO_MHZ(freq) ((freq) / 1000)
+#define DBI_TO_MBI(gain) ((gain) * 100)
+#define MBI_TO_DBI(gain) ((gain) / 100)
+#define DBM_TO_MBM(gain) ((gain) * 100)
+#define MBM_TO_DBM(gain) ((gain) / 100)
+
+#define REG_RULE(start, end, bw, gain, eirp, reg_flags) \
+{ \
+ .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \
+ .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \
+ .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \
+ .power_rule.max_antenna_gain = DBI_TO_MBI(gain),\
+ .power_rule.max_eirp = DBM_TO_MBM(eirp), \
+ .flags = reg_flags, \
+}
+
+#endif
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
new file mode 100644
index 00000000..4c0766e2
--- /dev/null
+++ b/include/net/request_sock.h
@@ -0,0 +1,258 @@
+/*
+ * NET Generic infrastructure for Network protocols.
+ *
+ * Definitions for request_sock
+ *
+ * Authors: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * From code originally in include/net/tcp.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _REQUEST_SOCK_H
+#define _REQUEST_SOCK_H
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/bug.h>
+
+#include <net/sock.h>
+
+struct request_sock;
+struct sk_buff;
+struct dst_entry;
+struct proto;
+
+/* empty to "strongly type" an otherwise void parameter.
+ */
+struct request_values {
+};
+
+struct request_sock_ops {
+ int family;
+ int obj_size;
+ struct kmem_cache *slab;
+ char *slab_name;
+ int (*rtx_syn_ack)(struct sock *sk,
+ struct request_sock *req,
+ struct request_values *rvp);
+ void (*send_ack)(struct sock *sk, struct sk_buff *skb,
+ struct request_sock *req);
+ void (*send_reset)(struct sock *sk,
+ struct sk_buff *skb);
+ void (*destructor)(struct request_sock *req);
+ void (*syn_ack_timeout)(struct sock *sk,
+ struct request_sock *req);
+};
+
+/* struct request_sock - mini sock to represent a connection request
+ */
+struct request_sock {
+ struct request_sock *dl_next; /* Must be first member! */
+ u16 mss;
+ u8 retrans;
+ u8 cookie_ts; /* syncookie: encode tcpopts in timestamp */
+ /* The following two fields can be easily recomputed I think -AK */
+ u32 window_clamp; /* window clamp at creation time */
+ u32 rcv_wnd; /* rcv_wnd offered first time */
+ u32 ts_recent;
+ unsigned long expires;
+ const struct request_sock_ops *rsk_ops;
+ struct sock *sk;
+ u32 secid;
+ u32 peer_secid;
+};
+
+static inline struct request_sock *reqsk_alloc(const struct request_sock_ops *ops)
+{
+ struct request_sock *req = kmem_cache_alloc(ops->slab, GFP_ATOMIC);
+
+ if (req != NULL)
+ req->rsk_ops = ops;
+
+ return req;
+}
+
+static inline void __reqsk_free(struct request_sock *req)
+{
+ kmem_cache_free(req->rsk_ops->slab, req);
+}
+
+static inline void reqsk_free(struct request_sock *req)
+{
+ req->rsk_ops->destructor(req);
+ __reqsk_free(req);
+}
+
+extern int sysctl_max_syn_backlog;
+
+/** struct listen_sock - listen state
+ *
+ * @max_qlen_log - log_2 of maximal queued SYNs/REQUESTs
+ */
+struct listen_sock {
+ u8 max_qlen_log;
+ u8 synflood_warned;
+ /* 2 bytes hole, try to use */
+ int qlen;
+ int qlen_young;
+ int clock_hand;
+ u32 hash_rnd;
+ u32 nr_table_entries;
+ struct request_sock *syn_table[0];
+};
+
+/** struct request_sock_queue - queue of request_socks
+ *
+ * @rskq_accept_head - FIFO head of established children
+ * @rskq_accept_tail - FIFO tail of established children
+ * @rskq_defer_accept - User waits for some data after accept()
+ * @syn_wait_lock - serializer
+ *
+ * %syn_wait_lock is necessary only to avoid proc interface having to grab the main
+ * lock sock while browsing the listening hash (otherwise it's deadlock prone).
+ *
+ * This lock is acquired in read mode only from listening_get_next() seq_file
+ * op and it's acquired in write mode _only_ from code that is actively
+ * changing rskq_accept_head. All readers that are holding the master sock lock
+ * don't need to grab this lock in read mode too as rskq_accept_head. writes
+ * are always protected from the main sock lock.
+ */
+struct request_sock_queue {
+ struct request_sock *rskq_accept_head;
+ struct request_sock *rskq_accept_tail;
+ rwlock_t syn_wait_lock;
+ u8 rskq_defer_accept;
+ /* 3 bytes hole, try to pack */
+ struct listen_sock *listen_opt;
+};
+
+extern int reqsk_queue_alloc(struct request_sock_queue *queue,
+ unsigned int nr_table_entries);
+
+extern void __reqsk_queue_destroy(struct request_sock_queue *queue);
+extern void reqsk_queue_destroy(struct request_sock_queue *queue);
+
+static inline struct request_sock *
+ reqsk_queue_yank_acceptq(struct request_sock_queue *queue)
+{
+ struct request_sock *req = queue->rskq_accept_head;
+
+ queue->rskq_accept_head = NULL;
+ return req;
+}
+
+static inline int reqsk_queue_empty(struct request_sock_queue *queue)
+{
+ return queue->rskq_accept_head == NULL;
+}
+
+static inline void reqsk_queue_unlink(struct request_sock_queue *queue,
+ struct request_sock *req,
+ struct request_sock **prev_req)
+{
+ write_lock(&queue->syn_wait_lock);
+ *prev_req = req->dl_next;
+ write_unlock(&queue->syn_wait_lock);
+}
+
+static inline void reqsk_queue_add(struct request_sock_queue *queue,
+ struct request_sock *req,
+ struct sock *parent,
+ struct sock *child)
+{
+ req->sk = child;
+ sk_acceptq_added(parent);
+
+ if (queue->rskq_accept_head == NULL)
+ queue->rskq_accept_head = req;
+ else
+ queue->rskq_accept_tail->dl_next = req;
+
+ queue->rskq_accept_tail = req;
+ req->dl_next = NULL;
+}
+
+static inline struct request_sock *reqsk_queue_remove(struct request_sock_queue *queue)
+{
+ struct request_sock *req = queue->rskq_accept_head;
+
+ WARN_ON(req == NULL);
+
+ queue->rskq_accept_head = req->dl_next;
+ if (queue->rskq_accept_head == NULL)
+ queue->rskq_accept_tail = NULL;
+
+ return req;
+}
+
+static inline struct sock *reqsk_queue_get_child(struct request_sock_queue *queue,
+ struct sock *parent)
+{
+ struct request_sock *req = reqsk_queue_remove(queue);
+ struct sock *child = req->sk;
+
+ WARN_ON(child == NULL);
+
+ sk_acceptq_removed(parent);
+ __reqsk_free(req);
+ return child;
+}
+
+static inline int reqsk_queue_removed(struct request_sock_queue *queue,
+ struct request_sock *req)
+{
+ struct listen_sock *lopt = queue->listen_opt;
+
+ if (req->retrans == 0)
+ --lopt->qlen_young;
+
+ return --lopt->qlen;
+}
+
+static inline int reqsk_queue_added(struct request_sock_queue *queue)
+{
+ struct listen_sock *lopt = queue->listen_opt;
+ const int prev_qlen = lopt->qlen;
+
+ lopt->qlen_young++;
+ lopt->qlen++;
+ return prev_qlen;
+}
+
+static inline int reqsk_queue_len(const struct request_sock_queue *queue)
+{
+ return queue->listen_opt != NULL ? queue->listen_opt->qlen : 0;
+}
+
+static inline int reqsk_queue_len_young(const struct request_sock_queue *queue)
+{
+ return queue->listen_opt->qlen_young;
+}
+
+static inline int reqsk_queue_is_full(const struct request_sock_queue *queue)
+{
+ return queue->listen_opt->qlen >> queue->listen_opt->max_qlen_log;
+}
+
+static inline void reqsk_queue_hash_req(struct request_sock_queue *queue,
+ u32 hash, struct request_sock *req,
+ unsigned long timeout)
+{
+ struct listen_sock *lopt = queue->listen_opt;
+
+ req->expires = jiffies + timeout;
+ req->retrans = 0;
+ req->sk = NULL;
+ req->dl_next = lopt->syn_table[hash];
+
+ write_lock(&queue->syn_wait_lock);
+ lopt->syn_table[hash] = req;
+ write_unlock(&queue->syn_wait_lock);
+}
+
+#endif /* _REQUEST_SOCK_H */
diff --git a/include/net/rose.h b/include/net/rose.h
new file mode 100644
index 00000000..555dd198
--- /dev/null
+++ b/include/net/rose.h
@@ -0,0 +1,241 @@
+/*
+ * Declarations of Rose type objects.
+ *
+ * Jonathan Naylor G4KLX 25/8/96
+ */
+
+#ifndef _ROSE_H
+#define _ROSE_H
+
+#include <linux/rose.h>
+#include <net/sock.h>
+
+#define ROSE_ADDR_LEN 5
+
+#define ROSE_MIN_LEN 3
+
+#define ROSE_CALL_REQ_ADDR_LEN_OFF 3
+#define ROSE_CALL_REQ_ADDR_LEN_VAL 0xAA /* each address is 10 digits */
+#define ROSE_CALL_REQ_DEST_ADDR_OFF 4
+#define ROSE_CALL_REQ_SRC_ADDR_OFF 9
+#define ROSE_CALL_REQ_FACILITIES_OFF 14
+
+#define ROSE_GFI 0x10
+#define ROSE_Q_BIT 0x80
+#define ROSE_D_BIT 0x40
+#define ROSE_M_BIT 0x10
+
+#define ROSE_CALL_REQUEST 0x0B
+#define ROSE_CALL_ACCEPTED 0x0F
+#define ROSE_CLEAR_REQUEST 0x13
+#define ROSE_CLEAR_CONFIRMATION 0x17
+#define ROSE_DATA 0x00
+#define ROSE_INTERRUPT 0x23
+#define ROSE_INTERRUPT_CONFIRMATION 0x27
+#define ROSE_RR 0x01
+#define ROSE_RNR 0x05
+#define ROSE_REJ 0x09
+#define ROSE_RESET_REQUEST 0x1B
+#define ROSE_RESET_CONFIRMATION 0x1F
+#define ROSE_REGISTRATION_REQUEST 0xF3
+#define ROSE_REGISTRATION_CONFIRMATION 0xF7
+#define ROSE_RESTART_REQUEST 0xFB
+#define ROSE_RESTART_CONFIRMATION 0xFF
+#define ROSE_DIAGNOSTIC 0xF1
+#define ROSE_ILLEGAL 0xFD
+
+/* Define Link State constants. */
+
+enum {
+ ROSE_STATE_0, /* Ready */
+ ROSE_STATE_1, /* Awaiting Call Accepted */
+ ROSE_STATE_2, /* Awaiting Clear Confirmation */
+ ROSE_STATE_3, /* Data Transfer */
+ ROSE_STATE_4, /* Awaiting Reset Confirmation */
+ ROSE_STATE_5 /* Deferred Call Acceptance */
+};
+
+#define ROSE_DEFAULT_T0 180000 /* Default T10 T20 value */
+#define ROSE_DEFAULT_T1 200000 /* Default T11 T21 value */
+#define ROSE_DEFAULT_T2 180000 /* Default T12 T22 value */
+#define ROSE_DEFAULT_T3 180000 /* Default T13 T23 value */
+#define ROSE_DEFAULT_HB 5000 /* Default Holdback value */
+#define ROSE_DEFAULT_IDLE 0 /* No Activity Timeout - none */
+#define ROSE_DEFAULT_ROUTING 1 /* Default routing flag */
+#define ROSE_DEFAULT_FAIL_TIMEOUT 120000 /* Time until link considered usable */
+#define ROSE_DEFAULT_MAXVC 50 /* Maximum number of VCs per neighbour */
+#define ROSE_DEFAULT_WINDOW_SIZE 7 /* Default window size */
+
+#define ROSE_MODULUS 8
+#define ROSE_MAX_PACKET_SIZE 251 /* Maximum packet size */
+
+#define ROSE_COND_ACK_PENDING 0x01
+#define ROSE_COND_PEER_RX_BUSY 0x02
+#define ROSE_COND_OWN_RX_BUSY 0x04
+
+#define FAC_NATIONAL 0x00
+#define FAC_CCITT 0x0F
+
+#define FAC_NATIONAL_RAND 0x7F
+#define FAC_NATIONAL_FLAGS 0x3F
+#define FAC_NATIONAL_DEST_DIGI 0xE9
+#define FAC_NATIONAL_SRC_DIGI 0xEB
+#define FAC_NATIONAL_FAIL_CALL 0xED
+#define FAC_NATIONAL_FAIL_ADD 0xEE
+#define FAC_NATIONAL_DIGIS 0xEF
+
+#define FAC_CCITT_DEST_NSAP 0xC9
+#define FAC_CCITT_SRC_NSAP 0xCB
+
+struct rose_neigh {
+ struct rose_neigh *next;
+ ax25_address callsign;
+ ax25_digi *digipeat;
+ ax25_cb *ax25;
+ struct net_device *dev;
+ unsigned short count;
+ unsigned short use;
+ unsigned int number;
+ char restarted;
+ char dce_mode;
+ char loopback;
+ struct sk_buff_head queue;
+ struct timer_list t0timer;
+ struct timer_list ftimer;
+};
+
+struct rose_node {
+ struct rose_node *next;
+ rose_address address;
+ unsigned short mask;
+ unsigned char count;
+ char loopback;
+ struct rose_neigh *neighbour[3];
+};
+
+struct rose_route {
+ struct rose_route *next;
+ unsigned int lci1, lci2;
+ rose_address src_addr, dest_addr;
+ ax25_address src_call, dest_call;
+ struct rose_neigh *neigh1, *neigh2;
+ unsigned int rand;
+};
+
+struct rose_sock {
+ struct sock sock;
+ rose_address source_addr, dest_addr;
+ ax25_address source_call, dest_call;
+ unsigned char source_ndigis, dest_ndigis;
+ ax25_address source_digis[ROSE_MAX_DIGIS];
+ ax25_address dest_digis[ROSE_MAX_DIGIS];
+ struct rose_neigh *neighbour;
+ struct net_device *device;
+ unsigned int lci, rand;
+ unsigned char state, condition, qbitincl, defer;
+ unsigned char cause, diagnostic;
+ unsigned short vs, vr, va, vl;
+ unsigned long t1, t2, t3, hb, idle;
+#ifdef M_BIT
+ unsigned short fraglen;
+ struct sk_buff_head frag_queue;
+#endif
+ struct sk_buff_head ack_queue;
+ struct rose_facilities_struct facilities;
+ struct timer_list timer;
+ struct timer_list idletimer;
+};
+
+#define rose_sk(sk) ((struct rose_sock *)(sk))
+
+/* af_rose.c */
+extern ax25_address rose_callsign;
+extern int sysctl_rose_restart_request_timeout;
+extern int sysctl_rose_call_request_timeout;
+extern int sysctl_rose_reset_request_timeout;
+extern int sysctl_rose_clear_request_timeout;
+extern int sysctl_rose_no_activity_timeout;
+extern int sysctl_rose_ack_hold_back_timeout;
+extern int sysctl_rose_routing_control;
+extern int sysctl_rose_link_fail_timeout;
+extern int sysctl_rose_maximum_vcs;
+extern int sysctl_rose_window_size;
+extern int rosecmp(rose_address *, rose_address *);
+extern int rosecmpm(rose_address *, rose_address *, unsigned short);
+extern char *rose2asc(char *buf, const rose_address *);
+extern struct sock *rose_find_socket(unsigned int, struct rose_neigh *);
+extern void rose_kill_by_neigh(struct rose_neigh *);
+extern unsigned int rose_new_lci(struct rose_neigh *);
+extern int rose_rx_call_request(struct sk_buff *, struct net_device *, struct rose_neigh *, unsigned int);
+extern void rose_destroy_socket(struct sock *);
+
+/* rose_dev.c */
+extern void rose_setup(struct net_device *);
+
+/* rose_in.c */
+extern int rose_process_rx_frame(struct sock *, struct sk_buff *);
+
+/* rose_link.c */
+extern void rose_start_ftimer(struct rose_neigh *);
+extern void rose_stop_ftimer(struct rose_neigh *);
+extern void rose_stop_t0timer(struct rose_neigh *);
+extern int rose_ftimer_running(struct rose_neigh *);
+extern void rose_link_rx_restart(struct sk_buff *, struct rose_neigh *, unsigned short);
+extern void rose_transmit_clear_request(struct rose_neigh *, unsigned int, unsigned char, unsigned char);
+extern void rose_transmit_link(struct sk_buff *, struct rose_neigh *);
+
+/* rose_loopback.c */
+extern void rose_loopback_init(void);
+extern void rose_loopback_clear(void);
+extern int rose_loopback_queue(struct sk_buff *, struct rose_neigh *);
+
+/* rose_out.c */
+extern void rose_kick(struct sock *);
+extern void rose_enquiry_response(struct sock *);
+
+/* rose_route.c */
+extern struct rose_neigh *rose_loopback_neigh;
+extern const struct file_operations rose_neigh_fops;
+extern const struct file_operations rose_nodes_fops;
+extern const struct file_operations rose_routes_fops;
+
+extern void rose_add_loopback_neigh(void);
+extern int __must_check rose_add_loopback_node(rose_address *);
+extern void rose_del_loopback_node(rose_address *);
+extern void rose_rt_device_down(struct net_device *);
+extern void rose_link_device_down(struct net_device *);
+extern struct net_device *rose_dev_first(void);
+extern struct net_device *rose_dev_get(rose_address *);
+extern struct rose_route *rose_route_free_lci(unsigned int, struct rose_neigh *);
+extern struct rose_neigh *rose_get_neigh(rose_address *, unsigned char *, unsigned char *, int);
+extern int rose_rt_ioctl(unsigned int, void __user *);
+extern void rose_link_failed(ax25_cb *, int);
+extern int rose_route_frame(struct sk_buff *, ax25_cb *);
+extern void rose_rt_free(void);
+
+/* rose_subr.c */
+extern void rose_clear_queues(struct sock *);
+extern void rose_frames_acked(struct sock *, unsigned short);
+extern void rose_requeue_frames(struct sock *);
+extern int rose_validate_nr(struct sock *, unsigned short);
+extern void rose_write_internal(struct sock *, int);
+extern int rose_decode(struct sk_buff *, int *, int *, int *, int *, int *);
+extern int rose_parse_facilities(unsigned char *, unsigned int, struct rose_facilities_struct *);
+extern void rose_disconnect(struct sock *, int, int, int);
+
+/* rose_timer.c */
+extern void rose_start_heartbeat(struct sock *);
+extern void rose_start_t1timer(struct sock *);
+extern void rose_start_t2timer(struct sock *);
+extern void rose_start_t3timer(struct sock *);
+extern void rose_start_hbtimer(struct sock *);
+extern void rose_start_idletimer(struct sock *);
+extern void rose_stop_heartbeat(struct sock *);
+extern void rose_stop_timer(struct sock *);
+extern void rose_stop_idletimer(struct sock *);
+
+/* sysctl_net_rose.c */
+extern void rose_register_sysctl(void);
+extern void rose_unregister_sysctl(void);
+
+#endif
diff --git a/include/net/route.h b/include/net/route.h
new file mode 100644
index 00000000..b1c0d5b5
--- /dev/null
+++ b/include/net/route.h
@@ -0,0 +1,324 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the IP router.
+ *
+ * Version: @(#)route.h 1.0.4 05/27/93
+ *
+ * Authors: Ross Biro
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Fixes:
+ * Alan Cox : Reformatted. Added ip_rt_local()
+ * Alan Cox : Support for TCP parameters.
+ * Alexey Kuznetsov: Major changes for new routing code.
+ * Mike McLagan : Routing by source
+ * Robert Olsson : Added rt_cache statistics
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _ROUTE_H
+#define _ROUTE_H
+
+#include <net/dst.h>
+#include <net/inetpeer.h>
+#include <net/flow.h>
+#include <net/inet_sock.h>
+#include <linux/in_route.h>
+#include <linux/rtnetlink.h>
+#include <linux/route.h>
+#include <linux/ip.h>
+#include <linux/cache.h>
+#include <linux/security.h>
+
+#define RTO_ONLINK 0x01
+
+#define RT_CONN_FLAGS(sk) (RT_TOS(inet_sk(sk)->tos) | sock_flag(sk, SOCK_LOCALROUTE))
+
+struct fib_nh;
+struct inet_peer;
+struct fib_info;
+struct rtable {
+ struct dst_entry dst;
+
+ /* Lookup key. */
+ __be32 rt_key_dst;
+ __be32 rt_key_src;
+
+ int rt_genid;
+ unsigned rt_flags;
+ __u16 rt_type;
+ __u8 rt_key_tos;
+
+ __be32 rt_dst; /* Path destination */
+ __be32 rt_src; /* Path source */
+ int rt_route_iif;
+ int rt_iif;
+ int rt_oif;
+ __u32 rt_mark;
+
+ /* Info on neighbour */
+ __be32 rt_gateway;
+
+ /* Miscellaneous cached information */
+ __be32 rt_spec_dst; /* RFC1122 specific destination */
+ u32 rt_peer_genid;
+ struct inet_peer *peer; /* long-living peer info */
+ struct fib_info *fi; /* for client ref to shared metrics */
+};
+
+static inline bool rt_is_input_route(const struct rtable *rt)
+{
+ return rt->rt_route_iif != 0;
+}
+
+static inline bool rt_is_output_route(const struct rtable *rt)
+{
+ return rt->rt_route_iif == 0;
+}
+
+struct ip_rt_acct {
+ __u32 o_bytes;
+ __u32 o_packets;
+ __u32 i_bytes;
+ __u32 i_packets;
+};
+
+struct rt_cache_stat {
+ unsigned int in_hit;
+ unsigned int in_slow_tot;
+ unsigned int in_slow_mc;
+ unsigned int in_no_route;
+ unsigned int in_brd;
+ unsigned int in_martian_dst;
+ unsigned int in_martian_src;
+ unsigned int out_hit;
+ unsigned int out_slow_tot;
+ unsigned int out_slow_mc;
+ unsigned int gc_total;
+ unsigned int gc_ignored;
+ unsigned int gc_goal_miss;
+ unsigned int gc_dst_overflow;
+ unsigned int in_hlist_search;
+ unsigned int out_hlist_search;
+};
+
+extern struct ip_rt_acct __percpu *ip_rt_acct;
+
+struct in_device;
+extern int ip_rt_init(void);
+extern void ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw,
+ __be32 src, struct net_device *dev);
+extern void rt_cache_flush(struct net *net, int how);
+extern void rt_cache_flush_batch(struct net *net);
+extern struct rtable *__ip_route_output_key(struct net *, struct flowi4 *flp);
+extern struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp,
+ struct sock *sk);
+extern struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig);
+
+static inline struct rtable *ip_route_output_key(struct net *net, struct flowi4 *flp)
+{
+ return ip_route_output_flow(net, flp, NULL);
+}
+
+static inline struct rtable *ip_route_output(struct net *net, __be32 daddr,
+ __be32 saddr, u8 tos, int oif)
+{
+ struct flowi4 fl4 = {
+ .flowi4_oif = oif,
+ .daddr = daddr,
+ .saddr = saddr,
+ .flowi4_tos = tos,
+ };
+ return ip_route_output_key(net, &fl4);
+}
+
+static inline struct rtable *ip_route_output_ports(struct net *net, struct flowi4 *fl4,
+ struct sock *sk,
+ __be32 daddr, __be32 saddr,
+ __be16 dport, __be16 sport,
+ __u8 proto, __u8 tos, int oif)
+{
+ flowi4_init_output(fl4, oif, sk ? sk->sk_mark : 0, tos,
+ RT_SCOPE_UNIVERSE, proto,
+ sk ? inet_sk_flowi_flags(sk) : 0,
+ daddr, saddr, dport, sport);
+ if (sk)
+ security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
+ return ip_route_output_flow(net, fl4, sk);
+}
+
+static inline struct rtable *ip_route_output_gre(struct net *net, struct flowi4 *fl4,
+ __be32 daddr, __be32 saddr,
+ __be32 gre_key, __u8 tos, int oif)
+{
+ memset(fl4, 0, sizeof(*fl4));
+ fl4->flowi4_oif = oif;
+ fl4->daddr = daddr;
+ fl4->saddr = saddr;
+ fl4->flowi4_tos = tos;
+ fl4->flowi4_proto = IPPROTO_GRE;
+ fl4->fl4_gre_key = gre_key;
+ return ip_route_output_key(net, fl4);
+}
+
+extern int ip_route_input_common(struct sk_buff *skb, __be32 dst, __be32 src,
+ u8 tos, struct net_device *devin, bool noref);
+
+static inline int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src,
+ u8 tos, struct net_device *devin)
+{
+ return ip_route_input_common(skb, dst, src, tos, devin, false);
+}
+
+static inline int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 src,
+ u8 tos, struct net_device *devin)
+{
+ return ip_route_input_common(skb, dst, src, tos, devin, true);
+}
+
+extern unsigned short ip_rt_frag_needed(struct net *net, const struct iphdr *iph,
+ unsigned short new_mtu, struct net_device *dev);
+extern void ip_rt_send_redirect(struct sk_buff *skb);
+
+extern unsigned inet_addr_type(struct net *net, __be32 addr);
+extern unsigned inet_dev_addr_type(struct net *net, const struct net_device *dev, __be32 addr);
+extern void ip_rt_multicast_event(struct in_device *);
+extern int ip_rt_ioctl(struct net *, unsigned int cmd, void __user *arg);
+extern void ip_rt_get_source(u8 *src, struct sk_buff *skb, struct rtable *rt);
+extern int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb);
+
+struct in_ifaddr;
+extern void fib_add_ifaddr(struct in_ifaddr *);
+extern void fib_del_ifaddr(struct in_ifaddr *, struct in_ifaddr *);
+
+static inline void ip_rt_put(struct rtable * rt)
+{
+ if (rt)
+ dst_release(&rt->dst);
+}
+
+#define IPTOS_RT_MASK (IPTOS_TOS_MASK & ~3)
+
+extern const __u8 ip_tos2prio[16];
+
+static inline char rt_tos2priority(u8 tos)
+{
+ return ip_tos2prio[IPTOS_TOS(tos)>>1];
+}
+
+/* ip_route_connect() and ip_route_newports() work in tandem whilst
+ * binding a socket for a new outgoing connection.
+ *
+ * In order to use IPSEC properly, we must, in the end, have a
+ * route that was looked up using all available keys including source
+ * and destination ports.
+ *
+ * However, if a source port needs to be allocated (the user specified
+ * a wildcard source port) we need to obtain addressing information
+ * in order to perform that allocation.
+ *
+ * So ip_route_connect() looks up a route using wildcarded source and
+ * destination ports in the key, simply so that we can get a pair of
+ * addresses to use for port allocation.
+ *
+ * Later, once the ports are allocated, ip_route_newports() will make
+ * another route lookup if needed to make sure we catch any IPSEC
+ * rules keyed on the port information.
+ *
+ * The callers allocate the flow key on their stack, and must pass in
+ * the same flowi4 object to both the ip_route_connect() and the
+ * ip_route_newports() calls.
+ */
+
+static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst, __be32 src,
+ u32 tos, int oif, u8 protocol,
+ __be16 sport, __be16 dport,
+ struct sock *sk, bool can_sleep)
+{
+ __u8 flow_flags = 0;
+
+ if (inet_sk(sk)->transparent)
+ flow_flags |= FLOWI_FLAG_ANYSRC;
+ if (protocol == IPPROTO_TCP)
+ flow_flags |= FLOWI_FLAG_PRECOW_METRICS;
+ if (can_sleep)
+ flow_flags |= FLOWI_FLAG_CAN_SLEEP;
+
+ flowi4_init_output(fl4, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE,
+ protocol, flow_flags, dst, src, dport, sport);
+}
+
+static inline struct rtable *ip_route_connect(struct flowi4 *fl4,
+ __be32 dst, __be32 src, u32 tos,
+ int oif, u8 protocol,
+ __be16 sport, __be16 dport,
+ struct sock *sk, bool can_sleep)
+{
+ struct net *net = sock_net(sk);
+ struct rtable *rt;
+
+ ip_route_connect_init(fl4, dst, src, tos, oif, protocol,
+ sport, dport, sk, can_sleep);
+
+ if (!dst || !src) {
+ rt = __ip_route_output_key(net, fl4);
+ if (IS_ERR(rt))
+ return rt;
+ ip_rt_put(rt);
+ flowi4_update_output(fl4, oif, tos, fl4->daddr, fl4->saddr);
+ }
+ security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
+ return ip_route_output_flow(net, fl4, sk);
+}
+
+static inline struct rtable *ip_route_newports(struct flowi4 *fl4, struct rtable *rt,
+ __be16 orig_sport, __be16 orig_dport,
+ __be16 sport, __be16 dport,
+ struct sock *sk)
+{
+ if (sport != orig_sport || dport != orig_dport) {
+ fl4->fl4_dport = dport;
+ fl4->fl4_sport = sport;
+ ip_rt_put(rt);
+ flowi4_update_output(fl4, sk->sk_bound_dev_if,
+ RT_CONN_FLAGS(sk), fl4->daddr,
+ fl4->saddr);
+ security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
+ return ip_route_output_flow(sock_net(sk), fl4, sk);
+ }
+ return rt;
+}
+
+extern void rt_bind_peer(struct rtable *rt, __be32 daddr, int create);
+
+static inline struct inet_peer *rt_get_peer(struct rtable *rt, __be32 daddr)
+{
+ if (rt->peer)
+ return rt->peer;
+
+ rt_bind_peer(rt, daddr, 0);
+ return rt->peer;
+}
+
+static inline int inet_iif(const struct sk_buff *skb)
+{
+ return skb_rtable(skb)->rt_iif;
+}
+
+extern int sysctl_ip_default_ttl;
+
+static inline int ip4_dst_hoplimit(const struct dst_entry *dst)
+{
+ int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT);
+
+ if (hoplimit == 0)
+ hoplimit = sysctl_ip_default_ttl;
+ return hoplimit;
+}
+
+#endif /* _ROUTE_H */
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
new file mode 100644
index 00000000..37029390
--- /dev/null
+++ b/include/net/rtnetlink.h
@@ -0,0 +1,133 @@
+#ifndef __NET_RTNETLINK_H
+#define __NET_RTNETLINK_H
+
+#include <linux/rtnetlink.h>
+#include <net/netlink.h>
+
+typedef int (*rtnl_doit_func)(struct sk_buff *, struct nlmsghdr *, void *);
+typedef int (*rtnl_dumpit_func)(struct sk_buff *, struct netlink_callback *);
+typedef u16 (*rtnl_calcit_func)(struct sk_buff *, struct nlmsghdr *);
+
+extern int __rtnl_register(int protocol, int msgtype,
+ rtnl_doit_func, rtnl_dumpit_func,
+ rtnl_calcit_func);
+extern void rtnl_register(int protocol, int msgtype,
+ rtnl_doit_func, rtnl_dumpit_func,
+ rtnl_calcit_func);
+extern int rtnl_unregister(int protocol, int msgtype);
+extern void rtnl_unregister_all(int protocol);
+
+static inline int rtnl_msg_family(const struct nlmsghdr *nlh)
+{
+ if (nlmsg_len(nlh) >= sizeof(struct rtgenmsg))
+ return ((struct rtgenmsg *) nlmsg_data(nlh))->rtgen_family;
+ else
+ return AF_UNSPEC;
+}
+
+/**
+ * struct rtnl_link_ops - rtnetlink link operations
+ *
+ * @list: Used internally
+ * @kind: Identifier
+ * @maxtype: Highest device specific netlink attribute number
+ * @policy: Netlink policy for device specific attribute validation
+ * @validate: Optional validation function for netlink/changelink parameters
+ * @priv_size: sizeof net_device private space
+ * @setup: net_device setup function
+ * @newlink: Function for configuring and registering a new device
+ * @changelink: Function for changing parameters of an existing device
+ * @dellink: Function to remove a device
+ * @get_size: Function to calculate required room for dumping device
+ * specific netlink attributes
+ * @fill_info: Function to dump device specific netlink attributes
+ * @get_xstats_size: Function to calculate required room for dumping devic
+ * specific statistics
+ * @fill_xstats: Function to dump device specific statistics
+ */
+struct rtnl_link_ops {
+ struct list_head list;
+
+ const char *kind;
+
+ size_t priv_size;
+ void (*setup)(struct net_device *dev);
+
+ int maxtype;
+ const struct nla_policy *policy;
+ int (*validate)(struct nlattr *tb[],
+ struct nlattr *data[]);
+
+ int (*newlink)(struct net *src_net,
+ struct net_device *dev,
+ struct nlattr *tb[],
+ struct nlattr *data[]);
+ int (*changelink)(struct net_device *dev,
+ struct nlattr *tb[],
+ struct nlattr *data[]);
+ void (*dellink)(struct net_device *dev,
+ struct list_head *head);
+
+ size_t (*get_size)(const struct net_device *dev);
+ int (*fill_info)(struct sk_buff *skb,
+ const struct net_device *dev);
+
+ size_t (*get_xstats_size)(const struct net_device *dev);
+ int (*fill_xstats)(struct sk_buff *skb,
+ const struct net_device *dev);
+ int (*get_tx_queues)(struct net *net, struct nlattr *tb[],
+ unsigned int *tx_queues,
+ unsigned int *real_tx_queues);
+};
+
+extern int __rtnl_link_register(struct rtnl_link_ops *ops);
+extern void __rtnl_link_unregister(struct rtnl_link_ops *ops);
+
+extern int rtnl_link_register(struct rtnl_link_ops *ops);
+extern void rtnl_link_unregister(struct rtnl_link_ops *ops);
+
+/**
+ * struct rtnl_af_ops - rtnetlink address family operations
+ *
+ * @list: Used internally
+ * @family: Address family
+ * @fill_link_af: Function to fill IFLA_AF_SPEC with address family
+ * specific netlink attributes.
+ * @get_link_af_size: Function to calculate size of address family specific
+ * netlink attributes exlusive the container attribute.
+ * @validate_link_af: Validate a IFLA_AF_SPEC attribute, must check attr
+ * for invalid configuration settings.
+ * @set_link_af: Function to parse a IFLA_AF_SPEC attribute and modify
+ * net_device accordingly.
+ */
+struct rtnl_af_ops {
+ struct list_head list;
+ int family;
+
+ int (*fill_link_af)(struct sk_buff *skb,
+ const struct net_device *dev);
+ size_t (*get_link_af_size)(const struct net_device *dev);
+
+ int (*validate_link_af)(const struct net_device *dev,
+ const struct nlattr *attr);
+ int (*set_link_af)(struct net_device *dev,
+ const struct nlattr *attr);
+};
+
+extern int __rtnl_af_register(struct rtnl_af_ops *ops);
+extern void __rtnl_af_unregister(struct rtnl_af_ops *ops);
+
+extern int rtnl_af_register(struct rtnl_af_ops *ops);
+extern void rtnl_af_unregister(struct rtnl_af_ops *ops);
+
+
+extern struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]);
+extern struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
+ char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]);
+extern int rtnl_configure_link(struct net_device *dev,
+ const struct ifinfomsg *ifm);
+extern const struct nla_policy ifla_policy[IFLA_MAX+1];
+
+#define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind)
+
+#endif
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
new file mode 100644
index 00000000..9d7d54a0
--- /dev/null
+++ b/include/net/sch_generic.h
@@ -0,0 +1,674 @@
+#ifndef __NET_SCHED_GENERIC_H
+#define __NET_SCHED_GENERIC_H
+
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <linux/rcupdate.h>
+#include <linux/pkt_sched.h>
+#include <linux/pkt_cls.h>
+#include <net/gen_stats.h>
+#include <net/rtnetlink.h>
+
+struct Qdisc_ops;
+struct qdisc_walker;
+struct tcf_walker;
+struct module;
+
+struct qdisc_rate_table {
+ struct tc_ratespec rate;
+ u32 data[256];
+ struct qdisc_rate_table *next;
+ int refcnt;
+};
+
+enum qdisc_state_t {
+ __QDISC_STATE_SCHED,
+ __QDISC_STATE_DEACTIVATED,
+ __QDISC_STATE_THROTTLED,
+};
+
+/*
+ * following bits are only changed while qdisc lock is held
+ */
+enum qdisc___state_t {
+ __QDISC___STATE_RUNNING = 1,
+};
+
+struct qdisc_size_table {
+ struct rcu_head rcu;
+ struct list_head list;
+ struct tc_sizespec szopts;
+ int refcnt;
+ u16 data[];
+};
+
+struct Qdisc {
+ int (*enqueue)(struct sk_buff *skb, struct Qdisc *dev);
+ struct sk_buff * (*dequeue)(struct Qdisc *dev);
+ unsigned int flags;
+#define TCQ_F_BUILTIN 1
+#define TCQ_F_INGRESS 2
+#define TCQ_F_CAN_BYPASS 4
+#define TCQ_F_MQROOT 8
+#define TCQ_F_WARN_NONWC (1 << 16)
+ int padded;
+ const struct Qdisc_ops *ops;
+ struct qdisc_size_table __rcu *stab;
+ struct list_head list;
+ u32 handle;
+ u32 parent;
+ atomic_t refcnt;
+ struct gnet_stats_rate_est rate_est;
+ int (*reshape_fail)(struct sk_buff *skb,
+ struct Qdisc *q);
+
+ void *u32_node;
+
+ /* This field is deprecated, but it is still used by CBQ
+ * and it will live until better solution will be invented.
+ */
+ struct Qdisc *__parent;
+ struct netdev_queue *dev_queue;
+ struct Qdisc *next_sched;
+
+ struct sk_buff *gso_skb;
+ /*
+ * For performance sake on SMP, we put highly modified fields at the end
+ */
+ unsigned long state;
+ struct sk_buff_head q;
+ struct gnet_stats_basic_packed bstats;
+ unsigned int __state;
+ struct gnet_stats_queue qstats;
+ struct rcu_head rcu_head;
+ spinlock_t busylock;
+ u32 limit;
+};
+
+static inline bool qdisc_is_running(const struct Qdisc *qdisc)
+{
+ return (qdisc->__state & __QDISC___STATE_RUNNING) ? true : false;
+}
+
+static inline bool qdisc_run_begin(struct Qdisc *qdisc)
+{
+ if (qdisc_is_running(qdisc))
+ return false;
+ qdisc->__state |= __QDISC___STATE_RUNNING;
+ return true;
+}
+
+static inline void qdisc_run_end(struct Qdisc *qdisc)
+{
+ qdisc->__state &= ~__QDISC___STATE_RUNNING;
+}
+
+static inline bool qdisc_is_throttled(const struct Qdisc *qdisc)
+{
+ return test_bit(__QDISC_STATE_THROTTLED, &qdisc->state) ? true : false;
+}
+
+static inline void qdisc_throttled(struct Qdisc *qdisc)
+{
+ set_bit(__QDISC_STATE_THROTTLED, &qdisc->state);
+}
+
+static inline void qdisc_unthrottled(struct Qdisc *qdisc)
+{
+ clear_bit(__QDISC_STATE_THROTTLED, &qdisc->state);
+}
+
+struct Qdisc_class_ops {
+ /* Child qdisc manipulation */
+ struct netdev_queue * (*select_queue)(struct Qdisc *, struct tcmsg *);
+ int (*graft)(struct Qdisc *, unsigned long cl,
+ struct Qdisc *, struct Qdisc **);
+ struct Qdisc * (*leaf)(struct Qdisc *, unsigned long cl);
+ void (*qlen_notify)(struct Qdisc *, unsigned long);
+
+ /* Class manipulation routines */
+ unsigned long (*get)(struct Qdisc *, u32 classid);
+ void (*put)(struct Qdisc *, unsigned long);
+ int (*change)(struct Qdisc *, u32, u32,
+ struct nlattr **, unsigned long *);
+ int (*delete)(struct Qdisc *, unsigned long);
+ void (*walk)(struct Qdisc *, struct qdisc_walker * arg);
+
+ /* Filter manipulation */
+ struct tcf_proto ** (*tcf_chain)(struct Qdisc *, unsigned long);
+ unsigned long (*bind_tcf)(struct Qdisc *, unsigned long,
+ u32 classid);
+ void (*unbind_tcf)(struct Qdisc *, unsigned long);
+
+ /* rtnetlink specific */
+ int (*dump)(struct Qdisc *, unsigned long,
+ struct sk_buff *skb, struct tcmsg*);
+ int (*dump_stats)(struct Qdisc *, unsigned long,
+ struct gnet_dump *);
+};
+
+struct Qdisc_ops {
+ struct Qdisc_ops *next;
+ const struct Qdisc_class_ops *cl_ops;
+ char id[IFNAMSIZ];
+ int priv_size;
+
+ int (*enqueue)(struct sk_buff *, struct Qdisc *);
+ struct sk_buff * (*dequeue)(struct Qdisc *);
+ struct sk_buff * (*peek)(struct Qdisc *);
+ unsigned int (*drop)(struct Qdisc *);
+
+ int (*init)(struct Qdisc *, struct nlattr *arg);
+ void (*reset)(struct Qdisc *);
+ void (*destroy)(struct Qdisc *);
+ int (*change)(struct Qdisc *, struct nlattr *arg);
+ void (*attach)(struct Qdisc *);
+
+ int (*dump)(struct Qdisc *, struct sk_buff *);
+ int (*dump_stats)(struct Qdisc *, struct gnet_dump *);
+
+ struct module *owner;
+};
+
+
+struct tcf_result {
+ unsigned long class;
+ u32 classid;
+};
+
+struct tcf_proto_ops {
+ struct tcf_proto_ops *next;
+ char kind[IFNAMSIZ];
+
+ int (*classify)(struct sk_buff *,
+ const struct tcf_proto *,
+ struct tcf_result *);
+ int (*init)(struct tcf_proto*);
+ void (*destroy)(struct tcf_proto*);
+
+ unsigned long (*get)(struct tcf_proto*, u32 handle);
+ void (*put)(struct tcf_proto*, unsigned long);
+ int (*change)(struct tcf_proto*, unsigned long,
+ u32 handle, struct nlattr **,
+ unsigned long *);
+ int (*delete)(struct tcf_proto*, unsigned long);
+ void (*walk)(struct tcf_proto*, struct tcf_walker *arg);
+
+ /* rtnetlink specific */
+ int (*dump)(struct tcf_proto*, unsigned long,
+ struct sk_buff *skb, struct tcmsg*);
+
+ struct module *owner;
+};
+
+struct tcf_proto {
+ /* Fast access part */
+ struct tcf_proto *next;
+ void *root;
+ int (*classify)(struct sk_buff *,
+ const struct tcf_proto *,
+ struct tcf_result *);
+ __be16 protocol;
+
+ /* All the rest */
+ u32 prio;
+ u32 classid;
+ struct Qdisc *q;
+ void *data;
+ const struct tcf_proto_ops *ops;
+};
+
+struct qdisc_skb_cb {
+ unsigned int pkt_len;
+ u16 bond_queue_mapping;
+ u16 _pad;
+ unsigned char data[20];
+};
+
+static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz)
+{
+ struct qdisc_skb_cb *qcb;
+
+ BUILD_BUG_ON(sizeof(skb->cb) < offsetof(struct qdisc_skb_cb, data) + sz);
+ BUILD_BUG_ON(sizeof(qcb->data) < sz);
+}
+
+static inline int qdisc_qlen(const struct Qdisc *q)
+{
+ return q->q.qlen;
+}
+
+static inline struct qdisc_skb_cb *qdisc_skb_cb(const struct sk_buff *skb)
+{
+ return (struct qdisc_skb_cb *)skb->cb;
+}
+
+static inline spinlock_t *qdisc_lock(struct Qdisc *qdisc)
+{
+ return &qdisc->q.lock;
+}
+
+static inline struct Qdisc *qdisc_root(const struct Qdisc *qdisc)
+{
+ return qdisc->dev_queue->qdisc;
+}
+
+static inline struct Qdisc *qdisc_root_sleeping(const struct Qdisc *qdisc)
+{
+ return qdisc->dev_queue->qdisc_sleeping;
+}
+
+/* The qdisc root lock is a mechanism by which to top level
+ * of a qdisc tree can be locked from any qdisc node in the
+ * forest. This allows changing the configuration of some
+ * aspect of the qdisc tree while blocking out asynchronous
+ * qdisc access in the packet processing paths.
+ *
+ * It is only legal to do this when the root will not change
+ * on us. Otherwise we'll potentially lock the wrong qdisc
+ * root. This is enforced by holding the RTNL semaphore, which
+ * all users of this lock accessor must do.
+ */
+static inline spinlock_t *qdisc_root_lock(const struct Qdisc *qdisc)
+{
+ struct Qdisc *root = qdisc_root(qdisc);
+
+ ASSERT_RTNL();
+ return qdisc_lock(root);
+}
+
+static inline spinlock_t *qdisc_root_sleeping_lock(const struct Qdisc *qdisc)
+{
+ struct Qdisc *root = qdisc_root_sleeping(qdisc);
+
+ ASSERT_RTNL();
+ return qdisc_lock(root);
+}
+
+static inline struct net_device *qdisc_dev(const struct Qdisc *qdisc)
+{
+ return qdisc->dev_queue->dev;
+}
+
+static inline void sch_tree_lock(const struct Qdisc *q)
+{
+ spin_lock_bh(qdisc_root_sleeping_lock(q));
+}
+
+static inline void sch_tree_unlock(const struct Qdisc *q)
+{
+ spin_unlock_bh(qdisc_root_sleeping_lock(q));
+}
+
+#define tcf_tree_lock(tp) sch_tree_lock((tp)->q)
+#define tcf_tree_unlock(tp) sch_tree_unlock((tp)->q)
+
+extern struct Qdisc noop_qdisc;
+extern struct Qdisc_ops noop_qdisc_ops;
+extern struct Qdisc_ops pfifo_fast_ops;
+extern struct Qdisc_ops mq_qdisc_ops;
+
+struct Qdisc_class_common {
+ u32 classid;
+ struct hlist_node hnode;
+};
+
+struct Qdisc_class_hash {
+ struct hlist_head *hash;
+ unsigned int hashsize;
+ unsigned int hashmask;
+ unsigned int hashelems;
+};
+
+static inline unsigned int qdisc_class_hash(u32 id, u32 mask)
+{
+ id ^= id >> 8;
+ id ^= id >> 4;
+ return id & mask;
+}
+
+static inline struct Qdisc_class_common *
+qdisc_class_find(const struct Qdisc_class_hash *hash, u32 id)
+{
+ struct Qdisc_class_common *cl;
+ struct hlist_node *n;
+ unsigned int h;
+
+ h = qdisc_class_hash(id, hash->hashmask);
+ hlist_for_each_entry(cl, n, &hash->hash[h], hnode) {
+ if (cl->classid == id)
+ return cl;
+ }
+ return NULL;
+}
+
+extern int qdisc_class_hash_init(struct Qdisc_class_hash *);
+extern void qdisc_class_hash_insert(struct Qdisc_class_hash *, struct Qdisc_class_common *);
+extern void qdisc_class_hash_remove(struct Qdisc_class_hash *, struct Qdisc_class_common *);
+extern void qdisc_class_hash_grow(struct Qdisc *, struct Qdisc_class_hash *);
+extern void qdisc_class_hash_destroy(struct Qdisc_class_hash *);
+
+extern void dev_init_scheduler(struct net_device *dev);
+extern void dev_shutdown(struct net_device *dev);
+extern void dev_activate(struct net_device *dev);
+extern void dev_deactivate(struct net_device *dev);
+extern void dev_deactivate_many(struct list_head *head);
+extern struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue,
+ struct Qdisc *qdisc);
+extern void qdisc_reset(struct Qdisc *qdisc);
+extern void qdisc_destroy(struct Qdisc *qdisc);
+extern void qdisc_tree_decrease_qlen(struct Qdisc *qdisc, unsigned int n);
+extern struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
+ struct Qdisc_ops *ops);
+extern struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
+ struct Qdisc_ops *ops, u32 parentid);
+extern void __qdisc_calculate_pkt_len(struct sk_buff *skb,
+ const struct qdisc_size_table *stab);
+extern void tcf_destroy(struct tcf_proto *tp);
+extern void tcf_destroy_chain(struct tcf_proto **fl);
+
+/* Reset all TX qdiscs greater then index of a device. */
+static inline void qdisc_reset_all_tx_gt(struct net_device *dev, unsigned int i)
+{
+ struct Qdisc *qdisc;
+
+ for (; i < dev->num_tx_queues; i++) {
+ qdisc = netdev_get_tx_queue(dev, i)->qdisc;
+ if (qdisc) {
+ spin_lock_bh(qdisc_lock(qdisc));
+ qdisc_reset(qdisc);
+ spin_unlock_bh(qdisc_lock(qdisc));
+ }
+ }
+}
+
+static inline void qdisc_reset_all_tx(struct net_device *dev)
+{
+ qdisc_reset_all_tx_gt(dev, 0);
+}
+
+/* Are all TX queues of the device empty? */
+static inline bool qdisc_all_tx_empty(const struct net_device *dev)
+{
+ unsigned int i;
+ for (i = 0; i < dev->num_tx_queues; i++) {
+ struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
+ const struct Qdisc *q = txq->qdisc;
+
+ if (q->q.qlen)
+ return false;
+ }
+ return true;
+}
+
+/* Are any of the TX qdiscs changing? */
+static inline bool qdisc_tx_changing(const struct net_device *dev)
+{
+ unsigned int i;
+ for (i = 0; i < dev->num_tx_queues; i++) {
+ struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
+ if (txq->qdisc != txq->qdisc_sleeping)
+ return true;
+ }
+ return false;
+}
+
+/* Is the device using the noop qdisc on all queues? */
+static inline bool qdisc_tx_is_noop(const struct net_device *dev)
+{
+ unsigned int i;
+ for (i = 0; i < dev->num_tx_queues; i++) {
+ struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
+ if (txq->qdisc != &noop_qdisc)
+ return false;
+ }
+ return true;
+}
+
+static inline unsigned int qdisc_pkt_len(const struct sk_buff *skb)
+{
+ return qdisc_skb_cb(skb)->pkt_len;
+}
+
+/* additional qdisc xmit flags (NET_XMIT_MASK in linux/netdevice.h) */
+enum net_xmit_qdisc_t {
+ __NET_XMIT_STOLEN = 0x00010000,
+ __NET_XMIT_BYPASS = 0x00020000,
+};
+
+#ifdef CONFIG_NET_CLS_ACT
+#define net_xmit_drop_count(e) ((e) & __NET_XMIT_STOLEN ? 0 : 1)
+#else
+#define net_xmit_drop_count(e) (1)
+#endif
+
+static inline void qdisc_calculate_pkt_len(struct sk_buff *skb,
+ const struct Qdisc *sch)
+{
+#ifdef CONFIG_NET_SCHED
+ struct qdisc_size_table *stab = rcu_dereference_bh(sch->stab);
+
+ if (stab)
+ __qdisc_calculate_pkt_len(skb, stab);
+#endif
+}
+
+static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+ qdisc_calculate_pkt_len(skb, sch);
+ return sch->enqueue(skb, sch);
+}
+
+static inline int qdisc_enqueue_root(struct sk_buff *skb, struct Qdisc *sch)
+{
+ qdisc_skb_cb(skb)->pkt_len = skb->len;
+ return qdisc_enqueue(skb, sch) & NET_XMIT_MASK;
+}
+
+
+static inline void bstats_update(struct gnet_stats_basic_packed *bstats,
+ const struct sk_buff *skb)
+{
+ bstats->bytes += qdisc_pkt_len(skb);
+ bstats->packets += skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 1;
+}
+
+static inline void qdisc_bstats_update(struct Qdisc *sch,
+ const struct sk_buff *skb)
+{
+ bstats_update(&sch->bstats, skb);
+}
+
+static inline int __qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch,
+ struct sk_buff_head *list)
+{
+ __skb_queue_tail(list, skb);
+ sch->qstats.backlog += qdisc_pkt_len(skb);
+
+ return NET_XMIT_SUCCESS;
+}
+
+static inline int qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch)
+{
+ return __qdisc_enqueue_tail(skb, sch, &sch->q);
+}
+
+static inline struct sk_buff *__qdisc_dequeue_head(struct Qdisc *sch,
+ struct sk_buff_head *list)
+{
+ struct sk_buff *skb = __skb_dequeue(list);
+
+ if (likely(skb != NULL)) {
+ sch->qstats.backlog -= qdisc_pkt_len(skb);
+ qdisc_bstats_update(sch, skb);
+ }
+
+ return skb;
+}
+
+static inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch)
+{
+ return __qdisc_dequeue_head(sch, &sch->q);
+}
+
+static inline unsigned int __qdisc_queue_drop_head(struct Qdisc *sch,
+ struct sk_buff_head *list)
+{
+ struct sk_buff *skb = __skb_dequeue(list);
+
+ if (likely(skb != NULL)) {
+ unsigned int len = qdisc_pkt_len(skb);
+ sch->qstats.backlog -= len;
+ kfree_skb(skb);
+ return len;
+ }
+
+ return 0;
+}
+
+static inline unsigned int qdisc_queue_drop_head(struct Qdisc *sch)
+{
+ return __qdisc_queue_drop_head(sch, &sch->q);
+}
+
+static inline struct sk_buff *__qdisc_dequeue_tail(struct Qdisc *sch,
+ struct sk_buff_head *list)
+{
+ struct sk_buff *skb = __skb_dequeue_tail(list);
+
+ if (likely(skb != NULL))
+ sch->qstats.backlog -= qdisc_pkt_len(skb);
+
+ return skb;
+}
+
+static inline struct sk_buff *qdisc_dequeue_tail(struct Qdisc *sch)
+{
+ return __qdisc_dequeue_tail(sch, &sch->q);
+}
+
+static inline struct sk_buff *qdisc_peek_head(struct Qdisc *sch)
+{
+ return skb_peek(&sch->q);
+}
+
+/* generic pseudo peek method for non-work-conserving qdisc */
+static inline struct sk_buff *qdisc_peek_dequeued(struct Qdisc *sch)
+{
+ /* we can reuse ->gso_skb because peek isn't called for root qdiscs */
+ if (!sch->gso_skb) {
+ sch->gso_skb = sch->dequeue(sch);
+ if (sch->gso_skb)
+ /* it's still part of the queue */
+ sch->q.qlen++;
+ }
+
+ return sch->gso_skb;
+}
+
+/* use instead of qdisc->dequeue() for all qdiscs queried with ->peek() */
+static inline struct sk_buff *qdisc_dequeue_peeked(struct Qdisc *sch)
+{
+ struct sk_buff *skb = sch->gso_skb;
+
+ if (skb) {
+ sch->gso_skb = NULL;
+ sch->q.qlen--;
+ } else {
+ skb = sch->dequeue(sch);
+ }
+
+ return skb;
+}
+
+static inline void __qdisc_reset_queue(struct Qdisc *sch,
+ struct sk_buff_head *list)
+{
+ /*
+ * We do not know the backlog in bytes of this list, it
+ * is up to the caller to correct it
+ */
+ __skb_queue_purge(list);
+}
+
+static inline void qdisc_reset_queue(struct Qdisc *sch)
+{
+ __qdisc_reset_queue(sch, &sch->q);
+ sch->qstats.backlog = 0;
+}
+
+static inline unsigned int __qdisc_queue_drop(struct Qdisc *sch,
+ struct sk_buff_head *list)
+{
+ struct sk_buff *skb = __qdisc_dequeue_tail(sch, list);
+
+ if (likely(skb != NULL)) {
+ unsigned int len = qdisc_pkt_len(skb);
+ kfree_skb(skb);
+ return len;
+ }
+
+ return 0;
+}
+
+static inline unsigned int qdisc_queue_drop(struct Qdisc *sch)
+{
+ return __qdisc_queue_drop(sch, &sch->q);
+}
+
+static inline int qdisc_drop(struct sk_buff *skb, struct Qdisc *sch)
+{
+ kfree_skb(skb);
+ sch->qstats.drops++;
+
+ return NET_XMIT_DROP;
+}
+
+static inline int qdisc_reshape_fail(struct sk_buff *skb, struct Qdisc *sch)
+{
+ sch->qstats.drops++;
+
+#ifdef CONFIG_NET_CLS_ACT
+ if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch))
+ goto drop;
+
+ return NET_XMIT_SUCCESS;
+
+drop:
+#endif
+ kfree_skb(skb);
+ return NET_XMIT_DROP;
+}
+
+/* Length to Time (L2T) lookup in a qdisc_rate_table, to determine how
+ long it will take to send a packet given its size.
+ */
+static inline u32 qdisc_l2t(struct qdisc_rate_table* rtab, unsigned int pktlen)
+{
+ int slot = pktlen + rtab->rate.cell_align + rtab->rate.overhead;
+ if (slot < 0)
+ slot = 0;
+ slot >>= rtab->rate.cell_log;
+ if (slot > 255)
+ return rtab->data[255]*(slot >> 8) + rtab->data[slot & 0xFF];
+ return rtab->data[slot];
+}
+
+#ifdef CONFIG_NET_CLS_ACT
+static inline struct sk_buff *skb_act_clone(struct sk_buff *skb, gfp_t gfp_mask,
+ int action)
+{
+ struct sk_buff *n;
+
+ n = skb_clone(skb, gfp_mask);
+
+ if (n) {
+ n->tc_verd = SET_TC_VERD(n->tc_verd, 0);
+ n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd);
+ n->tc_verd = CLR_TC_MUNGED(n->tc_verd);
+ }
+ return n;
+}
+#endif
+
+#endif
diff --git a/include/net/scm.h b/include/net/scm.h
new file mode 100644
index 00000000..0c0017ce
--- /dev/null
+++ b/include/net/scm.h
@@ -0,0 +1,131 @@
+#ifndef __LINUX_NET_SCM_H
+#define __LINUX_NET_SCM_H
+
+#include <linux/limits.h>
+#include <linux/net.h>
+#include <linux/security.h>
+#include <linux/pid.h>
+#include <linux/nsproxy.h>
+
+/* Well, we should have at least one descriptor open
+ * to accept passed FDs 8)
+ */
+#define SCM_MAX_FD 253
+
+struct scm_fp_list {
+ struct list_head list;
+ short count;
+ short max;
+ struct file *fp[SCM_MAX_FD];
+};
+
+struct scm_cookie {
+ struct pid *pid; /* Skb credentials */
+ const struct cred *cred;
+ struct scm_fp_list *fp; /* Passed files */
+ struct ucred creds; /* Skb credentials */
+#ifdef CONFIG_SECURITY_NETWORK
+ u32 secid; /* Passed security ID */
+#endif
+};
+
+extern void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm);
+extern void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm);
+extern int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm);
+extern void __scm_destroy(struct scm_cookie *scm);
+extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl);
+
+#ifdef CONFIG_SECURITY_NETWORK
+static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm)
+{
+ security_socket_getpeersec_dgram(sock, NULL, &scm->secid);
+}
+#else
+static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm)
+{ }
+#endif /* CONFIG_SECURITY_NETWORK */
+
+static __inline__ void scm_set_cred(struct scm_cookie *scm,
+ struct pid *pid, const struct cred *cred)
+{
+ scm->pid = get_pid(pid);
+ scm->cred = cred ? get_cred(cred) : NULL;
+ cred_to_ucred(pid, cred, &scm->creds);
+}
+
+static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
+{
+ put_pid(scm->pid);
+ scm->pid = NULL;
+
+ if (scm->cred)
+ put_cred(scm->cred);
+ scm->cred = NULL;
+}
+
+static __inline__ void scm_destroy(struct scm_cookie *scm)
+{
+ scm_destroy_cred(scm);
+ if (scm && scm->fp)
+ __scm_destroy(scm);
+}
+
+static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
+ struct scm_cookie *scm, bool forcecreds)
+{
+ memset(scm, 0, sizeof(*scm));
+ if (forcecreds)
+ scm_set_cred(scm, task_tgid(current), current_cred());
+ unix_get_peersec_dgram(sock, scm);
+ if (msg->msg_controllen <= 0)
+ return 0;
+ return __scm_send(sock, msg, scm);
+}
+
+#ifdef CONFIG_SECURITY_NETWORK
+static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
+{
+ char *secdata;
+ u32 seclen;
+ int err;
+
+ if (test_bit(SOCK_PASSSEC, &sock->flags)) {
+ err = security_secid_to_secctx(scm->secid, &secdata, &seclen);
+
+ if (!err) {
+ put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
+ security_release_secctx(secdata, seclen);
+ }
+ }
+}
+#else
+static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
+{ }
+#endif /* CONFIG_SECURITY_NETWORK */
+
+static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
+ struct scm_cookie *scm, int flags)
+{
+ if (!msg->msg_control) {
+ if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp)
+ msg->msg_flags |= MSG_CTRUNC;
+ scm_destroy(scm);
+ return;
+ }
+
+ if (test_bit(SOCK_PASSCRED, &sock->flags))
+ put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
+
+ scm_destroy_cred(scm);
+
+ scm_passec(sock, msg, scm);
+
+ if (!scm->fp)
+ return;
+
+ scm_detach_fds(msg, scm);
+}
+
+
+#endif /* __LINUX_NET_SCM_H */
+
diff --git a/include/net/sctp/auth.h b/include/net/sctp/auth.h
new file mode 100644
index 00000000..49bc9577
--- /dev/null
+++ b/include/net/sctp/auth.h
@@ -0,0 +1,127 @@
+/* SCTP kernel implementation
+ * (C) Copyright 2007 Hewlett-Packard Development Company, L.P.
+ *
+ * This file is part of the SCTP kernel implementation
+ *
+ * This SCTP implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This SCTP implementation is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * ************************
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Please send any bug reports or fixes you make to the
+ * email address(es):
+ * lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *
+ * Or submit a bug report through the following website:
+ * http://www.sf.net/projects/lksctp
+ *
+ * Written or modified by:
+ * Vlad Yasevich <vladislav.yasevich@hp.com>
+ *
+ * Any bugs reported given to us we will try to fix... any fixes shared will
+ * be incorporated into the next SCTP release.
+ */
+
+#ifndef __sctp_auth_h__
+#define __sctp_auth_h__
+
+#include <linux/list.h>
+#include <linux/crypto.h>
+
+struct sctp_endpoint;
+struct sctp_association;
+struct sctp_authkey;
+struct sctp_hmacalgo;
+
+/*
+ * Define a generic struct that will hold all the info
+ * necessary for an HMAC transform
+ */
+struct sctp_hmac {
+ __u16 hmac_id; /* one of the above ids */
+ char *hmac_name; /* name for loading */
+ __u16 hmac_len; /* length of the signature */
+};
+
+/* This is generic structure that containst authentication bytes used
+ * as keying material. It's a what is referred to as byte-vector all
+ * over SCTP-AUTH
+ */
+struct sctp_auth_bytes {
+ atomic_t refcnt;
+ __u32 len;
+ __u8 data[];
+};
+
+/* Definition for a shared key, weather endpoint or association */
+struct sctp_shared_key {
+ struct list_head key_list;
+ __u16 key_id;
+ struct sctp_auth_bytes *key;
+};
+
+#define key_for_each(__key, __list_head) \
+ list_for_each_entry(__key, __list_head, key_list)
+
+#define key_for_each_safe(__key, __tmp, __list_head) \
+ list_for_each_entry_safe(__key, __tmp, __list_head, key_list)
+
+static inline void sctp_auth_key_hold(struct sctp_auth_bytes *key)
+{
+ if (!key)
+ return;
+
+ atomic_inc(&key->refcnt);
+}
+
+void sctp_auth_key_put(struct sctp_auth_bytes *key);
+struct sctp_shared_key *sctp_auth_shkey_create(__u16 key_id, gfp_t gfp);
+void sctp_auth_destroy_keys(struct list_head *keys);
+int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp);
+struct sctp_shared_key *sctp_auth_get_shkey(
+ const struct sctp_association *asoc,
+ __u16 key_id);
+int sctp_auth_asoc_copy_shkeys(const struct sctp_endpoint *ep,
+ struct sctp_association *asoc,
+ gfp_t gfp);
+int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp);
+void sctp_auth_destroy_hmacs(struct crypto_hash *auth_hmacs[]);
+struct sctp_hmac *sctp_auth_get_hmac(__u16 hmac_id);
+struct sctp_hmac *sctp_auth_asoc_get_hmac(const struct sctp_association *asoc);
+void sctp_auth_asoc_set_default_hmac(struct sctp_association *asoc,
+ struct sctp_hmac_algo_param *hmacs);
+int sctp_auth_asoc_verify_hmac_id(const struct sctp_association *asoc,
+ __be16 hmac_id);
+int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc);
+int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc);
+void sctp_auth_calculate_hmac(const struct sctp_association *asoc,
+ struct sk_buff *skb,
+ struct sctp_auth_chunk *auth, gfp_t gfp);
+
+/* API Helpers */
+int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id);
+int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep,
+ struct sctp_hmacalgo *hmacs);
+int sctp_auth_set_key(struct sctp_endpoint *ep,
+ struct sctp_association *asoc,
+ struct sctp_authkey *auth_key);
+int sctp_auth_set_active_key(struct sctp_endpoint *ep,
+ struct sctp_association *asoc,
+ __u16 key_id);
+int sctp_auth_del_key_id(struct sctp_endpoint *ep,
+ struct sctp_association *asoc,
+ __u16 key_id);
+
+#endif
diff --git a/include/net/sctp/checksum.h b/include/net/sctp/checksum.h
new file mode 100644
index 00000000..befc8d2a
--- /dev/null
+++ b/include/net/sctp/checksum.h
@@ -0,0 +1,83 @@
+/* SCTP kernel reference Implementation
+ * Copyright (c) 1999-2001 Motorola, Inc.
+ * Copyright (c) 2001-2003 International Business Machines, Corp.
+ *
+ * This file is part of the SCTP kernel reference Implementation
+ *
+ * SCTP Checksum functions
+ *
+ * The SCTP reference implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * The SCTP reference implementation is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * ************************
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Please send any bug reports or fixes you make to the
+ * email address(es):
+ * lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *
+ * Or submit a bug report through the following website:
+ * http://www.sf.net/projects/lksctp
+ *
+ * Written or modified by:
+ * Dinakaran Joseph
+ * Jon Grimm <jgrimm@us.ibm.com>
+ * Sridhar Samudrala <sri@us.ibm.com>
+ *
+ * Rewritten to use libcrc32c by:
+ * Vlad Yasevich <vladislav.yasevich@hp.com>
+ *
+ * Any bugs reported given to us we will try to fix... any fixes shared will
+ * be incorporated into the next SCTP release.
+ */
+
+#include <linux/types.h>
+#include <net/sctp/sctp.h>
+#include <linux/crc32c.h>
+
+static inline __u32 sctp_crc32c(__u32 crc, u8 *buffer, u16 length)
+{
+ return crc32c(crc, buffer, length);
+}
+
+static inline __u32 sctp_start_cksum(__u8 *buffer, __u16 length)
+{
+ __u32 crc = ~(__u32)0;
+ __u8 zero[sizeof(__u32)] = {0};
+
+ /* Optimize this routine to be SCTP specific, knowing how
+ * to skip the checksum field of the SCTP header.
+ */
+
+ /* Calculate CRC up to the checksum. */
+ crc = sctp_crc32c(crc, buffer, sizeof(struct sctphdr) - sizeof(__u32));
+
+ /* Skip checksum field of the header. */
+ crc = sctp_crc32c(crc, zero, sizeof(__u32));
+
+ /* Calculate the rest of the CRC. */
+ crc = sctp_crc32c(crc, &buffer[sizeof(struct sctphdr)],
+ length - sizeof(struct sctphdr));
+ return crc;
+}
+
+static inline __u32 sctp_update_cksum(__u8 *buffer, __u16 length, __u32 crc32)
+{
+ return sctp_crc32c(crc32, buffer, length);
+}
+
+static inline __le32 sctp_end_cksum(__be32 crc32)
+{
+ return cpu_to_le32(~crc32);
+}
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
new file mode 100644
index 00000000..712b3beb
--- /dev/null
+++ b/include/net/sctp/command.h
@@ -0,0 +1,225 @@
+/* SCTP kernel Implementation
+ * (C) Copyright IBM Corp. 2001, 2004
+ * Copyright (C) 1999-2001 Cisco, Motorola
+ *
+ * This file is part of the SCTP kernel implementation
+ *
+ * These are the definitions needed for the command object.
+ *
+ * This SCTP implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This SCTP implementation is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * ************************
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Please send any bug reports or fixes you make to one of the
+ * following email addresses:
+ *
+ * La Monte H.P. Yarroll <piggy@acm.org>
+ * Karl Knutson <karl@athena.chicago.il.us>
+ * Ardelle Fan <ardelle.fan@intel.com>
+ * Sridhar Samudrala <sri@us.ibm.com>
+ *
+ * Any bugs reported given to us we will try to fix... any fixes shared will
+ * be incorporated into the next SCTP release.
+ */
+
+
+#ifndef __net_sctp_command_h__
+#define __net_sctp_command_h__
+
+#include <net/sctp/constants.h>
+#include <net/sctp/structs.h>
+
+
+typedef enum {
+ SCTP_CMD_NOP = 0, /* Do nothing. */
+ SCTP_CMD_NEW_ASOC, /* Register a new association. */
+ SCTP_CMD_DELETE_TCB, /* Delete the current association. */
+ SCTP_CMD_NEW_STATE, /* Enter a new state. */
+ SCTP_CMD_REPORT_TSN, /* Record the arrival of a TSN. */
+ SCTP_CMD_GEN_SACK, /* Send a Selective ACK (maybe). */
+ SCTP_CMD_PROCESS_SACK, /* Process an inbound SACK. */
+ SCTP_CMD_GEN_INIT_ACK, /* Generate an INIT ACK chunk. */
+ SCTP_CMD_PEER_INIT, /* Process a INIT from the peer. */
+ SCTP_CMD_GEN_COOKIE_ECHO, /* Generate a COOKIE ECHO chunk. */
+ SCTP_CMD_CHUNK_ULP, /* Send a chunk to the sockets layer. */
+ SCTP_CMD_EVENT_ULP, /* Send a notification to the sockets layer. */
+ SCTP_CMD_REPLY, /* Send a chunk to our peer. */
+ SCTP_CMD_SEND_PKT, /* Send a full packet to our peer. */
+ SCTP_CMD_RETRAN, /* Mark a transport for retransmission. */
+ SCTP_CMD_ECN_CE, /* Do delayed CE processing. */
+ SCTP_CMD_ECN_ECNE, /* Do delayed ECNE processing. */
+ SCTP_CMD_ECN_CWR, /* Do delayed CWR processing. */
+ SCTP_CMD_TIMER_START, /* Start a timer. */
+ SCTP_CMD_TIMER_START_ONCE, /* Start a timer once */
+ SCTP_CMD_TIMER_RESTART, /* Restart a timer. */
+ SCTP_CMD_TIMER_STOP, /* Stop a timer. */
+ SCTP_CMD_INIT_CHOOSE_TRANSPORT, /* Choose transport for an INIT. */
+ SCTP_CMD_INIT_COUNTER_RESET, /* Reset init counter. */
+ SCTP_CMD_INIT_COUNTER_INC, /* Increment init counter. */
+ SCTP_CMD_INIT_RESTART, /* High level, do init timer work. */
+ SCTP_CMD_COOKIEECHO_RESTART, /* High level, do cookie-echo timer work. */
+ SCTP_CMD_INIT_FAILED, /* High level, do init failure work. */
+ SCTP_CMD_REPORT_DUP, /* Report a duplicate TSN. */
+ SCTP_CMD_STRIKE, /* Mark a strike against a transport. */
+ SCTP_CMD_HB_TIMERS_START, /* Start the heartbeat timers. */
+ SCTP_CMD_HB_TIMER_UPDATE, /* Update a heartbeat timers. */
+ SCTP_CMD_HB_TIMERS_STOP, /* Stop the heartbeat timers. */
+ SCTP_CMD_TRANSPORT_HB_SENT, /* Reset the status of a transport. */
+ SCTP_CMD_TRANSPORT_IDLE, /* Do manipulations on idle transport */
+ SCTP_CMD_TRANSPORT_ON, /* Mark the transport as active. */
+ SCTP_CMD_REPORT_ERROR, /* Pass this error back out of the sm. */
+ SCTP_CMD_REPORT_BAD_TAG, /* Verification tags didn't match. */
+ SCTP_CMD_PROCESS_CTSN, /* Sideeffect from shutdown. */
+ SCTP_CMD_ASSOC_FAILED, /* Handle association failure. */
+ SCTP_CMD_DISCARD_PACKET, /* Discard the whole packet. */
+ SCTP_CMD_GEN_SHUTDOWN, /* Generate a SHUTDOWN chunk. */
+ SCTP_CMD_UPDATE_ASSOC, /* Update association information. */
+ SCTP_CMD_PURGE_OUTQUEUE, /* Purge all data waiting to be sent. */
+ SCTP_CMD_SETUP_T2, /* Hi-level, setup T2-shutdown parms. */
+ SCTP_CMD_RTO_PENDING, /* Set transport's rto_pending. */
+ SCTP_CMD_PART_DELIVER, /* Partial data delivery considerations. */
+ SCTP_CMD_RENEGE, /* Renege data on an association. */
+ SCTP_CMD_SETUP_T4, /* ADDIP, setup T4 RTO timer parms. */
+ SCTP_CMD_PROCESS_OPERR, /* Process an ERROR chunk. */
+ SCTP_CMD_REPORT_FWDTSN, /* Report new cumulative TSN Ack. */
+ SCTP_CMD_PROCESS_FWDTSN, /* Skips were reported, so process further. */
+ SCTP_CMD_CLEAR_INIT_TAG, /* Clears association peer's inittag. */
+ SCTP_CMD_DEL_NON_PRIMARY, /* Removes non-primary peer transports. */
+ SCTP_CMD_T3_RTX_TIMERS_STOP, /* Stops T3-rtx pending timers */
+ SCTP_CMD_FORCE_PRIM_RETRAN, /* Forces retrans. over primary path. */
+ SCTP_CMD_SET_SK_ERR, /* Set sk_err */
+ SCTP_CMD_ASSOC_CHANGE, /* generate and send assoc_change event */
+ SCTP_CMD_ADAPTATION_IND, /* generate and send adaptation event */
+ SCTP_CMD_ASSOC_SHKEY, /* generate the association shared keys */
+ SCTP_CMD_T1_RETRAN, /* Mark for retransmission after T1 timeout */
+ SCTP_CMD_UPDATE_INITTAG, /* Update peer inittag */
+ SCTP_CMD_SEND_MSG, /* Send the whole use message */
+ SCTP_CMD_SEND_NEXT_ASCONF, /* Send the next ASCONF after ACK */
+ SCTP_CMD_PURGE_ASCONF_QUEUE, /* Purge all asconf queues.*/
+ SCTP_CMD_SET_ASOC, /* Restore association context */
+ SCTP_CMD_LAST
+} sctp_verb_t;
+
+/* How many commands can you put in an sctp_cmd_seq_t?
+ * This is a rather arbitrary number, ideally derived from a careful
+ * analysis of the state functions, but in reality just taken from
+ * thin air in the hopes othat we don't trigger a kernel panic.
+ */
+#define SCTP_MAX_NUM_COMMANDS 14
+
+typedef union {
+ __s32 i32;
+ __u32 u32;
+ __be32 be32;
+ __u16 u16;
+ __u8 u8;
+ int error;
+ __be16 err;
+ sctp_state_t state;
+ sctp_event_timeout_t to;
+ unsigned long zero;
+ void *ptr;
+ struct sctp_chunk *chunk;
+ struct sctp_association *asoc;
+ struct sctp_transport *transport;
+ struct sctp_bind_addr *bp;
+ sctp_init_chunk_t *init;
+ struct sctp_ulpevent *ulpevent;
+ struct sctp_packet *packet;
+ sctp_sackhdr_t *sackh;
+ struct sctp_datamsg *msg;
+} sctp_arg_t;
+
+/* We are simulating ML type constructors here.
+ *
+ * SCTP_ARG_CONSTRUCTOR(NAME, TYPE, ELT) builds a function called
+ * SCTP_NAME() which takes an argument of type TYPE and returns an
+ * sctp_arg_t. It does this by inserting the sole argument into the
+ * ELT union element of a local sctp_arg_t.
+ *
+ * E.g., SCTP_ARG_CONSTRUCTOR(I32, __s32, i32) builds SCTP_I32(arg),
+ * which takes an __s32 and returns a sctp_arg_t containing the
+ * __s32. So, after foo = SCTP_I32(arg), foo.i32 == arg.
+ */
+static inline sctp_arg_t SCTP_NULL(void)
+{
+ sctp_arg_t retval; retval.ptr = NULL; return retval;
+}
+static inline sctp_arg_t SCTP_NOFORCE(void)
+{
+ sctp_arg_t retval = {.zero = 0UL}; retval.i32 = 0; return retval;
+}
+static inline sctp_arg_t SCTP_FORCE(void)
+{
+ sctp_arg_t retval = {.zero = 0UL}; retval.i32 = 1; return retval;
+}
+
+#define SCTP_ARG_CONSTRUCTOR(name, type, elt) \
+static inline sctp_arg_t \
+SCTP_## name (type arg) \
+{ sctp_arg_t retval = {.zero = 0UL}; retval.elt = arg; return retval; }
+
+SCTP_ARG_CONSTRUCTOR(I32, __s32, i32)
+SCTP_ARG_CONSTRUCTOR(U32, __u32, u32)
+SCTP_ARG_CONSTRUCTOR(BE32, __be32, be32)
+SCTP_ARG_CONSTRUCTOR(U16, __u16, u16)
+SCTP_ARG_CONSTRUCTOR(U8, __u8, u8)
+SCTP_ARG_CONSTRUCTOR(ERROR, int, error)
+SCTP_ARG_CONSTRUCTOR(PERR, __be16, err) /* protocol error */
+SCTP_ARG_CONSTRUCTOR(STATE, sctp_state_t, state)
+SCTP_ARG_CONSTRUCTOR(TO, sctp_event_timeout_t, to)
+SCTP_ARG_CONSTRUCTOR(PTR, void *, ptr)
+SCTP_ARG_CONSTRUCTOR(CHUNK, struct sctp_chunk *, chunk)
+SCTP_ARG_CONSTRUCTOR(ASOC, struct sctp_association *, asoc)
+SCTP_ARG_CONSTRUCTOR(TRANSPORT, struct sctp_transport *, transport)
+SCTP_ARG_CONSTRUCTOR(BA, struct sctp_bind_addr *, bp)
+SCTP_ARG_CONSTRUCTOR(PEER_INIT, sctp_init_chunk_t *, init)
+SCTP_ARG_CONSTRUCTOR(ULPEVENT, struct sctp_ulpevent *, ulpevent)
+SCTP_ARG_CONSTRUCTOR(PACKET, struct sctp_packet *, packet)
+SCTP_ARG_CONSTRUCTOR(SACKH, sctp_sackhdr_t *, sackh)
+SCTP_ARG_CONSTRUCTOR(DATAMSG, struct sctp_datamsg *, msg)
+
+typedef struct {
+ sctp_arg_t obj;
+ sctp_verb_t verb;
+} sctp_cmd_t;
+
+typedef struct {
+ sctp_cmd_t cmds[SCTP_MAX_NUM_COMMANDS];
+ __u8 next_free_slot;
+ __u8 next_cmd;
+} sctp_cmd_seq_t;
+
+
+/* Initialize a block of memory as a command sequence.
+ * Return 0 if the initialization fails.
+ */
+int sctp_init_cmd_seq(sctp_cmd_seq_t *seq);
+
+/* Add a command to an sctp_cmd_seq_t.
+ *
+ * Use the SCTP_* constructors defined by SCTP_ARG_CONSTRUCTOR() above
+ * to wrap data which goes in the obj argument.
+ */
+void sctp_add_cmd_sf(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_arg_t obj);
+
+/* Return the next command structure in an sctp_cmd_seq.
+ * Return NULL at the end of the sequence.
+ */
+sctp_cmd_t *sctp_next_cmd(sctp_cmd_seq_t *seq);
+
+#endif /* __net_sctp_command_h__ */
+
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
new file mode 100644
index 00000000..942b864f
--- /dev/null
+++ b/include/net/sctp/constants.h
@@ -0,0 +1,442 @@
+/* SCTP kernel implementation
+ * (C) Copyright IBM Corp. 2001, 2004
+ * Copyright (c) 1999-2000 Cisco, Inc.
+ * Copyright (c) 1999-2001 Motorola, Inc.
+ * Copyright (c) 2001 Intel Corp.
+ *
+ * This file is part of the SCTP kernel implementation
+ *
+ * This SCTP implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This SCTP implementation is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * ************************
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Please send any bug reports or fixes you make to the
+ * email address(es):
+ * lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *
+ * Or submit a bug report through the following website:
+ * http://www.sf.net/projects/lksctp
+ *
+ * Written or modified by:
+ * La Monte H.P. Yarroll <piggy@acm.org>
+ * Karl Knutson <karl@athena.chicago.il.us>
+ * Randall Stewart <randall@stewart.chicago.il.us>
+ * Ken Morneau <kmorneau@cisco.com>
+ * Qiaobing Xie <qxie1@motorola.com>
+ * Xingang Guo <xingang.guo@intel.com>
+ * Sridhar Samudrala <samudrala@us.ibm.com>
+ * Daisy Chang <daisyc@us.ibm.com>
+ *
+ * Any bugs reported given to us we will try to fix... any fixes shared will
+ * be incorporated into the next SCTP release.
+ */
+
+#ifndef __sctp_constants_h__
+#define __sctp_constants_h__
+
+#include <linux/sctp.h>
+#include <linux/ipv6.h> /* For ipv6hdr. */
+#include <net/sctp/user.h>
+#include <net/tcp_states.h> /* For TCP states used in sctp_sock_state_t */
+
+/* Value used for stream negotiation. */
+enum { SCTP_MAX_STREAM = 0xffff };
+enum { SCTP_DEFAULT_OUTSTREAMS = 10 };
+enum { SCTP_DEFAULT_INSTREAMS = SCTP_MAX_STREAM };
+
+/* Since CIDs are sparse, we need all four of the following
+ * symbols. CIDs are dense through SCTP_CID_BASE_MAX.
+ */
+#define SCTP_CID_BASE_MAX SCTP_CID_SHUTDOWN_COMPLETE
+
+#define SCTP_NUM_BASE_CHUNK_TYPES (SCTP_CID_BASE_MAX + 1)
+
+#define SCTP_NUM_ADDIP_CHUNK_TYPES 2
+
+#define SCTP_NUM_PRSCTP_CHUNK_TYPES 1
+
+#define SCTP_NUM_AUTH_CHUNK_TYPES 1
+
+#define SCTP_NUM_CHUNK_TYPES (SCTP_NUM_BASE_CHUNK_TYPES + \
+ SCTP_NUM_ADDIP_CHUNK_TYPES +\
+ SCTP_NUM_PRSCTP_CHUNK_TYPES +\
+ SCTP_NUM_AUTH_CHUNK_TYPES)
+
+/* These are the different flavours of event. */
+typedef enum {
+
+ SCTP_EVENT_T_CHUNK = 1,
+ SCTP_EVENT_T_TIMEOUT,
+ SCTP_EVENT_T_OTHER,
+ SCTP_EVENT_T_PRIMITIVE
+
+} sctp_event_t;
+
+/* As a convenience for the state machine, we append SCTP_EVENT_* and
+ * SCTP_ULP_* to the list of possible chunks.
+ */
+
+typedef enum {
+ SCTP_EVENT_TIMEOUT_NONE = 0,
+ SCTP_EVENT_TIMEOUT_T1_COOKIE,
+ SCTP_EVENT_TIMEOUT_T1_INIT,
+ SCTP_EVENT_TIMEOUT_T2_SHUTDOWN,
+ SCTP_EVENT_TIMEOUT_T3_RTX,
+ SCTP_EVENT_TIMEOUT_T4_RTO,
+ SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD,
+ SCTP_EVENT_TIMEOUT_HEARTBEAT,
+ SCTP_EVENT_TIMEOUT_SACK,
+ SCTP_EVENT_TIMEOUT_AUTOCLOSE,
+} sctp_event_timeout_t;
+
+#define SCTP_EVENT_TIMEOUT_MAX SCTP_EVENT_TIMEOUT_AUTOCLOSE
+#define SCTP_NUM_TIMEOUT_TYPES (SCTP_EVENT_TIMEOUT_MAX + 1)
+
+typedef enum {
+ SCTP_EVENT_NO_PENDING_TSN = 0,
+ SCTP_EVENT_ICMP_PROTO_UNREACH,
+} sctp_event_other_t;
+
+#define SCTP_EVENT_OTHER_MAX SCTP_EVENT_ICMP_PROTO_UNREACH
+#define SCTP_NUM_OTHER_TYPES (SCTP_EVENT_OTHER_MAX + 1)
+
+/* These are primitive requests from the ULP. */
+typedef enum {
+ SCTP_PRIMITIVE_ASSOCIATE = 0,
+ SCTP_PRIMITIVE_SHUTDOWN,
+ SCTP_PRIMITIVE_ABORT,
+ SCTP_PRIMITIVE_SEND,
+ SCTP_PRIMITIVE_REQUESTHEARTBEAT,
+ SCTP_PRIMITIVE_ASCONF,
+} sctp_event_primitive_t;
+
+#define SCTP_EVENT_PRIMITIVE_MAX SCTP_PRIMITIVE_ASCONF
+#define SCTP_NUM_PRIMITIVE_TYPES (SCTP_EVENT_PRIMITIVE_MAX + 1)
+
+/* We define here a utility type for manipulating subtypes.
+ * The subtype constructors all work like this:
+ *
+ * sctp_subtype_t foo = SCTP_ST_CHUNK(SCTP_CID_INIT);
+ */
+
+typedef union {
+ sctp_cid_t chunk;
+ sctp_event_timeout_t timeout;
+ sctp_event_other_t other;
+ sctp_event_primitive_t primitive;
+} sctp_subtype_t;
+
+#define SCTP_SUBTYPE_CONSTRUCTOR(_name, _type, _elt) \
+static inline sctp_subtype_t \
+SCTP_ST_## _name (_type _arg) \
+{ sctp_subtype_t _retval; _retval._elt = _arg; return _retval; }
+
+SCTP_SUBTYPE_CONSTRUCTOR(CHUNK, sctp_cid_t, chunk)
+SCTP_SUBTYPE_CONSTRUCTOR(TIMEOUT, sctp_event_timeout_t, timeout)
+SCTP_SUBTYPE_CONSTRUCTOR(OTHER, sctp_event_other_t, other)
+SCTP_SUBTYPE_CONSTRUCTOR(PRIMITIVE, sctp_event_primitive_t, primitive)
+
+
+#define sctp_chunk_is_data(a) (a->chunk_hdr->type == SCTP_CID_DATA)
+
+/* Calculate the actual data size in a data chunk */
+#define SCTP_DATA_SNDSIZE(c) ((int)((unsigned long)(c->chunk_end)\
+ - (unsigned long)(c->chunk_hdr)\
+ - sizeof(sctp_data_chunk_t)))
+
+/* Internal error codes */
+typedef enum {
+
+ SCTP_IERROR_NO_ERROR = 0,
+ SCTP_IERROR_BASE = 1000,
+ SCTP_IERROR_NO_COOKIE,
+ SCTP_IERROR_BAD_SIG,
+ SCTP_IERROR_STALE_COOKIE,
+ SCTP_IERROR_NOMEM,
+ SCTP_IERROR_MALFORMED,
+ SCTP_IERROR_BAD_TAG,
+ SCTP_IERROR_BIG_GAP,
+ SCTP_IERROR_DUP_TSN,
+ SCTP_IERROR_HIGH_TSN,
+ SCTP_IERROR_IGNORE_TSN,
+ SCTP_IERROR_NO_DATA,
+ SCTP_IERROR_BAD_STREAM,
+ SCTP_IERROR_BAD_PORTS,
+ SCTP_IERROR_AUTH_BAD_HMAC,
+ SCTP_IERROR_AUTH_BAD_KEYID,
+ SCTP_IERROR_PROTO_VIOLATION,
+ SCTP_IERROR_ERROR,
+ SCTP_IERROR_ABORT,
+} sctp_ierror_t;
+
+
+
+/* SCTP state defines for internal state machine */
+typedef enum {
+
+ SCTP_STATE_CLOSED = 0,
+ SCTP_STATE_COOKIE_WAIT = 1,
+ SCTP_STATE_COOKIE_ECHOED = 2,
+ SCTP_STATE_ESTABLISHED = 3,
+ SCTP_STATE_SHUTDOWN_PENDING = 4,
+ SCTP_STATE_SHUTDOWN_SENT = 5,
+ SCTP_STATE_SHUTDOWN_RECEIVED = 6,
+ SCTP_STATE_SHUTDOWN_ACK_SENT = 7,
+
+} sctp_state_t;
+
+#define SCTP_STATE_MAX SCTP_STATE_SHUTDOWN_ACK_SENT
+#define SCTP_STATE_NUM_STATES (SCTP_STATE_MAX + 1)
+
+/* These are values for sk->state.
+ * For a UDP-style SCTP socket, the states are defined as follows
+ * - A socket in SCTP_SS_CLOSED state indicates that it is not willing to
+ * accept new associations, but it can initiate the creation of new ones.
+ * - A socket in SCTP_SS_LISTENING state indicates that it is willing to
+ * accept new associations and can initiate the creation of new ones.
+ * - A socket in SCTP_SS_ESTABLISHED state indicates that it is a peeled off
+ * socket with one association.
+ * For a TCP-style SCTP socket, the states are defined as follows
+ * - A socket in SCTP_SS_CLOSED state indicates that it is not willing to
+ * accept new associations, but it can initiate the creation of new ones.
+ * - A socket in SCTP_SS_LISTENING state indicates that it is willing to
+ * accept new associations, but cannot initiate the creation of new ones.
+ * - A socket in SCTP_SS_ESTABLISHED state indicates that it has a single
+ * association.
+ */
+typedef enum {
+ SCTP_SS_CLOSED = TCP_CLOSE,
+ SCTP_SS_LISTENING = TCP_LISTEN,
+ SCTP_SS_ESTABLISHING = TCP_SYN_SENT,
+ SCTP_SS_ESTABLISHED = TCP_ESTABLISHED,
+ SCTP_SS_CLOSING = TCP_CLOSING,
+} sctp_sock_state_t;
+
+/* These functions map various type to printable names. */
+const char *sctp_cname(const sctp_subtype_t); /* chunk types */
+const char *sctp_oname(const sctp_subtype_t); /* other events */
+const char *sctp_tname(const sctp_subtype_t); /* timeouts */
+const char *sctp_pname(const sctp_subtype_t); /* primitives */
+
+/* This is a table of printable names of sctp_state_t's. */
+extern const char *const sctp_state_tbl[];
+extern const char *const sctp_evttype_tbl[];
+extern const char *const sctp_status_tbl[];
+
+/* Maximum chunk length considering padding requirements. */
+enum { SCTP_MAX_CHUNK_LEN = ((1<<16) - sizeof(__u32)) };
+
+/* Encourage Cookie-Echo bundling by pre-fragmenting chunks a little
+ * harder (until reaching ESTABLISHED state).
+ */
+enum { SCTP_ARBITRARY_COOKIE_ECHO_LEN = 200 };
+
+/* Guess at how big to make the TSN mapping array.
+ * We guarantee that we can handle at least this big a gap between the
+ * cumulative ACK and the highest TSN. In practice, we can often
+ * handle up to twice this value.
+ *
+ * NEVER make this more than 32767 (2^15-1). The Gap Ack Blocks in a
+ * SACK (see section 3.3.4) are only 16 bits, so 2*SCTP_TSN_MAP_SIZE
+ * must be less than 65535 (2^16 - 1), or we will have overflow
+ * problems creating SACK's.
+ */
+#define SCTP_TSN_MAP_INITIAL BITS_PER_LONG
+#define SCTP_TSN_MAP_INCREMENT SCTP_TSN_MAP_INITIAL
+#define SCTP_TSN_MAP_SIZE 4096
+
+/* We will not record more than this many duplicate TSNs between two
+ * SACKs. The minimum PMTU is 576. Remove all the headers and there
+ * is enough room for 131 duplicate reports. Round down to the
+ * nearest power of 2.
+ */
+enum { SCTP_MIN_PMTU = 576 };
+enum { SCTP_MAX_DUP_TSNS = 16 };
+enum { SCTP_MAX_GABS = 16 };
+
+/* Heartbeat interval - 30 secs */
+#define SCTP_DEFAULT_TIMEOUT_HEARTBEAT (30*1000)
+
+/* Delayed sack timer - 200ms */
+#define SCTP_DEFAULT_TIMEOUT_SACK (200)
+
+/* RTO.Initial - 3 seconds
+ * RTO.Min - 1 second
+ * RTO.Max - 60 seconds
+ * RTO.Alpha - 1/8
+ * RTO.Beta - 1/4
+ */
+#define SCTP_RTO_INITIAL (3 * 1000)
+#define SCTP_RTO_MIN (1 * 1000)
+#define SCTP_RTO_MAX (60 * 1000)
+
+#define SCTP_RTO_ALPHA 3 /* 1/8 when converted to right shifts. */
+#define SCTP_RTO_BETA 2 /* 1/4 when converted to right shifts. */
+
+/* Maximum number of new data packets that can be sent in a burst. */
+#define SCTP_DEFAULT_MAX_BURST 4
+
+#define SCTP_CLOCK_GRANULARITY 1 /* 1 jiffy */
+
+#define SCTP_DEFAULT_COOKIE_LIFE (60 * 1000) /* 60 seconds */
+
+#define SCTP_DEFAULT_MINWINDOW 1500 /* default minimum rwnd size */
+#define SCTP_DEFAULT_MAXWINDOW 65535 /* default rwnd size */
+#define SCTP_DEFAULT_RWND_SHIFT 4 /* by default, update on 1/16 of
+ * rcvbuf, which is 1/8 of initial
+ * window
+ */
+#define SCTP_DEFAULT_MAXSEGMENT 1500 /* MTU size, this is the limit
+ * to which we will raise the P-MTU.
+ */
+#define SCTP_DEFAULT_MINSEGMENT 512 /* MTU size ... if no mtu disc */
+#define SCTP_HOW_MANY_SECRETS 2 /* How many secrets I keep */
+#define SCTP_SECRET_SIZE 32 /* Number of octets in a 256 bits. */
+
+#define SCTP_SIGNATURE_SIZE 20 /* size of a SLA-1 signature */
+
+#define SCTP_COOKIE_MULTIPLE 32 /* Pad out our cookie to make our hash
+ * functions simpler to write.
+ */
+
+#if defined (CONFIG_SCTP_HMAC_MD5)
+#define SCTP_COOKIE_HMAC_ALG "hmac(md5)"
+#elif defined (CONFIG_SCTP_HMAC_SHA1)
+#define SCTP_COOKIE_HMAC_ALG "hmac(sha1)"
+#else
+#define SCTP_COOKIE_HMAC_ALG NULL
+#endif
+
+/* These return values describe the success or failure of a number of
+ * routines which form the lower interface to SCTP_outqueue.
+ */
+typedef enum {
+ SCTP_XMIT_OK,
+ SCTP_XMIT_PMTU_FULL,
+ SCTP_XMIT_RWND_FULL,
+ SCTP_XMIT_NAGLE_DELAY,
+} sctp_xmit_t;
+
+/* These are the commands for manipulating transports. */
+typedef enum {
+ SCTP_TRANSPORT_UP,
+ SCTP_TRANSPORT_DOWN,
+} sctp_transport_cmd_t;
+
+/* These are the address scopes defined mainly for IPv4 addresses
+ * based on draft of SCTP IPv4 scoping <draft-stewart-tsvwg-sctp-ipv4-00.txt>.
+ * These scopes are hopefully generic enough to be used on scoping both
+ * IPv4 and IPv6 addresses in SCTP.
+ * At this point, the IPv6 scopes will be mapped to these internal scopes
+ * as much as possible.
+ */
+typedef enum {
+ SCTP_SCOPE_GLOBAL, /* IPv4 global addresses */
+ SCTP_SCOPE_PRIVATE, /* IPv4 private addresses */
+ SCTP_SCOPE_LINK, /* IPv4 link local address */
+ SCTP_SCOPE_LOOPBACK, /* IPv4 loopback address */
+ SCTP_SCOPE_UNUSABLE, /* IPv4 unusable addresses */
+} sctp_scope_t;
+
+typedef enum {
+ SCTP_SCOPE_POLICY_DISABLE, /* Disable IPv4 address scoping */
+ SCTP_SCOPE_POLICY_ENABLE, /* Enable IPv4 address scoping */
+ SCTP_SCOPE_POLICY_PRIVATE, /* Follow draft but allow IPv4 private addresses */
+ SCTP_SCOPE_POLICY_LINK, /* Follow draft but allow IPv4 link local addresses */
+} sctp_scope_policy_t;
+
+/* Based on IPv4 scoping <draft-stewart-tsvwg-sctp-ipv4-00.txt>,
+ * SCTP IPv4 unusable addresses: 0.0.0.0/8, 224.0.0.0/4, 198.18.0.0/24,
+ * 192.88.99.0/24.
+ * Also, RFC 8.4, non-unicast addresses are not considered valid SCTP
+ * addresses.
+ */
+#define IS_IPV4_UNUSABLE_ADDRESS(a) \
+ ((htonl(INADDR_BROADCAST) == a) || \
+ ipv4_is_multicast(a) || \
+ ipv4_is_zeronet(a) || \
+ ipv4_is_test_198(a) || \
+ ipv4_is_anycast_6to4(a))
+
+/* Flags used for the bind address copy functions. */
+#define SCTP_ADDR6_ALLOWED 0x00000001 /* IPv6 address is allowed by
+ local sock family */
+#define SCTP_ADDR4_PEERSUPP 0x00000002 /* IPv4 address is supported by
+ peer */
+#define SCTP_ADDR6_PEERSUPP 0x00000004 /* IPv6 address is supported by
+ peer */
+
+/* Reasons to retransmit. */
+typedef enum {
+ SCTP_RTXR_T3_RTX,
+ SCTP_RTXR_FAST_RTX,
+ SCTP_RTXR_PMTUD,
+ SCTP_RTXR_T1_RTX,
+} sctp_retransmit_reason_t;
+
+/* Reasons to lower cwnd. */
+typedef enum {
+ SCTP_LOWER_CWND_T3_RTX,
+ SCTP_LOWER_CWND_FAST_RTX,
+ SCTP_LOWER_CWND_ECNE,
+ SCTP_LOWER_CWND_INACTIVE,
+} sctp_lower_cwnd_t;
+
+
+/* SCTP-AUTH Necessary constants */
+
+/* SCTP-AUTH, Section 3.3
+ *
+ * The following Table 2 shows the currently defined values for HMAC
+ * identifiers.
+ *
+ * +-----------------+--------------------------+
+ * | HMAC Identifier | Message Digest Algorithm |
+ * +-----------------+--------------------------+
+ * | 0 | Reserved |
+ * | 1 | SHA-1 defined in [8] |
+ * | 2 | Reserved |
+ * | 3 | SHA-256 defined in [8] |
+ * +-----------------+--------------------------+
+ */
+enum {
+ SCTP_AUTH_HMAC_ID_RESERVED_0,
+ SCTP_AUTH_HMAC_ID_SHA1,
+ SCTP_AUTH_HMAC_ID_RESERVED_2,
+#if defined (CONFIG_CRYPTO_SHA256) || defined (CONFIG_CRYPTO_SHA256_MODULE)
+ SCTP_AUTH_HMAC_ID_SHA256,
+#endif
+ __SCTP_AUTH_HMAC_MAX
+};
+
+#define SCTP_AUTH_HMAC_ID_MAX __SCTP_AUTH_HMAC_MAX - 1
+#define SCTP_AUTH_NUM_HMACS __SCTP_AUTH_HMAC_MAX
+#define SCTP_SHA1_SIG_SIZE 20
+#define SCTP_SHA256_SIG_SIZE 32
+
+/* SCTP-AUTH, Section 3.2
+ * The chunk types for INIT, INIT-ACK, SHUTDOWN-COMPLETE and AUTH chunks
+ * MUST NOT be listed in the CHUNKS parameter
+ */
+#define SCTP_NUM_NOAUTH_CHUNKS 4
+#define SCTP_AUTH_MAX_CHUNKS (SCTP_NUM_CHUNK_TYPES - SCTP_NUM_NOAUTH_CHUNKS)
+
+/* SCTP-AUTH Section 6.1
+ * The RANDOM parameter MUST contain a 32 byte random number.
+ */
+#define SCTP_AUTH_RANDOM_LENGTH 32
+
+#endif /* __sctp_constants_h__ */
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
new file mode 100644
index 00000000..a2ef8146
--- /dev/null
+++ b/include/net/sctp/sctp.h
@@ -0,0 +1,720 @@
+/* SCTP kernel implementation
+ * (C) Copyright IBM Corp. 2001, 2004
+ * Copyright (c) 1999-2000 Cisco, Inc.
+ * Copyright (c) 1999-2001 Motorola, Inc.
+ * Copyright (c) 2001-2003 Intel Corp.
+ *
+ * This file is part of the SCTP kernel implementation
+ *
+ * The base lksctp header.
+ *
+ * This SCTP implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This SCTP implementation is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * ************************
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Please send any bug reports or fixes you make to the
+ * email address(es):
+ * lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *
+ * Or submit a bug report through the following website:
+ * http://www.sf.net/projects/lksctp
+ *
+ * Written or modified by:
+ * La Monte H.P. Yarroll <piggy@acm.org>
+ * Xingang Guo <xingang.guo@intel.com>
+ * Jon Grimm <jgrimm@us.ibm.com>
+ * Daisy Chang <daisyc@us.ibm.com>
+ * Sridhar Samudrala <sri@us.ibm.com>
+ * Ardelle Fan <ardelle.fan@intel.com>
+ * Ryan Layer <rmlayer@us.ibm.com>
+ * Kevin Gao <kevin.gao@intel.com>
+ *
+ * Any bugs reported given to us we will try to fix... any fixes shared will
+ * be incorporated into the next SCTP release.
+ */
+
+#ifndef __net_sctp_h__
+#define __net_sctp_h__
+
+/* Header Strategy.
+ * Start getting some control over the header file depencies:
+ * includes
+ * constants
+ * structs
+ * prototypes
+ * macros, externs, and inlines
+ *
+ * Move test_frame specific items out of the kernel headers
+ * and into the test frame headers. This is not perfect in any sense
+ * and will continue to evolve.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/in.h>
+#include <linux/tty.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+#include <linux/jiffies.h>
+#include <linux/idr.h>
+
+#if IS_ENABLED(CONFIG_IPV6)
+#include <net/ipv6.h>
+#include <net/ip6_route.h>
+#endif
+
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <net/sock.h>
+#include <net/snmp.h>
+#include <net/sctp/structs.h>
+#include <net/sctp/constants.h>
+
+
+/* Set SCTP_DEBUG flag via config if not already set. */
+#ifndef SCTP_DEBUG
+#ifdef CONFIG_SCTP_DBG_MSG
+#define SCTP_DEBUG 1
+#else
+#define SCTP_DEBUG 0
+#endif /* CONFIG_SCTP_DBG */
+#endif /* SCTP_DEBUG */
+
+#ifdef CONFIG_IP_SCTP_MODULE
+#define SCTP_PROTOSW_FLAG 0
+#else /* static! */
+#define SCTP_PROTOSW_FLAG INET_PROTOSW_PERMANENT
+#endif
+
+
+/* Certain internal static functions need to be exported when
+ * compiled into the test frame.
+ */
+#ifndef SCTP_STATIC
+#define SCTP_STATIC static
+#endif
+
+/*
+ * Function declarations.
+ */
+
+/*
+ * sctp/protocol.c
+ */
+extern struct sock *sctp_get_ctl_sock(void);
+extern int sctp_copy_local_addr_list(struct sctp_bind_addr *,
+ sctp_scope_t, gfp_t gfp,
+ int flags);
+extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
+extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
+extern void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *, int);
+
+/*
+ * sctp/socket.c
+ */
+int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb);
+int sctp_inet_listen(struct socket *sock, int backlog);
+void sctp_write_space(struct sock *sk);
+void sctp_data_ready(struct sock *sk, int len);
+unsigned int sctp_poll(struct file *file, struct socket *sock,
+ poll_table *wait);
+void sctp_sock_rfree(struct sk_buff *skb);
+void sctp_copy_sock(struct sock *newsk, struct sock *sk,
+ struct sctp_association *asoc);
+extern struct percpu_counter sctp_sockets_allocated;
+extern int sctp_asconf_mgmt(struct sctp_sock *, struct sctp_sockaddr_entry *);
+
+/*
+ * sctp/primitive.c
+ */
+int sctp_primitive_ASSOCIATE(struct sctp_association *, void *arg);
+int sctp_primitive_SHUTDOWN(struct sctp_association *, void *arg);
+int sctp_primitive_ABORT(struct sctp_association *, void *arg);
+int sctp_primitive_SEND(struct sctp_association *, void *arg);
+int sctp_primitive_REQUESTHEARTBEAT(struct sctp_association *, void *arg);
+int sctp_primitive_ASCONF(struct sctp_association *, void *arg);
+
+/*
+ * sctp/input.c
+ */
+int sctp_rcv(struct sk_buff *skb);
+void sctp_v4_err(struct sk_buff *skb, u32 info);
+void sctp_hash_established(struct sctp_association *);
+void sctp_unhash_established(struct sctp_association *);
+void sctp_hash_endpoint(struct sctp_endpoint *);
+void sctp_unhash_endpoint(struct sctp_endpoint *);
+struct sock *sctp_err_lookup(int family, struct sk_buff *,
+ struct sctphdr *, struct sctp_association **,
+ struct sctp_transport **);
+void sctp_err_finish(struct sock *, struct sctp_association *);
+void sctp_icmp_frag_needed(struct sock *, struct sctp_association *,
+ struct sctp_transport *t, __u32 pmtu);
+void sctp_icmp_proto_unreachable(struct sock *sk,
+ struct sctp_association *asoc,
+ struct sctp_transport *t);
+void sctp_backlog_migrate(struct sctp_association *assoc,
+ struct sock *oldsk, struct sock *newsk);
+
+/*
+ * sctp/proc.c
+ */
+int sctp_snmp_proc_init(void);
+void sctp_snmp_proc_exit(void);
+int sctp_eps_proc_init(void);
+void sctp_eps_proc_exit(void);
+int sctp_assocs_proc_init(void);
+void sctp_assocs_proc_exit(void);
+int sctp_remaddr_proc_init(void);
+void sctp_remaddr_proc_exit(void);
+
+
+/*
+ * Module global variables
+ */
+
+ /*
+ * sctp/protocol.c
+ */
+extern struct kmem_cache *sctp_chunk_cachep __read_mostly;
+extern struct kmem_cache *sctp_bucket_cachep __read_mostly;
+
+/*
+ * Section: Macros, externs, and inlines
+ */
+
+
+#ifdef TEST_FRAME
+#include <test_frame.h>
+#else
+
+/* spin lock wrappers. */
+#define sctp_spin_lock_irqsave(lock, flags) spin_lock_irqsave(lock, flags)
+#define sctp_spin_unlock_irqrestore(lock, flags) \
+ spin_unlock_irqrestore(lock, flags)
+#define sctp_local_bh_disable() local_bh_disable()
+#define sctp_local_bh_enable() local_bh_enable()
+#define sctp_spin_lock(lock) spin_lock(lock)
+#define sctp_spin_unlock(lock) spin_unlock(lock)
+#define sctp_write_lock(lock) write_lock(lock)
+#define sctp_write_unlock(lock) write_unlock(lock)
+#define sctp_read_lock(lock) read_lock(lock)
+#define sctp_read_unlock(lock) read_unlock(lock)
+
+/* sock lock wrappers. */
+#define sctp_lock_sock(sk) lock_sock(sk)
+#define sctp_release_sock(sk) release_sock(sk)
+#define sctp_bh_lock_sock(sk) bh_lock_sock(sk)
+#define sctp_bh_unlock_sock(sk) bh_unlock_sock(sk)
+
+/* SCTP SNMP MIB stats handlers */
+DECLARE_SNMP_STAT(struct sctp_mib, sctp_statistics);
+#define SCTP_INC_STATS(field) SNMP_INC_STATS(sctp_statistics, field)
+#define SCTP_INC_STATS_BH(field) SNMP_INC_STATS_BH(sctp_statistics, field)
+#define SCTP_INC_STATS_USER(field) SNMP_INC_STATS_USER(sctp_statistics, field)
+#define SCTP_DEC_STATS(field) SNMP_DEC_STATS(sctp_statistics, field)
+
+#endif /* !TEST_FRAME */
+
+/* sctp mib definitions */
+enum {
+ SCTP_MIB_NUM = 0,
+ SCTP_MIB_CURRESTAB, /* CurrEstab */
+ SCTP_MIB_ACTIVEESTABS, /* ActiveEstabs */
+ SCTP_MIB_PASSIVEESTABS, /* PassiveEstabs */
+ SCTP_MIB_ABORTEDS, /* Aborteds */
+ SCTP_MIB_SHUTDOWNS, /* Shutdowns */
+ SCTP_MIB_OUTOFBLUES, /* OutOfBlues */
+ SCTP_MIB_CHECKSUMERRORS, /* ChecksumErrors */
+ SCTP_MIB_OUTCTRLCHUNKS, /* OutCtrlChunks */
+ SCTP_MIB_OUTORDERCHUNKS, /* OutOrderChunks */
+ SCTP_MIB_OUTUNORDERCHUNKS, /* OutUnorderChunks */
+ SCTP_MIB_INCTRLCHUNKS, /* InCtrlChunks */
+ SCTP_MIB_INORDERCHUNKS, /* InOrderChunks */
+ SCTP_MIB_INUNORDERCHUNKS, /* InUnorderChunks */
+ SCTP_MIB_FRAGUSRMSGS, /* FragUsrMsgs */
+ SCTP_MIB_REASMUSRMSGS, /* ReasmUsrMsgs */
+ SCTP_MIB_OUTSCTPPACKS, /* OutSCTPPacks */
+ SCTP_MIB_INSCTPPACKS, /* InSCTPPacks */
+ SCTP_MIB_T1_INIT_EXPIREDS,
+ SCTP_MIB_T1_COOKIE_EXPIREDS,
+ SCTP_MIB_T2_SHUTDOWN_EXPIREDS,
+ SCTP_MIB_T3_RTX_EXPIREDS,
+ SCTP_MIB_T4_RTO_EXPIREDS,
+ SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS,
+ SCTP_MIB_DELAY_SACK_EXPIREDS,
+ SCTP_MIB_AUTOCLOSE_EXPIREDS,
+ SCTP_MIB_T1_RETRANSMITS,
+ SCTP_MIB_T3_RETRANSMITS,
+ SCTP_MIB_PMTUD_RETRANSMITS,
+ SCTP_MIB_FAST_RETRANSMITS,
+ SCTP_MIB_IN_PKT_SOFTIRQ,
+ SCTP_MIB_IN_PKT_BACKLOG,
+ SCTP_MIB_IN_PKT_DISCARDS,
+ SCTP_MIB_IN_DATA_CHUNK_DISCARDS,
+ __SCTP_MIB_MAX
+};
+
+#define SCTP_MIB_MAX __SCTP_MIB_MAX
+struct sctp_mib {
+ unsigned long mibs[SCTP_MIB_MAX];
+};
+
+
+/* Print debugging messages. */
+#if SCTP_DEBUG
+extern int sctp_debug_flag;
+#define SCTP_DEBUG_PRINTK(fmt, args...) \
+do { \
+ if (sctp_debug_flag) \
+ printk(KERN_DEBUG pr_fmt(fmt), ##args); \
+} while (0)
+#define SCTP_DEBUG_PRINTK_CONT(fmt, args...) \
+do { \
+ if (sctp_debug_flag) \
+ pr_cont(fmt, ##args); \
+} while (0)
+#define SCTP_DEBUG_PRINTK_IPADDR(fmt_lead, fmt_trail, \
+ args_lead, addr, args_trail...) \
+do { \
+ const union sctp_addr *_addr = (addr); \
+ if (sctp_debug_flag) { \
+ if (_addr->sa.sa_family == AF_INET6) { \
+ printk(KERN_DEBUG \
+ pr_fmt(fmt_lead "%pI6" fmt_trail), \
+ args_lead, \
+ &_addr->v6.sin6_addr, \
+ args_trail); \
+ } else { \
+ printk(KERN_DEBUG \
+ pr_fmt(fmt_lead "%pI4" fmt_trail), \
+ args_lead, \
+ &_addr->v4.sin_addr.s_addr, \
+ args_trail); \
+ } \
+ } \
+} while (0)
+#define SCTP_ENABLE_DEBUG { sctp_debug_flag = 1; }
+#define SCTP_DISABLE_DEBUG { sctp_debug_flag = 0; }
+
+#define SCTP_ASSERT(expr, str, func) \
+ if (!(expr)) { \
+ SCTP_DEBUG_PRINTK("Assertion Failed: %s(%s) at %s:%s:%d\n", \
+ str, (#expr), __FILE__, __func__, __LINE__); \
+ func; \
+ }
+
+#else /* SCTP_DEBUG */
+
+#define SCTP_DEBUG_PRINTK(whatever...)
+#define SCTP_DEBUG_PRINTK_CONT(fmt, args...)
+#define SCTP_DEBUG_PRINTK_IPADDR(whatever...)
+#define SCTP_ENABLE_DEBUG
+#define SCTP_DISABLE_DEBUG
+#define SCTP_ASSERT(expr, str, func)
+
+#endif /* SCTP_DEBUG */
+
+
+/*
+ * Macros for keeping a global reference of object allocations.
+ */
+#ifdef CONFIG_SCTP_DBG_OBJCNT
+
+extern atomic_t sctp_dbg_objcnt_sock;
+extern atomic_t sctp_dbg_objcnt_ep;
+extern atomic_t sctp_dbg_objcnt_assoc;
+extern atomic_t sctp_dbg_objcnt_transport;
+extern atomic_t sctp_dbg_objcnt_chunk;
+extern atomic_t sctp_dbg_objcnt_bind_addr;
+extern atomic_t sctp_dbg_objcnt_bind_bucket;
+extern atomic_t sctp_dbg_objcnt_addr;
+extern atomic_t sctp_dbg_objcnt_ssnmap;
+extern atomic_t sctp_dbg_objcnt_datamsg;
+extern atomic_t sctp_dbg_objcnt_keys;
+
+/* Macros to atomically increment/decrement objcnt counters. */
+#define SCTP_DBG_OBJCNT_INC(name) \
+atomic_inc(&sctp_dbg_objcnt_## name)
+#define SCTP_DBG_OBJCNT_DEC(name) \
+atomic_dec(&sctp_dbg_objcnt_## name)
+#define SCTP_DBG_OBJCNT(name) \
+atomic_t sctp_dbg_objcnt_## name = ATOMIC_INIT(0)
+
+/* Macro to help create new entries in in the global array of
+ * objcnt counters.
+ */
+#define SCTP_DBG_OBJCNT_ENTRY(name) \
+{.label= #name, .counter= &sctp_dbg_objcnt_## name}
+
+void sctp_dbg_objcnt_init(void);
+void sctp_dbg_objcnt_exit(void);
+
+#else
+
+#define SCTP_DBG_OBJCNT_INC(name)
+#define SCTP_DBG_OBJCNT_DEC(name)
+
+static inline void sctp_dbg_objcnt_init(void) { return; }
+static inline void sctp_dbg_objcnt_exit(void) { return; }
+
+#endif /* CONFIG_SCTP_DBG_OBJCOUNT */
+
+#if defined CONFIG_SYSCTL
+void sctp_sysctl_register(void);
+void sctp_sysctl_unregister(void);
+#else
+static inline void sctp_sysctl_register(void) { return; }
+static inline void sctp_sysctl_unregister(void) { return; }
+#endif
+
+/* Size of Supported Address Parameter for 'x' address types. */
+#define SCTP_SAT_LEN(x) (sizeof(struct sctp_paramhdr) + (x) * sizeof(__u16))
+
+#if IS_ENABLED(CONFIG_IPV6)
+
+void sctp_v6_pf_init(void);
+void sctp_v6_pf_exit(void);
+int sctp_v6_protosw_init(void);
+void sctp_v6_protosw_exit(void);
+int sctp_v6_add_protocol(void);
+void sctp_v6_del_protocol(void);
+
+#else /* #ifdef defined(CONFIG_IPV6) */
+
+static inline void sctp_v6_pf_init(void) { return; }
+static inline void sctp_v6_pf_exit(void) { return; }
+static inline int sctp_v6_protosw_init(void) { return 0; }
+static inline void sctp_v6_protosw_exit(void) { return; }
+static inline int sctp_v6_add_protocol(void) { return 0; }
+static inline void sctp_v6_del_protocol(void) { return; }
+
+#endif /* #if defined(CONFIG_IPV6) */
+
+
+/* Map an association to an assoc_id. */
+static inline sctp_assoc_t sctp_assoc2id(const struct sctp_association *asoc)
+{
+ return asoc ? asoc->assoc_id : 0;
+}
+
+/* Look up the association by its id. */
+struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id);
+
+int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp);
+
+/* A macro to walk a list of skbs. */
+#define sctp_skb_for_each(pos, head, tmp) \
+ skb_queue_walk_safe(head, pos, tmp)
+
+/* A helper to append an entire skb list (list) to another (head). */
+static inline void sctp_skb_list_tail(struct sk_buff_head *list,
+ struct sk_buff_head *head)
+{
+ unsigned long flags;
+
+ sctp_spin_lock_irqsave(&head->lock, flags);
+ sctp_spin_lock(&list->lock);
+
+ skb_queue_splice_tail_init(list, head);
+
+ sctp_spin_unlock(&list->lock);
+ sctp_spin_unlock_irqrestore(&head->lock, flags);
+}
+
+/**
+ * sctp_list_dequeue - remove from the head of the queue
+ * @list: list to dequeue from
+ *
+ * Remove the head of the list. The head item is
+ * returned or %NULL if the list is empty.
+ */
+
+static inline struct list_head *sctp_list_dequeue(struct list_head *list)
+{
+ struct list_head *result = NULL;
+
+ if (list->next != list) {
+ result = list->next;
+ list->next = result->next;
+ list->next->prev = list;
+ INIT_LIST_HEAD(result);
+ }
+ return result;
+}
+
+/* SCTP version of skb_set_owner_r. We need this one because
+ * of the way we have to do receive buffer accounting on bundled
+ * chunks.
+ */
+static inline void sctp_skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
+{
+ struct sctp_ulpevent *event = sctp_skb2event(skb);
+
+ skb_orphan(skb);
+ skb->sk = sk;
+ skb->destructor = sctp_sock_rfree;
+ atomic_add(event->rmem_len, &sk->sk_rmem_alloc);
+ /*
+ * This mimics the behavior of skb_set_owner_r
+ */
+ sk->sk_forward_alloc -= event->rmem_len;
+}
+
+/* Tests if the list has one and only one entry. */
+static inline int sctp_list_single_entry(struct list_head *head)
+{
+ return (head->next != head) && (head->next == head->prev);
+}
+
+/* Generate a random jitter in the range of -50% ~ +50% of input RTO. */
+static inline __s32 sctp_jitter(__u32 rto)
+{
+ static __u32 sctp_rand;
+ __s32 ret;
+
+ /* Avoid divide by zero. */
+ if (!rto)
+ rto = 1;
+
+ sctp_rand += jiffies;
+ sctp_rand ^= (sctp_rand << 12);
+ sctp_rand ^= (sctp_rand >> 20);
+
+ /* Choose random number from 0 to rto, then move to -50% ~ +50%
+ * of rto.
+ */
+ ret = sctp_rand % rto - (rto >> 1);
+ return ret;
+}
+
+/* Break down data chunks at this point. */
+static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
+{
+ struct sctp_sock *sp = sctp_sk(asoc->base.sk);
+ int frag = pmtu;
+
+ frag -= sp->pf->af->net_header_len;
+ frag -= sizeof(struct sctphdr) + sizeof(struct sctp_data_chunk);
+
+ if (asoc->user_frag)
+ frag = min_t(int, frag, asoc->user_frag);
+
+ frag = min_t(int, frag, SCTP_MAX_CHUNK_LEN);
+
+ return frag;
+}
+
+static inline void sctp_assoc_pending_pmtu(struct sctp_association *asoc)
+{
+
+ sctp_assoc_sync_pmtu(asoc);
+ asoc->pmtu_pending = 0;
+}
+
+/* Walk through a list of TLV parameters. Don't trust the
+ * individual parameter lengths and instead depend on
+ * the chunk length to indicate when to stop. Make sure
+ * there is room for a param header too.
+ */
+#define sctp_walk_params(pos, chunk, member)\
+_sctp_walk_params((pos), (chunk), ntohs((chunk)->chunk_hdr.length), member)
+
+#define _sctp_walk_params(pos, chunk, end, member)\
+for (pos.v = chunk->member;\
+ pos.v <= (void *)chunk + end - ntohs(pos.p->length) &&\
+ ntohs(pos.p->length) >= sizeof(sctp_paramhdr_t);\
+ pos.v += WORD_ROUND(ntohs(pos.p->length)))
+
+#define sctp_walk_errors(err, chunk_hdr)\
+_sctp_walk_errors((err), (chunk_hdr), ntohs((chunk_hdr)->length))
+
+#define _sctp_walk_errors(err, chunk_hdr, end)\
+for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \
+ sizeof(sctp_chunkhdr_t));\
+ (void *)err <= (void *)chunk_hdr + end - ntohs(err->length) &&\
+ ntohs(err->length) >= sizeof(sctp_errhdr_t); \
+ err = (sctp_errhdr_t *)((void *)err + WORD_ROUND(ntohs(err->length))))
+
+#define sctp_walk_fwdtsn(pos, chunk)\
+_sctp_walk_fwdtsn((pos), (chunk), ntohs((chunk)->chunk_hdr->length) - sizeof(struct sctp_fwdtsn_chunk))
+
+#define _sctp_walk_fwdtsn(pos, chunk, end)\
+for (pos = chunk->subh.fwdtsn_hdr->skip;\
+ (void *)pos <= (void *)chunk->subh.fwdtsn_hdr->skip + end - sizeof(struct sctp_fwdtsn_skip);\
+ pos++)
+
+/* Round an int up to the next multiple of 4. */
+#define WORD_ROUND(s) (((s)+3)&~3)
+
+/* Make a new instance of type. */
+#define t_new(type, flags) (type *)kzalloc(sizeof(type), flags)
+
+/* Compare two timevals. */
+#define tv_lt(s, t) \
+ (s.tv_sec < t.tv_sec || (s.tv_sec == t.tv_sec && s.tv_usec < t.tv_usec))
+
+/* Add tv1 to tv2. */
+#define TIMEVAL_ADD(tv1, tv2) \
+({ \
+ suseconds_t usecs = (tv2).tv_usec + (tv1).tv_usec; \
+ time_t secs = (tv2).tv_sec + (tv1).tv_sec; \
+\
+ if (usecs >= 1000000) { \
+ usecs -= 1000000; \
+ secs++; \
+ } \
+ (tv2).tv_sec = secs; \
+ (tv2).tv_usec = usecs; \
+})
+
+/* External references. */
+
+extern struct proto sctp_prot;
+extern struct proto sctpv6_prot;
+extern struct proc_dir_entry *proc_net_sctp;
+void sctp_put_port(struct sock *sk);
+
+extern struct idr sctp_assocs_id;
+extern spinlock_t sctp_assocs_id_lock;
+
+/* Static inline functions. */
+
+/* Convert from an IP version number to an Address Family symbol. */
+static inline int ipver2af(__u8 ipver)
+{
+ switch (ipver) {
+ case 4:
+ return AF_INET;
+ case 6:
+ return AF_INET6;
+ default:
+ return 0;
+ }
+}
+
+/* Convert from an address parameter type to an address family. */
+static inline int param_type2af(__be16 type)
+{
+ switch (type) {
+ case SCTP_PARAM_IPV4_ADDRESS:
+ return AF_INET;
+ case SCTP_PARAM_IPV6_ADDRESS:
+ return AF_INET6;
+ default:
+ return 0;
+ }
+}
+
+/* Perform some sanity checks. */
+static inline int sctp_sanity_check(void)
+{
+ SCTP_ASSERT(sizeof(struct sctp_ulpevent) <=
+ sizeof(((struct sk_buff *)0)->cb),
+ "SCTP: ulpevent does not fit in skb!\n", return 0);
+
+ return 1;
+}
+
+/* Warning: The following hash functions assume a power of two 'size'. */
+/* This is the hash function for the SCTP port hash table. */
+static inline int sctp_phashfn(__u16 lport)
+{
+ return lport & (sctp_port_hashsize - 1);
+}
+
+/* This is the hash function for the endpoint hash table. */
+static inline int sctp_ep_hashfn(__u16 lport)
+{
+ return lport & (sctp_ep_hashsize - 1);
+}
+
+/* This is the hash function for the association hash table. */
+static inline int sctp_assoc_hashfn(__u16 lport, __u16 rport)
+{
+ int h = (lport << 16) + rport;
+ h ^= h>>8;
+ return h & (sctp_assoc_hashsize - 1);
+}
+
+/* This is the hash function for the association hash table. This is
+ * not used yet, but could be used as a better hash function when
+ * we have a vtag.
+ */
+static inline int sctp_vtag_hashfn(__u16 lport, __u16 rport, __u32 vtag)
+{
+ int h = (lport << 16) + rport;
+ h ^= vtag;
+ return h & (sctp_assoc_hashsize - 1);
+}
+
+#define sctp_for_each_hentry(epb, node, head) \
+ hlist_for_each_entry(epb, node, head, node)
+
+/* Is a socket of this style? */
+#define sctp_style(sk, style) __sctp_style((sk), (SCTP_SOCKET_##style))
+static inline int __sctp_style(const struct sock *sk, sctp_socket_type_t style)
+{
+ return sctp_sk(sk)->type == style;
+}
+
+/* Is the association in this state? */
+#define sctp_state(asoc, state) __sctp_state((asoc), (SCTP_STATE_##state))
+static inline int __sctp_state(const struct sctp_association *asoc,
+ sctp_state_t state)
+{
+ return asoc->state == state;
+}
+
+/* Is the socket in this state? */
+#define sctp_sstate(sk, state) __sctp_sstate((sk), (SCTP_SS_##state))
+static inline int __sctp_sstate(const struct sock *sk, sctp_sock_state_t state)
+{
+ return sk->sk_state == state;
+}
+
+/* Map v4-mapped v6 address back to v4 address */
+static inline void sctp_v6_map_v4(union sctp_addr *addr)
+{
+ addr->v4.sin_family = AF_INET;
+ addr->v4.sin_port = addr->v6.sin6_port;
+ addr->v4.sin_addr.s_addr = addr->v6.sin6_addr.s6_addr32[3];
+}
+
+/* Map v4 address to v4-mapped v6 address */
+static inline void sctp_v4_map_v6(union sctp_addr *addr)
+{
+ addr->v6.sin6_family = AF_INET6;
+ addr->v6.sin6_port = addr->v4.sin_port;
+ addr->v6.sin6_addr.s6_addr32[3] = addr->v4.sin_addr.s_addr;
+ addr->v6.sin6_addr.s6_addr32[0] = 0;
+ addr->v6.sin6_addr.s6_addr32[1] = 0;
+ addr->v6.sin6_addr.s6_addr32[2] = htonl(0x0000ffff);
+}
+
+/* The cookie is always 0 since this is how it's used in the
+ * pmtu code.
+ */
+static inline struct dst_entry *sctp_transport_dst_check(struct sctp_transport *t)
+{
+ if (t->dst && !dst_check(t->dst, 0)) {
+ dst_release(t->dst);
+ t->dst = NULL;
+ }
+
+ return t->dst;
+}
+
+#endif /* __net_sctp_h__ */
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
new file mode 100644
index 00000000..9148632b
--- /dev/null
+++ b/include/net/sctp/sm.h
@@ -0,0 +1,448 @@
+/* SCTP kernel implementation
+ * (C) Copyright IBM Corp. 2001, 2004
+ * Copyright (c) 1999-2000 Cisco, Inc.
+ * Copyright (c) 1999-2001 Motorola, Inc.
+ * Copyright (c) 2001 Intel Corp.
+ *
+ * This file is part of the SCTP kernel implementation
+ *
+ * These are definitions needed by the state machine.
+ *
+ * This SCTP implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This SCTP implementation is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * ************************
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Please send any bug reports or fixes you make to the
+ * email addresses:
+ * lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *
+ * Or submit a bug report through the following website:
+ * http://www.sf.net/projects/lksctp
+ *
+ * Written or modified by:
+ * La Monte H.P. Yarroll <piggy@acm.org>
+ * Karl Knutson <karl@athena.chicago.il.us>
+ * Xingang Guo <xingang.guo@intel.com>
+ * Jon Grimm <jgrimm@us.ibm.com>
+ * Dajiang Zhang <dajiang.zhang@nokia.com>
+ * Sridhar Samudrala <sri@us.ibm.com>
+ * Daisy Chang <daisyc@us.ibm.com>
+ * Ardelle Fan <ardelle.fan@intel.com>
+ * Kevin Gao <kevin.gao@intel.com>
+ *
+ * Any bugs reported given to us we will try to fix... any fixes shared will
+ * be incorporated into the next SCTP release.
+ */
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+#include <linux/slab.h>
+#include <linux/in.h>
+#include <net/sctp/command.h>
+#include <net/sctp/sctp.h>
+
+#ifndef __sctp_sm_h__
+#define __sctp_sm_h__
+
+/*
+ * Possible values for the disposition are:
+ */
+typedef enum {
+ SCTP_DISPOSITION_DISCARD, /* No further processing. */
+ SCTP_DISPOSITION_CONSUME, /* Process return values normally. */
+ SCTP_DISPOSITION_NOMEM, /* We ran out of memory--recover. */
+ SCTP_DISPOSITION_DELETE_TCB, /* Close the association. */
+ SCTP_DISPOSITION_ABORT, /* Close the association NOW. */
+ SCTP_DISPOSITION_VIOLATION, /* The peer is misbehaving. */
+ SCTP_DISPOSITION_NOT_IMPL, /* This entry is not implemented. */
+ SCTP_DISPOSITION_ERROR, /* This is plain old user error. */
+ SCTP_DISPOSITION_BUG, /* This is a bug. */
+} sctp_disposition_t;
+
+typedef struct {
+ int name;
+ int action;
+} sctp_sm_command_t;
+
+typedef sctp_disposition_t (sctp_state_fn_t) (const struct sctp_endpoint *,
+ const struct sctp_association *,
+ const sctp_subtype_t type,
+ void *arg,
+ sctp_cmd_seq_t *);
+typedef void (sctp_timer_event_t) (unsigned long);
+typedef struct {
+ sctp_state_fn_t *fn;
+ const char *name;
+} sctp_sm_table_entry_t;
+
+/* A naming convention of "sctp_sf_xxx" applies to all the state functions
+ * currently in use.
+ */
+
+/* Prototypes for generic state functions. */
+sctp_state_fn_t sctp_sf_not_impl;
+sctp_state_fn_t sctp_sf_bug;
+
+/* Prototypes for gener timer state functions. */
+sctp_state_fn_t sctp_sf_timer_ignore;
+
+/* Prototypes for chunk state functions. */
+sctp_state_fn_t sctp_sf_do_9_1_abort;
+sctp_state_fn_t sctp_sf_cookie_wait_abort;
+sctp_state_fn_t sctp_sf_cookie_echoed_abort;
+sctp_state_fn_t sctp_sf_shutdown_pending_abort;
+sctp_state_fn_t sctp_sf_shutdown_sent_abort;
+sctp_state_fn_t sctp_sf_shutdown_ack_sent_abort;
+sctp_state_fn_t sctp_sf_do_5_1B_init;
+sctp_state_fn_t sctp_sf_do_5_1C_ack;
+sctp_state_fn_t sctp_sf_do_5_1D_ce;
+sctp_state_fn_t sctp_sf_do_5_1E_ca;
+sctp_state_fn_t sctp_sf_do_4_C;
+sctp_state_fn_t sctp_sf_eat_data_6_2;
+sctp_state_fn_t sctp_sf_eat_data_fast_4_4;
+sctp_state_fn_t sctp_sf_eat_sack_6_2;
+sctp_state_fn_t sctp_sf_operr_notify;
+sctp_state_fn_t sctp_sf_t1_init_timer_expire;
+sctp_state_fn_t sctp_sf_t1_cookie_timer_expire;
+sctp_state_fn_t sctp_sf_t2_timer_expire;
+sctp_state_fn_t sctp_sf_t4_timer_expire;
+sctp_state_fn_t sctp_sf_t5_timer_expire;
+sctp_state_fn_t sctp_sf_sendbeat_8_3;
+sctp_state_fn_t sctp_sf_beat_8_3;
+sctp_state_fn_t sctp_sf_backbeat_8_3;
+sctp_state_fn_t sctp_sf_do_9_2_final;
+sctp_state_fn_t sctp_sf_do_9_2_shutdown;
+sctp_state_fn_t sctp_sf_do_9_2_shut_ctsn;
+sctp_state_fn_t sctp_sf_do_ecn_cwr;
+sctp_state_fn_t sctp_sf_do_ecne;
+sctp_state_fn_t sctp_sf_ootb;
+sctp_state_fn_t sctp_sf_pdiscard;
+sctp_state_fn_t sctp_sf_violation;
+sctp_state_fn_t sctp_sf_discard_chunk;
+sctp_state_fn_t sctp_sf_do_5_2_1_siminit;
+sctp_state_fn_t sctp_sf_do_5_2_2_dupinit;
+sctp_state_fn_t sctp_sf_do_5_2_3_initack;
+sctp_state_fn_t sctp_sf_do_5_2_4_dupcook;
+sctp_state_fn_t sctp_sf_unk_chunk;
+sctp_state_fn_t sctp_sf_do_8_5_1_E_sa;
+sctp_state_fn_t sctp_sf_cookie_echoed_err;
+sctp_state_fn_t sctp_sf_do_asconf;
+sctp_state_fn_t sctp_sf_do_asconf_ack;
+sctp_state_fn_t sctp_sf_do_9_2_reshutack;
+sctp_state_fn_t sctp_sf_eat_fwd_tsn;
+sctp_state_fn_t sctp_sf_eat_fwd_tsn_fast;
+sctp_state_fn_t sctp_sf_eat_auth;
+
+/* Prototypes for primitive event state functions. */
+sctp_state_fn_t sctp_sf_do_prm_asoc;
+sctp_state_fn_t sctp_sf_do_prm_send;
+sctp_state_fn_t sctp_sf_do_9_2_prm_shutdown;
+sctp_state_fn_t sctp_sf_cookie_wait_prm_shutdown;
+sctp_state_fn_t sctp_sf_cookie_echoed_prm_shutdown;
+sctp_state_fn_t sctp_sf_do_9_1_prm_abort;
+sctp_state_fn_t sctp_sf_cookie_wait_prm_abort;
+sctp_state_fn_t sctp_sf_cookie_echoed_prm_abort;
+sctp_state_fn_t sctp_sf_shutdown_pending_prm_abort;
+sctp_state_fn_t sctp_sf_shutdown_sent_prm_abort;
+sctp_state_fn_t sctp_sf_shutdown_ack_sent_prm_abort;
+sctp_state_fn_t sctp_sf_error_closed;
+sctp_state_fn_t sctp_sf_error_shutdown;
+sctp_state_fn_t sctp_sf_ignore_primitive;
+sctp_state_fn_t sctp_sf_do_prm_requestheartbeat;
+sctp_state_fn_t sctp_sf_do_prm_asconf;
+
+/* Prototypes for other event state functions. */
+sctp_state_fn_t sctp_sf_do_no_pending_tsn;
+sctp_state_fn_t sctp_sf_do_9_2_start_shutdown;
+sctp_state_fn_t sctp_sf_do_9_2_shutdown_ack;
+sctp_state_fn_t sctp_sf_ignore_other;
+sctp_state_fn_t sctp_sf_cookie_wait_icmp_abort;
+
+/* Prototypes for timeout event state functions. */
+sctp_state_fn_t sctp_sf_do_6_3_3_rtx;
+sctp_state_fn_t sctp_sf_do_6_2_sack;
+sctp_state_fn_t sctp_sf_autoclose_timer_expire;
+
+/* Prototypes for utility support functions. */
+__u8 sctp_get_chunk_type(struct sctp_chunk *chunk);
+const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t,
+ sctp_state_t,
+ sctp_subtype_t);
+int sctp_chunk_iif(const struct sctp_chunk *);
+struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *,
+ struct sctp_chunk *,
+ gfp_t gfp);
+__u32 sctp_generate_verification_tag(void);
+void sctp_populate_tie_tags(__u8 *cookie, __u32 curTag, __u32 hisTag);
+
+/* Prototypes for chunk-building functions. */
+struct sctp_chunk *sctp_make_init(const struct sctp_association *,
+ const struct sctp_bind_addr *,
+ gfp_t gfp, int vparam_len);
+struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *,
+ const struct sctp_chunk *,
+ const gfp_t gfp,
+ const int unkparam_len);
+struct sctp_chunk *sctp_make_cookie_echo(const struct sctp_association *,
+ const struct sctp_chunk *);
+struct sctp_chunk *sctp_make_cookie_ack(const struct sctp_association *,
+ const struct sctp_chunk *);
+struct sctp_chunk *sctp_make_cwr(const struct sctp_association *,
+ const __u32 lowest_tsn,
+ const struct sctp_chunk *);
+struct sctp_chunk * sctp_make_datafrag_empty(struct sctp_association *,
+ const struct sctp_sndrcvinfo *sinfo,
+ int len, const __u8 flags,
+ __u16 ssn);
+struct sctp_chunk *sctp_make_ecne(const struct sctp_association *,
+ const __u32);
+struct sctp_chunk *sctp_make_sack(const struct sctp_association *);
+struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc,
+ const struct sctp_chunk *chunk);
+struct sctp_chunk *sctp_make_shutdown_ack(const struct sctp_association *asoc,
+ const struct sctp_chunk *);
+struct sctp_chunk *sctp_make_shutdown_complete(const struct sctp_association *,
+ const struct sctp_chunk *);
+void sctp_init_cause(struct sctp_chunk *, __be16 cause, size_t);
+struct sctp_chunk *sctp_make_abort(const struct sctp_association *,
+ const struct sctp_chunk *,
+ const size_t hint);
+struct sctp_chunk *sctp_make_abort_no_data(const struct sctp_association *,
+ const struct sctp_chunk *,
+ __u32 tsn);
+struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *,
+ const struct msghdr *, size_t msg_len);
+struct sctp_chunk *sctp_make_abort_violation(const struct sctp_association *,
+ const struct sctp_chunk *,
+ const __u8 *,
+ const size_t );
+struct sctp_chunk *sctp_make_violation_paramlen(const struct sctp_association *,
+ const struct sctp_chunk *,
+ struct sctp_paramhdr *);
+struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *,
+ const struct sctp_transport *);
+struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *,
+ const struct sctp_chunk *,
+ const void *payload,
+ const size_t paylen);
+struct sctp_chunk *sctp_make_op_error(const struct sctp_association *,
+ const struct sctp_chunk *chunk,
+ __be16 cause_code,
+ const void *payload,
+ size_t paylen,
+ size_t reserve_tail);
+
+struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *,
+ union sctp_addr *,
+ struct sockaddr *,
+ int, __be16);
+struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
+ union sctp_addr *addr);
+int sctp_verify_asconf(const struct sctp_association *asoc,
+ struct sctp_paramhdr *param_hdr, void *chunk_end,
+ struct sctp_paramhdr **errp);
+struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
+ struct sctp_chunk *asconf);
+int sctp_process_asconf_ack(struct sctp_association *asoc,
+ struct sctp_chunk *asconf_ack);
+struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc,
+ __u32 new_cum_tsn, size_t nstreams,
+ struct sctp_fwdtsn_skip *skiplist);
+struct sctp_chunk *sctp_make_auth(const struct sctp_association *asoc);
+
+void sctp_chunk_assign_tsn(struct sctp_chunk *);
+void sctp_chunk_assign_ssn(struct sctp_chunk *);
+
+/* Prototypes for statetable processing. */
+
+int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
+ sctp_state_t state,
+ struct sctp_endpoint *,
+ struct sctp_association *asoc,
+ void *event_arg,
+ gfp_t gfp);
+
+/* 2nd level prototypes */
+void sctp_generate_t3_rtx_event(unsigned long peer);
+void sctp_generate_heartbeat_event(unsigned long peer);
+void sctp_generate_proto_unreach_event(unsigned long peer);
+
+void sctp_ootb_pkt_free(struct sctp_packet *);
+
+struct sctp_association *sctp_unpack_cookie(const struct sctp_endpoint *,
+ const struct sctp_association *,
+ struct sctp_chunk *,
+ gfp_t gfp, int *err,
+ struct sctp_chunk **err_chk_p);
+int sctp_addip_addr_config(struct sctp_association *, sctp_param_t,
+ struct sockaddr_storage*, int);
+
+/* 3rd level prototypes */
+__u32 sctp_generate_tag(const struct sctp_endpoint *);
+__u32 sctp_generate_tsn(const struct sctp_endpoint *);
+
+/* Extern declarations for major data structures. */
+extern sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES];
+
+
+/* Get the size of a DATA chunk payload. */
+static inline __u16 sctp_data_size(struct sctp_chunk *chunk)
+{
+ __u16 size;
+
+ size = ntohs(chunk->chunk_hdr->length);
+ size -= sizeof(sctp_data_chunk_t);
+
+ return size;
+}
+
+/* Compare two TSNs */
+
+/* RFC 1982 - Serial Number Arithmetic
+ *
+ * 2. Comparison
+ * Then, s1 is said to be equal to s2 if and only if i1 is equal to i2,
+ * in all other cases, s1 is not equal to s2.
+ *
+ * s1 is said to be less than s2 if, and only if, s1 is not equal to s2,
+ * and
+ *
+ * (i1 < i2 and i2 - i1 < 2^(SERIAL_BITS - 1)) or
+ * (i1 > i2 and i1 - i2 > 2^(SERIAL_BITS - 1))
+ *
+ * s1 is said to be greater than s2 if, and only if, s1 is not equal to
+ * s2, and
+ *
+ * (i1 < i2 and i2 - i1 > 2^(SERIAL_BITS - 1)) or
+ * (i1 > i2 and i1 - i2 < 2^(SERIAL_BITS - 1))
+ */
+
+/*
+ * RFC 2960
+ * 1.6 Serial Number Arithmetic
+ *
+ * Comparisons and arithmetic on TSNs in this document SHOULD use Serial
+ * Number Arithmetic as defined in [RFC1982] where SERIAL_BITS = 32.
+ */
+
+enum {
+ TSN_SIGN_BIT = (1<<31)
+};
+
+static inline int TSN_lt(__u32 s, __u32 t)
+{
+ return ((s) - (t)) & TSN_SIGN_BIT;
+}
+
+static inline int TSN_lte(__u32 s, __u32 t)
+{
+ return ((s) == (t)) || (((s) - (t)) & TSN_SIGN_BIT);
+}
+
+/* Compare two SSNs */
+
+/*
+ * RFC 2960
+ * 1.6 Serial Number Arithmetic
+ *
+ * Comparisons and arithmetic on Stream Sequence Numbers in this document
+ * SHOULD use Serial Number Arithmetic as defined in [RFC1982] where
+ * SERIAL_BITS = 16.
+ */
+enum {
+ SSN_SIGN_BIT = (1<<15)
+};
+
+static inline int SSN_lt(__u16 s, __u16 t)
+{
+ return ((s) - (t)) & SSN_SIGN_BIT;
+}
+
+static inline int SSN_lte(__u16 s, __u16 t)
+{
+ return ((s) == (t)) || (((s) - (t)) & SSN_SIGN_BIT);
+}
+
+/*
+ * ADDIP 3.1.1
+ * The valid range of Serial Number is from 0 to 4294967295 (2**32 - 1). Serial
+ * Numbers wrap back to 0 after reaching 4294967295.
+ */
+enum {
+ ADDIP_SERIAL_SIGN_BIT = (1<<31)
+};
+
+static inline int ADDIP_SERIAL_gte(__u16 s, __u16 t)
+{
+ return ((s) == (t)) || (((t) - (s)) & ADDIP_SERIAL_SIGN_BIT);
+}
+
+/* Check VTAG of the packet matches the sender's own tag. */
+static inline int
+sctp_vtag_verify(const struct sctp_chunk *chunk,
+ const struct sctp_association *asoc)
+{
+ /* RFC 2960 Sec 8.5 When receiving an SCTP packet, the endpoint
+ * MUST ensure that the value in the Verification Tag field of
+ * the received SCTP packet matches its own Tag. If the received
+ * Verification Tag value does not match the receiver's own
+ * tag value, the receiver shall silently discard the packet...
+ */
+ if (ntohl(chunk->sctp_hdr->vtag) == asoc->c.my_vtag)
+ return 1;
+
+ return 0;
+}
+
+/* Check VTAG of the packet matches the sender's own tag and the T bit is
+ * not set, OR its peer's tag and the T bit is set in the Chunk Flags.
+ */
+static inline int
+sctp_vtag_verify_either(const struct sctp_chunk *chunk,
+ const struct sctp_association *asoc)
+{
+ /* RFC 2960 Section 8.5.1, sctpimpguide Section 2.41
+ *
+ * B) The receiver of a ABORT MUST accept the packet
+ * if the Verification Tag field of the packet matches its own tag
+ * and the T bit is not set
+ * OR
+ * it is set to its peer's tag and the T bit is set in the Chunk
+ * Flags.
+ * Otherwise, the receiver MUST silently discard the packet
+ * and take no further action.
+ *
+ * C) The receiver of a SHUTDOWN COMPLETE shall accept the packet
+ * if the Verification Tag field of the packet matches its own tag
+ * and the T bit is not set
+ * OR
+ * it is set to its peer's tag and the T bit is set in the Chunk
+ * Flags.
+ * Otherwise, the receiver MUST silently discard the packet
+ * and take no further action. An endpoint MUST ignore the
+ * SHUTDOWN COMPLETE if it is not in the SHUTDOWN-ACK-SENT state.
+ */
+ if ((!sctp_test_T_bit(chunk) &&
+ (ntohl(chunk->sctp_hdr->vtag) == asoc->c.my_vtag)) ||
+ (sctp_test_T_bit(chunk) && asoc->c.peer_vtag &&
+ (ntohl(chunk->sctp_hdr->vtag) == asoc->c.peer_vtag))) {
+ return 1;
+ }
+
+ return 0;
+}
+
+#endif /* __sctp_sm_h__ */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
new file mode 100644
index 00000000..88949a99
--- /dev/null
+++ b/include/net/sctp/structs.h
@@ -0,0 +1,2037 @@
+/* SCTP kernel implementation
+ * (C) Copyright IBM Corp. 2001, 2004
+ * Copyright (c) 1999-2000 Cisco, Inc.
+ * Copyright (c) 1999-2001 Motorola, Inc.
+ * Copyright (c) 2001 Intel Corp.
+ *
+ * This file is part of the SCTP kernel implementation
+ *
+ * This SCTP implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This SCTP implementation is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * ************************
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Please send any bug reports or fixes you make to the
+ * email addresses:
+ * lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *
+ * Or submit a bug report through the following website:
+ * http://www.sf.net/projects/lksctp
+ *
+ * Written or modified by:
+ * Randall Stewart <randall@sctp.chicago.il.us>
+ * Ken Morneau <kmorneau@cisco.com>
+ * Qiaobing Xie <qxie1@email.mot.com>
+ * La Monte H.P. Yarroll <piggy@acm.org>
+ * Karl Knutson <karl@athena.chicago.il.us>
+ * Jon Grimm <jgrimm@us.ibm.com>
+ * Xingang Guo <xingang.guo@intel.com>
+ * Hui Huang <hui.huang@nokia.com>
+ * Sridhar Samudrala <sri@us.ibm.com>
+ * Daisy Chang <daisyc@us.ibm.com>
+ * Dajiang Zhang <dajiang.zhang@nokia.com>
+ * Ardelle Fan <ardelle.fan@intel.com>
+ * Ryan Layer <rmlayer@us.ibm.com>
+ * Anup Pemmaiah <pemmaiah@cc.usu.edu>
+ * Kevin Gao <kevin.gao@intel.com>
+ *
+ * Any bugs reported given to us we will try to fix... any fixes shared will
+ * be incorporated into the next SCTP release.
+ */
+
+#ifndef __sctp_structs_h__
+#define __sctp_structs_h__
+
+#include <linux/time.h> /* We get struct timespec. */
+#include <linux/socket.h> /* linux/in.h needs this!! */
+#include <linux/in.h> /* We get struct sockaddr_in. */
+#include <linux/in6.h> /* We get struct in6_addr */
+#include <linux/ipv6.h>
+#include <asm/param.h> /* We get MAXHOSTNAMELEN. */
+#include <linux/atomic.h> /* This gets us atomic counters. */
+#include <linux/skbuff.h> /* We need sk_buff_head. */
+#include <linux/workqueue.h> /* We need tq_struct. */
+#include <linux/sctp.h> /* We need sctp* header structs. */
+#include <net/sctp/auth.h> /* We need auth specific structs */
+
+/* A convenience structure for handling sockaddr structures.
+ * We should wean ourselves off this.
+ */
+union sctp_addr {
+ struct sockaddr_in v4;
+ struct sockaddr_in6 v6;
+ struct sockaddr sa;
+};
+
+/* Forward declarations for data structures. */
+struct sctp_globals;
+struct sctp_endpoint;
+struct sctp_association;
+struct sctp_transport;
+struct sctp_packet;
+struct sctp_chunk;
+struct sctp_inq;
+struct sctp_outq;
+struct sctp_bind_addr;
+struct sctp_ulpq;
+struct sctp_ep_common;
+struct sctp_ssnmap;
+struct crypto_hash;
+
+
+#include <net/sctp/tsnmap.h>
+#include <net/sctp/ulpevent.h>
+#include <net/sctp/ulpqueue.h>
+
+/* Structures useful for managing bind/connect. */
+
+struct sctp_bind_bucket {
+ unsigned short port;
+ unsigned short fastreuse;
+ struct hlist_node node;
+ struct hlist_head owner;
+};
+
+struct sctp_bind_hashbucket {
+ spinlock_t lock;
+ struct hlist_head chain;
+};
+
+/* Used for hashing all associations. */
+struct sctp_hashbucket {
+ rwlock_t lock;
+ struct hlist_head chain;
+} __attribute__((__aligned__(8)));
+
+
+/* The SCTP globals structure. */
+extern struct sctp_globals {
+ /* RFC2960 Section 14. Suggested SCTP Protocol Parameter Values
+ *
+ * The following protocol parameters are RECOMMENDED:
+ *
+ * RTO.Initial - 3 seconds
+ * RTO.Min - 1 second
+ * RTO.Max - 60 seconds
+ * RTO.Alpha - 1/8 (3 when converted to right shifts.)
+ * RTO.Beta - 1/4 (2 when converted to right shifts.)
+ */
+ unsigned int rto_initial;
+ unsigned int rto_min;
+ unsigned int rto_max;
+
+ /* Note: rto_alpha and rto_beta are really defined as inverse
+ * powers of two to facilitate integer operations.
+ */
+ int rto_alpha;
+ int rto_beta;
+
+ /* Max.Burst - 4 */
+ int max_burst;
+
+ /* Whether Cookie Preservative is enabled(1) or not(0) */
+ int cookie_preserve_enable;
+
+ /* Valid.Cookie.Life - 60 seconds */
+ unsigned int valid_cookie_life;
+
+ /* Delayed SACK timeout 200ms default*/
+ unsigned int sack_timeout;
+
+ /* HB.interval - 30 seconds */
+ unsigned int hb_interval;
+
+ /* Association.Max.Retrans - 10 attempts
+ * Path.Max.Retrans - 5 attempts (per destination address)
+ * Max.Init.Retransmits - 8 attempts
+ */
+ int max_retrans_association;
+ int max_retrans_path;
+ int max_retrans_init;
+
+ /*
+ * Policy for preforming sctp/socket accounting
+ * 0 - do socket level accounting, all assocs share sk_sndbuf
+ * 1 - do sctp accounting, each asoc may use sk_sndbuf bytes
+ */
+ int sndbuf_policy;
+
+ /*
+ * Policy for preforming sctp/socket accounting
+ * 0 - do socket level accounting, all assocs share sk_rcvbuf
+ * 1 - do sctp accounting, each asoc may use sk_rcvbuf bytes
+ */
+ int rcvbuf_policy;
+
+ /* The following variables are implementation specific. */
+
+ /* Default initialization values to be applied to new associations. */
+ __u16 max_instreams;
+ __u16 max_outstreams;
+
+ /* This is a list of groups of functions for each address
+ * family that we support.
+ */
+ struct list_head address_families;
+
+ /* This is the hash of all endpoints. */
+ int ep_hashsize;
+ struct sctp_hashbucket *ep_hashtable;
+
+ /* This is the hash of all associations. */
+ int assoc_hashsize;
+ struct sctp_hashbucket *assoc_hashtable;
+
+ /* This is the sctp port control hash. */
+ int port_hashsize;
+ struct sctp_bind_hashbucket *port_hashtable;
+
+ /* This is the global local address list.
+ * We actively maintain this complete list of addresses on
+ * the system by catching address add/delete events.
+ *
+ * It is a list of sctp_sockaddr_entry.
+ */
+ struct list_head local_addr_list;
+ int default_auto_asconf;
+ struct list_head addr_waitq;
+ struct timer_list addr_wq_timer;
+ struct list_head auto_asconf_splist;
+ spinlock_t addr_wq_lock;
+
+ /* Lock that protects the local_addr_list writers */
+ spinlock_t addr_list_lock;
+
+ /* Flag to indicate if addip is enabled. */
+ int addip_enable;
+ int addip_noauth_enable;
+
+ /* Flag to indicate if PR-SCTP is enabled. */
+ int prsctp_enable;
+
+ /* Flag to idicate if SCTP-AUTH is enabled */
+ int auth_enable;
+
+ /*
+ * Policy to control SCTP IPv4 address scoping
+ * 0 - Disable IPv4 address scoping
+ * 1 - Enable IPv4 address scoping
+ * 2 - Selectively allow only IPv4 private addresses
+ * 3 - Selectively allow only IPv4 link local address
+ */
+ int ipv4_scope_policy;
+
+ /* Flag to indicate whether computing and verifying checksum
+ * is disabled. */
+ bool checksum_disable;
+
+ /* Threshold for rwnd update SACKS. Receive buffer shifted this many
+ * bits is an indicator of when to send and window update SACK.
+ */
+ int rwnd_update_shift;
+
+ /* Threshold for autoclose timeout, in seconds. */
+ unsigned long max_autoclose;
+} sctp_globals;
+
+#define sctp_rto_initial (sctp_globals.rto_initial)
+#define sctp_rto_min (sctp_globals.rto_min)
+#define sctp_rto_max (sctp_globals.rto_max)
+#define sctp_rto_alpha (sctp_globals.rto_alpha)
+#define sctp_rto_beta (sctp_globals.rto_beta)
+#define sctp_max_burst (sctp_globals.max_burst)
+#define sctp_valid_cookie_life (sctp_globals.valid_cookie_life)
+#define sctp_cookie_preserve_enable (sctp_globals.cookie_preserve_enable)
+#define sctp_max_retrans_association (sctp_globals.max_retrans_association)
+#define sctp_sndbuf_policy (sctp_globals.sndbuf_policy)
+#define sctp_rcvbuf_policy (sctp_globals.rcvbuf_policy)
+#define sctp_max_retrans_path (sctp_globals.max_retrans_path)
+#define sctp_max_retrans_init (sctp_globals.max_retrans_init)
+#define sctp_sack_timeout (sctp_globals.sack_timeout)
+#define sctp_hb_interval (sctp_globals.hb_interval)
+#define sctp_max_instreams (sctp_globals.max_instreams)
+#define sctp_max_outstreams (sctp_globals.max_outstreams)
+#define sctp_address_families (sctp_globals.address_families)
+#define sctp_ep_hashsize (sctp_globals.ep_hashsize)
+#define sctp_ep_hashtable (sctp_globals.ep_hashtable)
+#define sctp_assoc_hashsize (sctp_globals.assoc_hashsize)
+#define sctp_assoc_hashtable (sctp_globals.assoc_hashtable)
+#define sctp_port_hashsize (sctp_globals.port_hashsize)
+#define sctp_port_hashtable (sctp_globals.port_hashtable)
+#define sctp_local_addr_list (sctp_globals.local_addr_list)
+#define sctp_local_addr_lock (sctp_globals.addr_list_lock)
+#define sctp_auto_asconf_splist (sctp_globals.auto_asconf_splist)
+#define sctp_addr_waitq (sctp_globals.addr_waitq)
+#define sctp_addr_wq_timer (sctp_globals.addr_wq_timer)
+#define sctp_addr_wq_lock (sctp_globals.addr_wq_lock)
+#define sctp_default_auto_asconf (sctp_globals.default_auto_asconf)
+#define sctp_scope_policy (sctp_globals.ipv4_scope_policy)
+#define sctp_addip_enable (sctp_globals.addip_enable)
+#define sctp_addip_noauth (sctp_globals.addip_noauth_enable)
+#define sctp_prsctp_enable (sctp_globals.prsctp_enable)
+#define sctp_auth_enable (sctp_globals.auth_enable)
+#define sctp_checksum_disable (sctp_globals.checksum_disable)
+#define sctp_rwnd_upd_shift (sctp_globals.rwnd_update_shift)
+#define sctp_max_autoclose (sctp_globals.max_autoclose)
+
+/* SCTP Socket type: UDP or TCP style. */
+typedef enum {
+ SCTP_SOCKET_UDP = 0,
+ SCTP_SOCKET_UDP_HIGH_BANDWIDTH,
+ SCTP_SOCKET_TCP
+} sctp_socket_type_t;
+
+/* Per socket SCTP information. */
+struct sctp_sock {
+ /* inet_sock has to be the first member of sctp_sock */
+ struct inet_sock inet;
+ /* What kind of a socket is this? */
+ sctp_socket_type_t type;
+
+ /* PF_ family specific functions. */
+ struct sctp_pf *pf;
+
+ /* Access to HMAC transform. */
+ struct crypto_hash *hmac;
+
+ /* What is our base endpointer? */
+ struct sctp_endpoint *ep;
+
+ struct sctp_bind_bucket *bind_hash;
+ /* Various Socket Options. */
+ __u16 default_stream;
+ __u32 default_ppid;
+ __u16 default_flags;
+ __u32 default_context;
+ __u32 default_timetolive;
+ __u32 default_rcv_context;
+ int max_burst;
+
+ /* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
+ * the destination address every heartbeat interval. This value
+ * will be inherited by all new associations.
+ */
+ __u32 hbinterval;
+
+ /* This is the max_retrans value for new associations. */
+ __u16 pathmaxrxt;
+
+ /* The initial Path MTU to use for new associations. */
+ __u32 pathmtu;
+
+ /* The default SACK delay timeout for new associations. */
+ __u32 sackdelay;
+ __u32 sackfreq;
+
+ /* Flags controlling Heartbeat, SACK delay, and Path MTU Discovery. */
+ __u32 param_flags;
+
+ struct sctp_initmsg initmsg;
+ struct sctp_rtoinfo rtoinfo;
+ struct sctp_paddrparams paddrparam;
+ struct sctp_event_subscribe subscribe;
+ struct sctp_assocparams assocparams;
+ int user_frag;
+ __u32 autoclose;
+ __u8 nodelay;
+ __u8 disable_fragments;
+ __u8 v4mapped;
+ __u8 frag_interleave;
+ __u32 adaptation_ind;
+ __u32 pd_point;
+
+ atomic_t pd_mode;
+ /* Receive to here while partial delivery is in effect. */
+ struct sk_buff_head pd_lobby;
+ struct list_head auto_asconf_list;
+ int do_auto_asconf;
+};
+
+static inline struct sctp_sock *sctp_sk(const struct sock *sk)
+{
+ return (struct sctp_sock *)sk;
+}
+
+static inline struct sock *sctp_opt2sk(const struct sctp_sock *sp)
+{
+ return (struct sock *)sp;
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+struct sctp6_sock {
+ struct sctp_sock sctp;
+ struct ipv6_pinfo inet6;
+};
+#endif /* CONFIG_IPV6 */
+
+
+/* This is our APPLICATION-SPECIFIC state cookie.
+ * THIS IS NOT DICTATED BY THE SPECIFICATION.
+ */
+/* These are the parts of an association which we send in the cookie.
+ * Most of these are straight out of:
+ * RFC2960 12.2 Parameters necessary per association (i.e. the TCB)
+ *
+ */
+
+struct sctp_cookie {
+
+ /* My : Tag expected in every inbound packet and sent
+ * Verification: in the INIT or INIT ACK chunk.
+ * Tag :
+ */
+ __u32 my_vtag;
+
+ /* Peer's : Tag expected in every outbound packet except
+ * Verification: in the INIT chunk.
+ * Tag :
+ */
+ __u32 peer_vtag;
+
+ /* The rest of these are not from the spec, but really need to
+ * be in the cookie.
+ */
+
+ /* My Tie Tag : Assist in discovering a restarting association. */
+ __u32 my_ttag;
+
+ /* Peer's Tie Tag: Assist in discovering a restarting association. */
+ __u32 peer_ttag;
+
+ /* When does this cookie expire? */
+ struct timeval expiration;
+
+ /* Number of inbound/outbound streams which are set
+ * and negotiated during the INIT process.
+ */
+ __u16 sinit_num_ostreams;
+ __u16 sinit_max_instreams;
+
+ /* This is the first sequence number I used. */
+ __u32 initial_tsn;
+
+ /* This holds the originating address of the INIT packet. */
+ union sctp_addr peer_addr;
+
+ /* IG Section 2.35.3
+ * Include the source port of the INIT-ACK
+ */
+ __u16 my_port;
+
+ __u8 prsctp_capable;
+
+ /* Padding for future use */
+ __u8 padding;
+
+ __u32 adaptation_ind;
+
+ __u8 auth_random[sizeof(sctp_paramhdr_t) + SCTP_AUTH_RANDOM_LENGTH];
+ __u8 auth_hmacs[SCTP_AUTH_NUM_HMACS * sizeof(__u16) + 2];
+ __u8 auth_chunks[sizeof(sctp_paramhdr_t) + SCTP_AUTH_MAX_CHUNKS];
+
+ /* This is a shim for my peer's INIT packet, followed by
+ * a copy of the raw address list of the association.
+ * The length of the raw address list is saved in the
+ * raw_addr_list_len field, which will be used at the time when
+ * the association TCB is re-constructed from the cookie.
+ */
+ __u32 raw_addr_list_len;
+ struct sctp_init_chunk peer_init[0];
+};
+
+
+/* The format of our cookie that we send to our peer. */
+struct sctp_signed_cookie {
+ __u8 signature[SCTP_SECRET_SIZE];
+ __u32 __pad; /* force sctp_cookie alignment to 64 bits */
+ struct sctp_cookie c;
+} __packed;
+
+/* This is another convenience type to allocate memory for address
+ * params for the maximum size and pass such structures around
+ * internally.
+ */
+union sctp_addr_param {
+ struct sctp_paramhdr p;
+ struct sctp_ipv4addr_param v4;
+ struct sctp_ipv6addr_param v6;
+};
+
+/* A convenience type to allow walking through the various
+ * parameters and avoid casting all over the place.
+ */
+union sctp_params {
+ void *v;
+ struct sctp_paramhdr *p;
+ struct sctp_cookie_preserve_param *life;
+ struct sctp_hostname_param *dns;
+ struct sctp_cookie_param *cookie;
+ struct sctp_supported_addrs_param *sat;
+ struct sctp_ipv4addr_param *v4;
+ struct sctp_ipv6addr_param *v6;
+ union sctp_addr_param *addr;
+ struct sctp_adaptation_ind_param *aind;
+ struct sctp_supported_ext_param *ext;
+ struct sctp_random_param *random;
+ struct sctp_chunks_param *chunks;
+ struct sctp_hmac_algo_param *hmac_algo;
+ struct sctp_addip_param *addip;
+};
+
+/* RFC 2960. Section 3.3.5 Heartbeat.
+ * Heartbeat Information: variable length
+ * The Sender-specific Heartbeat Info field should normally include
+ * information about the sender's current time when this HEARTBEAT
+ * chunk is sent and the destination transport address to which this
+ * HEARTBEAT is sent (see Section 8.3).
+ */
+typedef struct sctp_sender_hb_info {
+ struct sctp_paramhdr param_hdr;
+ union sctp_addr daddr;
+ unsigned long sent_at;
+ __u64 hb_nonce;
+} __packed sctp_sender_hb_info_t;
+
+/*
+ * RFC 2960 1.3.2 Sequenced Delivery within Streams
+ *
+ * The term "stream" is used in SCTP to refer to a sequence of user
+ * messages that are to be delivered to the upper-layer protocol in
+ * order with respect to other messages within the same stream. This is
+ * in contrast to its usage in TCP, where it refers to a sequence of
+ * bytes (in this document a byte is assumed to be eight bits).
+ * ...
+ *
+ * This is the structure we use to track both our outbound and inbound
+ * SSN, or Stream Sequence Numbers.
+ */
+
+struct sctp_stream {
+ __u16 *ssn;
+ unsigned int len;
+};
+
+struct sctp_ssnmap {
+ struct sctp_stream in;
+ struct sctp_stream out;
+ int malloced;
+};
+
+struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out,
+ gfp_t gfp);
+void sctp_ssnmap_free(struct sctp_ssnmap *map);
+void sctp_ssnmap_clear(struct sctp_ssnmap *map);
+
+/* What is the current SSN number for this stream? */
+static inline __u16 sctp_ssn_peek(struct sctp_stream *stream, __u16 id)
+{
+ return stream->ssn[id];
+}
+
+/* Return the next SSN number for this stream. */
+static inline __u16 sctp_ssn_next(struct sctp_stream *stream, __u16 id)
+{
+ return stream->ssn[id]++;
+}
+
+/* Skip over this ssn and all below. */
+static inline void sctp_ssn_skip(struct sctp_stream *stream, __u16 id,
+ __u16 ssn)
+{
+ stream->ssn[id] = ssn+1;
+}
+
+/*
+ * Pointers to address related SCTP functions.
+ * (i.e. things that depend on the address family.)
+ */
+struct sctp_af {
+ int (*sctp_xmit) (struct sk_buff *skb,
+ struct sctp_transport *);
+ int (*setsockopt) (struct sock *sk,
+ int level,
+ int optname,
+ char __user *optval,
+ unsigned int optlen);
+ int (*getsockopt) (struct sock *sk,
+ int level,
+ int optname,
+ char __user *optval,
+ int __user *optlen);
+ int (*compat_setsockopt) (struct sock *sk,
+ int level,
+ int optname,
+ char __user *optval,
+ unsigned int optlen);
+ int (*compat_getsockopt) (struct sock *sk,
+ int level,
+ int optname,
+ char __user *optval,
+ int __user *optlen);
+ void (*get_dst) (struct sctp_transport *t,
+ union sctp_addr *saddr,
+ struct flowi *fl,
+ struct sock *sk);
+ void (*get_saddr) (struct sctp_sock *sk,
+ struct sctp_transport *t,
+ struct flowi *fl);
+ void (*copy_addrlist) (struct list_head *,
+ struct net_device *);
+ int (*cmp_addr) (const union sctp_addr *addr1,
+ const union sctp_addr *addr2);
+ void (*addr_copy) (union sctp_addr *dst,
+ union sctp_addr *src);
+ void (*from_skb) (union sctp_addr *,
+ struct sk_buff *skb,
+ int saddr);
+ void (*from_sk) (union sctp_addr *,
+ struct sock *sk);
+ void (*to_sk_saddr) (union sctp_addr *,
+ struct sock *sk);
+ void (*to_sk_daddr) (union sctp_addr *,
+ struct sock *sk);
+ void (*from_addr_param) (union sctp_addr *,
+ union sctp_addr_param *,
+ __be16 port, int iif);
+ int (*to_addr_param) (const union sctp_addr *,
+ union sctp_addr_param *);
+ int (*addr_valid) (union sctp_addr *,
+ struct sctp_sock *,
+ const struct sk_buff *);
+ sctp_scope_t (*scope) (union sctp_addr *);
+ void (*inaddr_any) (union sctp_addr *, __be16);
+ int (*is_any) (const union sctp_addr *);
+ int (*available) (union sctp_addr *,
+ struct sctp_sock *);
+ int (*skb_iif) (const struct sk_buff *sk);
+ int (*is_ce) (const struct sk_buff *sk);
+ void (*seq_dump_addr)(struct seq_file *seq,
+ union sctp_addr *addr);
+ void (*ecn_capable)(struct sock *sk);
+ __u16 net_header_len;
+ int sockaddr_len;
+ sa_family_t sa_family;
+ struct list_head list;
+};
+
+struct sctp_af *sctp_get_af_specific(sa_family_t);
+int sctp_register_af(struct sctp_af *);
+
+/* Protocol family functions. */
+struct sctp_pf {
+ void (*event_msgname)(struct sctp_ulpevent *, char *, int *);
+ void (*skb_msgname) (struct sk_buff *, char *, int *);
+ int (*af_supported) (sa_family_t, struct sctp_sock *);
+ int (*cmp_addr) (const union sctp_addr *,
+ const union sctp_addr *,
+ struct sctp_sock *);
+ int (*bind_verify) (struct sctp_sock *, union sctp_addr *);
+ int (*send_verify) (struct sctp_sock *, union sctp_addr *);
+ int (*supported_addrs)(const struct sctp_sock *, __be16 *);
+ struct sock *(*create_accept_sk) (struct sock *sk,
+ struct sctp_association *asoc);
+ void (*addr_v4map) (struct sctp_sock *, union sctp_addr *);
+ struct sctp_af *af;
+};
+
+
+/* Structure to track chunk fragments that have been acked, but peer
+ * fragments of the same message have not.
+ */
+struct sctp_datamsg {
+ /* Chunks waiting to be submitted to lower layer. */
+ struct list_head chunks;
+ /* Reference counting. */
+ atomic_t refcnt;
+ /* When is this message no longer interesting to the peer? */
+ unsigned long expires_at;
+ /* Did the messenge fail to send? */
+ int send_error;
+ u8 send_failed:1,
+ can_abandon:1, /* can chunks from this message can be abandoned. */
+ can_delay; /* should this message be Nagle delayed */
+};
+
+struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *,
+ struct sctp_sndrcvinfo *,
+ struct msghdr *, int len);
+void sctp_datamsg_free(struct sctp_datamsg *);
+void sctp_datamsg_put(struct sctp_datamsg *);
+void sctp_chunk_fail(struct sctp_chunk *, int error);
+int sctp_chunk_abandoned(struct sctp_chunk *);
+
+/* RFC2960 1.4 Key Terms
+ *
+ * o Chunk: A unit of information within an SCTP packet, consisting of
+ * a chunk header and chunk-specific content.
+ *
+ * As a matter of convenience, we remember the SCTP common header for
+ * each chunk as well as a few other header pointers...
+ */
+struct sctp_chunk {
+ struct list_head list;
+
+ atomic_t refcnt;
+
+ /* This is our link to the per-transport transmitted list. */
+ struct list_head transmitted_list;
+
+ /* This field is used by chunks that hold fragmented data.
+ * For the first fragment this is the list that holds the rest of
+ * fragments. For the remaining fragments, this is the link to the
+ * frag_list maintained in the first fragment.
+ */
+ struct list_head frag_list;
+
+ /* This points to the sk_buff containing the actual data. */
+ struct sk_buff *skb;
+
+ /* These are the SCTP headers by reverse order in a packet.
+ * Note that some of these may happen more than once. In that
+ * case, we point at the "current" one, whatever that means
+ * for that level of header.
+ */
+
+ /* We point this at the FIRST TLV parameter to chunk_hdr. */
+ union sctp_params param_hdr;
+ union {
+ __u8 *v;
+ struct sctp_datahdr *data_hdr;
+ struct sctp_inithdr *init_hdr;
+ struct sctp_sackhdr *sack_hdr;
+ struct sctp_heartbeathdr *hb_hdr;
+ struct sctp_sender_hb_info *hbs_hdr;
+ struct sctp_shutdownhdr *shutdown_hdr;
+ struct sctp_signed_cookie *cookie_hdr;
+ struct sctp_ecnehdr *ecne_hdr;
+ struct sctp_cwrhdr *ecn_cwr_hdr;
+ struct sctp_errhdr *err_hdr;
+ struct sctp_addiphdr *addip_hdr;
+ struct sctp_fwdtsn_hdr *fwdtsn_hdr;
+ struct sctp_authhdr *auth_hdr;
+ } subh;
+
+ __u8 *chunk_end;
+
+ struct sctp_chunkhdr *chunk_hdr;
+ struct sctphdr *sctp_hdr;
+
+ /* This needs to be recoverable for SCTP_SEND_FAILED events. */
+ struct sctp_sndrcvinfo sinfo;
+
+ /* Which association does this belong to? */
+ struct sctp_association *asoc;
+
+ /* What endpoint received this chunk? */
+ struct sctp_ep_common *rcvr;
+
+ /* We fill this in if we are calculating RTT. */
+ unsigned long sent_at;
+
+ /* What is the origin IP address for this chunk? */
+ union sctp_addr source;
+ /* Destination address for this chunk. */
+ union sctp_addr dest;
+
+ /* For outbound message, track all fragments for SEND_FAILED. */
+ struct sctp_datamsg *msg;
+
+ /* For an inbound chunk, this tells us where it came from.
+ * For an outbound chunk, it tells us where we'd like it to
+ * go. It is NULL if we have no preference.
+ */
+ struct sctp_transport *transport;
+
+ /* SCTP-AUTH: For the special case inbound processing of COOKIE-ECHO
+ * we need save a pointer to the AUTH chunk, since the SCTP-AUTH
+ * spec violates the principle premis that all chunks are processed
+ * in order.
+ */
+ struct sk_buff *auth_chunk;
+
+#define SCTP_CAN_FRTX 0x0
+#define SCTP_NEED_FRTX 0x1
+#define SCTP_DONT_FRTX 0x2
+ __u16 rtt_in_progress:1, /* This chunk used for RTT calc? */
+ has_tsn:1, /* Does this chunk have a TSN yet? */
+ has_ssn:1, /* Does this chunk have a SSN yet? */
+ singleton:1, /* Only chunk in the packet? */
+ end_of_packet:1, /* Last chunk in the packet? */
+ ecn_ce_done:1, /* Have we processed the ECN CE bit? */
+ pdiscard:1, /* Discard the whole packet now? */
+ tsn_gap_acked:1, /* Is this chunk acked by a GAP ACK? */
+ data_accepted:1, /* At least 1 chunk accepted */
+ auth:1, /* IN: was auth'ed | OUT: needs auth */
+ has_asconf:1, /* IN: have seen an asconf before */
+ tsn_missing_report:2, /* Data chunk missing counter. */
+ fast_retransmit:2; /* Is this chunk fast retransmitted? */
+};
+
+void sctp_chunk_hold(struct sctp_chunk *);
+void sctp_chunk_put(struct sctp_chunk *);
+int sctp_user_addto_chunk(struct sctp_chunk *chunk, int off, int len,
+ struct iovec *data);
+void sctp_chunk_free(struct sctp_chunk *);
+void *sctp_addto_chunk(struct sctp_chunk *, int len, const void *data);
+void *sctp_addto_chunk_fixed(struct sctp_chunk *, int len, const void *data);
+struct sctp_chunk *sctp_chunkify(struct sk_buff *,
+ const struct sctp_association *,
+ struct sock *);
+void sctp_init_addrs(struct sctp_chunk *, union sctp_addr *,
+ union sctp_addr *);
+const union sctp_addr *sctp_source(const struct sctp_chunk *chunk);
+
+enum {
+ SCTP_ADDR_NEW, /* new address added to assoc/ep */
+ SCTP_ADDR_SRC, /* address can be used as source */
+ SCTP_ADDR_DEL, /* address about to be deleted */
+};
+
+/* This is a structure for holding either an IPv6 or an IPv4 address. */
+struct sctp_sockaddr_entry {
+ struct list_head list;
+ struct rcu_head rcu;
+ union sctp_addr a;
+ __u8 state;
+ __u8 valid;
+};
+
+#define SCTP_ADDRESS_TICK_DELAY 500
+
+typedef struct sctp_chunk *(sctp_packet_phandler_t)(struct sctp_association *);
+
+/* This structure holds lists of chunks as we are assembling for
+ * transmission.
+ */
+struct sctp_packet {
+ /* These are the SCTP header values (host order) for the packet. */
+ __u16 source_port;
+ __u16 destination_port;
+ __u32 vtag;
+
+ /* This contains the payload chunks. */
+ struct list_head chunk_list;
+
+ /* This is the overhead of the sctp and ip headers. */
+ size_t overhead;
+ /* This is the total size of all chunks INCLUDING padding. */
+ size_t size;
+
+ /* The packet is destined for this transport address.
+ * The function we finally use to pass down to the next lower
+ * layer lives in the transport structure.
+ */
+ struct sctp_transport *transport;
+
+ /* pointer to the auth chunk for this packet */
+ struct sctp_chunk *auth;
+
+ u8 has_cookie_echo:1, /* This packet contains a COOKIE-ECHO chunk. */
+ has_sack:1, /* This packet contains a SACK chunk. */
+ has_auth:1, /* This packet contains an AUTH chunk */
+ has_data:1, /* This packet contains at least 1 DATA chunk */
+ ipfragok:1, /* So let ip fragment this packet */
+ malloced:1; /* Is it malloced? */
+};
+
+struct sctp_packet *sctp_packet_init(struct sctp_packet *,
+ struct sctp_transport *,
+ __u16 sport, __u16 dport);
+struct sctp_packet *sctp_packet_config(struct sctp_packet *, __u32 vtag, int);
+sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *,
+ struct sctp_chunk *, int);
+sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *,
+ struct sctp_chunk *);
+int sctp_packet_transmit(struct sctp_packet *);
+void sctp_packet_free(struct sctp_packet *);
+
+static inline int sctp_packet_empty(struct sctp_packet *packet)
+{
+ return packet->size == packet->overhead;
+}
+
+/* This represents a remote transport address.
+ * For local transport addresses, we just use union sctp_addr.
+ *
+ * RFC2960 Section 1.4 Key Terms
+ *
+ * o Transport address: A Transport Address is traditionally defined
+ * by Network Layer address, Transport Layer protocol and Transport
+ * Layer port number. In the case of SCTP running over IP, a
+ * transport address is defined by the combination of an IP address
+ * and an SCTP port number (where SCTP is the Transport protocol).
+ *
+ * RFC2960 Section 7.1 SCTP Differences from TCP Congestion control
+ *
+ * o The sender keeps a separate congestion control parameter set for
+ * each of the destination addresses it can send to (not each
+ * source-destination pair but for each destination). The parameters
+ * should decay if the address is not used for a long enough time
+ * period.
+ *
+ */
+struct sctp_transport {
+ /* A list of transports. */
+ struct list_head transports;
+
+ /* Reference counting. */
+ atomic_t refcnt;
+ __u32 dead:1,
+ /* RTO-Pending : A flag used to track if one of the DATA
+ * chunks sent to this address is currently being
+ * used to compute a RTT. If this flag is 0,
+ * the next DATA chunk sent to this destination
+ * should be used to compute a RTT and this flag
+ * should be set. Every time the RTT
+ * calculation completes (i.e. the DATA chunk
+ * is SACK'd) clear this flag.
+ */
+ rto_pending:1,
+
+ /*
+ * hb_sent : a flag that signals that we have a pending
+ * heartbeat.
+ */
+ hb_sent:1,
+
+ /* Is the Path MTU update pending on this tranport */
+ pmtu_pending:1,
+
+ /* Is this structure kfree()able? */
+ malloced:1;
+
+ struct flowi fl;
+
+ /* This is the peer's IP address and port. */
+ union sctp_addr ipaddr;
+
+ /* These are the functions we call to handle LLP stuff. */
+ struct sctp_af *af_specific;
+
+ /* Which association do we belong to? */
+ struct sctp_association *asoc;
+
+ /* RFC2960
+ *
+ * 12.3 Per Transport Address Data
+ *
+ * For each destination transport address in the peer's
+ * address list derived from the INIT or INIT ACK chunk, a
+ * number of data elements needs to be maintained including:
+ */
+ /* RTO : The current retransmission timeout value. */
+ unsigned long rto;
+
+ __u32 rtt; /* This is the most recent RTT. */
+
+ /* RTTVAR : The current RTT variation. */
+ __u32 rttvar;
+
+ /* SRTT : The current smoothed round trip time. */
+ __u32 srtt;
+
+ /*
+ * These are the congestion stats.
+ */
+ /* cwnd : The current congestion window. */
+ __u32 cwnd; /* This is the actual cwnd. */
+
+ /* ssthresh : The current slow start threshold value. */
+ __u32 ssthresh;
+
+ /* partial : The tracking method for increase of cwnd when in
+ * bytes acked : congestion avoidance mode (see Section 6.2.2)
+ */
+ __u32 partial_bytes_acked;
+
+ /* Data that has been sent, but not acknowledged. */
+ __u32 flight_size;
+
+ __u32 burst_limited; /* Holds old cwnd when max.burst is applied */
+
+ /* Destination */
+ struct dst_entry *dst;
+ /* Source address. */
+ union sctp_addr saddr;
+
+ /* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
+ * the destination address every heartbeat interval.
+ */
+ unsigned long hbinterval;
+
+ /* SACK delay timeout */
+ unsigned long sackdelay;
+ __u32 sackfreq;
+
+ /* When was the last time (in jiffies) that we heard from this
+ * transport? We use this to pick new active and retran paths.
+ */
+ unsigned long last_time_heard;
+
+ /* Last time(in jiffies) when cwnd is reduced due to the congestion
+ * indication based on ECNE chunk.
+ */
+ unsigned long last_time_ecne_reduced;
+
+ /* This is the max_retrans value for the transport and will
+ * be initialized from the assocs value. This can be changed
+ * using SCTP_SET_PEER_ADDR_PARAMS socket option.
+ */
+ __u16 pathmaxrxt;
+
+ /* PMTU : The current known path MTU. */
+ __u32 pathmtu;
+
+ /* Flags controlling Heartbeat, SACK delay, and Path MTU Discovery. */
+ __u32 param_flags;
+
+ /* The number of times INIT has been sent on this transport. */
+ int init_sent_count;
+
+ /* state : The current state of this destination,
+ * : i.e. SCTP_ACTIVE, SCTP_INACTIVE, SCTP_UNKNOWN.
+ */
+ int state;
+
+ /* These are the error stats for this destination. */
+
+ /* Error count : The current error count for this destination. */
+ unsigned short error_count;
+
+ /* Per : A timer used by each destination.
+ * Destination :
+ * Timer :
+ *
+ * [Everywhere else in the text this is called T3-rtx. -ed]
+ */
+ struct timer_list T3_rtx_timer;
+
+ /* Heartbeat timer is per destination. */
+ struct timer_list hb_timer;
+
+ /* Timer to handle ICMP proto unreachable envets */
+ struct timer_list proto_unreach_timer;
+
+ /* Since we're using per-destination retransmission timers
+ * (see above), we're also using per-destination "transmitted"
+ * queues. This probably ought to be a private struct
+ * accessible only within the outqueue, but it's not, yet.
+ */
+ struct list_head transmitted;
+
+ /* We build bundle-able packets for this transport here. */
+ struct sctp_packet packet;
+
+ /* This is the list of transports that have chunks to send. */
+ struct list_head send_ready;
+
+ /* State information saved for SFR_CACC algorithm. The key
+ * idea in SFR_CACC is to maintain state at the sender on a
+ * per-destination basis when a changeover happens.
+ * char changeover_active;
+ * char cycling_changeover;
+ * __u32 next_tsn_at_change;
+ * char cacc_saw_newack;
+ */
+ struct {
+ /* An unsigned integer, which stores the next TSN to be
+ * used by the sender, at the moment of changeover.
+ */
+ __u32 next_tsn_at_change;
+
+ /* A flag which indicates the occurrence of a changeover */
+ char changeover_active;
+
+ /* A flag which indicates whether the change of primary is
+ * the first switch to this destination address during an
+ * active switch.
+ */
+ char cycling_changeover;
+
+ /* A temporary flag, which is used during the processing of
+ * a SACK to estimate the causative TSN(s)'s group.
+ */
+ char cacc_saw_newack;
+ } cacc;
+
+ /* 64-bit random number sent with heartbeat. */
+ __u64 hb_nonce;
+};
+
+struct sctp_transport *sctp_transport_new(const union sctp_addr *,
+ gfp_t);
+void sctp_transport_set_owner(struct sctp_transport *,
+ struct sctp_association *);
+void sctp_transport_route(struct sctp_transport *, union sctp_addr *,
+ struct sctp_sock *);
+void sctp_transport_pmtu(struct sctp_transport *, struct sock *sk);
+void sctp_transport_free(struct sctp_transport *);
+void sctp_transport_reset_timers(struct sctp_transport *);
+void sctp_transport_hold(struct sctp_transport *);
+void sctp_transport_put(struct sctp_transport *);
+void sctp_transport_update_rto(struct sctp_transport *, __u32);
+void sctp_transport_raise_cwnd(struct sctp_transport *, __u32, __u32);
+void sctp_transport_lower_cwnd(struct sctp_transport *, sctp_lower_cwnd_t);
+void sctp_transport_burst_limited(struct sctp_transport *);
+void sctp_transport_burst_reset(struct sctp_transport *);
+unsigned long sctp_transport_timeout(struct sctp_transport *);
+void sctp_transport_reset(struct sctp_transport *);
+void sctp_transport_update_pmtu(struct sctp_transport *, u32);
+void sctp_transport_immediate_rtx(struct sctp_transport *);
+
+
+/* This is the structure we use to queue packets as they come into
+ * SCTP. We write packets to it and read chunks from it.
+ */
+struct sctp_inq {
+ /* This is actually a queue of sctp_chunk each
+ * containing a partially decoded packet.
+ */
+ struct list_head in_chunk_list;
+ /* This is the packet which is currently off the in queue and is
+ * being worked on through the inbound chunk processing.
+ */
+ struct sctp_chunk *in_progress;
+
+ /* This is the delayed task to finish delivering inbound
+ * messages.
+ */
+ struct work_struct immediate;
+
+ int malloced; /* Is this structure kfree()able? */
+};
+
+void sctp_inq_init(struct sctp_inq *);
+void sctp_inq_free(struct sctp_inq *);
+void sctp_inq_push(struct sctp_inq *, struct sctp_chunk *packet);
+struct sctp_chunk *sctp_inq_pop(struct sctp_inq *);
+struct sctp_chunkhdr *sctp_inq_peek(struct sctp_inq *);
+void sctp_inq_set_th_handler(struct sctp_inq *, work_func_t);
+
+/* This is the structure we use to hold outbound chunks. You push
+ * chunks in and they automatically pop out the other end as bundled
+ * packets (it calls (*output_handler)()).
+ *
+ * This structure covers sections 6.3, 6.4, 6.7, 6.8, 6.10, 7., 8.1,
+ * and 8.2 of the v13 draft.
+ *
+ * It handles retransmissions. The connection to the timeout portion
+ * of the state machine is through sctp_..._timeout() and timeout_handler.
+ *
+ * If you feed it SACKs, it will eat them.
+ *
+ * If you give it big chunks, it will fragment them.
+ *
+ * It assigns TSN's to data chunks. This happens at the last possible
+ * instant before transmission.
+ *
+ * When free()'d, it empties itself out via output_handler().
+ */
+struct sctp_outq {
+ struct sctp_association *asoc;
+
+ /* Data pending that has never been transmitted. */
+ struct list_head out_chunk_list;
+
+ unsigned out_qlen; /* Total length of queued data chunks. */
+
+ /* Error of send failed, may used in SCTP_SEND_FAILED event. */
+ unsigned error;
+
+ /* These are control chunks we want to send. */
+ struct list_head control_chunk_list;
+
+ /* These are chunks that have been sacked but are above the
+ * CTSN, or cumulative tsn ack point.
+ */
+ struct list_head sacked;
+
+ /* Put chunks on this list to schedule them for
+ * retransmission.
+ */
+ struct list_head retransmit;
+
+ /* Put chunks on this list to save them for FWD TSN processing as
+ * they were abandoned.
+ */
+ struct list_head abandoned;
+
+ /* How many unackd bytes do we have in-flight? */
+ __u32 outstanding_bytes;
+
+ /* Are we doing fast-rtx on this queue */
+ char fast_rtx;
+
+ /* Corked? */
+ char cork;
+
+ /* Is this structure empty? */
+ char empty;
+
+ /* Are we kfree()able? */
+ char malloced;
+};
+
+void sctp_outq_init(struct sctp_association *, struct sctp_outq *);
+void sctp_outq_teardown(struct sctp_outq *);
+void sctp_outq_free(struct sctp_outq*);
+int sctp_outq_tail(struct sctp_outq *, struct sctp_chunk *chunk);
+int sctp_outq_sack(struct sctp_outq *, struct sctp_sackhdr *);
+int sctp_outq_is_empty(const struct sctp_outq *);
+void sctp_outq_restart(struct sctp_outq *);
+
+void sctp_retransmit(struct sctp_outq *, struct sctp_transport *,
+ sctp_retransmit_reason_t);
+void sctp_retransmit_mark(struct sctp_outq *, struct sctp_transport *, __u8);
+int sctp_outq_uncork(struct sctp_outq *);
+/* Uncork and flush an outqueue. */
+static inline void sctp_outq_cork(struct sctp_outq *q)
+{
+ q->cork = 1;
+}
+
+/* These bind address data fields common between endpoints and associations */
+struct sctp_bind_addr {
+
+ /* RFC 2960 12.1 Parameters necessary for the SCTP instance
+ *
+ * SCTP Port: The local SCTP port number the endpoint is
+ * bound to.
+ */
+ __u16 port;
+
+ /* RFC 2960 12.1 Parameters necessary for the SCTP instance
+ *
+ * Address List: The list of IP addresses that this instance
+ * has bound. This information is passed to one's
+ * peer(s) in INIT and INIT ACK chunks.
+ */
+ struct list_head address_list;
+
+ int malloced; /* Are we kfree()able? */
+};
+
+void sctp_bind_addr_init(struct sctp_bind_addr *, __u16 port);
+void sctp_bind_addr_free(struct sctp_bind_addr *);
+int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
+ const struct sctp_bind_addr *src,
+ sctp_scope_t scope, gfp_t gfp,
+ int flags);
+int sctp_bind_addr_dup(struct sctp_bind_addr *dest,
+ const struct sctp_bind_addr *src,
+ gfp_t gfp);
+int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
+ __u8 addr_state, gfp_t gfp);
+int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *);
+int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *,
+ struct sctp_sock *);
+int sctp_bind_addr_conflict(struct sctp_bind_addr *, const union sctp_addr *,
+ struct sctp_sock *, struct sctp_sock *);
+int sctp_bind_addr_state(const struct sctp_bind_addr *bp,
+ const union sctp_addr *addr);
+union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp,
+ const union sctp_addr *addrs,
+ int addrcnt,
+ struct sctp_sock *opt);
+union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
+ int *addrs_len,
+ gfp_t gfp);
+int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw, int len,
+ __u16 port, gfp_t gfp);
+
+sctp_scope_t sctp_scope(const union sctp_addr *);
+int sctp_in_scope(const union sctp_addr *addr, const sctp_scope_t scope);
+int sctp_is_any(struct sock *sk, const union sctp_addr *addr);
+int sctp_addr_is_valid(const union sctp_addr *addr);
+int sctp_is_ep_boundall(struct sock *sk);
+
+
+/* What type of endpoint? */
+typedef enum {
+ SCTP_EP_TYPE_SOCKET,
+ SCTP_EP_TYPE_ASSOCIATION,
+} sctp_endpoint_type_t;
+
+/*
+ * A common base class to bridge the implmentation view of a
+ * socket (usually listening) endpoint versus an association's
+ * local endpoint.
+ * This common structure is useful for several purposes:
+ * 1) Common interface for lookup routines.
+ * a) Subfunctions work for either endpoint or association
+ * b) Single interface to lookup allows hiding the lookup lock rather
+ * than acquiring it externally.
+ * 2) Common interface for the inbound chunk handling/state machine.
+ * 3) Common object handling routines for reference counting, etc.
+ * 4) Disentangle association lookup from endpoint lookup, where we
+ * do not have to find our endpoint to find our association.
+ *
+ */
+
+struct sctp_ep_common {
+ /* Fields to help us manage our entries in the hash tables. */
+ struct hlist_node node;
+ int hashent;
+
+ /* Runtime type information. What kind of endpoint is this? */
+ sctp_endpoint_type_t type;
+
+ /* Some fields to help us manage this object.
+ * refcnt - Reference count access to this object.
+ * dead - Do not attempt to use this object.
+ * malloced - Do we need to kfree this object?
+ */
+ atomic_t refcnt;
+ char dead;
+ char malloced;
+
+ /* What socket does this endpoint belong to? */
+ struct sock *sk;
+
+ /* This is where we receive inbound chunks. */
+ struct sctp_inq inqueue;
+
+ /* This substructure includes the defining parameters of the
+ * endpoint:
+ * bind_addr.port is our shared port number.
+ * bind_addr.address_list is our set of local IP addresses.
+ */
+ struct sctp_bind_addr bind_addr;
+};
+
+
+/* RFC Section 1.4 Key Terms
+ *
+ * o SCTP endpoint: The logical sender/receiver of SCTP packets. On a
+ * multi-homed host, an SCTP endpoint is represented to its peers as a
+ * combination of a set of eligible destination transport addresses to
+ * which SCTP packets can be sent and a set of eligible source
+ * transport addresses from which SCTP packets can be received.
+ * All transport addresses used by an SCTP endpoint must use the
+ * same port number, but can use multiple IP addresses. A transport
+ * address used by an SCTP endpoint must not be used by another
+ * SCTP endpoint. In other words, a transport address is unique
+ * to an SCTP endpoint.
+ *
+ * From an implementation perspective, each socket has one of these.
+ * A TCP-style socket will have exactly one association on one of
+ * these. An UDP-style socket will have multiple associations hanging
+ * off one of these.
+ */
+
+struct sctp_endpoint {
+ /* Common substructure for endpoint and association. */
+ struct sctp_ep_common base;
+
+ /* Associations: A list of current associations and mappings
+ * to the data consumers for each association. This
+ * may be in the form of a hash table or other
+ * implementation dependent structure. The data
+ * consumers may be process identification
+ * information such as file descriptors, named pipe
+ * pointer, or table pointers dependent on how SCTP
+ * is implemented.
+ */
+ /* This is really a list of struct sctp_association entries. */
+ struct list_head asocs;
+
+ /* Secret Key: A secret key used by this endpoint to compute
+ * the MAC. This SHOULD be a cryptographic quality
+ * random number with a sufficient length.
+ * Discussion in [RFC1750] can be helpful in
+ * selection of the key.
+ */
+ __u8 secret_key[SCTP_HOW_MANY_SECRETS][SCTP_SECRET_SIZE];
+ int current_key;
+ int last_key;
+ int key_changed_at;
+
+ /* digest: This is a digest of the sctp cookie. This field is
+ * only used on the receive path when we try to validate
+ * that the cookie has not been tampered with. We put
+ * this here so we pre-allocate this once and can re-use
+ * on every receive.
+ */
+ __u8 *digest;
+
+ /* sendbuf acct. policy. */
+ __u32 sndbuf_policy;
+
+ /* rcvbuf acct. policy. */
+ __u32 rcvbuf_policy;
+
+ /* SCTP AUTH: array of the HMACs that will be allocated
+ * we need this per association so that we don't serialize
+ */
+ struct crypto_hash **auth_hmacs;
+
+ /* SCTP-AUTH: hmacs for the endpoint encoded into parameter */
+ struct sctp_hmac_algo_param *auth_hmacs_list;
+
+ /* SCTP-AUTH: chunks to authenticate encoded into parameter */
+ struct sctp_chunks_param *auth_chunk_list;
+
+ /* SCTP-AUTH: endpoint shared keys */
+ struct list_head endpoint_shared_keys;
+ __u16 active_key_id;
+};
+
+/* Recover the outter endpoint structure. */
+static inline struct sctp_endpoint *sctp_ep(struct sctp_ep_common *base)
+{
+ struct sctp_endpoint *ep;
+
+ ep = container_of(base, struct sctp_endpoint, base);
+ return ep;
+}
+
+/* These are function signatures for manipulating endpoints. */
+struct sctp_endpoint *sctp_endpoint_new(struct sock *, gfp_t);
+void sctp_endpoint_free(struct sctp_endpoint *);
+void sctp_endpoint_put(struct sctp_endpoint *);
+void sctp_endpoint_hold(struct sctp_endpoint *);
+void sctp_endpoint_add_asoc(struct sctp_endpoint *, struct sctp_association *);
+struct sctp_association *sctp_endpoint_lookup_assoc(
+ const struct sctp_endpoint *ep,
+ const union sctp_addr *paddr,
+ struct sctp_transport **);
+int sctp_endpoint_is_peeled_off(struct sctp_endpoint *,
+ const union sctp_addr *);
+struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *,
+ const union sctp_addr *);
+int sctp_has_association(const union sctp_addr *laddr,
+ const union sctp_addr *paddr);
+
+int sctp_verify_init(const struct sctp_association *asoc, sctp_cid_t,
+ sctp_init_chunk_t *peer_init, struct sctp_chunk *chunk,
+ struct sctp_chunk **err_chunk);
+int sctp_process_init(struct sctp_association *, struct sctp_chunk *chunk,
+ const union sctp_addr *peer,
+ sctp_init_chunk_t *init, gfp_t gfp);
+__u32 sctp_generate_tag(const struct sctp_endpoint *);
+__u32 sctp_generate_tsn(const struct sctp_endpoint *);
+
+struct sctp_inithdr_host {
+ __u32 init_tag;
+ __u32 a_rwnd;
+ __u16 num_outbound_streams;
+ __u16 num_inbound_streams;
+ __u32 initial_tsn;
+};
+
+/* RFC2960
+ *
+ * 12. Recommended Transmission Control Block (TCB) Parameters
+ *
+ * This section details a recommended set of parameters that should
+ * be contained within the TCB for an implementation. This section is
+ * for illustrative purposes and should not be deemed as requirements
+ * on an implementation or as an exhaustive list of all parameters
+ * inside an SCTP TCB. Each implementation may need its own additional
+ * parameters for optimization.
+ */
+
+
+/* Here we have information about each individual association. */
+struct sctp_association {
+
+ /* A base structure common to endpoint and association.
+ * In this context, it represents the associations's view
+ * of the local endpoint of the association.
+ */
+ struct sctp_ep_common base;
+
+ /* Associations on the same socket. */
+ struct list_head asocs;
+
+ /* association id. */
+ sctp_assoc_t assoc_id;
+
+ /* This is our parent endpoint. */
+ struct sctp_endpoint *ep;
+
+ /* These are those association elements needed in the cookie. */
+ struct sctp_cookie c;
+
+ /* This is all information about our peer. */
+ struct {
+ /* rwnd
+ *
+ * Peer Rwnd : Current calculated value of the peer's rwnd.
+ */
+ __u32 rwnd;
+
+ /* transport_addr_list
+ *
+ * Peer : A list of SCTP transport addresses that the
+ * Transport : peer is bound to. This information is derived
+ * Address : from the INIT or INIT ACK and is used to
+ * List : associate an inbound packet with a given
+ * : association. Normally this information is
+ * : hashed or keyed for quick lookup and access
+ * : of the TCB.
+ * : The list is also initialized with the list
+ * : of addresses passed with the sctp_connectx()
+ * : call.
+ *
+ * It is a list of SCTP_transport's.
+ */
+ struct list_head transport_addr_list;
+
+ /* transport_count
+ *
+ * Peer : A count of the number of peer addresses
+ * Transport : in the Peer Transport Address List.
+ * Address :
+ * Count :
+ */
+ __u16 transport_count;
+
+ /* port
+ * The transport layer port number.
+ */
+ __u16 port;
+
+ /* primary_path
+ *
+ * Primary : This is the current primary destination
+ * Path : transport address of the peer endpoint. It
+ * : may also specify a source transport address
+ * : on this endpoint.
+ *
+ * All of these paths live on transport_addr_list.
+ *
+ * At the bakeoffs, we discovered that the intent of
+ * primaryPath is that it only changes when the ULP
+ * asks to have it changed. We add the activePath to
+ * designate the connection we are currently using to
+ * transmit new data and most control chunks.
+ */
+ struct sctp_transport *primary_path;
+
+ /* Cache the primary path address here, when we
+ * need a an address for msg_name.
+ */
+ union sctp_addr primary_addr;
+
+ /* active_path
+ * The path that we are currently using to
+ * transmit new data and most control chunks.
+ */
+ struct sctp_transport *active_path;
+
+ /* retran_path
+ *
+ * RFC2960 6.4 Multi-homed SCTP Endpoints
+ * ...
+ * Furthermore, when its peer is multi-homed, an
+ * endpoint SHOULD try to retransmit a chunk to an
+ * active destination transport address that is
+ * different from the last destination address to
+ * which the DATA chunk was sent.
+ */
+ struct sctp_transport *retran_path;
+
+ /* Pointer to last transport I have sent on. */
+ struct sctp_transport *last_sent_to;
+
+ /* This is the last transport I have received DATA on. */
+ struct sctp_transport *last_data_from;
+
+ /*
+ * Mapping An array of bits or bytes indicating which out of
+ * Array order TSN's have been received (relative to the
+ * Last Rcvd TSN). If no gaps exist, i.e. no out of
+ * order packets have been received, this array
+ * will be set to all zero. This structure may be
+ * in the form of a circular buffer or bit array.
+ *
+ * Last Rcvd : This is the last TSN received in
+ * TSN : sequence. This value is set initially by
+ * : taking the peer's Initial TSN, received in
+ * : the INIT or INIT ACK chunk, and subtracting
+ * : one from it.
+ *
+ * Throughout most of the specification this is called the
+ * "Cumulative TSN ACK Point". In this case, we
+ * ignore the advice in 12.2 in favour of the term
+ * used in the bulk of the text. This value is hidden
+ * in tsn_map--we get it by calling sctp_tsnmap_get_ctsn().
+ */
+ struct sctp_tsnmap tsn_map;
+
+ /* Ack State : This flag indicates if the next received
+ * : packet is to be responded to with a
+ * : SACK. This is initializedto 0. When a packet
+ * : is received it is incremented. If this value
+ * : reaches 2 or more, a SACK is sent and the
+ * : value is reset to 0. Note: This is used only
+ * : when no DATA chunks are received out of
+ * : order. When DATA chunks are out of order,
+ * : SACK's are not delayed (see Section 6).
+ */
+ __u8 sack_needed; /* Do we need to sack the peer? */
+ __u32 sack_cnt;
+
+ /* These are capabilities which our peer advertised. */
+ __u8 ecn_capable:1, /* Can peer do ECN? */
+ ipv4_address:1, /* Peer understands IPv4 addresses? */
+ ipv6_address:1, /* Peer understands IPv6 addresses? */
+ hostname_address:1, /* Peer understands DNS addresses? */
+ asconf_capable:1, /* Does peer support ADDIP? */
+ prsctp_capable:1, /* Can peer do PR-SCTP? */
+ auth_capable:1; /* Is peer doing SCTP-AUTH? */
+
+ __u32 adaptation_ind; /* Adaptation Code point. */
+
+ /* This mask is used to disable sending the ASCONF chunk
+ * with specified parameter to peer.
+ */
+ __be16 addip_disabled_mask;
+
+ struct sctp_inithdr_host i;
+ int cookie_len;
+ void *cookie;
+
+ /* ADDIP Section 4.2 Upon reception of an ASCONF Chunk.
+ * C1) ... "Peer-Serial-Number'. This value MUST be initialized to the
+ * Initial TSN Value minus 1
+ */
+ __u32 addip_serial;
+
+ /* SCTP-AUTH: We need to know pears random number, hmac list
+ * and authenticated chunk list. All that is part of the
+ * cookie and these are just pointers to those locations
+ */
+ sctp_random_param_t *peer_random;
+ sctp_chunks_param_t *peer_chunks;
+ sctp_hmac_algo_param_t *peer_hmacs;
+ } peer;
+
+ /* State : A state variable indicating what state the
+ * : association is in, i.e. COOKIE-WAIT,
+ * : COOKIE-ECHOED, ESTABLISHED, SHUTDOWN-PENDING,
+ * : SHUTDOWN-SENT, SHUTDOWN-RECEIVED, SHUTDOWN-ACK-SENT.
+ *
+ * Note: No "CLOSED" state is illustrated since if a
+ * association is "CLOSED" its TCB SHOULD be removed.
+ *
+ * In this implementation we DO have a CLOSED
+ * state which is used during initiation and shutdown.
+ *
+ * State takes values from SCTP_STATE_*.
+ */
+ sctp_state_t state;
+
+ /* The cookie life I award for any cookie. */
+ struct timeval cookie_life;
+
+ /* Overall : The overall association error count.
+ * Error Count : [Clear this any time I get something.]
+ */
+ int overall_error_count;
+
+ /* These are the association's initial, max, and min RTO values.
+ * These values will be initialized by system defaults, but can
+ * be modified via the SCTP_RTOINFO socket option.
+ */
+ unsigned long rto_initial;
+ unsigned long rto_max;
+ unsigned long rto_min;
+
+ /* Maximum number of new data packets that can be sent in a burst. */
+ int max_burst;
+
+ /* This is the max_retrans value for the association. This value will
+ * be initialized initialized from system defaults, but can be
+ * modified by the SCTP_ASSOCINFO socket option.
+ */
+ int max_retrans;
+
+ /* Maximum number of times the endpoint will retransmit INIT */
+ __u16 max_init_attempts;
+
+ /* How many times have we resent an INIT? */
+ __u16 init_retries;
+
+ /* The largest timeout or RTO value to use in attempting an INIT */
+ unsigned long max_init_timeo;
+
+ /* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
+ * the destination address every heartbeat interval. This value
+ * will be inherited by all new transports.
+ */
+ unsigned long hbinterval;
+
+ /* This is the max_retrans value for new transports in the
+ * association.
+ */
+ __u16 pathmaxrxt;
+
+ /* Flag that path mtu update is pending */
+ __u8 pmtu_pending;
+
+ /* Association : The smallest PMTU discovered for all of the
+ * PMTU : peer's transport addresses.
+ */
+ __u32 pathmtu;
+
+ /* Flags controlling Heartbeat, SACK delay, and Path MTU Discovery. */
+ __u32 param_flags;
+
+ /* SACK delay timeout */
+ unsigned long sackdelay;
+ __u32 sackfreq;
+
+
+ unsigned long timeouts[SCTP_NUM_TIMEOUT_TYPES];
+ struct timer_list timers[SCTP_NUM_TIMEOUT_TYPES];
+
+ /* Transport to which SHUTDOWN chunk was last sent. */
+ struct sctp_transport *shutdown_last_sent_to;
+
+ /* How many times have we resent a SHUTDOWN */
+ int shutdown_retries;
+
+ /* Transport to which INIT chunk was last sent. */
+ struct sctp_transport *init_last_sent_to;
+
+ /* Next TSN : The next TSN number to be assigned to a new
+ * : DATA chunk. This is sent in the INIT or INIT
+ * : ACK chunk to the peer and incremented each
+ * : time a DATA chunk is assigned a TSN
+ * : (normally just prior to transmit or during
+ * : fragmentation).
+ */
+ __u32 next_tsn;
+
+ /*
+ * Last Rcvd : This is the last TSN received in sequence. This value
+ * TSN : is set initially by taking the peer's Initial TSN,
+ * : received in the INIT or INIT ACK chunk, and
+ * : subtracting one from it.
+ *
+ * Most of RFC 2960 refers to this as the Cumulative TSN Ack Point.
+ */
+
+ __u32 ctsn_ack_point;
+
+ /* PR-SCTP Advanced.Peer.Ack.Point */
+ __u32 adv_peer_ack_point;
+
+ /* Highest TSN that is acknowledged by incoming SACKs. */
+ __u32 highest_sacked;
+
+ /* TSN marking the fast recovery exit point */
+ __u32 fast_recovery_exit;
+
+ /* Flag to track the current fast recovery state */
+ __u8 fast_recovery;
+
+ /* The number of unacknowledged data chunks. Reported through
+ * the SCTP_STATUS sockopt.
+ */
+ __u16 unack_data;
+
+ /* The total number of data chunks that we've had to retransmit
+ * as the result of a T3 timer expiration
+ */
+ __u32 rtx_data_chunks;
+
+ /* This is the association's receive buffer space. This value is used
+ * to set a_rwnd field in an INIT or a SACK chunk.
+ */
+ __u32 rwnd;
+
+ /* This is the last advertised value of rwnd over a SACK chunk. */
+ __u32 a_rwnd;
+
+ /* Number of bytes by which the rwnd has slopped. The rwnd is allowed
+ * to slop over a maximum of the association's frag_point.
+ */
+ __u32 rwnd_over;
+
+ /* Keeps treack of rwnd pressure. This happens when we have
+ * a window, but not recevie buffer (i.e small packets). This one
+ * is releases slowly (1 PMTU at a time ).
+ */
+ __u32 rwnd_press;
+
+ /* This is the sndbuf size in use for the association.
+ * This corresponds to the sndbuf size for the association,
+ * as specified in the sk->sndbuf.
+ */
+ int sndbuf_used;
+
+ /* This is the amount of memory that this association has allocated
+ * in the receive path at any given time.
+ */
+ atomic_t rmem_alloc;
+
+ /* This is the wait queue head for send requests waiting on
+ * the association sndbuf space.
+ */
+ wait_queue_head_t wait;
+
+ /* The message size at which SCTP fragmentation will occur. */
+ __u32 frag_point;
+ __u32 user_frag;
+
+ /* Counter used to count INIT errors. */
+ int init_err_counter;
+
+ /* Count the number of INIT cycles (for doubling timeout). */
+ int init_cycle;
+
+ /* Default send parameters. */
+ __u16 default_stream;
+ __u16 default_flags;
+ __u32 default_ppid;
+ __u32 default_context;
+ __u32 default_timetolive;
+
+ /* Default receive parameters */
+ __u32 default_rcv_context;
+
+ /* This tracks outbound ssn for a given stream. */
+ struct sctp_ssnmap *ssnmap;
+
+ /* All outbound chunks go through this structure. */
+ struct sctp_outq outqueue;
+
+ /* A smart pipe that will handle reordering and fragmentation,
+ * as well as handle passing events up to the ULP.
+ */
+ struct sctp_ulpq ulpq;
+
+ /* Last TSN that caused an ECNE Chunk to be sent. */
+ __u32 last_ecne_tsn;
+
+ /* Last TSN that caused a CWR Chunk to be sent. */
+ __u32 last_cwr_tsn;
+
+ /* How many duplicated TSNs have we seen? */
+ int numduptsns;
+
+ /* Number of seconds of idle time before an association is closed.
+ * In the association context, this is really used as a boolean
+ * since the real timeout is stored in the timeouts array
+ */
+ __u32 autoclose;
+
+ /* These are to support
+ * "SCTP Extensions for Dynamic Reconfiguration of IP Addresses
+ * and Enforcement of Flow and Message Limits"
+ * <draft-ietf-tsvwg-addip-sctp-02.txt>
+ * or "ADDIP" for short.
+ */
+
+
+
+ /* ADDIP Section 4.1.1 Congestion Control of ASCONF Chunks
+ *
+ * R1) One and only one ASCONF Chunk MAY be in transit and
+ * unacknowledged at any one time. If a sender, after sending
+ * an ASCONF chunk, decides it needs to transfer another
+ * ASCONF Chunk, it MUST wait until the ASCONF-ACK Chunk
+ * returns from the previous ASCONF Chunk before sending a
+ * subsequent ASCONF. Note this restriction binds each side,
+ * so at any time two ASCONF may be in-transit on any given
+ * association (one sent from each endpoint).
+ *
+ * [This is our one-and-only-one ASCONF in flight. If we do
+ * not have an ASCONF in flight, this is NULL.]
+ */
+ struct sctp_chunk *addip_last_asconf;
+
+ /* ADDIP Section 5.2 Upon reception of an ASCONF Chunk.
+ *
+ * This is needed to implement itmes E1 - E4 of the updated
+ * spec. Here is the justification:
+ *
+ * Since the peer may bundle multiple ASCONF chunks toward us,
+ * we now need the ability to cache multiple ACKs. The section
+ * describes in detail how they are cached and cleaned up.
+ */
+ struct list_head asconf_ack_list;
+
+ /* These ASCONF chunks are waiting to be sent.
+ *
+ * These chunaks can't be pushed to outqueue until receiving
+ * ASCONF_ACK for the previous ASCONF indicated by
+ * addip_last_asconf, so as to guarantee that only one ASCONF
+ * is in flight at any time.
+ *
+ * ADDIP Section 4.1.1 Congestion Control of ASCONF Chunks
+ *
+ * In defining the ASCONF Chunk transfer procedures, it is
+ * essential that these transfers MUST NOT cause congestion
+ * within the network. To achieve this, we place these
+ * restrictions on the transfer of ASCONF Chunks:
+ *
+ * R1) One and only one ASCONF Chunk MAY be in transit and
+ * unacknowledged at any one time. If a sender, after sending
+ * an ASCONF chunk, decides it needs to transfer another
+ * ASCONF Chunk, it MUST wait until the ASCONF-ACK Chunk
+ * returns from the previous ASCONF Chunk before sending a
+ * subsequent ASCONF. Note this restriction binds each side,
+ * so at any time two ASCONF may be in-transit on any given
+ * association (one sent from each endpoint).
+ *
+ *
+ * [I really think this is EXACTLY the sort of intelligence
+ * which already resides in sctp_outq. Please move this
+ * queue and its supporting logic down there. --piggy]
+ */
+ struct list_head addip_chunk_list;
+
+ /* ADDIP Section 4.1 ASCONF Chunk Procedures
+ *
+ * A2) A serial number should be assigned to the Chunk. The
+ * serial number SHOULD be a monotonically increasing
+ * number. The serial number SHOULD be initialized at
+ * the start of the association to the same value as the
+ * Initial TSN and every time a new ASCONF chunk is created
+ * it is incremented by one after assigning the serial number
+ * to the newly created chunk.
+ *
+ * ADDIP
+ * 3.1.1 Address/Stream Configuration Change Chunk (ASCONF)
+ *
+ * Serial Number : 32 bits (unsigned integer)
+ *
+ * This value represents a Serial Number for the ASCONF
+ * Chunk. The valid range of Serial Number is from 0 to
+ * 4294967295 (2^32 - 1). Serial Numbers wrap back to 0
+ * after reaching 4294967295.
+ */
+ __u32 addip_serial;
+ union sctp_addr *asconf_addr_del_pending;
+ int src_out_of_asoc_ok;
+ struct sctp_transport *new_transport;
+
+ /* SCTP AUTH: list of the endpoint shared keys. These
+ * keys are provided out of band by the user applicaton
+ * and can't change during the lifetime of the association
+ */
+ struct list_head endpoint_shared_keys;
+
+ /* SCTP AUTH:
+ * The current generated assocaition shared key (secret)
+ */
+ struct sctp_auth_bytes *asoc_shared_key;
+
+ /* SCTP AUTH: hmac id of the first peer requested algorithm
+ * that we support.
+ */
+ __u16 default_hmac_id;
+
+ __u16 active_key_id;
+
+ __u8 need_ecne:1, /* Need to send an ECNE Chunk? */
+ temp:1; /* Is it a temporary association? */
+};
+
+
+/* An eyecatcher for determining if we are really looking at an
+ * association data structure.
+ */
+enum {
+ SCTP_ASSOC_EYECATCHER = 0xa550c123,
+};
+
+/* Recover the outter association structure. */
+static inline struct sctp_association *sctp_assoc(struct sctp_ep_common *base)
+{
+ struct sctp_association *asoc;
+
+ asoc = container_of(base, struct sctp_association, base);
+ return asoc;
+}
+
+/* These are function signatures for manipulating associations. */
+
+
+struct sctp_association *
+sctp_association_new(const struct sctp_endpoint *, const struct sock *,
+ sctp_scope_t scope, gfp_t gfp);
+void sctp_association_free(struct sctp_association *);
+void sctp_association_put(struct sctp_association *);
+void sctp_association_hold(struct sctp_association *);
+
+struct sctp_transport *sctp_assoc_choose_alter_transport(
+ struct sctp_association *, struct sctp_transport *);
+void sctp_assoc_update_retran_path(struct sctp_association *);
+struct sctp_transport *sctp_assoc_lookup_paddr(const struct sctp_association *,
+ const union sctp_addr *);
+int sctp_assoc_lookup_laddr(struct sctp_association *asoc,
+ const union sctp_addr *laddr);
+struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *,
+ const union sctp_addr *address,
+ const gfp_t gfp,
+ const int peer_state);
+void sctp_assoc_del_peer(struct sctp_association *asoc,
+ const union sctp_addr *addr);
+void sctp_assoc_rm_peer(struct sctp_association *asoc,
+ struct sctp_transport *peer);
+void sctp_assoc_control_transport(struct sctp_association *,
+ struct sctp_transport *,
+ sctp_transport_cmd_t, sctp_sn_error_t);
+struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *, __u32);
+struct sctp_transport *sctp_assoc_is_match(struct sctp_association *,
+ const union sctp_addr *,
+ const union sctp_addr *);
+void sctp_assoc_migrate(struct sctp_association *, struct sock *);
+void sctp_assoc_update(struct sctp_association *old,
+ struct sctp_association *new);
+
+__u32 sctp_association_get_next_tsn(struct sctp_association *);
+
+void sctp_assoc_sync_pmtu(struct sctp_association *);
+void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned);
+void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned);
+void sctp_assoc_set_primary(struct sctp_association *,
+ struct sctp_transport *);
+void sctp_assoc_del_nonprimary_peers(struct sctp_association *,
+ struct sctp_transport *);
+int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *,
+ sctp_scope_t, gfp_t);
+int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *,
+ struct sctp_cookie*,
+ gfp_t gfp);
+int sctp_assoc_set_id(struct sctp_association *, gfp_t);
+void sctp_assoc_clean_asconf_ack_cache(const struct sctp_association *asoc);
+struct sctp_chunk *sctp_assoc_lookup_asconf_ack(
+ const struct sctp_association *asoc,
+ __be32 serial);
+void sctp_asconf_queue_teardown(struct sctp_association *asoc);
+
+int sctp_cmp_addr_exact(const union sctp_addr *ss1,
+ const union sctp_addr *ss2);
+struct sctp_chunk *sctp_get_ecne_prepend(struct sctp_association *asoc);
+
+/* A convenience structure to parse out SCTP specific CMSGs. */
+typedef struct sctp_cmsgs {
+ struct sctp_initmsg *init;
+ struct sctp_sndrcvinfo *info;
+} sctp_cmsgs_t;
+
+/* Structure for tracking memory objects */
+typedef struct {
+ char *label;
+ atomic_t *counter;
+} sctp_dbg_objcnt_entry_t;
+
+#endif /* __sctp_structs_h__ */
diff --git a/include/net/sctp/tsnmap.h b/include/net/sctp/tsnmap.h
new file mode 100644
index 00000000..e7728bc1
--- /dev/null
+++ b/include/net/sctp/tsnmap.h
@@ -0,0 +1,178 @@
+/* SCTP kernel implementation
+ * (C) Copyright IBM Corp. 2001, 2004
+ * Copyright (c) 1999-2000 Cisco, Inc.
+ * Copyright (c) 1999-2001 Motorola, Inc.
+ * Copyright (c) 2001 Intel Corp.
+ *
+ * This file is part of the SCTP kernel implementation
+ *
+ * These are the definitions needed for the tsnmap type. The tsnmap is used
+ * to track out of order TSNs received.
+ *
+ * This SCTP implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This SCTP implementation is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * ************************
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Please send any bug reports or fixes you make to the
+ * email address(es):
+ * lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *
+ * Or submit a bug report through the following website:
+ * http://www.sf.net/projects/lksctp
+ *
+ * Written or modified by:
+ * Jon Grimm <jgrimm@us.ibm.com>
+ * La Monte H.P. Yarroll <piggy@acm.org>
+ * Karl Knutson <karl@athena.chicago.il.us>
+ * Sridhar Samudrala <sri@us.ibm.com>
+ *
+ * Any bugs reported given to us we will try to fix... any fixes shared will
+ * be incorporated into the next SCTP release.
+ */
+#include <net/sctp/constants.h>
+
+#ifndef __sctp_tsnmap_h__
+#define __sctp_tsnmap_h__
+
+/* RFC 2960 12.2 Parameters necessary per association (i.e. the TCB)
+ * Mapping An array of bits or bytes indicating which out of
+ * Array order TSN's have been received (relative to the
+ * Last Rcvd TSN). If no gaps exist, i.e. no out of
+ * order packets have been received, this array
+ * will be set to all zero. This structure may be
+ * in the form of a circular buffer or bit array.
+ */
+struct sctp_tsnmap {
+ /* This array counts the number of chunks with each TSN.
+ * It points at one of the two buffers with which we will
+ * ping-pong between.
+ */
+ unsigned long *tsn_map;
+
+ /* This is the TSN at tsn_map[0]. */
+ __u32 base_tsn;
+
+ /* Last Rcvd : This is the last TSN received in
+ * TSN : sequence. This value is set initially by
+ * : taking the peer's Initial TSN, received in
+ * : the INIT or INIT ACK chunk, and subtracting
+ * : one from it.
+ *
+ * Throughout most of the specification this is called the
+ * "Cumulative TSN ACK Point". In this case, we
+ * ignore the advice in 12.2 in favour of the term
+ * used in the bulk of the text.
+ */
+ __u32 cumulative_tsn_ack_point;
+
+ /* This is the highest TSN we've marked. */
+ __u32 max_tsn_seen;
+
+ /* This is the minimum number of TSNs we can track. This corresponds
+ * to the size of tsn_map. Note: the overflow_map allows us to
+ * potentially track more than this quantity.
+ */
+ __u16 len;
+
+ /* Data chunks pending receipt. used by SCTP_STATUS sockopt */
+ __u16 pending_data;
+
+ /* Record duplicate TSNs here. We clear this after
+ * every SACK. Store up to SCTP_MAX_DUP_TSNS worth of
+ * information.
+ */
+ __u16 num_dup_tsns;
+ __be32 dup_tsns[SCTP_MAX_DUP_TSNS];
+};
+
+struct sctp_tsnmap_iter {
+ __u32 start;
+};
+
+/* Initialize a block of memory as a tsnmap. */
+struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *, __u16 len,
+ __u32 initial_tsn, gfp_t gfp);
+
+void sctp_tsnmap_free(struct sctp_tsnmap *map);
+
+/* Test the tracking state of this TSN.
+ * Returns:
+ * 0 if the TSN has not yet been seen
+ * >0 if the TSN has been seen (duplicate)
+ * <0 if the TSN is invalid (too large to track)
+ */
+int sctp_tsnmap_check(const struct sctp_tsnmap *, __u32 tsn);
+
+/* Mark this TSN as seen. */
+int sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn);
+
+/* Mark this TSN and all lower as seen. */
+void sctp_tsnmap_skip(struct sctp_tsnmap *map, __u32 tsn);
+
+/* Retrieve the Cumulative TSN ACK Point. */
+static inline __u32 sctp_tsnmap_get_ctsn(const struct sctp_tsnmap *map)
+{
+ return map->cumulative_tsn_ack_point;
+}
+
+/* Retrieve the highest TSN we've seen. */
+static inline __u32 sctp_tsnmap_get_max_tsn_seen(const struct sctp_tsnmap *map)
+{
+ return map->max_tsn_seen;
+}
+
+/* How many duplicate TSNs are stored? */
+static inline __u16 sctp_tsnmap_num_dups(struct sctp_tsnmap *map)
+{
+ return map->num_dup_tsns;
+}
+
+/* Return pointer to duplicate tsn array as needed by SACK. */
+static inline __be32 *sctp_tsnmap_get_dups(struct sctp_tsnmap *map)
+{
+ map->num_dup_tsns = 0;
+ return map->dup_tsns;
+}
+
+/* How many gap ack blocks do we have recorded? */
+__u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map,
+ struct sctp_gap_ack_block *gabs);
+
+/* Refresh the count on pending data. */
+__u16 sctp_tsnmap_pending(struct sctp_tsnmap *map);
+
+/* Is there a gap in the TSN map? */
+static inline int sctp_tsnmap_has_gap(const struct sctp_tsnmap *map)
+{
+ return map->cumulative_tsn_ack_point != map->max_tsn_seen;
+}
+
+/* Mark a duplicate TSN. Note: limit the storage of duplicate TSN
+ * information.
+ */
+static inline void sctp_tsnmap_mark_dup(struct sctp_tsnmap *map, __u32 tsn)
+{
+ if (map->num_dup_tsns < SCTP_MAX_DUP_TSNS)
+ map->dup_tsns[map->num_dup_tsns++] = htonl(tsn);
+}
+
+/* Renege a TSN that was seen. */
+void sctp_tsnmap_renege(struct sctp_tsnmap *, __u32 tsn);
+
+/* Is there a gap in the TSN map? */
+int sctp_tsnmap_has_gap(const struct sctp_tsnmap *);
+
+#endif /* __sctp_tsnmap_h__ */
diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
new file mode 100644
index 00000000..ca4693b4
--- /dev/null
+++ b/include/net/sctp/ulpevent.h
@@ -0,0 +1,171 @@
+/* SCTP kernel implementation
+ * (C) Copyright IBM Corp. 2001, 2004
+ * Copyright (c) 1999-2000 Cisco, Inc.
+ * Copyright (c) 1999-2001 Motorola, Inc.
+ * Copyright (c) 2001 Intel Corp.
+ * Copyright (c) 2001 Nokia, Inc.
+ * Copyright (c) 2001 La Monte H.P. Yarroll
+ *
+ * These are the definitions needed for the sctp_ulpevent type. The
+ * sctp_ulpevent type is used to carry information from the state machine
+ * upwards to the ULP.
+ *
+ * This file is part of the SCTP kernel implementation
+ *
+ * This SCTP implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This SCTP implementation is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * ************************
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Please send any bug reports or fixes you make to the
+ * email address(es):
+ * lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *
+ * Or submit a bug report through the following website:
+ * http://www.sf.net/projects/lksctp
+ *
+ * Written or modified by:
+ * Jon Grimm <jgrimm@us.ibm.com>
+ * La Monte H.P. Yarroll <piggy@acm.org>
+ * Karl Knutson <karl@athena.chicago.il.us>
+ * Sridhar Samudrala <sri@us.ibm.com>
+ *
+ * Any bugs reported given to us we will try to fix... any fixes shared will
+ * be incorporated into the next SCTP release.
+ */
+
+#ifndef __sctp_ulpevent_h__
+#define __sctp_ulpevent_h__
+
+/* A structure to carry information to the ULP (e.g. Sockets API) */
+/* Warning: This sits inside an skb.cb[] area. Be very careful of
+ * growing this structure as it is at the maximum limit now.
+ */
+struct sctp_ulpevent {
+ struct sctp_association *asoc;
+ __u16 stream;
+ __u16 ssn;
+ __u16 flags;
+ __u32 ppid;
+ __u32 tsn;
+ __u32 cumtsn;
+ int msg_flags;
+ int iif;
+ unsigned int rmem_len;
+};
+
+/* Retrieve the skb this event sits inside of. */
+static inline struct sk_buff *sctp_event2skb(const struct sctp_ulpevent *ev)
+{
+ return container_of((void *)ev, struct sk_buff, cb);
+}
+
+/* Retrieve & cast the event sitting inside the skb. */
+static inline struct sctp_ulpevent *sctp_skb2event(struct sk_buff *skb)
+{
+ return (struct sctp_ulpevent *)skb->cb;
+}
+
+void sctp_ulpevent_free(struct sctp_ulpevent *);
+int sctp_ulpevent_is_notification(const struct sctp_ulpevent *);
+unsigned int sctp_queue_purge_ulpevents(struct sk_buff_head *list);
+
+struct sctp_ulpevent *sctp_ulpevent_make_assoc_change(
+ const struct sctp_association *asoc,
+ __u16 flags,
+ __u16 state,
+ __u16 error,
+ __u16 outbound,
+ __u16 inbound,
+ struct sctp_chunk *chunk,
+ gfp_t gfp);
+
+struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
+ const struct sctp_association *asoc,
+ const struct sockaddr_storage *aaddr,
+ int flags,
+ int state,
+ int error,
+ gfp_t gfp);
+
+struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
+ const struct sctp_association *asoc,
+ struct sctp_chunk *chunk,
+ __u16 flags,
+ gfp_t gfp);
+struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
+ const struct sctp_association *asoc,
+ struct sctp_chunk *chunk,
+ __u16 flags,
+ __u32 error,
+ gfp_t gfp);
+
+struct sctp_ulpevent *sctp_ulpevent_make_shutdown_event(
+ const struct sctp_association *asoc,
+ __u16 flags,
+ gfp_t gfp);
+
+struct sctp_ulpevent *sctp_ulpevent_make_pdapi(
+ const struct sctp_association *asoc,
+ __u32 indication, gfp_t gfp);
+
+struct sctp_ulpevent *sctp_ulpevent_make_adaptation_indication(
+ const struct sctp_association *asoc, gfp_t gfp);
+
+struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
+ struct sctp_chunk *chunk,
+ gfp_t gfp);
+
+struct sctp_ulpevent *sctp_ulpevent_make_authkey(
+ const struct sctp_association *asoc, __u16 key_id,
+ __u32 indication, gfp_t gfp);
+
+struct sctp_ulpevent *sctp_ulpevent_make_sender_dry_event(
+ const struct sctp_association *asoc, gfp_t gfp);
+
+void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
+ struct msghdr *);
+__u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event);
+
+/* Is this event type enabled? */
+static inline int sctp_ulpevent_type_enabled(__u16 sn_type,
+ struct sctp_event_subscribe *mask)
+{
+ char *amask = (char *) mask;
+ return amask[sn_type - SCTP_SN_TYPE_BASE];
+}
+
+/* Given an event subscription, is this event enabled? */
+static inline int sctp_ulpevent_is_enabled(const struct sctp_ulpevent *event,
+ struct sctp_event_subscribe *mask)
+{
+ __u16 sn_type;
+ int enabled = 1;
+
+ if (sctp_ulpevent_is_notification(event)) {
+ sn_type = sctp_ulpevent_get_notification_type(event);
+ enabled = sctp_ulpevent_type_enabled(sn_type, mask);
+ }
+ return enabled;
+}
+
+#endif /* __sctp_ulpevent_h__ */
+
+
+
+
+
+
+
diff --git a/include/net/sctp/ulpqueue.h b/include/net/sctp/ulpqueue.h
new file mode 100644
index 00000000..2e5ee0d8
--- /dev/null
+++ b/include/net/sctp/ulpqueue.h
@@ -0,0 +1,94 @@
+/* SCTP kernel implementation
+ * (C) Copyright IBM Corp. 2001, 2004
+ * Copyright (c) 1999-2000 Cisco, Inc.
+ * Copyright (c) 1999-2001 Motorola, Inc.
+ * Copyright (c) 2001 Intel Corp.
+ * Copyright (c) 2001 Nokia, Inc.
+ * Copyright (c) 2001 La Monte H.P. Yarroll
+ *
+ * These are the definitions needed for the sctp_ulpq type. The
+ * sctp_ulpq is the interface between the Upper Layer Protocol, or ULP,
+ * and the core SCTP state machine. This is the component which handles
+ * reassembly and ordering.
+ *
+ * This SCTP implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This SCTP implementation is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * ************************
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Please send any bug reports or fixes you make to the
+ * email addresses:
+ * lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *
+ * Or submit a bug report through the following website:
+ * http://www.sf.net/projects/lksctp
+ *
+ * Written or modified by:
+ * Jon Grimm <jgrimm@us.ibm.com>
+ * La Monte H.P. Yarroll <piggy@acm.org>
+ * Sridhar Samudrala <sri@us.ibm.com>
+ *
+ * Any bugs reported given to us we will try to fix... any fixes shared will
+ * be incorporated into the next SCTP release.
+ */
+
+#ifndef __sctp_ulpqueue_h__
+#define __sctp_ulpqueue_h__
+
+/* A structure to carry information to the ULP (e.g. Sockets API) */
+struct sctp_ulpq {
+ char malloced;
+ char pd_mode;
+ struct sctp_association *asoc;
+ struct sk_buff_head reasm;
+ struct sk_buff_head lobby;
+};
+
+/* Prototypes. */
+struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *,
+ struct sctp_association *);
+void sctp_ulpq_flush(struct sctp_ulpq *ulpq);
+void sctp_ulpq_free(struct sctp_ulpq *);
+
+/* Add a new DATA chunk for processing. */
+int sctp_ulpq_tail_data(struct sctp_ulpq *, struct sctp_chunk *, gfp_t);
+
+/* Add a new event for propagation to the ULP. */
+int sctp_ulpq_tail_event(struct sctp_ulpq *, struct sctp_ulpevent *ev);
+
+/* Renege previously received chunks. */
+void sctp_ulpq_renege(struct sctp_ulpq *, struct sctp_chunk *, gfp_t);
+
+/* Perform partial delivery. */
+void sctp_ulpq_partial_delivery(struct sctp_ulpq *, struct sctp_chunk *, gfp_t);
+
+/* Abort the partial delivery. */
+void sctp_ulpq_abort_pd(struct sctp_ulpq *, gfp_t);
+
+/* Clear the partial data delivery condition on this socket. */
+int sctp_clear_pd(struct sock *sk, struct sctp_association *asoc);
+
+/* Skip over an SSN. */
+void sctp_ulpq_skip(struct sctp_ulpq *ulpq, __u16 sid, __u16 ssn);
+
+void sctp_ulpq_reasm_flushtsn(struct sctp_ulpq *, __u32);
+#endif /* __sctp_ulpqueue_h__ */
+
+
+
+
+
+
+
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h
new file mode 100644
index 00000000..0842ef00
--- /dev/null
+++ b/include/net/sctp/user.h
@@ -0,0 +1,744 @@
+/* SCTP kernel implementation
+ * (C) Copyright IBM Corp. 2001, 2004
+ * Copyright (c) 1999-2000 Cisco, Inc.
+ * Copyright (c) 1999-2001 Motorola, Inc.
+ * Copyright (c) 2002 Intel Corp.
+ *
+ * This file is part of the SCTP kernel implementation
+ *
+ * This header represents the structures and constants needed to support
+ * the SCTP Extension to the Sockets API.
+ *
+ * This SCTP implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This SCTP implementation is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * ************************
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Please send any bug reports or fixes you make to the
+ * email address(es):
+ * lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *
+ * Or submit a bug report through the following website:
+ * http://www.sf.net/projects/lksctp
+ *
+ * Written or modified by:
+ * La Monte H.P. Yarroll <piggy@acm.org>
+ * R. Stewart <randall@sctp.chicago.il.us>
+ * K. Morneau <kmorneau@cisco.com>
+ * Q. Xie <qxie1@email.mot.com>
+ * Karl Knutson <karl@athena.chicago.il.us>
+ * Jon Grimm <jgrimm@us.ibm.com>
+ * Daisy Chang <daisyc@us.ibm.com>
+ * Ryan Layer <rmlayer@us.ibm.com>
+ * Ardelle Fan <ardelle.fan@intel.com>
+ * Sridhar Samudrala <sri@us.ibm.com>
+ *
+ * Any bugs reported given to us we will try to fix... any fixes shared will
+ * be incorporated into the next SCTP release.
+ */
+
+#ifndef __net_sctp_user_h__
+#define __net_sctp_user_h__
+
+#include <linux/types.h>
+#include <linux/socket.h>
+
+typedef __s32 sctp_assoc_t;
+
+/* The following symbols come from the Sockets API Extensions for
+ * SCTP <draft-ietf-tsvwg-sctpsocket-07.txt>.
+ */
+#define SCTP_RTOINFO 0
+#define SCTP_ASSOCINFO 1
+#define SCTP_INITMSG 2
+#define SCTP_NODELAY 3 /* Get/set nodelay option. */
+#define SCTP_AUTOCLOSE 4
+#define SCTP_SET_PEER_PRIMARY_ADDR 5
+#define SCTP_PRIMARY_ADDR 6
+#define SCTP_ADAPTATION_LAYER 7
+#define SCTP_DISABLE_FRAGMENTS 8
+#define SCTP_PEER_ADDR_PARAMS 9
+#define SCTP_DEFAULT_SEND_PARAM 10
+#define SCTP_EVENTS 11
+#define SCTP_I_WANT_MAPPED_V4_ADDR 12 /* Turn on/off mapped v4 addresses */
+#define SCTP_MAXSEG 13 /* Get/set maximum fragment. */
+#define SCTP_STATUS 14
+#define SCTP_GET_PEER_ADDR_INFO 15
+#define SCTP_DELAYED_ACK_TIME 16
+#define SCTP_DELAYED_ACK SCTP_DELAYED_ACK_TIME
+#define SCTP_DELAYED_SACK SCTP_DELAYED_ACK_TIME
+#define SCTP_CONTEXT 17
+#define SCTP_FRAGMENT_INTERLEAVE 18
+#define SCTP_PARTIAL_DELIVERY_POINT 19 /* Set/Get partial delivery point */
+#define SCTP_MAX_BURST 20 /* Set/Get max burst */
+#define SCTP_AUTH_CHUNK 21 /* Set only: add a chunk type to authenticate */
+#define SCTP_HMAC_IDENT 22
+#define SCTP_AUTH_KEY 23
+#define SCTP_AUTH_ACTIVE_KEY 24
+#define SCTP_AUTH_DELETE_KEY 25
+#define SCTP_PEER_AUTH_CHUNKS 26 /* Read only */
+#define SCTP_LOCAL_AUTH_CHUNKS 27 /* Read only */
+#define SCTP_GET_ASSOC_NUMBER 28 /* Read only */
+#define SCTP_GET_ASSOC_ID_LIST 29 /* Read only */
+#define SCTP_AUTO_ASCONF 30
+
+/* Internal Socket Options. Some of the sctp library functions are
+ * implemented using these socket options.
+ */
+#define SCTP_SOCKOPT_BINDX_ADD 100 /* BINDX requests for adding addrs */
+#define SCTP_SOCKOPT_BINDX_REM 101 /* BINDX requests for removing addrs. */
+#define SCTP_SOCKOPT_PEELOFF 102 /* peel off association. */
+/* Options 104-106 are deprecated and removed. Do not use this space */
+#define SCTP_SOCKOPT_CONNECTX_OLD 107 /* CONNECTX old requests. */
+#define SCTP_GET_PEER_ADDRS 108 /* Get all peer address. */
+#define SCTP_GET_LOCAL_ADDRS 109 /* Get all local address. */
+#define SCTP_SOCKOPT_CONNECTX 110 /* CONNECTX requests. */
+#define SCTP_SOCKOPT_CONNECTX3 111 /* CONNECTX requests (updated) */
+
+/*
+ * 5.2.1 SCTP Initiation Structure (SCTP_INIT)
+ *
+ * This cmsghdr structure provides information for initializing new
+ * SCTP associations with sendmsg(). The SCTP_INITMSG socket option
+ * uses this same data structure. This structure is not used for
+ * recvmsg().
+ *
+ * cmsg_level cmsg_type cmsg_data[]
+ * ------------ ------------ ----------------------
+ * IPPROTO_SCTP SCTP_INIT struct sctp_initmsg
+ *
+ */
+struct sctp_initmsg {
+ __u16 sinit_num_ostreams;
+ __u16 sinit_max_instreams;
+ __u16 sinit_max_attempts;
+ __u16 sinit_max_init_timeo;
+};
+
+/*
+ * 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV)
+ *
+ * This cmsghdr structure specifies SCTP options for sendmsg() and
+ * describes SCTP header information about a received message through
+ * recvmsg().
+ *
+ * cmsg_level cmsg_type cmsg_data[]
+ * ------------ ------------ ----------------------
+ * IPPROTO_SCTP SCTP_SNDRCV struct sctp_sndrcvinfo
+ *
+ */
+struct sctp_sndrcvinfo {
+ __u16 sinfo_stream;
+ __u16 sinfo_ssn;
+ __u16 sinfo_flags;
+ __u32 sinfo_ppid;
+ __u32 sinfo_context;
+ __u32 sinfo_timetolive;
+ __u32 sinfo_tsn;
+ __u32 sinfo_cumtsn;
+ sctp_assoc_t sinfo_assoc_id;
+};
+
+/*
+ * sinfo_flags: 16 bits (unsigned integer)
+ *
+ * This field may contain any of the following flags and is composed of
+ * a bitwise OR of these values.
+ */
+
+enum sctp_sinfo_flags {
+ SCTP_UNORDERED = 1, /* Send/receive message unordered. */
+ SCTP_ADDR_OVER = 2, /* Override the primary destination. */
+ SCTP_ABORT=4, /* Send an ABORT message to the peer. */
+ SCTP_SACK_IMMEDIATELY = 8, /* SACK should be sent without delay */
+ SCTP_EOF=MSG_FIN, /* Initiate graceful shutdown process. */
+};
+
+
+/* These are cmsg_types. */
+typedef enum sctp_cmsg_type {
+ SCTP_INIT, /* 5.2.1 SCTP Initiation Structure */
+ SCTP_SNDRCV, /* 5.2.2 SCTP Header Information Structure */
+} sctp_cmsg_t;
+
+
+/*
+ * 5.3.1.1 SCTP_ASSOC_CHANGE
+ *
+ * Communication notifications inform the ULP that an SCTP association
+ * has either begun or ended. The identifier for a new association is
+ * provided by this notificaion. The notification information has the
+ * following format:
+ *
+ */
+struct sctp_assoc_change {
+ __u16 sac_type;
+ __u16 sac_flags;
+ __u32 sac_length;
+ __u16 sac_state;
+ __u16 sac_error;
+ __u16 sac_outbound_streams;
+ __u16 sac_inbound_streams;
+ sctp_assoc_t sac_assoc_id;
+ __u8 sac_info[0];
+};
+
+/*
+ * sac_state: 32 bits (signed integer)
+ *
+ * This field holds one of a number of values that communicate the
+ * event that happened to the association. They include:
+ *
+ * Note: The following state names deviate from the API draft as
+ * the names clash too easily with other kernel symbols.
+ */
+enum sctp_sac_state {
+ SCTP_COMM_UP,
+ SCTP_COMM_LOST,
+ SCTP_RESTART,
+ SCTP_SHUTDOWN_COMP,
+ SCTP_CANT_STR_ASSOC,
+};
+
+/*
+ * 5.3.1.2 SCTP_PEER_ADDR_CHANGE
+ *
+ * When a destination address on a multi-homed peer encounters a change
+ * an interface details event is sent. The information has the
+ * following structure:
+ */
+struct sctp_paddr_change {
+ __u16 spc_type;
+ __u16 spc_flags;
+ __u32 spc_length;
+ struct sockaddr_storage spc_aaddr;
+ int spc_state;
+ int spc_error;
+ sctp_assoc_t spc_assoc_id;
+} __attribute__((packed, aligned(4)));
+
+/*
+ * spc_state: 32 bits (signed integer)
+ *
+ * This field holds one of a number of values that communicate the
+ * event that happened to the address. They include:
+ */
+enum sctp_spc_state {
+ SCTP_ADDR_AVAILABLE,
+ SCTP_ADDR_UNREACHABLE,
+ SCTP_ADDR_REMOVED,
+ SCTP_ADDR_ADDED,
+ SCTP_ADDR_MADE_PRIM,
+ SCTP_ADDR_CONFIRMED,
+};
+
+
+/*
+ * 5.3.1.3 SCTP_REMOTE_ERROR
+ *
+ * A remote peer may send an Operational Error message to its peer.
+ * This message indicates a variety of error conditions on an
+ * association. The entire error TLV as it appears on the wire is
+ * included in a SCTP_REMOTE_ERROR event. Please refer to the SCTP
+ * specification [SCTP] and any extensions for a list of possible
+ * error formats. SCTP error TLVs have the format:
+ */
+struct sctp_remote_error {
+ __u16 sre_type;
+ __u16 sre_flags;
+ __u32 sre_length;
+ __u16 sre_error;
+ sctp_assoc_t sre_assoc_id;
+ __u8 sre_data[0];
+};
+
+
+/*
+ * 5.3.1.4 SCTP_SEND_FAILED
+ *
+ * If SCTP cannot deliver a message it may return the message as a
+ * notification.
+ */
+struct sctp_send_failed {
+ __u16 ssf_type;
+ __u16 ssf_flags;
+ __u32 ssf_length;
+ __u32 ssf_error;
+ struct sctp_sndrcvinfo ssf_info;
+ sctp_assoc_t ssf_assoc_id;
+ __u8 ssf_data[0];
+};
+
+/*
+ * ssf_flags: 16 bits (unsigned integer)
+ *
+ * The flag value will take one of the following values
+ *
+ * SCTP_DATA_UNSENT - Indicates that the data was never put on
+ * the wire.
+ *
+ * SCTP_DATA_SENT - Indicates that the data was put on the wire.
+ * Note that this does not necessarily mean that the
+ * data was (or was not) successfully delivered.
+ */
+enum sctp_ssf_flags {
+ SCTP_DATA_UNSENT,
+ SCTP_DATA_SENT,
+};
+
+/*
+ * 5.3.1.5 SCTP_SHUTDOWN_EVENT
+ *
+ * When a peer sends a SHUTDOWN, SCTP delivers this notification to
+ * inform the application that it should cease sending data.
+ */
+struct sctp_shutdown_event {
+ __u16 sse_type;
+ __u16 sse_flags;
+ __u32 sse_length;
+ sctp_assoc_t sse_assoc_id;
+};
+
+/*
+ * 5.3.1.6 SCTP_ADAPTATION_INDICATION
+ *
+ * When a peer sends a Adaptation Layer Indication parameter , SCTP
+ * delivers this notification to inform the application
+ * that of the peers requested adaptation layer.
+ */
+struct sctp_adaptation_event {
+ __u16 sai_type;
+ __u16 sai_flags;
+ __u32 sai_length;
+ __u32 sai_adaptation_ind;
+ sctp_assoc_t sai_assoc_id;
+};
+
+/*
+ * 5.3.1.7 SCTP_PARTIAL_DELIVERY_EVENT
+ *
+ * When a receiver is engaged in a partial delivery of a
+ * message this notification will be used to indicate
+ * various events.
+ */
+struct sctp_pdapi_event {
+ __u16 pdapi_type;
+ __u16 pdapi_flags;
+ __u32 pdapi_length;
+ __u32 pdapi_indication;
+ sctp_assoc_t pdapi_assoc_id;
+};
+
+enum { SCTP_PARTIAL_DELIVERY_ABORTED=0, };
+
+struct sctp_authkey_event {
+ __u16 auth_type;
+ __u16 auth_flags;
+ __u32 auth_length;
+ __u16 auth_keynumber;
+ __u16 auth_altkeynumber;
+ __u32 auth_indication;
+ sctp_assoc_t auth_assoc_id;
+};
+
+enum { SCTP_AUTH_NEWKEY = 0, };
+
+/*
+ * 6.1.9. SCTP_SENDER_DRY_EVENT
+ *
+ * When the SCTP stack has no more user data to send or retransmit, this
+ * notification is given to the user. Also, at the time when a user app
+ * subscribes to this event, if there is no data to be sent or
+ * retransmit, the stack will immediately send up this notification.
+ */
+struct sctp_sender_dry_event {
+ __u16 sender_dry_type;
+ __u16 sender_dry_flags;
+ __u32 sender_dry_length;
+ sctp_assoc_t sender_dry_assoc_id;
+};
+
+/*
+ * Described in Section 7.3
+ * Ancillary Data and Notification Interest Options
+ */
+struct sctp_event_subscribe {
+ __u8 sctp_data_io_event;
+ __u8 sctp_association_event;
+ __u8 sctp_address_event;
+ __u8 sctp_send_failure_event;
+ __u8 sctp_peer_error_event;
+ __u8 sctp_shutdown_event;
+ __u8 sctp_partial_delivery_event;
+ __u8 sctp_adaptation_layer_event;
+ __u8 sctp_authentication_event;
+ __u8 sctp_sender_dry_event;
+};
+
+/*
+ * 5.3.1 SCTP Notification Structure
+ *
+ * The notification structure is defined as the union of all
+ * notification types.
+ *
+ */
+union sctp_notification {
+ struct {
+ __u16 sn_type; /* Notification type. */
+ __u16 sn_flags;
+ __u32 sn_length;
+ } sn_header;
+ struct sctp_assoc_change sn_assoc_change;
+ struct sctp_paddr_change sn_paddr_change;
+ struct sctp_remote_error sn_remote_error;
+ struct sctp_send_failed sn_send_failed;
+ struct sctp_shutdown_event sn_shutdown_event;
+ struct sctp_adaptation_event sn_adaptation_event;
+ struct sctp_pdapi_event sn_pdapi_event;
+ struct sctp_authkey_event sn_authkey_event;
+ struct sctp_sender_dry_event sn_sender_dry_event;
+};
+
+/* Section 5.3.1
+ * All standard values for sn_type flags are greater than 2^15.
+ * Values from 2^15 and down are reserved.
+ */
+
+enum sctp_sn_type {
+ SCTP_SN_TYPE_BASE = (1<<15),
+ SCTP_ASSOC_CHANGE,
+ SCTP_PEER_ADDR_CHANGE,
+ SCTP_SEND_FAILED,
+ SCTP_REMOTE_ERROR,
+ SCTP_SHUTDOWN_EVENT,
+ SCTP_PARTIAL_DELIVERY_EVENT,
+ SCTP_ADAPTATION_INDICATION,
+ SCTP_AUTHENTICATION_EVENT,
+#define SCTP_AUTHENTICATION_INDICATION SCTP_AUTHENTICATION_EVENT
+ SCTP_SENDER_DRY_EVENT,
+};
+
+/* Notification error codes used to fill up the error fields in some
+ * notifications.
+ * SCTP_PEER_ADDRESS_CHAGE : spc_error
+ * SCTP_ASSOC_CHANGE : sac_error
+ * These names should be potentially included in the draft 04 of the SCTP
+ * sockets API specification.
+ */
+typedef enum sctp_sn_error {
+ SCTP_FAILED_THRESHOLD,
+ SCTP_RECEIVED_SACK,
+ SCTP_HEARTBEAT_SUCCESS,
+ SCTP_RESPONSE_TO_USER_REQ,
+ SCTP_INTERNAL_ERROR,
+ SCTP_SHUTDOWN_GUARD_EXPIRES,
+ SCTP_PEER_FAULTY,
+} sctp_sn_error_t;
+
+/*
+ * 7.1.1 Retransmission Timeout Parameters (SCTP_RTOINFO)
+ *
+ * The protocol parameters used to initialize and bound retransmission
+ * timeout (RTO) are tunable. See [SCTP] for more information on how
+ * these parameters are used in RTO calculation.
+ */
+struct sctp_rtoinfo {
+ sctp_assoc_t srto_assoc_id;
+ __u32 srto_initial;
+ __u32 srto_max;
+ __u32 srto_min;
+};
+
+/*
+ * 7.1.2 Association Parameters (SCTP_ASSOCINFO)
+ *
+ * This option is used to both examine and set various association and
+ * endpoint parameters.
+ */
+struct sctp_assocparams {
+ sctp_assoc_t sasoc_assoc_id;
+ __u16 sasoc_asocmaxrxt;
+ __u16 sasoc_number_peer_destinations;
+ __u32 sasoc_peer_rwnd;
+ __u32 sasoc_local_rwnd;
+ __u32 sasoc_cookie_life;
+};
+
+/*
+ * 7.1.9 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR)
+ *
+ * Requests that the peer mark the enclosed address as the association
+ * primary. The enclosed address must be one of the association's
+ * locally bound addresses. The following structure is used to make a
+ * set primary request:
+ */
+struct sctp_setpeerprim {
+ sctp_assoc_t sspp_assoc_id;
+ struct sockaddr_storage sspp_addr;
+} __attribute__((packed, aligned(4)));
+
+/*
+ * 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR)
+ *
+ * Requests that the local SCTP stack use the enclosed peer address as
+ * the association primary. The enclosed address must be one of the
+ * association peer's addresses. The following structure is used to
+ * make a set peer primary request:
+ */
+struct sctp_prim {
+ sctp_assoc_t ssp_assoc_id;
+ struct sockaddr_storage ssp_addr;
+} __attribute__((packed, aligned(4)));
+
+/*
+ * 7.1.11 Set Adaptation Layer Indicator (SCTP_ADAPTATION_LAYER)
+ *
+ * Requests that the local endpoint set the specified Adaptation Layer
+ * Indication parameter for all future INIT and INIT-ACK exchanges.
+ */
+struct sctp_setadaptation {
+ __u32 ssb_adaptation_ind;
+};
+
+/*
+ * 7.1.13 Peer Address Parameters (SCTP_PEER_ADDR_PARAMS)
+ *
+ * Applications can enable or disable heartbeats for any peer address
+ * of an association, modify an address's heartbeat interval, force a
+ * heartbeat to be sent immediately, and adjust the address's maximum
+ * number of retransmissions sent before an address is considered
+ * unreachable. The following structure is used to access and modify an
+ * address's parameters:
+ */
+enum sctp_spp_flags {
+ SPP_HB_ENABLE = 1<<0, /*Enable heartbeats*/
+ SPP_HB_DISABLE = 1<<1, /*Disable heartbeats*/
+ SPP_HB = SPP_HB_ENABLE | SPP_HB_DISABLE,
+ SPP_HB_DEMAND = 1<<2, /*Send heartbeat immediately*/
+ SPP_PMTUD_ENABLE = 1<<3, /*Enable PMTU discovery*/
+ SPP_PMTUD_DISABLE = 1<<4, /*Disable PMTU discovery*/
+ SPP_PMTUD = SPP_PMTUD_ENABLE | SPP_PMTUD_DISABLE,
+ SPP_SACKDELAY_ENABLE = 1<<5, /*Enable SACK*/
+ SPP_SACKDELAY_DISABLE = 1<<6, /*Disable SACK*/
+ SPP_SACKDELAY = SPP_SACKDELAY_ENABLE | SPP_SACKDELAY_DISABLE,
+ SPP_HB_TIME_IS_ZERO = 1<<7, /* Set HB delay to 0 */
+};
+
+struct sctp_paddrparams {
+ sctp_assoc_t spp_assoc_id;
+ struct sockaddr_storage spp_address;
+ __u32 spp_hbinterval;
+ __u16 spp_pathmaxrxt;
+ __u32 spp_pathmtu;
+ __u32 spp_sackdelay;
+ __u32 spp_flags;
+} __attribute__((packed, aligned(4)));
+
+/*
+ * 7.1.18. Add a chunk that must be authenticated (SCTP_AUTH_CHUNK)
+ *
+ * This set option adds a chunk type that the user is requesting to be
+ * received only in an authenticated way. Changes to the list of chunks
+ * will only effect future associations on the socket.
+ */
+struct sctp_authchunk {
+ __u8 sauth_chunk;
+};
+
+/*
+ * 7.1.19. Get or set the list of supported HMAC Identifiers (SCTP_HMAC_IDENT)
+ *
+ * This option gets or sets the list of HMAC algorithms that the local
+ * endpoint requires the peer to use.
+*/
+struct sctp_hmacalgo {
+ __u32 shmac_num_idents;
+ __u16 shmac_idents[];
+};
+
+/*
+ * 7.1.20. Set a shared key (SCTP_AUTH_KEY)
+ *
+ * This option will set a shared secret key which is used to build an
+ * association shared key.
+ */
+struct sctp_authkey {
+ sctp_assoc_t sca_assoc_id;
+ __u16 sca_keynumber;
+ __u16 sca_keylength;
+ __u8 sca_key[];
+};
+
+/*
+ * 7.1.21. Get or set the active shared key (SCTP_AUTH_ACTIVE_KEY)
+ *
+ * This option will get or set the active shared key to be used to build
+ * the association shared key.
+ */
+
+struct sctp_authkeyid {
+ sctp_assoc_t scact_assoc_id;
+ __u16 scact_keynumber;
+};
+
+
+/*
+ * 7.1.23. Get or set delayed ack timer (SCTP_DELAYED_SACK)
+ *
+ * This option will effect the way delayed acks are performed. This
+ * option allows you to get or set the delayed ack time, in
+ * milliseconds. It also allows changing the delayed ack frequency.
+ * Changing the frequency to 1 disables the delayed sack algorithm. If
+ * the assoc_id is 0, then this sets or gets the endpoints default
+ * values. If the assoc_id field is non-zero, then the set or get
+ * effects the specified association for the one to many model (the
+ * assoc_id field is ignored by the one to one model). Note that if
+ * sack_delay or sack_freq are 0 when setting this option, then the
+ * current values will remain unchanged.
+ */
+struct sctp_sack_info {
+ sctp_assoc_t sack_assoc_id;
+ uint32_t sack_delay;
+ uint32_t sack_freq;
+};
+
+struct sctp_assoc_value {
+ sctp_assoc_t assoc_id;
+ uint32_t assoc_value;
+};
+
+/*
+ * 7.2.2 Peer Address Information
+ *
+ * Applications can retrieve information about a specific peer address
+ * of an association, including its reachability state, congestion
+ * window, and retransmission timer values. This information is
+ * read-only. The following structure is used to access this
+ * information:
+ */
+struct sctp_paddrinfo {
+ sctp_assoc_t spinfo_assoc_id;
+ struct sockaddr_storage spinfo_address;
+ __s32 spinfo_state;
+ __u32 spinfo_cwnd;
+ __u32 spinfo_srtt;
+ __u32 spinfo_rto;
+ __u32 spinfo_mtu;
+} __attribute__((packed, aligned(4)));
+
+/* Peer addresses's state. */
+/* UNKNOWN: Peer address passed by the upper layer in sendmsg or connect[x]
+ * calls.
+ * UNCONFIRMED: Peer address received in INIT/INIT-ACK address parameters.
+ * Not yet confirmed by a heartbeat and not available for data
+ * transfers.
+ * ACTIVE : Peer address confirmed, active and available for data transfers.
+ * INACTIVE: Peer address inactive and not available for data transfers.
+ */
+enum sctp_spinfo_state {
+ SCTP_INACTIVE,
+ SCTP_ACTIVE,
+ SCTP_UNCONFIRMED,
+ SCTP_UNKNOWN = 0xffff /* Value used for transport state unknown */
+};
+
+/*
+ * 7.2.1 Association Status (SCTP_STATUS)
+ *
+ * Applications can retrieve current status information about an
+ * association, including association state, peer receiver window size,
+ * number of unacked data chunks, and number of data chunks pending
+ * receipt. This information is read-only. The following structure is
+ * used to access this information:
+ */
+struct sctp_status {
+ sctp_assoc_t sstat_assoc_id;
+ __s32 sstat_state;
+ __u32 sstat_rwnd;
+ __u16 sstat_unackdata;
+ __u16 sstat_penddata;
+ __u16 sstat_instrms;
+ __u16 sstat_outstrms;
+ __u32 sstat_fragmentation_point;
+ struct sctp_paddrinfo sstat_primary;
+};
+
+/*
+ * 7.2.3. Get the list of chunks the peer requires to be authenticated
+ * (SCTP_PEER_AUTH_CHUNKS)
+ *
+ * This option gets a list of chunks for a specified association that
+ * the peer requires to be received authenticated only.
+ */
+struct sctp_authchunks {
+ sctp_assoc_t gauth_assoc_id;
+ __u32 gauth_number_of_chunks;
+ uint8_t gauth_chunks[];
+};
+
+/*
+ * 8.2.6. Get the Current Identifiers of Associations
+ * (SCTP_GET_ASSOC_ID_LIST)
+ *
+ * This option gets the current list of SCTP association identifiers of
+ * the SCTP associations handled by a one-to-many style socket.
+ */
+struct sctp_assoc_ids {
+ __u32 gaids_number_of_ids;
+ sctp_assoc_t gaids_assoc_id[];
+};
+
+/*
+ * 8.3, 8.5 get all peer/local addresses in an association.
+ * This parameter struct is used by SCTP_GET_PEER_ADDRS and
+ * SCTP_GET_LOCAL_ADDRS socket options used internally to implement
+ * sctp_getpaddrs() and sctp_getladdrs() API.
+ */
+struct sctp_getaddrs_old {
+ sctp_assoc_t assoc_id;
+ int addr_num;
+ struct sockaddr __user *addrs;
+};
+struct sctp_getaddrs {
+ sctp_assoc_t assoc_id; /*input*/
+ __u32 addr_num; /*output*/
+ __u8 addrs[0]; /*output, variable size*/
+};
+
+/* These are bit fields for msghdr->msg_flags. See section 5.1. */
+/* On user space Linux, these live in <bits/socket.h> as an enum. */
+enum sctp_msg_flags {
+ MSG_NOTIFICATION = 0x8000,
+#define MSG_NOTIFICATION MSG_NOTIFICATION
+};
+
+/*
+ * 8.1 sctp_bindx()
+ *
+ * The flags parameter is formed from the bitwise OR of zero or more of the
+ * following currently defined flags:
+ */
+#define SCTP_BINDX_ADD_ADDR 0x01
+#define SCTP_BINDX_REM_ADDR 0x02
+
+/* This is the structure that is passed as an argument(optval) to
+ * getsockopt(SCTP_SOCKOPT_PEELOFF).
+ */
+typedef struct {
+ sctp_assoc_t associd;
+ int sd;
+} sctp_peeloff_arg_t;
+
+#endif /* __net_sctp_user_h__ */
diff --git a/include/net/secure_seq.h b/include/net/secure_seq.h
new file mode 100644
index 00000000..c2e542b2
--- /dev/null
+++ b/include/net/secure_seq.h
@@ -0,0 +1,20 @@
+#ifndef _NET_SECURE_SEQ
+#define _NET_SECURE_SEQ
+
+#include <linux/types.h>
+
+extern __u32 secure_ip_id(__be32 daddr);
+extern __u32 secure_ipv6_id(const __be32 daddr[4]);
+extern u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
+extern u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
+ __be16 dport);
+extern __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
+ __be16 sport, __be16 dport);
+extern __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
+ __be16 sport, __be16 dport);
+extern u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
+ __be16 sport, __be16 dport);
+extern u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
+ __be16 sport, __be16 dport);
+
+#endif /* _NET_SECURE_SEQ */
diff --git a/include/net/slhc_vj.h b/include/net/slhc_vj.h
new file mode 100644
index 00000000..8716d594
--- /dev/null
+++ b/include/net/slhc_vj.h
@@ -0,0 +1,183 @@
+#ifndef _SLHC_H
+#define _SLHC_H
+/*
+ * Definitions for tcp compression routines.
+ *
+ * $Header: slcompress.h,v 1.10 89/12/31 08:53:02 van Exp $
+ *
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
+ * - Initial distribution.
+ *
+ *
+ * modified for KA9Q Internet Software Package by
+ * Katie Stevens (dkstevens@ucdavis.edu)
+ * University of California, Davis
+ * Computing Services
+ * - 01-31-90 initial adaptation
+ *
+ * - Feb 1991 Bill_Simpson@um.cc.umich.edu
+ * variable number of conversation slots
+ * allow zero or one slots
+ * separate routines
+ * status display
+ */
+
+/*
+ * Compressed packet format:
+ *
+ * The first octet contains the packet type (top 3 bits), TCP
+ * 'push' bit, and flags that indicate which of the 4 TCP sequence
+ * numbers have changed (bottom 5 bits). The next octet is a
+ * conversation number that associates a saved IP/TCP header with
+ * the compressed packet. The next two octets are the TCP checksum
+ * from the original datagram. The next 0 to 15 octets are
+ * sequence number changes, one change per bit set in the header
+ * (there may be no changes and there are two special cases where
+ * the receiver implicitly knows what changed -- see below).
+ *
+ * There are 5 numbers which can change (they are always inserted
+ * in the following order): TCP urgent pointer, window,
+ * acknowledgment, sequence number and IP ID. (The urgent pointer
+ * is different from the others in that its value is sent, not the
+ * change in value.) Since typical use of SLIP links is biased
+ * toward small packets (see comments on MTU/MSS below), changes
+ * use a variable length coding with one octet for numbers in the
+ * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the
+ * range 256 - 65535 or 0. (If the change in sequence number or
+ * ack is more than 65535, an uncompressed packet is sent.)
+ */
+
+/*
+ * Packet types (must not conflict with IP protocol version)
+ *
+ * The top nibble of the first octet is the packet type. There are
+ * three possible types: IP (not proto TCP or tcp with one of the
+ * control flags set); uncompressed TCP (a normal IP/TCP packet but
+ * with the 8-bit protocol field replaced by an 8-bit connection id --
+ * this type of packet syncs the sender & receiver); and compressed
+ * TCP (described above).
+ *
+ * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and
+ * is logically part of the 4-bit "changes" field that follows. Top
+ * three bits are actual packet type. For backward compatibility
+ * and in the interest of conserving bits, numbers are chosen so the
+ * IP protocol version number (4) which normally appears in this nibble
+ * means "IP packet".
+ */
+
+
+#include <linux/ip.h>
+#include <linux/tcp.h>
+
+/* SLIP compression masks for len/vers byte */
+#define SL_TYPE_IP 0x40
+#define SL_TYPE_UNCOMPRESSED_TCP 0x70
+#define SL_TYPE_COMPRESSED_TCP 0x80
+#define SL_TYPE_ERROR 0x00
+
+/* Bits in first octet of compressed packet */
+#define NEW_C 0x40 /* flag bits for what changed in a packet */
+#define NEW_I 0x20
+#define NEW_S 0x08
+#define NEW_A 0x04
+#define NEW_W 0x02
+#define NEW_U 0x01
+
+/* reserved, special-case values of above */
+#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */
+#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */
+#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U)
+
+#define TCP_PUSH_BIT 0x10
+
+/*
+ * data type and sizes conversion assumptions:
+ *
+ * VJ code KA9Q style generic
+ * u_char byte_t unsigned char 8 bits
+ * u_short int16 unsigned short 16 bits
+ * u_int int16 unsigned short 16 bits
+ * u_long unsigned long unsigned long 32 bits
+ * int int32 long 32 bits
+ */
+
+typedef __u8 byte_t;
+typedef __u32 int32;
+
+/*
+ * "state" data for each active tcp conversation on the wire. This is
+ * basically a copy of the entire IP/TCP header from the last packet
+ * we saw from the conversation together with a small identifier
+ * the transmit & receive ends of the line use to locate saved header.
+ */
+struct cstate {
+ byte_t cs_this; /* connection id number (xmit) */
+ struct cstate *next; /* next in ring (xmit) */
+ struct iphdr cs_ip; /* ip/tcp hdr from most recent packet */
+ struct tcphdr cs_tcp;
+ unsigned char cs_ipopt[64];
+ unsigned char cs_tcpopt[64];
+ int cs_hsize;
+};
+#define NULLSLSTATE (struct cstate *)0
+
+/*
+ * all the state data for one serial line (we need one of these per line).
+ */
+struct slcompress {
+ struct cstate *tstate; /* transmit connection states (array)*/
+ struct cstate *rstate; /* receive connection states (array)*/
+
+ byte_t tslot_limit; /* highest transmit slot id (0-l)*/
+ byte_t rslot_limit; /* highest receive slot id (0-l)*/
+
+ byte_t xmit_oldest; /* oldest xmit in ring */
+ byte_t xmit_current; /* most recent xmit id */
+ byte_t recv_current; /* most recent rcvd id */
+
+ byte_t flags;
+#define SLF_TOSS 0x01 /* tossing rcvd frames until id received */
+
+ int32 sls_o_nontcp; /* outbound non-TCP packets */
+ int32 sls_o_tcp; /* outbound TCP packets */
+ int32 sls_o_uncompressed; /* outbound uncompressed packets */
+ int32 sls_o_compressed; /* outbound compressed packets */
+ int32 sls_o_searches; /* searches for connection state */
+ int32 sls_o_misses; /* times couldn't find conn. state */
+
+ int32 sls_i_uncompressed; /* inbound uncompressed packets */
+ int32 sls_i_compressed; /* inbound compressed packets */
+ int32 sls_i_error; /* inbound error packets */
+ int32 sls_i_tossed; /* inbound packets tossed because of error */
+
+ int32 sls_i_runt;
+ int32 sls_i_badcheck;
+};
+#define NULLSLCOMPR (struct slcompress *)0
+
+/* In slhc.c: */
+struct slcompress *slhc_init(int rslots, int tslots);
+void slhc_free(struct slcompress *comp);
+
+int slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
+ unsigned char *ocp, unsigned char **cpp, int compress_cid);
+int slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize);
+int slhc_remember(struct slcompress *comp, unsigned char *icp, int isize);
+int slhc_toss(struct slcompress *comp);
+
+#endif /* _SLHC_H */
diff --git a/include/net/snmp.h b/include/net/snmp.h
new file mode 100644
index 00000000..0147b901
--- /dev/null
+++ b/include/net/snmp.h
@@ -0,0 +1,217 @@
+/*
+ *
+ * SNMP MIB entries for the IP subsystem.
+ *
+ * Alan Cox <gw4pts@gw4pts.ampr.org>
+ *
+ * We don't chose to implement SNMP in the kernel (this would
+ * be silly as SNMP is a pain in the backside in places). We do
+ * however need to collect the MIB statistics and export them
+ * out of /proc (eventually)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#ifndef _SNMP_H
+#define _SNMP_H
+
+#include <linux/cache.h>
+#include <linux/snmp.h>
+#include <linux/smp.h>
+
+/*
+ * Mibs are stored in array of unsigned long.
+ */
+/*
+ * struct snmp_mib{}
+ * - list of entries for particular API (such as /proc/net/snmp)
+ * - name of entries.
+ */
+struct snmp_mib {
+ const char *name;
+ int entry;
+};
+
+#define SNMP_MIB_ITEM(_name,_entry) { \
+ .name = _name, \
+ .entry = _entry, \
+}
+
+#define SNMP_MIB_SENTINEL { \
+ .name = NULL, \
+ .entry = 0, \
+}
+
+/*
+ * We use unsigned longs for most mibs but u64 for ipstats.
+ */
+#include <linux/u64_stats_sync.h>
+
+/* IPstats */
+#define IPSTATS_MIB_MAX __IPSTATS_MIB_MAX
+struct ipstats_mib {
+ /* mibs[] must be first field of struct ipstats_mib */
+ u64 mibs[IPSTATS_MIB_MAX];
+ struct u64_stats_sync syncp;
+};
+
+/* ICMP */
+#define ICMP_MIB_MAX __ICMP_MIB_MAX
+struct icmp_mib {
+ unsigned long mibs[ICMP_MIB_MAX];
+};
+
+#define ICMPMSG_MIB_MAX __ICMPMSG_MIB_MAX
+struct icmpmsg_mib {
+ atomic_long_t mibs[ICMPMSG_MIB_MAX];
+};
+
+/* ICMP6 (IPv6-ICMP) */
+#define ICMP6_MIB_MAX __ICMP6_MIB_MAX
+/* per network ns counters */
+struct icmpv6_mib {
+ unsigned long mibs[ICMP6_MIB_MAX];
+};
+/* per device counters, (shared on all cpus) */
+struct icmpv6_mib_device {
+ atomic_long_t mibs[ICMP6_MIB_MAX];
+};
+
+#define ICMP6MSG_MIB_MAX __ICMP6MSG_MIB_MAX
+/* per network ns counters */
+struct icmpv6msg_mib {
+ atomic_long_t mibs[ICMP6MSG_MIB_MAX];
+};
+/* per device counters, (shared on all cpus) */
+struct icmpv6msg_mib_device {
+ atomic_long_t mibs[ICMP6MSG_MIB_MAX];
+};
+
+
+/* TCP */
+#define TCP_MIB_MAX __TCP_MIB_MAX
+struct tcp_mib {
+ unsigned long mibs[TCP_MIB_MAX];
+};
+
+/* UDP */
+#define UDP_MIB_MAX __UDP_MIB_MAX
+struct udp_mib {
+ unsigned long mibs[UDP_MIB_MAX];
+};
+
+/* Linux */
+#define LINUX_MIB_MAX __LINUX_MIB_MAX
+struct linux_mib {
+ unsigned long mibs[LINUX_MIB_MAX];
+};
+
+/* Linux Xfrm */
+#define LINUX_MIB_XFRMMAX __LINUX_MIB_XFRMMAX
+struct linux_xfrm_mib {
+ unsigned long mibs[LINUX_MIB_XFRMMAX];
+};
+
+#define SNMP_ARRAY_SZ 1
+
+#define DEFINE_SNMP_STAT(type, name) \
+ __typeof__(type) __percpu *name[SNMP_ARRAY_SZ]
+#define DEFINE_SNMP_STAT_ATOMIC(type, name) \
+ __typeof__(type) *name
+#define DECLARE_SNMP_STAT(type, name) \
+ extern __typeof__(type) __percpu *name[SNMP_ARRAY_SZ]
+
+#define SNMP_INC_STATS_BH(mib, field) \
+ __this_cpu_inc(mib[0]->mibs[field])
+
+#define SNMP_INC_STATS_USER(mib, field) \
+ this_cpu_inc(mib[0]->mibs[field])
+
+#define SNMP_INC_STATS_ATOMIC_LONG(mib, field) \
+ atomic_long_inc(&mib->mibs[field])
+
+#define SNMP_INC_STATS(mib, field) \
+ this_cpu_inc(mib[0]->mibs[field])
+
+#define SNMP_DEC_STATS(mib, field) \
+ this_cpu_dec(mib[0]->mibs[field])
+
+#define SNMP_ADD_STATS_BH(mib, field, addend) \
+ __this_cpu_add(mib[0]->mibs[field], addend)
+
+#define SNMP_ADD_STATS_USER(mib, field, addend) \
+ this_cpu_add(mib[0]->mibs[field], addend)
+
+#define SNMP_ADD_STATS(mib, field, addend) \
+ this_cpu_add(mib[0]->mibs[field], addend)
+/*
+ * Use "__typeof__(*mib[0]) *ptr" instead of "__typeof__(mib[0]) ptr"
+ * to make @ptr a non-percpu pointer.
+ */
+#define SNMP_UPD_PO_STATS(mib, basefield, addend) \
+ do { \
+ this_cpu_inc(mib[0]->mibs[basefield##PKTS]); \
+ this_cpu_add(mib[0]->mibs[basefield##OCTETS], addend); \
+ } while (0)
+#define SNMP_UPD_PO_STATS_BH(mib, basefield, addend) \
+ do { \
+ __this_cpu_inc(mib[0]->mibs[basefield##PKTS]); \
+ __this_cpu_add(mib[0]->mibs[basefield##OCTETS], addend); \
+ } while (0)
+
+
+#if BITS_PER_LONG==32
+
+#define SNMP_ADD_STATS64_BH(mib, field, addend) \
+ do { \
+ __typeof__(*mib[0]) *ptr = __this_cpu_ptr((mib)[0]); \
+ u64_stats_update_begin(&ptr->syncp); \
+ ptr->mibs[field] += addend; \
+ u64_stats_update_end(&ptr->syncp); \
+ } while (0)
+
+#define SNMP_ADD_STATS64_USER(mib, field, addend) \
+ do { \
+ local_bh_disable(); \
+ SNMP_ADD_STATS64_BH(mib, field, addend); \
+ local_bh_enable(); \
+ } while (0)
+
+#define SNMP_ADD_STATS64(mib, field, addend) \
+ SNMP_ADD_STATS64_USER(mib, field, addend)
+
+#define SNMP_INC_STATS64_BH(mib, field) SNMP_ADD_STATS64_BH(mib, field, 1)
+#define SNMP_INC_STATS64_USER(mib, field) SNMP_ADD_STATS64_USER(mib, field, 1)
+#define SNMP_INC_STATS64(mib, field) SNMP_ADD_STATS64(mib, field, 1)
+#define SNMP_UPD_PO_STATS64_BH(mib, basefield, addend) \
+ do { \
+ __typeof__(*mib[0]) *ptr; \
+ ptr = __this_cpu_ptr((mib)[0]); \
+ u64_stats_update_begin(&ptr->syncp); \
+ ptr->mibs[basefield##PKTS]++; \
+ ptr->mibs[basefield##OCTETS] += addend; \
+ u64_stats_update_end(&ptr->syncp); \
+ } while (0)
+#define SNMP_UPD_PO_STATS64(mib, basefield, addend) \
+ do { \
+ local_bh_disable(); \
+ SNMP_UPD_PO_STATS64_BH(mib, basefield, addend); \
+ local_bh_enable(); \
+ } while (0)
+#else
+#define SNMP_INC_STATS64_BH(mib, field) SNMP_INC_STATS_BH(mib, field)
+#define SNMP_INC_STATS64_USER(mib, field) SNMP_INC_STATS_USER(mib, field)
+#define SNMP_INC_STATS64(mib, field) SNMP_INC_STATS(mib, field)
+#define SNMP_DEC_STATS64(mib, field) SNMP_DEC_STATS(mib, field)
+#define SNMP_ADD_STATS64_BH(mib, field, addend) SNMP_ADD_STATS_BH(mib, field, addend)
+#define SNMP_ADD_STATS64_USER(mib, field, addend) SNMP_ADD_STATS_USER(mib, field, addend)
+#define SNMP_ADD_STATS64(mib, field, addend) SNMP_ADD_STATS(mib, field, addend)
+#define SNMP_UPD_PO_STATS64(mib, basefield, addend) SNMP_UPD_PO_STATS(mib, basefield, addend)
+#define SNMP_UPD_PO_STATS64_BH(mib, basefield, addend) SNMP_UPD_PO_STATS_BH(mib, basefield, addend)
+#endif
+
+#endif
diff --git a/include/net/sock.h b/include/net/sock.h
new file mode 100644
index 00000000..5a0a58ac
--- /dev/null
+++ b/include/net/sock.h
@@ -0,0 +1,2157 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the AF_INET socket handler.
+ *
+ * Version: @(#)sock.h 1.0.4 05/13/93
+ *
+ * Authors: Ross Biro
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Corey Minyard <wf-rch!minyard@relay.EU.net>
+ * Florian La Roche <flla@stud.uni-sb.de>
+ *
+ * Fixes:
+ * Alan Cox : Volatiles in skbuff pointers. See
+ * skbuff comments. May be overdone,
+ * better to prove they can be removed
+ * than the reverse.
+ * Alan Cox : Added a zapped field for tcp to note
+ * a socket is reset and must stay shut up
+ * Alan Cox : New fields for options
+ * Pauline Middelink : identd support
+ * Alan Cox : Eliminate low level recv/recvfrom
+ * David S. Miller : New socket lookup architecture.
+ * Steve Whitehouse: Default routines for sock_ops
+ * Arnaldo C. Melo : removed net_pinfo, tp_pinfo and made
+ * protinfo be just a void pointer, as the
+ * protocol specific parts were moved to
+ * respective headers and ipv4/v6, etc now
+ * use private slabcaches for its socks
+ * Pedro Hortas : New flags field for socket options
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _SOCK_H
+#define _SOCK_H
+
+#include <linux/hardirq.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/list_nulls.h>
+#include <linux/timer.h>
+#include <linux/cache.h>
+#include <linux/lockdep.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h> /* struct sk_buff */
+#include <linux/mm.h>
+#include <linux/security.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/memcontrol.h>
+#include <linux/res_counter.h>
+#include <linux/static_key.h>
+#include <linux/aio.h>
+#include <linux/sched.h>
+
+#include <linux/filter.h>
+#include <linux/rculist_nulls.h>
+#include <linux/poll.h>
+
+#include <linux/atomic.h>
+#include <net/dst.h>
+#include <net/checksum.h>
+
+struct cgroup;
+struct cgroup_subsys;
+#ifdef CONFIG_NET
+int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss);
+void mem_cgroup_sockets_destroy(struct cgroup *cgrp);
+#else
+static inline
+int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss)
+{
+ return 0;
+}
+static inline
+void mem_cgroup_sockets_destroy(struct cgroup *cgrp)
+{
+}
+#endif
+/*
+ * This structure really needs to be cleaned up.
+ * Most of it is for TCP, and not used by any of
+ * the other protocols.
+ */
+
+/* Define this to get the SOCK_DBG debugging facility. */
+#define SOCK_DEBUGGING
+#ifdef SOCK_DEBUGGING
+#define SOCK_DEBUG(sk, msg...) do { if ((sk) && sock_flag((sk), SOCK_DBG)) \
+ printk(KERN_DEBUG msg); } while (0)
+#else
+/* Validate arguments and do nothing */
+static inline __printf(2, 3)
+void SOCK_DEBUG(struct sock *sk, const char *msg, ...)
+{
+}
+#endif
+
+/* This is the per-socket lock. The spinlock provides a synchronization
+ * between user contexts and software interrupt processing, whereas the
+ * mini-semaphore synchronizes multiple users amongst themselves.
+ */
+typedef struct {
+ spinlock_t slock;
+ int owned;
+ wait_queue_head_t wq;
+ /*
+ * We express the mutex-alike socket_lock semantics
+ * to the lock validator by explicitly managing
+ * the slock as a lock variant (in addition to
+ * the slock itself):
+ */
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+ struct lockdep_map dep_map;
+#endif
+} socket_lock_t;
+
+struct sock;
+struct proto;
+struct net;
+
+/**
+ * struct sock_common - minimal network layer representation of sockets
+ * @skc_daddr: Foreign IPv4 addr
+ * @skc_rcv_saddr: Bound local IPv4 addr
+ * @skc_hash: hash value used with various protocol lookup tables
+ * @skc_u16hashes: two u16 hash values used by UDP lookup tables
+ * @skc_family: network address family
+ * @skc_state: Connection state
+ * @skc_reuse: %SO_REUSEADDR setting
+ * @skc_bound_dev_if: bound device index if != 0
+ * @skc_bind_node: bind hash linkage for various protocol lookup tables
+ * @skc_portaddr_node: second hash linkage for UDP/UDP-Lite protocol
+ * @skc_prot: protocol handlers inside a network family
+ * @skc_net: reference to the network namespace of this socket
+ * @skc_node: main hash linkage for various protocol lookup tables
+ * @skc_nulls_node: main hash linkage for TCP/UDP/UDP-Lite protocol
+ * @skc_tx_queue_mapping: tx queue number for this connection
+ * @skc_refcnt: reference count
+ *
+ * This is the minimal network layer representation of sockets, the header
+ * for struct sock and struct inet_timewait_sock.
+ */
+struct sock_common {
+ /* skc_daddr and skc_rcv_saddr must be grouped :
+ * cf INET_MATCH() and INET_TW_MATCH()
+ */
+ __be32 skc_daddr;
+ __be32 skc_rcv_saddr;
+
+ union {
+ unsigned int skc_hash;
+ __u16 skc_u16hashes[2];
+ };
+ unsigned short skc_family;
+ volatile unsigned char skc_state;
+ unsigned char skc_reuse;
+ int skc_bound_dev_if;
+ union {
+ struct hlist_node skc_bind_node;
+ struct hlist_nulls_node skc_portaddr_node;
+ };
+ struct proto *skc_prot;
+#ifdef CONFIG_NET_NS
+ struct net *skc_net;
+#endif
+ /*
+ * fields between dontcopy_begin/dontcopy_end
+ * are not copied in sock_copy()
+ */
+ /* private: */
+ int skc_dontcopy_begin[0];
+ /* public: */
+ union {
+ struct hlist_node skc_node;
+ struct hlist_nulls_node skc_nulls_node;
+ };
+ int skc_tx_queue_mapping;
+ atomic_t skc_refcnt;
+ /* private: */
+ int skc_dontcopy_end[0];
+ /* public: */
+};
+
+struct cg_proto;
+/**
+ * struct sock - network layer representation of sockets
+ * @__sk_common: shared layout with inet_timewait_sock
+ * @sk_shutdown: mask of %SEND_SHUTDOWN and/or %RCV_SHUTDOWN
+ * @sk_userlocks: %SO_SNDBUF and %SO_RCVBUF settings
+ * @sk_lock: synchronizer
+ * @sk_rcvbuf: size of receive buffer in bytes
+ * @sk_wq: sock wait queue and async head
+ * @sk_dst_cache: destination cache
+ * @sk_dst_lock: destination cache lock
+ * @sk_policy: flow policy
+ * @sk_receive_queue: incoming packets
+ * @sk_wmem_alloc: transmit queue bytes committed
+ * @sk_write_queue: Packet sending queue
+ * @sk_async_wait_queue: DMA copied packets
+ * @sk_omem_alloc: "o" is "option" or "other"
+ * @sk_wmem_queued: persistent queue size
+ * @sk_forward_alloc: space allocated forward
+ * @sk_allocation: allocation mode
+ * @sk_sndbuf: size of send buffer in bytes
+ * @sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE,
+ * %SO_OOBINLINE settings, %SO_TIMESTAMPING settings
+ * @sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets
+ * @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO)
+ * @sk_route_nocaps: forbidden route capabilities (e.g NETIF_F_GSO_MASK)
+ * @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4)
+ * @sk_gso_max_size: Maximum GSO segment size to build
+ * @sk_lingertime: %SO_LINGER l_linger setting
+ * @sk_backlog: always used with the per-socket spinlock held
+ * @sk_callback_lock: used with the callbacks in the end of this struct
+ * @sk_error_queue: rarely used
+ * @sk_prot_creator: sk_prot of original sock creator (see ipv6_setsockopt,
+ * IPV6_ADDRFORM for instance)
+ * @sk_err: last error
+ * @sk_err_soft: errors that don't cause failure but are the cause of a
+ * persistent failure not just 'timed out'
+ * @sk_drops: raw/udp drops counter
+ * @sk_ack_backlog: current listen backlog
+ * @sk_max_ack_backlog: listen backlog set in listen()
+ * @sk_priority: %SO_PRIORITY setting
+ * @sk_cgrp_prioidx: socket group's priority map index
+ * @sk_type: socket type (%SOCK_STREAM, etc)
+ * @sk_protocol: which protocol this socket belongs in this network family
+ * @sk_peer_pid: &struct pid for this socket's peer
+ * @sk_peer_cred: %SO_PEERCRED setting
+ * @sk_rcvlowat: %SO_RCVLOWAT setting
+ * @sk_rcvtimeo: %SO_RCVTIMEO setting
+ * @sk_sndtimeo: %SO_SNDTIMEO setting
+ * @sk_rxhash: flow hash received from netif layer
+ * @sk_filter: socket filtering instructions
+ * @sk_protinfo: private area, net family specific, when not using slab
+ * @sk_timer: sock cleanup timer
+ * @sk_stamp: time stamp of last packet received
+ * @sk_socket: Identd and reporting IO signals
+ * @sk_user_data: RPC layer private data
+ * @sk_sndmsg_page: cached page for sendmsg
+ * @sk_sndmsg_off: cached offset for sendmsg
+ * @sk_peek_off: current peek_offset value
+ * @sk_send_head: front of stuff to transmit
+ * @sk_security: used by security modules
+ * @sk_mark: generic packet mark
+ * @sk_classid: this socket's cgroup classid
+ * @sk_cgrp: this socket's cgroup-specific proto data
+ * @sk_write_pending: a write to stream socket waits to start
+ * @sk_state_change: callback to indicate change in the state of the sock
+ * @sk_data_ready: callback to indicate there is data to be processed
+ * @sk_write_space: callback to indicate there is bf sending space available
+ * @sk_error_report: callback to indicate errors (e.g. %MSG_ERRQUEUE)
+ * @sk_backlog_rcv: callback to process the backlog
+ * @sk_destruct: called at sock freeing time, i.e. when all refcnt == 0
+ */
+struct sock {
+ /*
+ * Now struct inet_timewait_sock also uses sock_common, so please just
+ * don't add nothing before this first member (__sk_common) --acme
+ */
+ struct sock_common __sk_common;
+#define sk_node __sk_common.skc_node
+#define sk_nulls_node __sk_common.skc_nulls_node
+#define sk_refcnt __sk_common.skc_refcnt
+#define sk_tx_queue_mapping __sk_common.skc_tx_queue_mapping
+
+#define sk_dontcopy_begin __sk_common.skc_dontcopy_begin
+#define sk_dontcopy_end __sk_common.skc_dontcopy_end
+#define sk_hash __sk_common.skc_hash
+#define sk_family __sk_common.skc_family
+#define sk_state __sk_common.skc_state
+#define sk_reuse __sk_common.skc_reuse
+#define sk_bound_dev_if __sk_common.skc_bound_dev_if
+#define sk_bind_node __sk_common.skc_bind_node
+#define sk_prot __sk_common.skc_prot
+#define sk_net __sk_common.skc_net
+ socket_lock_t sk_lock;
+ struct sk_buff_head sk_receive_queue;
+ /*
+ * The backlog queue is special, it is always used with
+ * the per-socket spinlock held and requires low latency
+ * access. Therefore we special case it's implementation.
+ * Note : rmem_alloc is in this structure to fill a hole
+ * on 64bit arches, not because its logically part of
+ * backlog.
+ */
+ struct {
+ atomic_t rmem_alloc;
+ int len;
+ struct sk_buff *head;
+ struct sk_buff *tail;
+ } sk_backlog;
+#define sk_rmem_alloc sk_backlog.rmem_alloc
+ int sk_forward_alloc;
+#ifdef CONFIG_RPS
+ __u32 sk_rxhash;
+#endif
+ atomic_t sk_drops;
+ int sk_rcvbuf;
+
+ struct sk_filter __rcu *sk_filter;
+ struct socket_wq __rcu *sk_wq;
+
+#ifdef CONFIG_NET_DMA
+ struct sk_buff_head sk_async_wait_queue;
+#endif
+
+#ifdef CONFIG_XFRM
+ struct xfrm_policy *sk_policy[2];
+#endif
+ unsigned long sk_flags;
+ struct dst_entry *sk_dst_cache;
+ spinlock_t sk_dst_lock;
+ atomic_t sk_wmem_alloc;
+ atomic_t sk_omem_alloc;
+ int sk_sndbuf;
+ struct sk_buff_head sk_write_queue;
+ kmemcheck_bitfield_begin(flags);
+ unsigned int sk_shutdown : 2,
+ sk_no_check : 2,
+ sk_userlocks : 4,
+ sk_protocol : 8,
+ sk_type : 16;
+ kmemcheck_bitfield_end(flags);
+ int sk_wmem_queued;
+ gfp_t sk_allocation;
+ netdev_features_t sk_route_caps;
+ netdev_features_t sk_route_nocaps;
+ int sk_gso_type;
+ unsigned int sk_gso_max_size;
+ int sk_rcvlowat;
+ unsigned long sk_lingertime;
+ struct sk_buff_head sk_error_queue;
+ struct proto *sk_prot_creator;
+ rwlock_t sk_callback_lock;
+ int sk_err,
+ sk_err_soft;
+ unsigned short sk_ack_backlog;
+ unsigned short sk_max_ack_backlog;
+ __u32 sk_priority;
+#ifdef CONFIG_CGROUPS
+ __u32 sk_cgrp_prioidx;
+#endif
+ struct pid *sk_peer_pid;
+ const struct cred *sk_peer_cred;
+ long sk_rcvtimeo;
+ long sk_sndtimeo;
+ void *sk_protinfo;
+ struct timer_list sk_timer;
+ ktime_t sk_stamp;
+ struct socket *sk_socket;
+ void *sk_user_data;
+ struct page *sk_sndmsg_page;
+ struct sk_buff *sk_send_head;
+ __u32 sk_sndmsg_off;
+ __s32 sk_peek_off;
+ int sk_write_pending;
+#ifdef CONFIG_SECURITY
+ void *sk_security;
+#endif
+ __u32 sk_mark;
+ u32 sk_classid;
+ struct cg_proto *sk_cgrp;
+ void (*sk_state_change)(struct sock *sk);
+ void (*sk_data_ready)(struct sock *sk, int bytes);
+ void (*sk_write_space)(struct sock *sk);
+ void (*sk_error_report)(struct sock *sk);
+ int (*sk_backlog_rcv)(struct sock *sk,
+ struct sk_buff *skb);
+ void (*sk_destruct)(struct sock *sk);
+};
+
+static inline int sk_peek_offset(struct sock *sk, int flags)
+{
+ if ((flags & MSG_PEEK) && (sk->sk_peek_off >= 0))
+ return sk->sk_peek_off;
+ else
+ return 0;
+}
+
+static inline void sk_peek_offset_bwd(struct sock *sk, int val)
+{
+ if (sk->sk_peek_off >= 0) {
+ if (sk->sk_peek_off >= val)
+ sk->sk_peek_off -= val;
+ else
+ sk->sk_peek_off = 0;
+ }
+}
+
+static inline void sk_peek_offset_fwd(struct sock *sk, int val)
+{
+ if (sk->sk_peek_off >= 0)
+ sk->sk_peek_off += val;
+}
+
+/*
+ * Hashed lists helper routines
+ */
+static inline struct sock *sk_entry(const struct hlist_node *node)
+{
+ return hlist_entry(node, struct sock, sk_node);
+}
+
+static inline struct sock *__sk_head(const struct hlist_head *head)
+{
+ return hlist_entry(head->first, struct sock, sk_node);
+}
+
+static inline struct sock *sk_head(const struct hlist_head *head)
+{
+ return hlist_empty(head) ? NULL : __sk_head(head);
+}
+
+static inline struct sock *__sk_nulls_head(const struct hlist_nulls_head *head)
+{
+ return hlist_nulls_entry(head->first, struct sock, sk_nulls_node);
+}
+
+static inline struct sock *sk_nulls_head(const struct hlist_nulls_head *head)
+{
+ return hlist_nulls_empty(head) ? NULL : __sk_nulls_head(head);
+}
+
+static inline struct sock *sk_next(const struct sock *sk)
+{
+ return sk->sk_node.next ?
+ hlist_entry(sk->sk_node.next, struct sock, sk_node) : NULL;
+}
+
+static inline struct sock *sk_nulls_next(const struct sock *sk)
+{
+ return (!is_a_nulls(sk->sk_nulls_node.next)) ?
+ hlist_nulls_entry(sk->sk_nulls_node.next,
+ struct sock, sk_nulls_node) :
+ NULL;
+}
+
+static inline int sk_unhashed(const struct sock *sk)
+{
+ return hlist_unhashed(&sk->sk_node);
+}
+
+static inline int sk_hashed(const struct sock *sk)
+{
+ return !sk_unhashed(sk);
+}
+
+static __inline__ void sk_node_init(struct hlist_node *node)
+{
+ node->pprev = NULL;
+}
+
+static __inline__ void sk_nulls_node_init(struct hlist_nulls_node *node)
+{
+ node->pprev = NULL;
+}
+
+static __inline__ void __sk_del_node(struct sock *sk)
+{
+ __hlist_del(&sk->sk_node);
+}
+
+/* NB: equivalent to hlist_del_init_rcu */
+static __inline__ int __sk_del_node_init(struct sock *sk)
+{
+ if (sk_hashed(sk)) {
+ __sk_del_node(sk);
+ sk_node_init(&sk->sk_node);
+ return 1;
+ }
+ return 0;
+}
+
+/* Grab socket reference count. This operation is valid only
+ when sk is ALREADY grabbed f.e. it is found in hash table
+ or a list and the lookup is made under lock preventing hash table
+ modifications.
+ */
+
+static inline void sock_hold(struct sock *sk)
+{
+ atomic_inc(&sk->sk_refcnt);
+}
+
+/* Ungrab socket in the context, which assumes that socket refcnt
+ cannot hit zero, f.e. it is true in context of any socketcall.
+ */
+static inline void __sock_put(struct sock *sk)
+{
+ atomic_dec(&sk->sk_refcnt);
+}
+
+static __inline__ int sk_del_node_init(struct sock *sk)
+{
+ int rc = __sk_del_node_init(sk);
+
+ if (rc) {
+ /* paranoid for a while -acme */
+ WARN_ON(atomic_read(&sk->sk_refcnt) == 1);
+ __sock_put(sk);
+ }
+ return rc;
+}
+#define sk_del_node_init_rcu(sk) sk_del_node_init(sk)
+
+static __inline__ int __sk_nulls_del_node_init_rcu(struct sock *sk)
+{
+ if (sk_hashed(sk)) {
+ hlist_nulls_del_init_rcu(&sk->sk_nulls_node);
+ return 1;
+ }
+ return 0;
+}
+
+static __inline__ int sk_nulls_del_node_init_rcu(struct sock *sk)
+{
+ int rc = __sk_nulls_del_node_init_rcu(sk);
+
+ if (rc) {
+ /* paranoid for a while -acme */
+ WARN_ON(atomic_read(&sk->sk_refcnt) == 1);
+ __sock_put(sk);
+ }
+ return rc;
+}
+
+static __inline__ void __sk_add_node(struct sock *sk, struct hlist_head *list)
+{
+ hlist_add_head(&sk->sk_node, list);
+}
+
+static __inline__ void sk_add_node(struct sock *sk, struct hlist_head *list)
+{
+ sock_hold(sk);
+ __sk_add_node(sk, list);
+}
+
+static __inline__ void sk_add_node_rcu(struct sock *sk, struct hlist_head *list)
+{
+ sock_hold(sk);
+ hlist_add_head_rcu(&sk->sk_node, list);
+}
+
+static __inline__ void __sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_head *list)
+{
+ hlist_nulls_add_head_rcu(&sk->sk_nulls_node, list);
+}
+
+static __inline__ void sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_head *list)
+{
+ sock_hold(sk);
+ __sk_nulls_add_node_rcu(sk, list);
+}
+
+static __inline__ void __sk_del_bind_node(struct sock *sk)
+{
+ __hlist_del(&sk->sk_bind_node);
+}
+
+static __inline__ void sk_add_bind_node(struct sock *sk,
+ struct hlist_head *list)
+{
+ hlist_add_head(&sk->sk_bind_node, list);
+}
+
+#define sk_for_each(__sk, node, list) \
+ hlist_for_each_entry(__sk, node, list, sk_node)
+#define sk_for_each_rcu(__sk, node, list) \
+ hlist_for_each_entry_rcu(__sk, node, list, sk_node)
+#define sk_nulls_for_each(__sk, node, list) \
+ hlist_nulls_for_each_entry(__sk, node, list, sk_nulls_node)
+#define sk_nulls_for_each_rcu(__sk, node, list) \
+ hlist_nulls_for_each_entry_rcu(__sk, node, list, sk_nulls_node)
+#define sk_for_each_from(__sk, node) \
+ if (__sk && ({ node = &(__sk)->sk_node; 1; })) \
+ hlist_for_each_entry_from(__sk, node, sk_node)
+#define sk_nulls_for_each_from(__sk, node) \
+ if (__sk && ({ node = &(__sk)->sk_nulls_node; 1; })) \
+ hlist_nulls_for_each_entry_from(__sk, node, sk_nulls_node)
+#define sk_for_each_safe(__sk, node, tmp, list) \
+ hlist_for_each_entry_safe(__sk, node, tmp, list, sk_node)
+#define sk_for_each_bound(__sk, node, list) \
+ hlist_for_each_entry(__sk, node, list, sk_bind_node)
+
+/* Sock flags */
+enum sock_flags {
+ SOCK_DEAD,
+ SOCK_DONE,
+ SOCK_URGINLINE,
+ SOCK_KEEPOPEN,
+ SOCK_LINGER,
+ SOCK_DESTROY,
+ SOCK_BROADCAST,
+ SOCK_TIMESTAMP,
+ SOCK_ZAPPED,
+ SOCK_USE_WRITE_QUEUE, /* whether to call sk->sk_write_space in sock_wfree */
+ SOCK_DBG, /* %SO_DEBUG setting */
+ SOCK_RCVTSTAMP, /* %SO_TIMESTAMP setting */
+ SOCK_RCVTSTAMPNS, /* %SO_TIMESTAMPNS setting */
+ SOCK_LOCALROUTE, /* route locally only, %SO_DONTROUTE setting */
+ SOCK_QUEUE_SHRUNK, /* write queue has been shrunk recently */
+ SOCK_TIMESTAMPING_TX_HARDWARE, /* %SOF_TIMESTAMPING_TX_HARDWARE */
+ SOCK_TIMESTAMPING_TX_SOFTWARE, /* %SOF_TIMESTAMPING_TX_SOFTWARE */
+ SOCK_TIMESTAMPING_RX_HARDWARE, /* %SOF_TIMESTAMPING_RX_HARDWARE */
+ SOCK_TIMESTAMPING_RX_SOFTWARE, /* %SOF_TIMESTAMPING_RX_SOFTWARE */
+ SOCK_TIMESTAMPING_SOFTWARE, /* %SOF_TIMESTAMPING_SOFTWARE */
+ SOCK_TIMESTAMPING_RAW_HARDWARE, /* %SOF_TIMESTAMPING_RAW_HARDWARE */
+ SOCK_TIMESTAMPING_SYS_HARDWARE, /* %SOF_TIMESTAMPING_SYS_HARDWARE */
+ SOCK_FASYNC, /* fasync() active */
+ SOCK_RXQ_OVFL,
+ SOCK_ZEROCOPY, /* buffers from userspace */
+ SOCK_WIFI_STATUS, /* push wifi status to userspace */
+ SOCK_NOFCS, /* Tell NIC not to do the Ethernet FCS.
+ * Will use last 4 bytes of packet sent from
+ * user-space instead.
+ */
+};
+
+static inline void sock_copy_flags(struct sock *nsk, struct sock *osk)
+{
+ nsk->sk_flags = osk->sk_flags;
+}
+
+static inline void sock_set_flag(struct sock *sk, enum sock_flags flag)
+{
+ __set_bit(flag, &sk->sk_flags);
+}
+
+static inline void sock_reset_flag(struct sock *sk, enum sock_flags flag)
+{
+ __clear_bit(flag, &sk->sk_flags);
+}
+
+static inline int sock_flag(struct sock *sk, enum sock_flags flag)
+{
+ return test_bit(flag, &sk->sk_flags);
+}
+
+static inline void sk_acceptq_removed(struct sock *sk)
+{
+ sk->sk_ack_backlog--;
+}
+
+static inline void sk_acceptq_added(struct sock *sk)
+{
+ sk->sk_ack_backlog++;
+}
+
+static inline int sk_acceptq_is_full(struct sock *sk)
+{
+ return sk->sk_ack_backlog > sk->sk_max_ack_backlog;
+}
+
+/*
+ * Compute minimal free write space needed to queue new packets.
+ */
+static inline int sk_stream_min_wspace(struct sock *sk)
+{
+ return sk->sk_wmem_queued >> 1;
+}
+
+static inline int sk_stream_wspace(struct sock *sk)
+{
+ return sk->sk_sndbuf - sk->sk_wmem_queued;
+}
+
+extern void sk_stream_write_space(struct sock *sk);
+
+static inline int sk_stream_memory_free(struct sock *sk)
+{
+ return sk->sk_wmem_queued < sk->sk_sndbuf;
+}
+
+/* OOB backlog add */
+static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb)
+{
+ /* dont let skb dst not refcounted, we are going to leave rcu lock */
+ skb_dst_force(skb);
+
+ if (!sk->sk_backlog.tail)
+ sk->sk_backlog.head = skb;
+ else
+ sk->sk_backlog.tail->next = skb;
+
+ sk->sk_backlog.tail = skb;
+ skb->next = NULL;
+}
+
+/*
+ * Take into account size of receive queue and backlog queue
+ * Do not take into account this skb truesize,
+ * to allow even a single big packet to come.
+ */
+static inline bool sk_rcvqueues_full(const struct sock *sk, const struct sk_buff *skb)
+{
+ unsigned int qsize = sk->sk_backlog.len + atomic_read(&sk->sk_rmem_alloc);
+
+ return qsize > sk->sk_rcvbuf;
+}
+
+/* The per-socket spinlock must be held here. */
+static inline __must_check int sk_add_backlog(struct sock *sk, struct sk_buff *skb)
+{
+ if (sk_rcvqueues_full(sk, skb))
+ return -ENOBUFS;
+
+ __sk_add_backlog(sk, skb);
+ sk->sk_backlog.len += skb->truesize;
+ return 0;
+}
+
+static inline int sk_backlog_rcv(struct sock *sk, struct sk_buff *skb)
+{
+ return sk->sk_backlog_rcv(sk, skb);
+}
+
+static inline void sock_rps_record_flow(const struct sock *sk)
+{
+#ifdef CONFIG_RPS
+ struct rps_sock_flow_table *sock_flow_table;
+
+ rcu_read_lock();
+ sock_flow_table = rcu_dereference(rps_sock_flow_table);
+ rps_record_sock_flow(sock_flow_table, sk->sk_rxhash);
+ rcu_read_unlock();
+#endif
+}
+
+static inline void sock_rps_reset_flow(const struct sock *sk)
+{
+#ifdef CONFIG_RPS
+ struct rps_sock_flow_table *sock_flow_table;
+
+ rcu_read_lock();
+ sock_flow_table = rcu_dereference(rps_sock_flow_table);
+ rps_reset_sock_flow(sock_flow_table, sk->sk_rxhash);
+ rcu_read_unlock();
+#endif
+}
+
+static inline void sock_rps_save_rxhash(struct sock *sk,
+ const struct sk_buff *skb)
+{
+#ifdef CONFIG_RPS
+ if (unlikely(sk->sk_rxhash != skb->rxhash)) {
+ sock_rps_reset_flow(sk);
+ sk->sk_rxhash = skb->rxhash;
+ }
+#endif
+}
+
+static inline void sock_rps_reset_rxhash(struct sock *sk)
+{
+#ifdef CONFIG_RPS
+ sock_rps_reset_flow(sk);
+ sk->sk_rxhash = 0;
+#endif
+}
+
+#define sk_wait_event(__sk, __timeo, __condition) \
+ ({ int __rc; \
+ release_sock(__sk); \
+ __rc = __condition; \
+ if (!__rc) { \
+ *(__timeo) = schedule_timeout(*(__timeo)); \
+ } \
+ lock_sock(__sk); \
+ __rc = __condition; \
+ __rc; \
+ })
+
+extern int sk_stream_wait_connect(struct sock *sk, long *timeo_p);
+extern int sk_stream_wait_memory(struct sock *sk, long *timeo_p);
+extern void sk_stream_wait_close(struct sock *sk, long timeo_p);
+extern int sk_stream_error(struct sock *sk, int flags, int err);
+extern void sk_stream_kill_queues(struct sock *sk);
+
+extern int sk_wait_data(struct sock *sk, long *timeo);
+
+struct request_sock_ops;
+struct timewait_sock_ops;
+struct inet_hashinfo;
+struct raw_hashinfo;
+struct module;
+
+/* Networking protocol blocks we attach to sockets.
+ * socket layer -> transport layer interface
+ * transport -> network interface is defined by struct inet_proto
+ */
+struct proto {
+ void (*close)(struct sock *sk,
+ long timeout);
+ int (*connect)(struct sock *sk,
+ struct sockaddr *uaddr,
+ int addr_len);
+ int (*disconnect)(struct sock *sk, int flags);
+
+ struct sock * (*accept) (struct sock *sk, int flags, int *err);
+
+ int (*ioctl)(struct sock *sk, int cmd,
+ unsigned long arg);
+ int (*init)(struct sock *sk);
+ void (*destroy)(struct sock *sk);
+ void (*shutdown)(struct sock *sk, int how);
+ int (*setsockopt)(struct sock *sk, int level,
+ int optname, char __user *optval,
+ unsigned int optlen);
+ int (*getsockopt)(struct sock *sk, int level,
+ int optname, char __user *optval,
+ int __user *option);
+#ifdef CONFIG_COMPAT
+ int (*compat_setsockopt)(struct sock *sk,
+ int level,
+ int optname, char __user *optval,
+ unsigned int optlen);
+ int (*compat_getsockopt)(struct sock *sk,
+ int level,
+ int optname, char __user *optval,
+ int __user *option);
+ int (*compat_ioctl)(struct sock *sk,
+ unsigned int cmd, unsigned long arg);
+#endif
+ int (*sendmsg)(struct kiocb *iocb, struct sock *sk,
+ struct msghdr *msg, size_t len);
+ int (*recvmsg)(struct kiocb *iocb, struct sock *sk,
+ struct msghdr *msg,
+ size_t len, int noblock, int flags,
+ int *addr_len);
+ int (*sendpage)(struct sock *sk, struct page *page,
+ int offset, size_t size, int flags);
+ int (*bind)(struct sock *sk,
+ struct sockaddr *uaddr, int addr_len);
+
+ int (*backlog_rcv) (struct sock *sk,
+ struct sk_buff *skb);
+
+ /* Keeping track of sk's, looking them up, and port selection methods. */
+ void (*hash)(struct sock *sk);
+ void (*unhash)(struct sock *sk);
+ void (*rehash)(struct sock *sk);
+ int (*get_port)(struct sock *sk, unsigned short snum);
+ void (*clear_sk)(struct sock *sk, int size);
+
+ /* Keeping track of sockets in use */
+#ifdef CONFIG_PROC_FS
+ unsigned int inuse_idx;
+#endif
+
+ /* Memory pressure */
+ void (*enter_memory_pressure)(struct sock *sk);
+ atomic_long_t *memory_allocated; /* Current allocated memory. */
+ struct percpu_counter *sockets_allocated; /* Current number of sockets. */
+ /*
+ * Pressure flag: try to collapse.
+ * Technical note: it is used by multiple contexts non atomically.
+ * All the __sk_mem_schedule() is of this nature: accounting
+ * is strict, actions are advisory and have some latency.
+ */
+ int *memory_pressure;
+ long *sysctl_mem;
+ int *sysctl_wmem;
+ int *sysctl_rmem;
+ int max_header;
+ bool no_autobind;
+
+ struct kmem_cache *slab;
+ unsigned int obj_size;
+ int slab_flags;
+
+ struct percpu_counter *orphan_count;
+
+ struct request_sock_ops *rsk_prot;
+ struct timewait_sock_ops *twsk_prot;
+
+ union {
+ struct inet_hashinfo *hashinfo;
+ struct udp_table *udp_table;
+ struct raw_hashinfo *raw_hash;
+ } h;
+
+ struct module *owner;
+
+ char name[32];
+
+ struct list_head node;
+#ifdef SOCK_REFCNT_DEBUG
+ atomic_t socks;
+#endif
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
+ /*
+ * cgroup specific init/deinit functions. Called once for all
+ * protocols that implement it, from cgroups populate function.
+ * This function has to setup any files the protocol want to
+ * appear in the kmem cgroup filesystem.
+ */
+ int (*init_cgroup)(struct cgroup *cgrp,
+ struct cgroup_subsys *ss);
+ void (*destroy_cgroup)(struct cgroup *cgrp);
+ struct cg_proto *(*proto_cgroup)(struct mem_cgroup *memcg);
+#endif
+};
+
+struct cg_proto {
+ void (*enter_memory_pressure)(struct sock *sk);
+ struct res_counter *memory_allocated; /* Current allocated memory. */
+ struct percpu_counter *sockets_allocated; /* Current number of sockets. */
+ int *memory_pressure;
+ long *sysctl_mem;
+ /*
+ * memcg field is used to find which memcg we belong directly
+ * Each memcg struct can hold more than one cg_proto, so container_of
+ * won't really cut.
+ *
+ * The elegant solution would be having an inverse function to
+ * proto_cgroup in struct proto, but that means polluting the structure
+ * for everybody, instead of just for memcg users.
+ */
+ struct mem_cgroup *memcg;
+};
+
+extern int proto_register(struct proto *prot, int alloc_slab);
+extern void proto_unregister(struct proto *prot);
+
+#ifdef SOCK_REFCNT_DEBUG
+static inline void sk_refcnt_debug_inc(struct sock *sk)
+{
+ atomic_inc(&sk->sk_prot->socks);
+}
+
+static inline void sk_refcnt_debug_dec(struct sock *sk)
+{
+ atomic_dec(&sk->sk_prot->socks);
+ printk(KERN_DEBUG "%s socket %p released, %d are still alive\n",
+ sk->sk_prot->name, sk, atomic_read(&sk->sk_prot->socks));
+}
+
+inline void sk_refcnt_debug_release(const struct sock *sk)
+{
+ if (atomic_read(&sk->sk_refcnt) != 1)
+ printk(KERN_DEBUG "Destruction of the %s socket %p delayed, refcnt=%d\n",
+ sk->sk_prot->name, sk, atomic_read(&sk->sk_refcnt));
+}
+#else /* SOCK_REFCNT_DEBUG */
+#define sk_refcnt_debug_inc(sk) do { } while (0)
+#define sk_refcnt_debug_dec(sk) do { } while (0)
+#define sk_refcnt_debug_release(sk) do { } while (0)
+#endif /* SOCK_REFCNT_DEBUG */
+
+#if defined(CONFIG_CGROUP_MEM_RES_CTLR_KMEM) && defined(CONFIG_NET)
+extern struct static_key memcg_socket_limit_enabled;
+static inline struct cg_proto *parent_cg_proto(struct proto *proto,
+ struct cg_proto *cg_proto)
+{
+ return proto->proto_cgroup(parent_mem_cgroup(cg_proto->memcg));
+}
+#define mem_cgroup_sockets_enabled static_key_false(&memcg_socket_limit_enabled)
+#else
+#define mem_cgroup_sockets_enabled 0
+static inline struct cg_proto *parent_cg_proto(struct proto *proto,
+ struct cg_proto *cg_proto)
+{
+ return NULL;
+}
+#endif
+
+
+static inline bool sk_has_memory_pressure(const struct sock *sk)
+{
+ return sk->sk_prot->memory_pressure != NULL;
+}
+
+static inline bool sk_under_memory_pressure(const struct sock *sk)
+{
+ if (!sk->sk_prot->memory_pressure)
+ return false;
+
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
+ return !!*sk->sk_cgrp->memory_pressure;
+
+ return !!*sk->sk_prot->memory_pressure;
+}
+
+static inline void sk_leave_memory_pressure(struct sock *sk)
+{
+ int *memory_pressure = sk->sk_prot->memory_pressure;
+
+ if (!memory_pressure)
+ return;
+
+ if (*memory_pressure)
+ *memory_pressure = 0;
+
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp) {
+ struct cg_proto *cg_proto = sk->sk_cgrp;
+ struct proto *prot = sk->sk_prot;
+
+ for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto))
+ if (*cg_proto->memory_pressure)
+ *cg_proto->memory_pressure = 0;
+ }
+
+}
+
+static inline void sk_enter_memory_pressure(struct sock *sk)
+{
+ if (!sk->sk_prot->enter_memory_pressure)
+ return;
+
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp) {
+ struct cg_proto *cg_proto = sk->sk_cgrp;
+ struct proto *prot = sk->sk_prot;
+
+ for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto))
+ cg_proto->enter_memory_pressure(sk);
+ }
+
+ sk->sk_prot->enter_memory_pressure(sk);
+}
+
+static inline long sk_prot_mem_limits(const struct sock *sk, int index)
+{
+ long *prot = sk->sk_prot->sysctl_mem;
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
+ prot = sk->sk_cgrp->sysctl_mem;
+ return prot[index];
+}
+
+static inline void memcg_memory_allocated_add(struct cg_proto *prot,
+ unsigned long amt,
+ int *parent_status)
+{
+ struct res_counter *fail;
+ int ret;
+
+ ret = res_counter_charge_nofail(prot->memory_allocated,
+ amt << PAGE_SHIFT, &fail);
+ if (ret < 0)
+ *parent_status = OVER_LIMIT;
+}
+
+static inline void memcg_memory_allocated_sub(struct cg_proto *prot,
+ unsigned long amt)
+{
+ res_counter_uncharge(prot->memory_allocated, amt << PAGE_SHIFT);
+}
+
+static inline u64 memcg_memory_allocated_read(struct cg_proto *prot)
+{
+ u64 ret;
+ ret = res_counter_read_u64(prot->memory_allocated, RES_USAGE);
+ return ret >> PAGE_SHIFT;
+}
+
+static inline long
+sk_memory_allocated(const struct sock *sk)
+{
+ struct proto *prot = sk->sk_prot;
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
+ return memcg_memory_allocated_read(sk->sk_cgrp);
+
+ return atomic_long_read(prot->memory_allocated);
+}
+
+static inline long
+sk_memory_allocated_add(struct sock *sk, int amt, int *parent_status)
+{
+ struct proto *prot = sk->sk_prot;
+
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp) {
+ memcg_memory_allocated_add(sk->sk_cgrp, amt, parent_status);
+ /* update the root cgroup regardless */
+ atomic_long_add_return(amt, prot->memory_allocated);
+ return memcg_memory_allocated_read(sk->sk_cgrp);
+ }
+
+ return atomic_long_add_return(amt, prot->memory_allocated);
+}
+
+static inline void
+sk_memory_allocated_sub(struct sock *sk, int amt)
+{
+ struct proto *prot = sk->sk_prot;
+
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
+ memcg_memory_allocated_sub(sk->sk_cgrp, amt);
+
+ atomic_long_sub(amt, prot->memory_allocated);
+}
+
+static inline void sk_sockets_allocated_dec(struct sock *sk)
+{
+ struct proto *prot = sk->sk_prot;
+
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp) {
+ struct cg_proto *cg_proto = sk->sk_cgrp;
+
+ for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto))
+ percpu_counter_dec(cg_proto->sockets_allocated);
+ }
+
+ percpu_counter_dec(prot->sockets_allocated);
+}
+
+static inline void sk_sockets_allocated_inc(struct sock *sk)
+{
+ struct proto *prot = sk->sk_prot;
+
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp) {
+ struct cg_proto *cg_proto = sk->sk_cgrp;
+
+ for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto))
+ percpu_counter_inc(cg_proto->sockets_allocated);
+ }
+
+ percpu_counter_inc(prot->sockets_allocated);
+}
+
+static inline int
+sk_sockets_allocated_read_positive(struct sock *sk)
+{
+ struct proto *prot = sk->sk_prot;
+
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
+ return percpu_counter_read_positive(sk->sk_cgrp->sockets_allocated);
+
+ return percpu_counter_read_positive(prot->sockets_allocated);
+}
+
+static inline int
+proto_sockets_allocated_sum_positive(struct proto *prot)
+{
+ return percpu_counter_sum_positive(prot->sockets_allocated);
+}
+
+static inline long
+proto_memory_allocated(struct proto *prot)
+{
+ return atomic_long_read(prot->memory_allocated);
+}
+
+static inline bool
+proto_memory_pressure(struct proto *prot)
+{
+ if (!prot->memory_pressure)
+ return false;
+ return !!*prot->memory_pressure;
+}
+
+
+#ifdef CONFIG_PROC_FS
+/* Called with local bh disabled */
+extern void sock_prot_inuse_add(struct net *net, struct proto *prot, int inc);
+extern int sock_prot_inuse_get(struct net *net, struct proto *proto);
+#else
+static void inline sock_prot_inuse_add(struct net *net, struct proto *prot,
+ int inc)
+{
+}
+#endif
+
+
+/* With per-bucket locks this operation is not-atomic, so that
+ * this version is not worse.
+ */
+static inline void __sk_prot_rehash(struct sock *sk)
+{
+ sk->sk_prot->unhash(sk);
+ sk->sk_prot->hash(sk);
+}
+
+void sk_prot_clear_portaddr_nulls(struct sock *sk, int size);
+
+/* About 10 seconds */
+#define SOCK_DESTROY_TIME (10*HZ)
+
+/* Sockets 0-1023 can't be bound to unless you are superuser */
+#define PROT_SOCK 1024
+
+#define SHUTDOWN_MASK 3
+#define RCV_SHUTDOWN 1
+#define SEND_SHUTDOWN 2
+
+#define SOCK_SNDBUF_LOCK 1
+#define SOCK_RCVBUF_LOCK 2
+#define SOCK_BINDADDR_LOCK 4
+#define SOCK_BINDPORT_LOCK 8
+
+/* sock_iocb: used to kick off async processing of socket ios */
+struct sock_iocb {
+ struct list_head list;
+
+ int flags;
+ int size;
+ struct socket *sock;
+ struct sock *sk;
+ struct scm_cookie *scm;
+ struct msghdr *msg, async_msg;
+ struct kiocb *kiocb;
+};
+
+static inline struct sock_iocb *kiocb_to_siocb(struct kiocb *iocb)
+{
+ return (struct sock_iocb *)iocb->private;
+}
+
+static inline struct kiocb *siocb_to_kiocb(struct sock_iocb *si)
+{
+ return si->kiocb;
+}
+
+struct socket_alloc {
+ struct socket socket;
+ struct inode vfs_inode;
+};
+
+static inline struct socket *SOCKET_I(struct inode *inode)
+{
+ return &container_of(inode, struct socket_alloc, vfs_inode)->socket;
+}
+
+static inline struct inode *SOCK_INODE(struct socket *socket)
+{
+ return &container_of(socket, struct socket_alloc, socket)->vfs_inode;
+}
+
+/*
+ * Functions for memory accounting
+ */
+extern int __sk_mem_schedule(struct sock *sk, int size, int kind);
+extern void __sk_mem_reclaim(struct sock *sk);
+
+#define SK_MEM_QUANTUM ((int)PAGE_SIZE)
+#define SK_MEM_QUANTUM_SHIFT ilog2(SK_MEM_QUANTUM)
+#define SK_MEM_SEND 0
+#define SK_MEM_RECV 1
+
+static inline int sk_mem_pages(int amt)
+{
+ return (amt + SK_MEM_QUANTUM - 1) >> SK_MEM_QUANTUM_SHIFT;
+}
+
+static inline int sk_has_account(struct sock *sk)
+{
+ /* return true if protocol supports memory accounting */
+ return !!sk->sk_prot->memory_allocated;
+}
+
+static inline int sk_wmem_schedule(struct sock *sk, int size)
+{
+ if (!sk_has_account(sk))
+ return 1;
+ return size <= sk->sk_forward_alloc ||
+ __sk_mem_schedule(sk, size, SK_MEM_SEND);
+}
+
+static inline int sk_rmem_schedule(struct sock *sk, int size)
+{
+ if (!sk_has_account(sk))
+ return 1;
+ return size <= sk->sk_forward_alloc ||
+ __sk_mem_schedule(sk, size, SK_MEM_RECV);
+}
+
+static inline void sk_mem_reclaim(struct sock *sk)
+{
+ if (!sk_has_account(sk))
+ return;
+ if (sk->sk_forward_alloc >= SK_MEM_QUANTUM)
+ __sk_mem_reclaim(sk);
+}
+
+static inline void sk_mem_reclaim_partial(struct sock *sk)
+{
+ if (!sk_has_account(sk))
+ return;
+ if (sk->sk_forward_alloc > SK_MEM_QUANTUM)
+ __sk_mem_reclaim(sk);
+}
+
+static inline void sk_mem_charge(struct sock *sk, int size)
+{
+ if (!sk_has_account(sk))
+ return;
+ sk->sk_forward_alloc -= size;
+}
+
+static inline void sk_mem_uncharge(struct sock *sk, int size)
+{
+ if (!sk_has_account(sk))
+ return;
+ sk->sk_forward_alloc += size;
+}
+
+static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb)
+{
+ sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
+ sk->sk_wmem_queued -= skb->truesize;
+ sk_mem_uncharge(sk, skb->truesize);
+ __kfree_skb(skb);
+}
+
+/* Used by processes to "lock" a socket state, so that
+ * interrupts and bottom half handlers won't change it
+ * from under us. It essentially blocks any incoming
+ * packets, so that we won't get any new data or any
+ * packets that change the state of the socket.
+ *
+ * While locked, BH processing will add new packets to
+ * the backlog queue. This queue is processed by the
+ * owner of the socket lock right before it is released.
+ *
+ * Since ~2.3.5 it is also exclusive sleep lock serializing
+ * accesses from user process context.
+ */
+#define sock_owned_by_user(sk) ((sk)->sk_lock.owned)
+
+/*
+ * Macro so as to not evaluate some arguments when
+ * lockdep is not enabled.
+ *
+ * Mark both the sk_lock and the sk_lock.slock as a
+ * per-address-family lock class.
+ */
+#define sock_lock_init_class_and_name(sk, sname, skey, name, key) \
+do { \
+ sk->sk_lock.owned = 0; \
+ init_waitqueue_head(&sk->sk_lock.wq); \
+ spin_lock_init(&(sk)->sk_lock.slock); \
+ debug_check_no_locks_freed((void *)&(sk)->sk_lock, \
+ sizeof((sk)->sk_lock)); \
+ lockdep_set_class_and_name(&(sk)->sk_lock.slock, \
+ (skey), (sname)); \
+ lockdep_init_map(&(sk)->sk_lock.dep_map, (name), (key), 0); \
+} while (0)
+
+extern void lock_sock_nested(struct sock *sk, int subclass);
+
+static inline void lock_sock(struct sock *sk)
+{
+ lock_sock_nested(sk, 0);
+}
+
+extern void release_sock(struct sock *sk);
+
+/* BH context may only use the following locking interface. */
+#define bh_lock_sock(__sk) spin_lock(&((__sk)->sk_lock.slock))
+#define bh_lock_sock_nested(__sk) \
+ spin_lock_nested(&((__sk)->sk_lock.slock), \
+ SINGLE_DEPTH_NESTING)
+#define bh_unlock_sock(__sk) spin_unlock(&((__sk)->sk_lock.slock))
+
+extern bool lock_sock_fast(struct sock *sk);
+/**
+ * unlock_sock_fast - complement of lock_sock_fast
+ * @sk: socket
+ * @slow: slow mode
+ *
+ * fast unlock socket for user context.
+ * If slow mode is on, we call regular release_sock()
+ */
+static inline void unlock_sock_fast(struct sock *sk, bool slow)
+{
+ if (slow)
+ release_sock(sk);
+ else
+ spin_unlock_bh(&sk->sk_lock.slock);
+}
+
+
+extern struct sock *sk_alloc(struct net *net, int family,
+ gfp_t priority,
+ struct proto *prot);
+extern void sk_free(struct sock *sk);
+extern void sk_release_kernel(struct sock *sk);
+extern struct sock *sk_clone_lock(const struct sock *sk,
+ const gfp_t priority);
+
+extern struct sk_buff *sock_wmalloc(struct sock *sk,
+ unsigned long size, int force,
+ gfp_t priority);
+extern struct sk_buff *sock_rmalloc(struct sock *sk,
+ unsigned long size, int force,
+ gfp_t priority);
+extern void sock_wfree(struct sk_buff *skb);
+extern void sock_rfree(struct sk_buff *skb);
+
+extern int sock_setsockopt(struct socket *sock, int level,
+ int op, char __user *optval,
+ unsigned int optlen);
+
+extern int sock_getsockopt(struct socket *sock, int level,
+ int op, char __user *optval,
+ int __user *optlen);
+extern struct sk_buff *sock_alloc_send_skb(struct sock *sk,
+ unsigned long size,
+ int noblock,
+ int *errcode);
+extern struct sk_buff *sock_alloc_send_pskb(struct sock *sk,
+ unsigned long header_len,
+ unsigned long data_len,
+ int noblock,
+ int *errcode);
+extern void *sock_kmalloc(struct sock *sk, int size,
+ gfp_t priority);
+extern void sock_kfree_s(struct sock *sk, void *mem, int size);
+extern void sk_send_sigurg(struct sock *sk);
+
+#ifdef CONFIG_CGROUPS
+extern void sock_update_classid(struct sock *sk);
+#else
+static inline void sock_update_classid(struct sock *sk)
+{
+}
+#endif
+
+/*
+ * Functions to fill in entries in struct proto_ops when a protocol
+ * does not implement a particular function.
+ */
+extern int sock_no_bind(struct socket *,
+ struct sockaddr *, int);
+extern int sock_no_connect(struct socket *,
+ struct sockaddr *, int, int);
+extern int sock_no_socketpair(struct socket *,
+ struct socket *);
+extern int sock_no_accept(struct socket *,
+ struct socket *, int);
+extern int sock_no_getname(struct socket *,
+ struct sockaddr *, int *, int);
+extern unsigned int sock_no_poll(struct file *, struct socket *,
+ struct poll_table_struct *);
+extern int sock_no_ioctl(struct socket *, unsigned int,
+ unsigned long);
+extern int sock_no_listen(struct socket *, int);
+extern int sock_no_shutdown(struct socket *, int);
+extern int sock_no_getsockopt(struct socket *, int , int,
+ char __user *, int __user *);
+extern int sock_no_setsockopt(struct socket *, int, int,
+ char __user *, unsigned int);
+extern int sock_no_sendmsg(struct kiocb *, struct socket *,
+ struct msghdr *, size_t);
+extern int sock_no_recvmsg(struct kiocb *, struct socket *,
+ struct msghdr *, size_t, int);
+extern int sock_no_mmap(struct file *file,
+ struct socket *sock,
+ struct vm_area_struct *vma);
+extern ssize_t sock_no_sendpage(struct socket *sock,
+ struct page *page,
+ int offset, size_t size,
+ int flags);
+
+/*
+ * Functions to fill in entries in struct proto_ops when a protocol
+ * uses the inet style.
+ */
+extern int sock_common_getsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, int __user *optlen);
+extern int sock_common_recvmsg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *msg, size_t size, int flags);
+extern int sock_common_setsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, unsigned int optlen);
+extern int compat_sock_common_getsockopt(struct socket *sock, int level,
+ int optname, char __user *optval, int __user *optlen);
+extern int compat_sock_common_setsockopt(struct socket *sock, int level,
+ int optname, char __user *optval, unsigned int optlen);
+
+extern void sk_common_release(struct sock *sk);
+
+/*
+ * Default socket callbacks and setup code
+ */
+
+/* Initialise core socket variables */
+extern void sock_init_data(struct socket *sock, struct sock *sk);
+
+extern void sk_filter_release_rcu(struct rcu_head *rcu);
+
+/**
+ * sk_filter_release - release a socket filter
+ * @fp: filter to remove
+ *
+ * Remove a filter from a socket and release its resources.
+ */
+
+static inline void sk_filter_release(struct sk_filter *fp)
+{
+ if (atomic_dec_and_test(&fp->refcnt))
+ call_rcu(&fp->rcu, sk_filter_release_rcu);
+}
+
+static inline void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp)
+{
+ unsigned int size = sk_filter_len(fp);
+
+ atomic_sub(size, &sk->sk_omem_alloc);
+ sk_filter_release(fp);
+}
+
+static inline void sk_filter_charge(struct sock *sk, struct sk_filter *fp)
+{
+ atomic_inc(&fp->refcnt);
+ atomic_add(sk_filter_len(fp), &sk->sk_omem_alloc);
+}
+
+/*
+ * Socket reference counting postulates.
+ *
+ * * Each user of socket SHOULD hold a reference count.
+ * * Each access point to socket (an hash table bucket, reference from a list,
+ * running timer, skb in flight MUST hold a reference count.
+ * * When reference count hits 0, it means it will never increase back.
+ * * When reference count hits 0, it means that no references from
+ * outside exist to this socket and current process on current CPU
+ * is last user and may/should destroy this socket.
+ * * sk_free is called from any context: process, BH, IRQ. When
+ * it is called, socket has no references from outside -> sk_free
+ * may release descendant resources allocated by the socket, but
+ * to the time when it is called, socket is NOT referenced by any
+ * hash tables, lists etc.
+ * * Packets, delivered from outside (from network or from another process)
+ * and enqueued on receive/error queues SHOULD NOT grab reference count,
+ * when they sit in queue. Otherwise, packets will leak to hole, when
+ * socket is looked up by one cpu and unhasing is made by another CPU.
+ * It is true for udp/raw, netlink (leak to receive and error queues), tcp
+ * (leak to backlog). Packet socket does all the processing inside
+ * BR_NETPROTO_LOCK, so that it has not this race condition. UNIX sockets
+ * use separate SMP lock, so that they are prone too.
+ */
+
+/* Ungrab socket and destroy it, if it was the last reference. */
+static inline void sock_put(struct sock *sk)
+{
+ if (atomic_dec_and_test(&sk->sk_refcnt))
+ sk_free(sk);
+}
+
+extern int sk_receive_skb(struct sock *sk, struct sk_buff *skb,
+ const int nested);
+
+static inline void sk_tx_queue_set(struct sock *sk, int tx_queue)
+{
+ sk->sk_tx_queue_mapping = tx_queue;
+}
+
+static inline void sk_tx_queue_clear(struct sock *sk)
+{
+ sk->sk_tx_queue_mapping = -1;
+}
+
+static inline int sk_tx_queue_get(const struct sock *sk)
+{
+ return sk ? sk->sk_tx_queue_mapping : -1;
+}
+
+static inline void sk_set_socket(struct sock *sk, struct socket *sock)
+{
+ sk_tx_queue_clear(sk);
+ sk->sk_socket = sock;
+}
+
+static inline wait_queue_head_t *sk_sleep(struct sock *sk)
+{
+ BUILD_BUG_ON(offsetof(struct socket_wq, wait) != 0);
+ return &rcu_dereference_raw(sk->sk_wq)->wait;
+}
+/* Detach socket from process context.
+ * Announce socket dead, detach it from wait queue and inode.
+ * Note that parent inode held reference count on this struct sock,
+ * we do not release it in this function, because protocol
+ * probably wants some additional cleanups or even continuing
+ * to work with this socket (TCP).
+ */
+static inline void sock_orphan(struct sock *sk)
+{
+ write_lock_bh(&sk->sk_callback_lock);
+ sock_set_flag(sk, SOCK_DEAD);
+ sk_set_socket(sk, NULL);
+ sk->sk_wq = NULL;
+ write_unlock_bh(&sk->sk_callback_lock);
+}
+
+static inline void sock_graft(struct sock *sk, struct socket *parent)
+{
+ write_lock_bh(&sk->sk_callback_lock);
+ sk->sk_wq = parent->wq;
+ parent->sk = sk;
+ sk_set_socket(sk, parent);
+ security_sock_graft(sk, parent);
+ write_unlock_bh(&sk->sk_callback_lock);
+}
+
+extern int sock_i_uid(struct sock *sk);
+extern unsigned long sock_i_ino(struct sock *sk);
+
+static inline struct dst_entry *
+__sk_dst_get(struct sock *sk)
+{
+ return rcu_dereference_check(sk->sk_dst_cache, sock_owned_by_user(sk) ||
+ lockdep_is_held(&sk->sk_lock.slock));
+}
+
+static inline struct dst_entry *
+sk_dst_get(struct sock *sk)
+{
+ struct dst_entry *dst;
+
+ rcu_read_lock();
+ dst = rcu_dereference(sk->sk_dst_cache);
+ if (dst)
+ dst_hold(dst);
+ rcu_read_unlock();
+ return dst;
+}
+
+extern void sk_reset_txq(struct sock *sk);
+
+static inline void dst_negative_advice(struct sock *sk)
+{
+ struct dst_entry *ndst, *dst = __sk_dst_get(sk);
+
+ if (dst && dst->ops->negative_advice) {
+ ndst = dst->ops->negative_advice(dst);
+
+ if (ndst != dst) {
+ rcu_assign_pointer(sk->sk_dst_cache, ndst);
+ sk_reset_txq(sk);
+ }
+ }
+}
+
+static inline void
+__sk_dst_set(struct sock *sk, struct dst_entry *dst)
+{
+ struct dst_entry *old_dst;
+
+ sk_tx_queue_clear(sk);
+ /*
+ * This can be called while sk is owned by the caller only,
+ * with no state that can be checked in a rcu_dereference_check() cond
+ */
+ old_dst = rcu_dereference_raw(sk->sk_dst_cache);
+ rcu_assign_pointer(sk->sk_dst_cache, dst);
+ dst_release(old_dst);
+}
+
+static inline void
+sk_dst_set(struct sock *sk, struct dst_entry *dst)
+{
+ spin_lock(&sk->sk_dst_lock);
+ __sk_dst_set(sk, dst);
+ spin_unlock(&sk->sk_dst_lock);
+}
+
+static inline void
+__sk_dst_reset(struct sock *sk)
+{
+ __sk_dst_set(sk, NULL);
+}
+
+static inline void
+sk_dst_reset(struct sock *sk)
+{
+ spin_lock(&sk->sk_dst_lock);
+ __sk_dst_reset(sk);
+ spin_unlock(&sk->sk_dst_lock);
+}
+
+extern struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie);
+
+extern struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie);
+
+static inline int sk_can_gso(const struct sock *sk)
+{
+ return net_gso_ok(sk->sk_route_caps, sk->sk_gso_type);
+}
+
+extern void sk_setup_caps(struct sock *sk, struct dst_entry *dst);
+
+static inline void sk_nocaps_add(struct sock *sk, netdev_features_t flags)
+{
+ sk->sk_route_nocaps |= flags;
+ sk->sk_route_caps &= ~flags;
+}
+
+static inline int skb_do_copy_data_nocache(struct sock *sk, struct sk_buff *skb,
+ char __user *from, char *to,
+ int copy, int offset)
+{
+ if (skb->ip_summed == CHECKSUM_NONE) {
+ int err = 0;
+ __wsum csum = csum_and_copy_from_user(from, to, copy, 0, &err);
+ if (err)
+ return err;
+ skb->csum = csum_block_add(skb->csum, csum, offset);
+ } else if (sk->sk_route_caps & NETIF_F_NOCACHE_COPY) {
+ if (!access_ok(VERIFY_READ, from, copy) ||
+ __copy_from_user_nocache(to, from, copy))
+ return -EFAULT;
+ } else if (copy_from_user(to, from, copy))
+ return -EFAULT;
+
+ return 0;
+}
+
+static inline int skb_add_data_nocache(struct sock *sk, struct sk_buff *skb,
+ char __user *from, int copy)
+{
+ int err, offset = skb->len;
+
+ err = skb_do_copy_data_nocache(sk, skb, from, skb_put(skb, copy),
+ copy, offset);
+ if (err)
+ __skb_trim(skb, offset);
+
+ return err;
+}
+
+static inline int skb_copy_to_page_nocache(struct sock *sk, char __user *from,
+ struct sk_buff *skb,
+ struct page *page,
+ int off, int copy)
+{
+ int err;
+
+ err = skb_do_copy_data_nocache(sk, skb, from, page_address(page) + off,
+ copy, skb->len);
+ if (err)
+ return err;
+
+ skb->len += copy;
+ skb->data_len += copy;
+ skb->truesize += copy;
+ sk->sk_wmem_queued += copy;
+ sk_mem_charge(sk, copy);
+ return 0;
+}
+
+static inline int skb_copy_to_page(struct sock *sk, char __user *from,
+ struct sk_buff *skb, struct page *page,
+ int off, int copy)
+{
+ if (skb->ip_summed == CHECKSUM_NONE) {
+ int err = 0;
+ __wsum csum = csum_and_copy_from_user(from,
+ page_address(page) + off,
+ copy, 0, &err);
+ if (err)
+ return err;
+ skb->csum = csum_block_add(skb->csum, csum, skb->len);
+ } else if (copy_from_user(page_address(page) + off, from, copy))
+ return -EFAULT;
+
+ skb->len += copy;
+ skb->data_len += copy;
+ skb->truesize += copy;
+ sk->sk_wmem_queued += copy;
+ sk_mem_charge(sk, copy);
+ return 0;
+}
+
+/**
+ * sk_wmem_alloc_get - returns write allocations
+ * @sk: socket
+ *
+ * Returns sk_wmem_alloc minus initial offset of one
+ */
+static inline int sk_wmem_alloc_get(const struct sock *sk)
+{
+ return atomic_read(&sk->sk_wmem_alloc) - 1;
+}
+
+/**
+ * sk_rmem_alloc_get - returns read allocations
+ * @sk: socket
+ *
+ * Returns sk_rmem_alloc
+ */
+static inline int sk_rmem_alloc_get(const struct sock *sk)
+{
+ return atomic_read(&sk->sk_rmem_alloc);
+}
+
+/**
+ * sk_has_allocations - check if allocations are outstanding
+ * @sk: socket
+ *
+ * Returns true if socket has write or read allocations
+ */
+static inline int sk_has_allocations(const struct sock *sk)
+{
+ return sk_wmem_alloc_get(sk) || sk_rmem_alloc_get(sk);
+}
+
+/**
+ * wq_has_sleeper - check if there are any waiting processes
+ * @wq: struct socket_wq
+ *
+ * Returns true if socket_wq has waiting processes
+ *
+ * The purpose of the wq_has_sleeper and sock_poll_wait is to wrap the memory
+ * barrier call. They were added due to the race found within the tcp code.
+ *
+ * Consider following tcp code paths:
+ *
+ * CPU1 CPU2
+ *
+ * sys_select receive packet
+ * ... ...
+ * __add_wait_queue update tp->rcv_nxt
+ * ... ...
+ * tp->rcv_nxt check sock_def_readable
+ * ... {
+ * schedule rcu_read_lock();
+ * wq = rcu_dereference(sk->sk_wq);
+ * if (wq && waitqueue_active(&wq->wait))
+ * wake_up_interruptible(&wq->wait)
+ * ...
+ * }
+ *
+ * The race for tcp fires when the __add_wait_queue changes done by CPU1 stay
+ * in its cache, and so does the tp->rcv_nxt update on CPU2 side. The CPU1
+ * could then endup calling schedule and sleep forever if there are no more
+ * data on the socket.
+ *
+ */
+static inline bool wq_has_sleeper(struct socket_wq *wq)
+{
+
+ /*
+ * We need to be sure we are in sync with the
+ * add_wait_queue modifications to the wait queue.
+ *
+ * This memory barrier is paired in the sock_poll_wait.
+ */
+ smp_mb();
+ return wq && waitqueue_active(&wq->wait);
+}
+
+/**
+ * sock_poll_wait - place memory barrier behind the poll_wait call.
+ * @filp: file
+ * @wait_address: socket wait queue
+ * @p: poll_table
+ *
+ * See the comments in the wq_has_sleeper function.
+ */
+static inline void sock_poll_wait(struct file *filp,
+ wait_queue_head_t *wait_address, poll_table *p)
+{
+ if (!poll_does_not_wait(p) && wait_address) {
+ poll_wait(filp, wait_address, p);
+ /*
+ * We need to be sure we are in sync with the
+ * socket flags modification.
+ *
+ * This memory barrier is paired in the wq_has_sleeper.
+ */
+ smp_mb();
+ }
+}
+
+/*
+ * Queue a received datagram if it will fit. Stream and sequenced
+ * protocols can't normally use this as they need to fit buffers in
+ * and play with them.
+ *
+ * Inlined as it's very short and called for pretty much every
+ * packet ever received.
+ */
+
+static inline void skb_set_owner_w(struct sk_buff *skb, struct sock *sk)
+{
+ skb_orphan(skb);
+ skb->sk = sk;
+ skb->destructor = sock_wfree;
+ /*
+ * We used to take a refcount on sk, but following operation
+ * is enough to guarantee sk_free() wont free this sock until
+ * all in-flight packets are completed
+ */
+ atomic_add(skb->truesize, &sk->sk_wmem_alloc);
+}
+
+static inline void skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
+{
+ skb_orphan(skb);
+ skb->sk = sk;
+ skb->destructor = sock_rfree;
+ atomic_add(skb->truesize, &sk->sk_rmem_alloc);
+ sk_mem_charge(sk, skb->truesize);
+}
+
+extern void sk_reset_timer(struct sock *sk, struct timer_list* timer,
+ unsigned long expires);
+
+extern void sk_stop_timer(struct sock *sk, struct timer_list* timer);
+
+extern int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
+
+extern int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb);
+
+/*
+ * Recover an error report and clear atomically
+ */
+
+static inline int sock_error(struct sock *sk)
+{
+ int err;
+ if (likely(!sk->sk_err))
+ return 0;
+ err = xchg(&sk->sk_err, 0);
+ return -err;
+}
+
+static inline unsigned long sock_wspace(struct sock *sk)
+{
+ int amt = 0;
+
+ if (!(sk->sk_shutdown & SEND_SHUTDOWN)) {
+ amt = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);
+ if (amt < 0)
+ amt = 0;
+ }
+ return amt;
+}
+
+static inline void sk_wake_async(struct sock *sk, int how, int band)
+{
+ if (sock_flag(sk, SOCK_FASYNC))
+ sock_wake_async(sk->sk_socket, how, band);
+}
+
+#define SOCK_MIN_SNDBUF 2048
+/*
+ * Since sk_rmem_alloc sums skb->truesize, even a small frame might need
+ * sizeof(sk_buff) + MTU + padding, unless net driver perform copybreak
+ */
+#define SOCK_MIN_RCVBUF (2048 + sizeof(struct sk_buff))
+
+static inline void sk_stream_moderate_sndbuf(struct sock *sk)
+{
+ if (!(sk->sk_userlocks & SOCK_SNDBUF_LOCK)) {
+ sk->sk_sndbuf = min(sk->sk_sndbuf, sk->sk_wmem_queued >> 1);
+ sk->sk_sndbuf = max(sk->sk_sndbuf, SOCK_MIN_SNDBUF);
+ }
+}
+
+struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp);
+
+static inline struct page *sk_stream_alloc_page(struct sock *sk)
+{
+ struct page *page = NULL;
+
+ page = alloc_pages(sk->sk_allocation, 0);
+ if (!page) {
+ sk_enter_memory_pressure(sk);
+ sk_stream_moderate_sndbuf(sk);
+ }
+ return page;
+}
+
+/*
+ * Default write policy as shown to user space via poll/select/SIGIO
+ */
+static inline int sock_writeable(const struct sock *sk)
+{
+ return atomic_read(&sk->sk_wmem_alloc) < (sk->sk_sndbuf >> 1);
+}
+
+static inline gfp_t gfp_any(void)
+{
+ return in_softirq() ? GFP_ATOMIC : GFP_KERNEL;
+}
+
+static inline long sock_rcvtimeo(const struct sock *sk, int noblock)
+{
+ return noblock ? 0 : sk->sk_rcvtimeo;
+}
+
+static inline long sock_sndtimeo(const struct sock *sk, int noblock)
+{
+ return noblock ? 0 : sk->sk_sndtimeo;
+}
+
+static inline int sock_rcvlowat(const struct sock *sk, int waitall, int len)
+{
+ return (waitall ? len : min_t(int, sk->sk_rcvlowat, len)) ? : 1;
+}
+
+/* Alas, with timeout socket operations are not restartable.
+ * Compare this to poll().
+ */
+static inline int sock_intr_errno(long timeo)
+{
+ return timeo == MAX_SCHEDULE_TIMEOUT ? -ERESTARTSYS : -EINTR;
+}
+
+extern void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
+ struct sk_buff *skb);
+extern void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
+ struct sk_buff *skb);
+
+static __inline__ void
+sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
+{
+ ktime_t kt = skb->tstamp;
+ struct skb_shared_hwtstamps *hwtstamps = skb_hwtstamps(skb);
+
+ /*
+ * generate control messages if
+ * - receive time stamping in software requested (SOCK_RCVTSTAMP
+ * or SOCK_TIMESTAMPING_RX_SOFTWARE)
+ * - software time stamp available and wanted
+ * (SOCK_TIMESTAMPING_SOFTWARE)
+ * - hardware time stamps available and wanted
+ * (SOCK_TIMESTAMPING_SYS_HARDWARE or
+ * SOCK_TIMESTAMPING_RAW_HARDWARE)
+ */
+ if (sock_flag(sk, SOCK_RCVTSTAMP) ||
+ sock_flag(sk, SOCK_TIMESTAMPING_RX_SOFTWARE) ||
+ (kt.tv64 && sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) ||
+ (hwtstamps->hwtstamp.tv64 &&
+ sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE)) ||
+ (hwtstamps->syststamp.tv64 &&
+ sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE)))
+ __sock_recv_timestamp(msg, sk, skb);
+ else
+ sk->sk_stamp = kt;
+
+ if (sock_flag(sk, SOCK_WIFI_STATUS) && skb->wifi_acked_valid)
+ __sock_recv_wifi_status(msg, sk, skb);
+}
+
+extern void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
+ struct sk_buff *skb);
+
+static inline void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
+ struct sk_buff *skb)
+{
+#define FLAGS_TS_OR_DROPS ((1UL << SOCK_RXQ_OVFL) | \
+ (1UL << SOCK_RCVTSTAMP) | \
+ (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE) | \
+ (1UL << SOCK_TIMESTAMPING_SOFTWARE) | \
+ (1UL << SOCK_TIMESTAMPING_RAW_HARDWARE) | \
+ (1UL << SOCK_TIMESTAMPING_SYS_HARDWARE))
+
+ if (sk->sk_flags & FLAGS_TS_OR_DROPS)
+ __sock_recv_ts_and_drops(msg, sk, skb);
+ else
+ sk->sk_stamp = skb->tstamp;
+}
+
+/**
+ * sock_tx_timestamp - checks whether the outgoing packet is to be time stamped
+ * @sk: socket sending this packet
+ * @tx_flags: filled with instructions for time stamping
+ *
+ * Currently only depends on SOCK_TIMESTAMPING* flags. Returns error code if
+ * parameters are invalid.
+ */
+extern int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags);
+
+/**
+ * sk_eat_skb - Release a skb if it is no longer needed
+ * @sk: socket to eat this skb from
+ * @skb: socket buffer to eat
+ * @copied_early: flag indicating whether DMA operations copied this data early
+ *
+ * This routine must be called with interrupts disabled or with the socket
+ * locked so that the sk_buff queue operation is ok.
+*/
+#ifdef CONFIG_NET_DMA
+static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb, int copied_early)
+{
+ __skb_unlink(skb, &sk->sk_receive_queue);
+ if (!copied_early)
+ __kfree_skb(skb);
+ else
+ __skb_queue_tail(&sk->sk_async_wait_queue, skb);
+}
+#else
+static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb, int copied_early)
+{
+ __skb_unlink(skb, &sk->sk_receive_queue);
+ __kfree_skb(skb);
+}
+#endif
+
+static inline
+struct net *sock_net(const struct sock *sk)
+{
+ return read_pnet(&sk->sk_net);
+}
+
+static inline
+void sock_net_set(struct sock *sk, struct net *net)
+{
+ write_pnet(&sk->sk_net, net);
+}
+
+/*
+ * Kernel sockets, f.e. rtnl or icmp_socket, are a part of a namespace.
+ * They should not hold a reference to a namespace in order to allow
+ * to stop it.
+ * Sockets after sk_change_net should be released using sk_release_kernel
+ */
+static inline void sk_change_net(struct sock *sk, struct net *net)
+{
+ put_net(sock_net(sk));
+ sock_net_set(sk, hold_net(net));
+}
+
+static inline struct sock *skb_steal_sock(struct sk_buff *skb)
+{
+ if (unlikely(skb->sk)) {
+ struct sock *sk = skb->sk;
+
+ skb->destructor = NULL;
+ skb->sk = NULL;
+ return sk;
+ }
+ return NULL;
+}
+
+extern void sock_enable_timestamp(struct sock *sk, int flag);
+extern int sock_get_timestamp(struct sock *, struct timeval __user *);
+extern int sock_get_timestampns(struct sock *, struct timespec __user *);
+
+/*
+ * Enable debug/info messages
+ */
+extern int net_msg_warn;
+#define NETDEBUG(fmt, args...) \
+ do { if (net_msg_warn) printk(fmt,##args); } while (0)
+
+#define LIMIT_NETDEBUG(fmt, args...) \
+ do { if (net_msg_warn && net_ratelimit()) printk(fmt,##args); } while(0)
+
+extern __u32 sysctl_wmem_max;
+extern __u32 sysctl_rmem_max;
+
+extern void sk_init(void);
+
+extern int sysctl_optmem_max;
+
+extern __u32 sysctl_wmem_default;
+extern __u32 sysctl_rmem_default;
+
+#endif /* _SOCK_H */
diff --git a/include/net/stp.h b/include/net/stp.h
new file mode 100644
index 00000000..ad447f10
--- /dev/null
+++ b/include/net/stp.h
@@ -0,0 +1,14 @@
+#ifndef _NET_STP_H
+#define _NET_STP_H
+
+struct stp_proto {
+ unsigned char group_address[ETH_ALEN];
+ void (*rcv)(const struct stp_proto *, struct sk_buff *,
+ struct net_device *);
+ void *data;
+};
+
+extern int stp_proto_register(const struct stp_proto *proto);
+extern void stp_proto_unregister(const struct stp_proto *proto);
+
+#endif /* _NET_STP_H */
diff --git a/include/net/tc_act/tc_csum.h b/include/net/tc_act/tc_csum.h
new file mode 100644
index 00000000..9e8710be
--- /dev/null
+++ b/include/net/tc_act/tc_csum.h
@@ -0,0 +1,15 @@
+#ifndef __NET_TC_CSUM_H
+#define __NET_TC_CSUM_H
+
+#include <linux/types.h>
+#include <net/act_api.h>
+
+struct tcf_csum {
+ struct tcf_common common;
+
+ u32 update_flags;
+};
+#define to_tcf_csum(pc) \
+ container_of(pc,struct tcf_csum,common)
+
+#endif /* __NET_TC_CSUM_H */
diff --git a/include/net/tc_act/tc_defact.h b/include/net/tc_act/tc_defact.h
new file mode 100644
index 00000000..65f024b8
--- /dev/null
+++ b/include/net/tc_act/tc_defact.h
@@ -0,0 +1,14 @@
+#ifndef __NET_TC_DEF_H
+#define __NET_TC_DEF_H
+
+#include <net/act_api.h>
+
+struct tcf_defact {
+ struct tcf_common common;
+ u32 tcfd_datalen;
+ void *tcfd_defdata;
+};
+#define to_defact(pc) \
+ container_of(pc, struct tcf_defact, common)
+
+#endif /* __NET_TC_DEF_H */
diff --git a/include/net/tc_act/tc_gact.h b/include/net/tc_act/tc_gact.h
new file mode 100644
index 00000000..9e3f6767
--- /dev/null
+++ b/include/net/tc_act/tc_gact.h
@@ -0,0 +1,17 @@
+#ifndef __NET_TC_GACT_H
+#define __NET_TC_GACT_H
+
+#include <net/act_api.h>
+
+struct tcf_gact {
+ struct tcf_common common;
+#ifdef CONFIG_GACT_PROB
+ u16 tcfg_ptype;
+ u16 tcfg_pval;
+ int tcfg_paction;
+#endif
+};
+#define to_gact(pc) \
+ container_of(pc, struct tcf_gact, common)
+
+#endif /* __NET_TC_GACT_H */
diff --git a/include/net/tc_act/tc_ipt.h b/include/net/tc_act/tc_ipt.h
new file mode 100644
index 00000000..f7d25dfc
--- /dev/null
+++ b/include/net/tc_act/tc_ipt.h
@@ -0,0 +1,17 @@
+#ifndef __NET_TC_IPT_H
+#define __NET_TC_IPT_H
+
+#include <net/act_api.h>
+
+struct xt_entry_target;
+
+struct tcf_ipt {
+ struct tcf_common common;
+ u32 tcfi_hook;
+ char *tcfi_tname;
+ struct xt_entry_target *tcfi_t;
+};
+#define to_ipt(pc) \
+ container_of(pc, struct tcf_ipt, common)
+
+#endif /* __NET_TC_IPT_H */
diff --git a/include/net/tc_act/tc_mirred.h b/include/net/tc_act/tc_mirred.h
new file mode 100644
index 00000000..cfe29436
--- /dev/null
+++ b/include/net/tc_act/tc_mirred.h
@@ -0,0 +1,17 @@
+#ifndef __NET_TC_MIR_H
+#define __NET_TC_MIR_H
+
+#include <net/act_api.h>
+
+struct tcf_mirred {
+ struct tcf_common common;
+ int tcfm_eaction;
+ int tcfm_ifindex;
+ int tcfm_ok_push;
+ struct net_device *tcfm_dev;
+ struct list_head tcfm_list;
+};
+#define to_mirred(pc) \
+ container_of(pc, struct tcf_mirred, common)
+
+#endif /* __NET_TC_MIR_H */
diff --git a/include/net/tc_act/tc_nat.h b/include/net/tc_act/tc_nat.h
new file mode 100644
index 00000000..4a691f34
--- /dev/null
+++ b/include/net/tc_act/tc_nat.h
@@ -0,0 +1,21 @@
+#ifndef __NET_TC_NAT_H
+#define __NET_TC_NAT_H
+
+#include <linux/types.h>
+#include <net/act_api.h>
+
+struct tcf_nat {
+ struct tcf_common common;
+
+ __be32 old_addr;
+ __be32 new_addr;
+ __be32 mask;
+ u32 flags;
+};
+
+static inline struct tcf_nat *to_tcf_nat(struct tcf_common *pc)
+{
+ return container_of(pc, struct tcf_nat, common);
+}
+
+#endif /* __NET_TC_NAT_H */
diff --git a/include/net/tc_act/tc_pedit.h b/include/net/tc_act/tc_pedit.h
new file mode 100644
index 00000000..e6f6e159
--- /dev/null
+++ b/include/net/tc_act/tc_pedit.h
@@ -0,0 +1,15 @@
+#ifndef __NET_TC_PED_H
+#define __NET_TC_PED_H
+
+#include <net/act_api.h>
+
+struct tcf_pedit {
+ struct tcf_common common;
+ unsigned char tcfp_nkeys;
+ unsigned char tcfp_flags;
+ struct tc_pedit_key *tcfp_keys;
+};
+#define to_pedit(pc) \
+ container_of(pc, struct tcf_pedit, common)
+
+#endif /* __NET_TC_PED_H */
diff --git a/include/net/tc_act/tc_skbedit.h b/include/net/tc_act/tc_skbedit.h
new file mode 100644
index 00000000..e103fe02
--- /dev/null
+++ b/include/net/tc_act/tc_skbedit.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2008, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Author: Alexander Duyck <alexander.h.duyck@intel.com>
+ */
+
+#ifndef __NET_TC_SKBEDIT_H
+#define __NET_TC_SKBEDIT_H
+
+#include <net/act_api.h>
+
+struct tcf_skbedit {
+ struct tcf_common common;
+ u32 flags;
+ u32 priority;
+ u32 mark;
+ u16 queue_mapping;
+ /* XXX: 16-bit pad here? */
+};
+#define to_skbedit(pc) \
+ container_of(pc, struct tcf_skbedit, common)
+
+#endif /* __NET_TC_SKBEDIT_H */
diff --git a/include/net/tcp.h b/include/net/tcp.h
new file mode 100644
index 00000000..50660b3e
--- /dev/null
+++ b/include/net/tcp.h
@@ -0,0 +1,1581 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the TCP module.
+ *
+ * Version: @(#)tcp.h 1.0.5 05/23/93
+ *
+ * Authors: Ross Biro
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _TCP_H
+#define _TCP_H
+
+#define FASTRETRANS_DEBUG 1
+
+#include <linux/list.h>
+#include <linux/tcp.h>
+#include <linux/bug.h>
+#include <linux/slab.h>
+#include <linux/cache.h>
+#include <linux/percpu.h>
+#include <linux/skbuff.h>
+#include <linux/dmaengine.h>
+#include <linux/crypto.h>
+#include <linux/cryptohash.h>
+#include <linux/kref.h>
+
+#include <net/inet_connection_sock.h>
+#include <net/inet_timewait_sock.h>
+#include <net/inet_hashtables.h>
+#include <net/checksum.h>
+#include <net/request_sock.h>
+#include <net/sock.h>
+#include <net/snmp.h>
+#include <net/ip.h>
+#include <net/tcp_states.h>
+#include <net/inet_ecn.h>
+#include <net/dst.h>
+
+#include <linux/seq_file.h>
+#include <linux/memcontrol.h>
+
+extern struct inet_hashinfo tcp_hashinfo;
+
+extern struct percpu_counter tcp_orphan_count;
+extern void tcp_time_wait(struct sock *sk, int state, int timeo);
+
+#define MAX_TCP_HEADER (128 + MAX_HEADER)
+#define MAX_TCP_OPTION_SPACE 40
+
+/*
+ * Never offer a window over 32767 without using window scaling. Some
+ * poor stacks do signed 16bit maths!
+ */
+#define MAX_TCP_WINDOW 32767U
+
+/* Offer an initial receive window of 10 mss. */
+#define TCP_DEFAULT_INIT_RCVWND 10
+
+/* Minimal accepted MSS. It is (60+60+8) - (20+20). */
+#define TCP_MIN_MSS 88U
+
+/* The least MTU to use for probing */
+#define TCP_BASE_MSS 512
+
+/* After receiving this amount of duplicate ACKs fast retransmit starts. */
+#define TCP_FASTRETRANS_THRESH 3
+
+/* Maximal reordering. */
+#define TCP_MAX_REORDERING 127
+
+/* Maximal number of ACKs sent quickly to accelerate slow-start. */
+#define TCP_MAX_QUICKACKS 16U
+
+/* urg_data states */
+#define TCP_URG_VALID 0x0100
+#define TCP_URG_NOTYET 0x0200
+#define TCP_URG_READ 0x0400
+
+#define TCP_RETR1 3 /*
+ * This is how many retries it does before it
+ * tries to figure out if the gateway is
+ * down. Minimal RFC value is 3; it corresponds
+ * to ~3sec-8min depending on RTO.
+ */
+
+#define TCP_RETR2 15 /*
+ * This should take at least
+ * 90 minutes to time out.
+ * RFC1122 says that the limit is 100 sec.
+ * 15 is ~13-30min depending on RTO.
+ */
+
+#define TCP_SYN_RETRIES 5 /* number of times to retry active opening a
+ * connection: ~180sec is RFC minimum */
+
+#define TCP_SYNACK_RETRIES 5 /* number of times to retry passive opening a
+ * connection: ~180sec is RFC minimum */
+
+#define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy TIME-WAIT
+ * state, about 60 seconds */
+#define TCP_FIN_TIMEOUT TCP_TIMEWAIT_LEN
+ /* BSD style FIN_WAIT2 deadlock breaker.
+ * It used to be 3min, new value is 60sec,
+ * to combine FIN-WAIT-2 timeout with
+ * TIME-WAIT timer.
+ */
+
+#define TCP_DELACK_MAX ((unsigned)(HZ/5)) /* maximal time to delay before sending an ACK */
+#if HZ >= 100
+#define TCP_DELACK_MIN ((unsigned)(HZ/25)) /* minimal time to delay before sending an ACK */
+#define TCP_ATO_MIN ((unsigned)(HZ/25))
+#else
+#define TCP_DELACK_MIN 4U
+#define TCP_ATO_MIN 4U
+#endif
+#define TCP_RTO_MAX ((unsigned)(120*HZ))
+#define TCP_RTO_MIN ((unsigned)(HZ/5))
+#define TCP_TIMEOUT_INIT ((unsigned)(1*HZ)) /* RFC2988bis initial RTO value */
+#define TCP_TIMEOUT_FALLBACK ((unsigned)(3*HZ)) /* RFC 1122 initial RTO value, now
+ * used as a fallback RTO for the
+ * initial data transmission if no
+ * valid RTT sample has been acquired,
+ * most likely due to retrans in 3WHS.
+ */
+
+#define TCP_RESOURCE_PROBE_INTERVAL ((unsigned)(HZ/2U)) /* Maximal interval between probes
+ * for local resources.
+ */
+
+#define TCP_KEEPALIVE_TIME (120*60*HZ) /* two hours */
+#define TCP_KEEPALIVE_PROBES 9 /* Max of 9 keepalive probes */
+#define TCP_KEEPALIVE_INTVL (75*HZ)
+
+#define MAX_TCP_KEEPIDLE 32767
+#define MAX_TCP_KEEPINTVL 32767
+#define MAX_TCP_KEEPCNT 127
+#define MAX_TCP_SYNCNT 127
+
+#define TCP_SYNQ_INTERVAL (HZ/5) /* Period of SYNACK timer */
+
+#define TCP_PAWS_24DAYS (60 * 60 * 24 * 24)
+#define TCP_PAWS_MSL 60 /* Per-host timestamps are invalidated
+ * after this time. It should be equal
+ * (or greater than) TCP_TIMEWAIT_LEN
+ * to provide reliability equal to one
+ * provided by timewait state.
+ */
+#define TCP_PAWS_WINDOW 1 /* Replay window for per-host
+ * timestamps. It must be less than
+ * minimal timewait lifetime.
+ */
+/*
+ * TCP option
+ */
+
+#define TCPOPT_NOP 1 /* Padding */
+#define TCPOPT_EOL 0 /* End of options */
+#define TCPOPT_MSS 2 /* Segment size negotiating */
+#define TCPOPT_WINDOW 3 /* Window scaling */
+#define TCPOPT_SACK_PERM 4 /* SACK Permitted */
+#define TCPOPT_SACK 5 /* SACK Block */
+#define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
+#define TCPOPT_MD5SIG 19 /* MD5 Signature (RFC2385) */
+#define TCPOPT_COOKIE 253 /* Cookie extension (experimental) */
+
+/*
+ * TCP option lengths
+ */
+
+#define TCPOLEN_MSS 4
+#define TCPOLEN_WINDOW 3
+#define TCPOLEN_SACK_PERM 2
+#define TCPOLEN_TIMESTAMP 10
+#define TCPOLEN_MD5SIG 18
+#define TCPOLEN_COOKIE_BASE 2 /* Cookie-less header extension */
+#define TCPOLEN_COOKIE_PAIR 3 /* Cookie pair header extension */
+#define TCPOLEN_COOKIE_MIN (TCPOLEN_COOKIE_BASE+TCP_COOKIE_MIN)
+#define TCPOLEN_COOKIE_MAX (TCPOLEN_COOKIE_BASE+TCP_COOKIE_MAX)
+
+/* But this is what stacks really send out. */
+#define TCPOLEN_TSTAMP_ALIGNED 12
+#define TCPOLEN_WSCALE_ALIGNED 4
+#define TCPOLEN_SACKPERM_ALIGNED 4
+#define TCPOLEN_SACK_BASE 2
+#define TCPOLEN_SACK_BASE_ALIGNED 4
+#define TCPOLEN_SACK_PERBLOCK 8
+#define TCPOLEN_MD5SIG_ALIGNED 20
+#define TCPOLEN_MSS_ALIGNED 4
+
+/* Flags in tp->nonagle */
+#define TCP_NAGLE_OFF 1 /* Nagle's algo is disabled */
+#define TCP_NAGLE_CORK 2 /* Socket is corked */
+#define TCP_NAGLE_PUSH 4 /* Cork is overridden for already queued data */
+
+/* TCP thin-stream limits */
+#define TCP_THIN_LINEAR_RETRIES 6 /* After 6 linear retries, do exp. backoff */
+
+/* TCP initial congestion window as per draft-hkchu-tcpm-initcwnd-01 */
+#define TCP_INIT_CWND 10
+
+extern struct inet_timewait_death_row tcp_death_row;
+
+/* sysctl variables for tcp */
+extern int sysctl_tcp_timestamps;
+extern int sysctl_tcp_window_scaling;
+extern int sysctl_tcp_sack;
+extern int sysctl_tcp_fin_timeout;
+extern int sysctl_tcp_keepalive_time;
+extern int sysctl_tcp_keepalive_probes;
+extern int sysctl_tcp_keepalive_intvl;
+extern int sysctl_tcp_syn_retries;
+extern int sysctl_tcp_synack_retries;
+extern int sysctl_tcp_retries1;
+extern int sysctl_tcp_retries2;
+extern int sysctl_tcp_orphan_retries;
+extern int sysctl_tcp_syncookies;
+extern int sysctl_tcp_retrans_collapse;
+extern int sysctl_tcp_stdurg;
+extern int sysctl_tcp_rfc1337;
+extern int sysctl_tcp_abort_on_overflow;
+extern int sysctl_tcp_max_orphans;
+extern int sysctl_tcp_fack;
+extern int sysctl_tcp_reordering;
+extern int sysctl_tcp_ecn;
+extern int sysctl_tcp_dsack;
+extern int sysctl_tcp_wmem[3];
+extern int sysctl_tcp_rmem[3];
+extern int sysctl_tcp_app_win;
+extern int sysctl_tcp_adv_win_scale;
+extern int sysctl_tcp_tw_reuse;
+extern int sysctl_tcp_frto;
+extern int sysctl_tcp_frto_response;
+extern int sysctl_tcp_low_latency;
+extern int sysctl_tcp_dma_copybreak;
+extern int sysctl_tcp_nometrics_save;
+extern int sysctl_tcp_moderate_rcvbuf;
+extern int sysctl_tcp_tso_win_divisor;
+extern int sysctl_tcp_abc;
+extern int sysctl_tcp_mtu_probing;
+extern int sysctl_tcp_base_mss;
+extern int sysctl_tcp_workaround_signed_windows;
+extern int sysctl_tcp_slow_start_after_idle;
+extern int sysctl_tcp_max_ssthresh;
+extern int sysctl_tcp_cookie_size;
+extern int sysctl_tcp_thin_linear_timeouts;
+extern int sysctl_tcp_thin_dupack;
+
+extern atomic_long_t tcp_memory_allocated;
+extern struct percpu_counter tcp_sockets_allocated;
+extern int tcp_memory_pressure;
+
+/*
+ * The next routines deal with comparing 32 bit unsigned ints
+ * and worry about wraparound (automatic with unsigned arithmetic).
+ */
+
+static inline int before(__u32 seq1, __u32 seq2)
+{
+ return (__s32)(seq1-seq2) < 0;
+}
+#define after(seq2, seq1) before(seq1, seq2)
+
+/* is s2<=s1<=s3 ? */
+static inline int between(__u32 seq1, __u32 seq2, __u32 seq3)
+{
+ return seq3 - seq2 >= seq1 - seq2;
+}
+
+static inline bool tcp_out_of_memory(struct sock *sk)
+{
+ if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
+ sk_memory_allocated(sk) > sk_prot_mem_limits(sk, 2))
+ return true;
+ return false;
+}
+
+static inline bool tcp_too_many_orphans(struct sock *sk, int shift)
+{
+ struct percpu_counter *ocp = sk->sk_prot->orphan_count;
+ int orphans = percpu_counter_read_positive(ocp);
+
+ if (orphans << shift > sysctl_tcp_max_orphans) {
+ orphans = percpu_counter_sum_positive(ocp);
+ if (orphans << shift > sysctl_tcp_max_orphans)
+ return true;
+ }
+ return false;
+}
+
+extern bool tcp_check_oom(struct sock *sk, int shift);
+
+/* syncookies: remember time of last synqueue overflow */
+static inline void tcp_synq_overflow(struct sock *sk)
+{
+ tcp_sk(sk)->rx_opt.ts_recent_stamp = jiffies;
+}
+
+/* syncookies: no recent synqueue overflow on this listening socket? */
+static inline int tcp_synq_no_recent_overflow(const struct sock *sk)
+{
+ unsigned long last_overflow = tcp_sk(sk)->rx_opt.ts_recent_stamp;
+ return time_after(jiffies, last_overflow + TCP_TIMEOUT_FALLBACK);
+}
+
+extern struct proto tcp_prot;
+
+#define TCP_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.tcp_statistics, field)
+#define TCP_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.tcp_statistics, field)
+#define TCP_DEC_STATS(net, field) SNMP_DEC_STATS((net)->mib.tcp_statistics, field)
+#define TCP_ADD_STATS_USER(net, field, val) SNMP_ADD_STATS_USER((net)->mib.tcp_statistics, field, val)
+#define TCP_ADD_STATS(net, field, val) SNMP_ADD_STATS((net)->mib.tcp_statistics, field, val)
+
+extern void tcp_init_mem(struct net *net);
+
+extern void tcp_v4_err(struct sk_buff *skb, u32);
+
+extern void tcp_shutdown (struct sock *sk, int how);
+
+extern int tcp_v4_rcv(struct sk_buff *skb);
+
+extern struct inet_peer *tcp_v4_get_peer(struct sock *sk, bool *release_it);
+extern void *tcp_v4_tw_get_peer(struct sock *sk);
+extern int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
+extern int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ size_t size);
+extern int tcp_sendpage(struct sock *sk, struct page *page, int offset,
+ size_t size, int flags);
+extern int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg);
+extern int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
+ const struct tcphdr *th, unsigned int len);
+extern int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
+ const struct tcphdr *th, unsigned int len);
+extern void tcp_rcv_space_adjust(struct sock *sk);
+extern void tcp_cleanup_rbuf(struct sock *sk, int copied);
+extern int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp);
+extern void tcp_twsk_destructor(struct sock *sk);
+extern ssize_t tcp_splice_read(struct socket *sk, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t len,
+ unsigned int flags);
+
+static inline void tcp_dec_quickack_mode(struct sock *sk,
+ const unsigned int pkts)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+
+ if (icsk->icsk_ack.quick) {
+ if (pkts >= icsk->icsk_ack.quick) {
+ icsk->icsk_ack.quick = 0;
+ /* Leaving quickack mode we deflate ATO. */
+ icsk->icsk_ack.ato = TCP_ATO_MIN;
+ } else
+ icsk->icsk_ack.quick -= pkts;
+ }
+}
+
+#define TCP_ECN_OK 1
+#define TCP_ECN_QUEUE_CWR 2
+#define TCP_ECN_DEMAND_CWR 4
+#define TCP_ECN_SEEN 8
+
+static __inline__ void
+TCP_ECN_create_request(struct request_sock *req, struct tcphdr *th)
+{
+ if (sysctl_tcp_ecn && th->ece && th->cwr)
+ inet_rsk(req)->ecn_ok = 1;
+}
+
+enum tcp_tw_status {
+ TCP_TW_SUCCESS = 0,
+ TCP_TW_RST = 1,
+ TCP_TW_ACK = 2,
+ TCP_TW_SYN = 3
+};
+
+
+extern enum tcp_tw_status tcp_timewait_state_process(struct inet_timewait_sock *tw,
+ struct sk_buff *skb,
+ const struct tcphdr *th);
+extern struct sock * tcp_check_req(struct sock *sk,struct sk_buff *skb,
+ struct request_sock *req,
+ struct request_sock **prev);
+extern int tcp_child_process(struct sock *parent, struct sock *child,
+ struct sk_buff *skb);
+extern int tcp_use_frto(struct sock *sk);
+extern void tcp_enter_frto(struct sock *sk);
+extern void tcp_enter_loss(struct sock *sk, int how);
+extern void tcp_clear_retrans(struct tcp_sock *tp);
+extern void tcp_update_metrics(struct sock *sk);
+extern void tcp_close(struct sock *sk, long timeout);
+extern unsigned int tcp_poll(struct file * file, struct socket *sock,
+ struct poll_table_struct *wait);
+extern int tcp_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+extern int tcp_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, unsigned int optlen);
+extern int compat_tcp_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+extern int compat_tcp_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, unsigned int optlen);
+extern void tcp_set_keepalive(struct sock *sk, int val);
+extern void tcp_syn_ack_timeout(struct sock *sk, struct request_sock *req);
+extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ size_t len, int nonblock, int flags, int *addr_len);
+extern void tcp_parse_options(const struct sk_buff *skb,
+ struct tcp_options_received *opt_rx, const u8 **hvpp,
+ int estab);
+extern const u8 *tcp_parse_md5sig_option(const struct tcphdr *th);
+
+/*
+ * TCP v4 functions exported for the inet6 API
+ */
+
+extern void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb);
+extern int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb);
+extern struct sock * tcp_create_openreq_child(struct sock *sk,
+ struct request_sock *req,
+ struct sk_buff *skb);
+extern struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
+ struct request_sock *req,
+ struct dst_entry *dst);
+extern int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb);
+extern int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
+ int addr_len);
+extern int tcp_connect(struct sock *sk);
+extern struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
+ struct request_sock *req,
+ struct request_values *rvp);
+extern int tcp_disconnect(struct sock *sk, int flags);
+
+
+/* From syncookies.c */
+extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS];
+extern struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
+ struct ip_options *opt);
+#ifdef CONFIG_SYN_COOKIES
+extern __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb,
+ __u16 *mss);
+#else
+static inline __u32 cookie_v4_init_sequence(struct sock *sk,
+ struct sk_buff *skb,
+ __u16 *mss)
+{
+ return 0;
+}
+#endif
+
+extern __u32 cookie_init_timestamp(struct request_sock *req);
+extern bool cookie_check_timestamp(struct tcp_options_received *opt, bool *);
+
+/* From net/ipv6/syncookies.c */
+extern struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb);
+#ifdef CONFIG_SYN_COOKIES
+extern __u32 cookie_v6_init_sequence(struct sock *sk, const struct sk_buff *skb,
+ __u16 *mss);
+#else
+static inline __u32 cookie_v6_init_sequence(struct sock *sk,
+ struct sk_buff *skb,
+ __u16 *mss)
+{
+ return 0;
+}
+#endif
+/* tcp_output.c */
+
+extern void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss,
+ int nonagle);
+extern int tcp_may_send_now(struct sock *sk);
+extern int tcp_retransmit_skb(struct sock *, struct sk_buff *);
+extern void tcp_retransmit_timer(struct sock *sk);
+extern void tcp_xmit_retransmit_queue(struct sock *);
+extern void tcp_simple_retransmit(struct sock *);
+extern int tcp_trim_head(struct sock *, struct sk_buff *, u32);
+extern int tcp_fragment(struct sock *, struct sk_buff *, u32, unsigned int);
+
+extern void tcp_send_probe0(struct sock *);
+extern void tcp_send_partial(struct sock *);
+extern int tcp_write_wakeup(struct sock *);
+extern void tcp_send_fin(struct sock *sk);
+extern void tcp_send_active_reset(struct sock *sk, gfp_t priority);
+extern int tcp_send_synack(struct sock *);
+extern int tcp_syn_flood_action(struct sock *sk,
+ const struct sk_buff *skb,
+ const char *proto);
+extern void tcp_push_one(struct sock *, unsigned int mss_now);
+extern void tcp_send_ack(struct sock *sk);
+extern void tcp_send_delayed_ack(struct sock *sk);
+
+/* tcp_input.c */
+extern void tcp_cwnd_application_limited(struct sock *sk);
+
+/* tcp_timer.c */
+extern void tcp_init_xmit_timers(struct sock *);
+static inline void tcp_clear_xmit_timers(struct sock *sk)
+{
+ inet_csk_clear_xmit_timers(sk);
+}
+
+extern unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu);
+extern unsigned int tcp_current_mss(struct sock *sk);
+
+/* Bound MSS / TSO packet size with the half of the window */
+static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize)
+{
+ int cutoff;
+
+ /* When peer uses tiny windows, there is no use in packetizing
+ * to sub-MSS pieces for the sake of SWS or making sure there
+ * are enough packets in the pipe for fast recovery.
+ *
+ * On the other hand, for extremely large MSS devices, handling
+ * smaller than MSS windows in this way does make sense.
+ */
+ if (tp->max_window >= 512)
+ cutoff = (tp->max_window >> 1);
+ else
+ cutoff = tp->max_window;
+
+ if (cutoff && pktsize > cutoff)
+ return max_t(int, cutoff, 68U - tp->tcp_header_len);
+ else
+ return pktsize;
+}
+
+/* tcp.c */
+extern void tcp_get_info(const struct sock *, struct tcp_info *);
+
+/* Read 'sendfile()'-style from a TCP socket */
+typedef int (*sk_read_actor_t)(read_descriptor_t *, struct sk_buff *,
+ unsigned int, size_t);
+extern int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
+ sk_read_actor_t recv_actor);
+
+extern void tcp_initialize_rcv_mss(struct sock *sk);
+
+extern int tcp_mtu_to_mss(const struct sock *sk, int pmtu);
+extern int tcp_mss_to_mtu(const struct sock *sk, int mss);
+extern void tcp_mtup_init(struct sock *sk);
+extern void tcp_valid_rtt_meas(struct sock *sk, u32 seq_rtt);
+
+static inline void tcp_bound_rto(const struct sock *sk)
+{
+ if (inet_csk(sk)->icsk_rto > TCP_RTO_MAX)
+ inet_csk(sk)->icsk_rto = TCP_RTO_MAX;
+}
+
+static inline u32 __tcp_set_rto(const struct tcp_sock *tp)
+{
+ return (tp->srtt >> 3) + tp->rttvar;
+}
+
+static inline void __tcp_fast_path_on(struct tcp_sock *tp, u32 snd_wnd)
+{
+ tp->pred_flags = htonl((tp->tcp_header_len << 26) |
+ ntohl(TCP_FLAG_ACK) |
+ snd_wnd);
+}
+
+static inline void tcp_fast_path_on(struct tcp_sock *tp)
+{
+ __tcp_fast_path_on(tp, tp->snd_wnd >> tp->rx_opt.snd_wscale);
+}
+
+static inline void tcp_fast_path_check(struct sock *sk)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+
+ if (skb_queue_empty(&tp->out_of_order_queue) &&
+ tp->rcv_wnd &&
+ atomic_read(&sk->sk_rmem_alloc) < sk->sk_rcvbuf &&
+ !tp->urg_data)
+ tcp_fast_path_on(tp);
+}
+
+/* Compute the actual rto_min value */
+static inline u32 tcp_rto_min(struct sock *sk)
+{
+ const struct dst_entry *dst = __sk_dst_get(sk);
+ u32 rto_min = TCP_RTO_MIN;
+
+ if (dst && dst_metric_locked(dst, RTAX_RTO_MIN))
+ rto_min = dst_metric_rtt(dst, RTAX_RTO_MIN);
+ return rto_min;
+}
+
+/* Compute the actual receive window we are currently advertising.
+ * Rcv_nxt can be after the window if our peer push more data
+ * than the offered window.
+ */
+static inline u32 tcp_receive_window(const struct tcp_sock *tp)
+{
+ s32 win = tp->rcv_wup + tp->rcv_wnd - tp->rcv_nxt;
+
+ if (win < 0)
+ win = 0;
+ return (u32) win;
+}
+
+/* Choose a new window, without checks for shrinking, and without
+ * scaling applied to the result. The caller does these things
+ * if necessary. This is a "raw" window selection.
+ */
+extern u32 __tcp_select_window(struct sock *sk);
+
+/* TCP timestamps are only 32-bits, this causes a slight
+ * complication on 64-bit systems since we store a snapshot
+ * of jiffies in the buffer control blocks below. We decided
+ * to use only the low 32-bits of jiffies and hide the ugly
+ * casts with the following macro.
+ */
+#define tcp_time_stamp ((__u32)(jiffies))
+
+#define tcp_flag_byte(th) (((u_int8_t *)th)[13])
+
+#define TCPHDR_FIN 0x01
+#define TCPHDR_SYN 0x02
+#define TCPHDR_RST 0x04
+#define TCPHDR_PSH 0x08
+#define TCPHDR_ACK 0x10
+#define TCPHDR_URG 0x20
+#define TCPHDR_ECE 0x40
+#define TCPHDR_CWR 0x80
+
+/* This is what the send packet queuing engine uses to pass
+ * TCP per-packet control information to the transmission code.
+ * We also store the host-order sequence numbers in here too.
+ * This is 44 bytes if IPV6 is enabled.
+ * If this grows please adjust skbuff.h:skbuff->cb[xxx] size appropriately.
+ */
+struct tcp_skb_cb {
+ union {
+ struct inet_skb_parm h4;
+#if IS_ENABLED(CONFIG_IPV6)
+ struct inet6_skb_parm h6;
+#endif
+ } header; /* For incoming frames */
+ __u32 seq; /* Starting sequence number */
+ __u32 end_seq; /* SEQ + FIN + SYN + datalen */
+ __u32 when; /* used to compute rtt's */
+ __u8 tcp_flags; /* TCP header flags. (tcp[13]) */
+ __u8 sacked; /* State flags for SACK/FACK. */
+#define TCPCB_SACKED_ACKED 0x01 /* SKB ACK'd by a SACK block */
+#define TCPCB_SACKED_RETRANS 0x02 /* SKB retransmitted */
+#define TCPCB_LOST 0x04 /* SKB is lost */
+#define TCPCB_TAGBITS 0x07 /* All tag bits */
+ __u8 ip_dsfield; /* IPv4 tos or IPv6 dsfield */
+ /* 1 byte hole */
+#define TCPCB_EVER_RETRANS 0x80 /* Ever retransmitted frame */
+#define TCPCB_RETRANS (TCPCB_SACKED_RETRANS|TCPCB_EVER_RETRANS)
+
+ __u32 ack_seq; /* Sequence number ACK'd */
+};
+
+#define TCP_SKB_CB(__skb) ((struct tcp_skb_cb *)&((__skb)->cb[0]))
+
+/* Due to TSO, an SKB can be composed of multiple actual
+ * packets. To keep these tracked properly, we use this.
+ */
+static inline int tcp_skb_pcount(const struct sk_buff *skb)
+{
+ return skb_shinfo(skb)->gso_segs;
+}
+
+/* This is valid iff tcp_skb_pcount() > 1. */
+static inline int tcp_skb_mss(const struct sk_buff *skb)
+{
+ return skb_shinfo(skb)->gso_size;
+}
+
+/* Events passed to congestion control interface */
+enum tcp_ca_event {
+ CA_EVENT_TX_START, /* first transmit when no packets in flight */
+ CA_EVENT_CWND_RESTART, /* congestion window restart */
+ CA_EVENT_COMPLETE_CWR, /* end of congestion recovery */
+ CA_EVENT_FRTO, /* fast recovery timeout */
+ CA_EVENT_LOSS, /* loss timeout */
+ CA_EVENT_FAST_ACK, /* in sequence ack */
+ CA_EVENT_SLOW_ACK, /* other ack */
+};
+
+/*
+ * Interface for adding new TCP congestion control handlers
+ */
+#define TCP_CA_NAME_MAX 16
+#define TCP_CA_MAX 128
+#define TCP_CA_BUF_MAX (TCP_CA_NAME_MAX*TCP_CA_MAX)
+
+#define TCP_CONG_NON_RESTRICTED 0x1
+#define TCP_CONG_RTT_STAMP 0x2
+
+struct tcp_congestion_ops {
+ struct list_head list;
+ unsigned long flags;
+
+ /* initialize private data (optional) */
+ void (*init)(struct sock *sk);
+ /* cleanup private data (optional) */
+ void (*release)(struct sock *sk);
+
+ /* return slow start threshold (required) */
+ u32 (*ssthresh)(struct sock *sk);
+ /* lower bound for congestion window (optional) */
+ u32 (*min_cwnd)(const struct sock *sk);
+ /* do new cwnd calculation (required) */
+ void (*cong_avoid)(struct sock *sk, u32 ack, u32 in_flight);
+ /* call before changing ca_state (optional) */
+ void (*set_state)(struct sock *sk, u8 new_state);
+ /* call when cwnd event occurs (optional) */
+ void (*cwnd_event)(struct sock *sk, enum tcp_ca_event ev);
+ /* new value of cwnd after loss (optional) */
+ u32 (*undo_cwnd)(struct sock *sk);
+ /* hook for packet ack accounting (optional) */
+ void (*pkts_acked)(struct sock *sk, u32 num_acked, s32 rtt_us);
+ /* get info for inet_diag (optional) */
+ void (*get_info)(struct sock *sk, u32 ext, struct sk_buff *skb);
+
+ char name[TCP_CA_NAME_MAX];
+ struct module *owner;
+};
+
+extern int tcp_register_congestion_control(struct tcp_congestion_ops *type);
+extern void tcp_unregister_congestion_control(struct tcp_congestion_ops *type);
+
+extern void tcp_init_congestion_control(struct sock *sk);
+extern void tcp_cleanup_congestion_control(struct sock *sk);
+extern int tcp_set_default_congestion_control(const char *name);
+extern void tcp_get_default_congestion_control(char *name);
+extern void tcp_get_available_congestion_control(char *buf, size_t len);
+extern void tcp_get_allowed_congestion_control(char *buf, size_t len);
+extern int tcp_set_allowed_congestion_control(char *allowed);
+extern int tcp_set_congestion_control(struct sock *sk, const char *name);
+extern void tcp_slow_start(struct tcp_sock *tp);
+extern void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w);
+
+extern struct tcp_congestion_ops tcp_init_congestion_ops;
+extern u32 tcp_reno_ssthresh(struct sock *sk);
+extern void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 in_flight);
+extern u32 tcp_reno_min_cwnd(const struct sock *sk);
+extern struct tcp_congestion_ops tcp_reno;
+
+static inline void tcp_set_ca_state(struct sock *sk, const u8 ca_state)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+
+ if (icsk->icsk_ca_ops->set_state)
+ icsk->icsk_ca_ops->set_state(sk, ca_state);
+ icsk->icsk_ca_state = ca_state;
+}
+
+static inline void tcp_ca_event(struct sock *sk, const enum tcp_ca_event event)
+{
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+
+ if (icsk->icsk_ca_ops->cwnd_event)
+ icsk->icsk_ca_ops->cwnd_event(sk, event);
+}
+
+/* These functions determine how the current flow behaves in respect of SACK
+ * handling. SACK is negotiated with the peer, and therefore it can vary
+ * between different flows.
+ *
+ * tcp_is_sack - SACK enabled
+ * tcp_is_reno - No SACK
+ * tcp_is_fack - FACK enabled, implies SACK enabled
+ */
+static inline int tcp_is_sack(const struct tcp_sock *tp)
+{
+ return tp->rx_opt.sack_ok;
+}
+
+static inline int tcp_is_reno(const struct tcp_sock *tp)
+{
+ return !tcp_is_sack(tp);
+}
+
+static inline int tcp_is_fack(const struct tcp_sock *tp)
+{
+ return tp->rx_opt.sack_ok & TCP_FACK_ENABLED;
+}
+
+static inline void tcp_enable_fack(struct tcp_sock *tp)
+{
+ tp->rx_opt.sack_ok |= TCP_FACK_ENABLED;
+}
+
+static inline unsigned int tcp_left_out(const struct tcp_sock *tp)
+{
+ return tp->sacked_out + tp->lost_out;
+}
+
+/* This determines how many packets are "in the network" to the best
+ * of our knowledge. In many cases it is conservative, but where
+ * detailed information is available from the receiver (via SACK
+ * blocks etc.) we can make more aggressive calculations.
+ *
+ * Use this for decisions involving congestion control, use just
+ * tp->packets_out to determine if the send queue is empty or not.
+ *
+ * Read this equation as:
+ *
+ * "Packets sent once on transmission queue" MINUS
+ * "Packets left network, but not honestly ACKed yet" PLUS
+ * "Packets fast retransmitted"
+ */
+static inline unsigned int tcp_packets_in_flight(const struct tcp_sock *tp)
+{
+ return tp->packets_out - tcp_left_out(tp) + tp->retrans_out;
+}
+
+#define TCP_INFINITE_SSTHRESH 0x7fffffff
+
+static inline bool tcp_in_initial_slowstart(const struct tcp_sock *tp)
+{
+ return tp->snd_ssthresh >= TCP_INFINITE_SSTHRESH;
+}
+
+/* If cwnd > ssthresh, we may raise ssthresh to be half-way to cwnd.
+ * The exception is rate halving phase, when cwnd is decreasing towards
+ * ssthresh.
+ */
+static inline __u32 tcp_current_ssthresh(const struct sock *sk)
+{
+ const struct tcp_sock *tp = tcp_sk(sk);
+
+ if ((1 << inet_csk(sk)->icsk_ca_state) & (TCPF_CA_CWR | TCPF_CA_Recovery))
+ return tp->snd_ssthresh;
+ else
+ return max(tp->snd_ssthresh,
+ ((tp->snd_cwnd >> 1) +
+ (tp->snd_cwnd >> 2)));
+}
+
+/* Use define here intentionally to get WARN_ON location shown at the caller */
+#define tcp_verify_left_out(tp) WARN_ON(tcp_left_out(tp) > tp->packets_out)
+
+extern void tcp_enter_cwr(struct sock *sk, const int set_ssthresh);
+extern __u32 tcp_init_cwnd(const struct tcp_sock *tp, const struct dst_entry *dst);
+
+/* The maximum number of MSS of available cwnd for which TSO defers
+ * sending if not using sysctl_tcp_tso_win_divisor.
+ */
+static inline __u32 tcp_max_tso_deferred_mss(const struct tcp_sock *tp)
+{
+ return 3;
+}
+
+/* Slow start with delack produces 3 packets of burst, so that
+ * it is safe "de facto". This will be the default - same as
+ * the default reordering threshold - but if reordering increases,
+ * we must be able to allow cwnd to burst at least this much in order
+ * to not pull it back when holes are filled.
+ */
+static __inline__ __u32 tcp_max_burst(const struct tcp_sock *tp)
+{
+ return tp->reordering;
+}
+
+/* Returns end sequence number of the receiver's advertised window */
+static inline u32 tcp_wnd_end(const struct tcp_sock *tp)
+{
+ return tp->snd_una + tp->snd_wnd;
+}
+extern int tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight);
+
+static inline void tcp_minshall_update(struct tcp_sock *tp, unsigned int mss,
+ const struct sk_buff *skb)
+{
+ if (skb->len < mss)
+ tp->snd_sml = TCP_SKB_CB(skb)->end_seq;
+}
+
+static inline void tcp_check_probe_timer(struct sock *sk)
+{
+ const struct tcp_sock *tp = tcp_sk(sk);
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+
+ if (!tp->packets_out && !icsk->icsk_pending)
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_PROBE0,
+ icsk->icsk_rto, TCP_RTO_MAX);
+}
+
+static inline void tcp_init_wl(struct tcp_sock *tp, u32 seq)
+{
+ tp->snd_wl1 = seq;
+}
+
+static inline void tcp_update_wl(struct tcp_sock *tp, u32 seq)
+{
+ tp->snd_wl1 = seq;
+}
+
+/*
+ * Calculate(/check) TCP checksum
+ */
+static inline __sum16 tcp_v4_check(int len, __be32 saddr,
+ __be32 daddr, __wsum base)
+{
+ return csum_tcpudp_magic(saddr,daddr,len,IPPROTO_TCP,base);
+}
+
+static inline __sum16 __tcp_checksum_complete(struct sk_buff *skb)
+{
+ return __skb_checksum_complete(skb);
+}
+
+static inline int tcp_checksum_complete(struct sk_buff *skb)
+{
+ return !skb_csum_unnecessary(skb) &&
+ __tcp_checksum_complete(skb);
+}
+
+/* Prequeue for VJ style copy to user, combined with checksumming. */
+
+static inline void tcp_prequeue_init(struct tcp_sock *tp)
+{
+ tp->ucopy.task = NULL;
+ tp->ucopy.len = 0;
+ tp->ucopy.memory = 0;
+ skb_queue_head_init(&tp->ucopy.prequeue);
+#ifdef CONFIG_NET_DMA
+ tp->ucopy.dma_chan = NULL;
+ tp->ucopy.wakeup = 0;
+ tp->ucopy.pinned_list = NULL;
+ tp->ucopy.dma_cookie = 0;
+#endif
+}
+
+/* Packet is added to VJ-style prequeue for processing in process
+ * context, if a reader task is waiting. Apparently, this exciting
+ * idea (VJ's mail "Re: query about TCP header on tcp-ip" of 07 Sep 93)
+ * failed somewhere. Latency? Burstiness? Well, at least now we will
+ * see, why it failed. 8)8) --ANK
+ *
+ * NOTE: is this not too big to inline?
+ */
+static inline int tcp_prequeue(struct sock *sk, struct sk_buff *skb)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+
+ if (sysctl_tcp_low_latency || !tp->ucopy.task)
+ return 0;
+
+ __skb_queue_tail(&tp->ucopy.prequeue, skb);
+ tp->ucopy.memory += skb->truesize;
+ if (tp->ucopy.memory > sk->sk_rcvbuf) {
+ struct sk_buff *skb1;
+
+ BUG_ON(sock_owned_by_user(sk));
+
+ while ((skb1 = __skb_dequeue(&tp->ucopy.prequeue)) != NULL) {
+ sk_backlog_rcv(sk, skb1);
+ NET_INC_STATS_BH(sock_net(sk),
+ LINUX_MIB_TCPPREQUEUEDROPPED);
+ }
+
+ tp->ucopy.memory = 0;
+ } else if (skb_queue_len(&tp->ucopy.prequeue) == 1) {
+ wake_up_interruptible_sync_poll(sk_sleep(sk),
+ POLLIN | POLLRDNORM | POLLRDBAND);
+ if (!inet_csk_ack_scheduled(sk))
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
+ (3 * tcp_rto_min(sk)) / 4,
+ TCP_RTO_MAX);
+ }
+ return 1;
+}
+
+
+#undef STATE_TRACE
+
+#ifdef STATE_TRACE
+static const char *statename[]={
+ "Unused","Established","Syn Sent","Syn Recv",
+ "Fin Wait 1","Fin Wait 2","Time Wait", "Close",
+ "Close Wait","Last ACK","Listen","Closing"
+};
+#endif
+extern void tcp_set_state(struct sock *sk, int state);
+
+extern void tcp_done(struct sock *sk);
+
+static inline void tcp_sack_reset(struct tcp_options_received *rx_opt)
+{
+ rx_opt->dsack = 0;
+ rx_opt->num_sacks = 0;
+}
+
+/* Determine a window scaling and initial window to offer. */
+extern void tcp_select_initial_window(int __space, __u32 mss,
+ __u32 *rcv_wnd, __u32 *window_clamp,
+ int wscale_ok, __u8 *rcv_wscale,
+ __u32 init_rcv_wnd);
+
+static inline int tcp_win_from_space(int space)
+{
+ return sysctl_tcp_adv_win_scale<=0 ?
+ (space>>(-sysctl_tcp_adv_win_scale)) :
+ space - (space>>sysctl_tcp_adv_win_scale);
+}
+
+/* Note: caller must be prepared to deal with negative returns */
+static inline int tcp_space(const struct sock *sk)
+{
+ return tcp_win_from_space(sk->sk_rcvbuf -
+ atomic_read(&sk->sk_rmem_alloc));
+}
+
+static inline int tcp_full_space(const struct sock *sk)
+{
+ return tcp_win_from_space(sk->sk_rcvbuf);
+}
+
+static inline void tcp_openreq_init(struct request_sock *req,
+ struct tcp_options_received *rx_opt,
+ struct sk_buff *skb)
+{
+ struct inet_request_sock *ireq = inet_rsk(req);
+
+ req->rcv_wnd = 0; /* So that tcp_send_synack() knows! */
+ req->cookie_ts = 0;
+ tcp_rsk(req)->rcv_isn = TCP_SKB_CB(skb)->seq;
+ req->mss = rx_opt->mss_clamp;
+ req->ts_recent = rx_opt->saw_tstamp ? rx_opt->rcv_tsval : 0;
+ ireq->tstamp_ok = rx_opt->tstamp_ok;
+ ireq->sack_ok = rx_opt->sack_ok;
+ ireq->snd_wscale = rx_opt->snd_wscale;
+ ireq->wscale_ok = rx_opt->wscale_ok;
+ ireq->acked = 0;
+ ireq->ecn_ok = 0;
+ ireq->rmt_port = tcp_hdr(skb)->source;
+ ireq->loc_port = tcp_hdr(skb)->dest;
+}
+
+extern void tcp_enter_memory_pressure(struct sock *sk);
+
+static inline int keepalive_intvl_when(const struct tcp_sock *tp)
+{
+ return tp->keepalive_intvl ? : sysctl_tcp_keepalive_intvl;
+}
+
+static inline int keepalive_time_when(const struct tcp_sock *tp)
+{
+ return tp->keepalive_time ? : sysctl_tcp_keepalive_time;
+}
+
+static inline int keepalive_probes(const struct tcp_sock *tp)
+{
+ return tp->keepalive_probes ? : sysctl_tcp_keepalive_probes;
+}
+
+static inline u32 keepalive_time_elapsed(const struct tcp_sock *tp)
+{
+ const struct inet_connection_sock *icsk = &tp->inet_conn;
+
+ return min_t(u32, tcp_time_stamp - icsk->icsk_ack.lrcvtime,
+ tcp_time_stamp - tp->rcv_tstamp);
+}
+
+static inline int tcp_fin_time(const struct sock *sk)
+{
+ int fin_timeout = tcp_sk(sk)->linger2 ? : sysctl_tcp_fin_timeout;
+ const int rto = inet_csk(sk)->icsk_rto;
+
+ if (fin_timeout < (rto << 2) - (rto >> 1))
+ fin_timeout = (rto << 2) - (rto >> 1);
+
+ return fin_timeout;
+}
+
+static inline int tcp_paws_check(const struct tcp_options_received *rx_opt,
+ int paws_win)
+{
+ if ((s32)(rx_opt->ts_recent - rx_opt->rcv_tsval) <= paws_win)
+ return 1;
+ if (unlikely(get_seconds() >= rx_opt->ts_recent_stamp + TCP_PAWS_24DAYS))
+ return 1;
+ /*
+ * Some OSes send SYN and SYNACK messages with tsval=0 tsecr=0,
+ * then following tcp messages have valid values. Ignore 0 value,
+ * or else 'negative' tsval might forbid us to accept their packets.
+ */
+ if (!rx_opt->ts_recent)
+ return 1;
+ return 0;
+}
+
+static inline int tcp_paws_reject(const struct tcp_options_received *rx_opt,
+ int rst)
+{
+ if (tcp_paws_check(rx_opt, 0))
+ return 0;
+
+ /* RST segments are not recommended to carry timestamp,
+ and, if they do, it is recommended to ignore PAWS because
+ "their cleanup function should take precedence over timestamps."
+ Certainly, it is mistake. It is necessary to understand the reasons
+ of this constraint to relax it: if peer reboots, clock may go
+ out-of-sync and half-open connections will not be reset.
+ Actually, the problem would be not existing if all
+ the implementations followed draft about maintaining clock
+ via reboots. Linux-2.2 DOES NOT!
+
+ However, we can relax time bounds for RST segments to MSL.
+ */
+ if (rst && get_seconds() >= rx_opt->ts_recent_stamp + TCP_PAWS_MSL)
+ return 0;
+ return 1;
+}
+
+static inline void tcp_mib_init(struct net *net)
+{
+ /* See RFC 2012 */
+ TCP_ADD_STATS_USER(net, TCP_MIB_RTOALGORITHM, 1);
+ TCP_ADD_STATS_USER(net, TCP_MIB_RTOMIN, TCP_RTO_MIN*1000/HZ);
+ TCP_ADD_STATS_USER(net, TCP_MIB_RTOMAX, TCP_RTO_MAX*1000/HZ);
+ TCP_ADD_STATS_USER(net, TCP_MIB_MAXCONN, -1);
+}
+
+/* from STCP */
+static inline void tcp_clear_retrans_hints_partial(struct tcp_sock *tp)
+{
+ tp->lost_skb_hint = NULL;
+ tp->scoreboard_skb_hint = NULL;
+}
+
+static inline void tcp_clear_all_retrans_hints(struct tcp_sock *tp)
+{
+ tcp_clear_retrans_hints_partial(tp);
+ tp->retransmit_skb_hint = NULL;
+}
+
+/* MD5 Signature */
+struct crypto_hash;
+
+union tcp_md5_addr {
+ struct in_addr a4;
+#if IS_ENABLED(CONFIG_IPV6)
+ struct in6_addr a6;
+#endif
+};
+
+/* - key database */
+struct tcp_md5sig_key {
+ struct hlist_node node;
+ u8 keylen;
+ u8 family; /* AF_INET or AF_INET6 */
+ union tcp_md5_addr addr;
+ u8 key[TCP_MD5SIG_MAXKEYLEN];
+ struct rcu_head rcu;
+};
+
+/* - sock block */
+struct tcp_md5sig_info {
+ struct hlist_head head;
+ struct rcu_head rcu;
+};
+
+/* - pseudo header */
+struct tcp4_pseudohdr {
+ __be32 saddr;
+ __be32 daddr;
+ __u8 pad;
+ __u8 protocol;
+ __be16 len;
+};
+
+struct tcp6_pseudohdr {
+ struct in6_addr saddr;
+ struct in6_addr daddr;
+ __be32 len;
+ __be32 protocol; /* including padding */
+};
+
+union tcp_md5sum_block {
+ struct tcp4_pseudohdr ip4;
+#if IS_ENABLED(CONFIG_IPV6)
+ struct tcp6_pseudohdr ip6;
+#endif
+};
+
+/* - pool: digest algorithm, hash description and scratch buffer */
+struct tcp_md5sig_pool {
+ struct hash_desc md5_desc;
+ union tcp_md5sum_block md5_blk;
+};
+
+/* - functions */
+extern int tcp_v4_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key,
+ const struct sock *sk,
+ const struct request_sock *req,
+ const struct sk_buff *skb);
+extern int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
+ int family, const u8 *newkey,
+ u8 newkeylen, gfp_t gfp);
+extern int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr,
+ int family);
+extern struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk,
+ struct sock *addr_sk);
+
+#ifdef CONFIG_TCP_MD5SIG
+extern struct tcp_md5sig_key *tcp_md5_do_lookup(struct sock *sk,
+ const union tcp_md5_addr *addr, int family);
+#define tcp_twsk_md5_key(twsk) ((twsk)->tw_md5_key)
+#else
+static inline struct tcp_md5sig_key *tcp_md5_do_lookup(struct sock *sk,
+ const union tcp_md5_addr *addr,
+ int family)
+{
+ return NULL;
+}
+#define tcp_twsk_md5_key(twsk) NULL
+#endif
+
+extern struct tcp_md5sig_pool __percpu *tcp_alloc_md5sig_pool(struct sock *);
+extern void tcp_free_md5sig_pool(void);
+
+extern struct tcp_md5sig_pool *tcp_get_md5sig_pool(void);
+extern void tcp_put_md5sig_pool(void);
+
+extern int tcp_md5_hash_header(struct tcp_md5sig_pool *, const struct tcphdr *);
+extern int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *, const struct sk_buff *,
+ unsigned header_len);
+extern int tcp_md5_hash_key(struct tcp_md5sig_pool *hp,
+ const struct tcp_md5sig_key *key);
+
+/* write queue abstraction */
+static inline void tcp_write_queue_purge(struct sock *sk)
+{
+ struct sk_buff *skb;
+
+ while ((skb = __skb_dequeue(&sk->sk_write_queue)) != NULL)
+ sk_wmem_free_skb(sk, skb);
+ sk_mem_reclaim(sk);
+ tcp_clear_all_retrans_hints(tcp_sk(sk));
+}
+
+static inline struct sk_buff *tcp_write_queue_head(const struct sock *sk)
+{
+ return skb_peek(&sk->sk_write_queue);
+}
+
+static inline struct sk_buff *tcp_write_queue_tail(const struct sock *sk)
+{
+ return skb_peek_tail(&sk->sk_write_queue);
+}
+
+static inline struct sk_buff *tcp_write_queue_next(const struct sock *sk,
+ const struct sk_buff *skb)
+{
+ return skb_queue_next(&sk->sk_write_queue, skb);
+}
+
+static inline struct sk_buff *tcp_write_queue_prev(const struct sock *sk,
+ const struct sk_buff *skb)
+{
+ return skb_queue_prev(&sk->sk_write_queue, skb);
+}
+
+#define tcp_for_write_queue(skb, sk) \
+ skb_queue_walk(&(sk)->sk_write_queue, skb)
+
+#define tcp_for_write_queue_from(skb, sk) \
+ skb_queue_walk_from(&(sk)->sk_write_queue, skb)
+
+#define tcp_for_write_queue_from_safe(skb, tmp, sk) \
+ skb_queue_walk_from_safe(&(sk)->sk_write_queue, skb, tmp)
+
+static inline struct sk_buff *tcp_send_head(const struct sock *sk)
+{
+ return sk->sk_send_head;
+}
+
+static inline bool tcp_skb_is_last(const struct sock *sk,
+ const struct sk_buff *skb)
+{
+ return skb_queue_is_last(&sk->sk_write_queue, skb);
+}
+
+static inline void tcp_advance_send_head(struct sock *sk, const struct sk_buff *skb)
+{
+ if (tcp_skb_is_last(sk, skb))
+ sk->sk_send_head = NULL;
+ else
+ sk->sk_send_head = tcp_write_queue_next(sk, skb);
+}
+
+static inline void tcp_check_send_head(struct sock *sk, struct sk_buff *skb_unlinked)
+{
+ if (sk->sk_send_head == skb_unlinked)
+ sk->sk_send_head = NULL;
+}
+
+static inline void tcp_init_send_head(struct sock *sk)
+{
+ sk->sk_send_head = NULL;
+}
+
+static inline void __tcp_add_write_queue_tail(struct sock *sk, struct sk_buff *skb)
+{
+ __skb_queue_tail(&sk->sk_write_queue, skb);
+}
+
+static inline void tcp_add_write_queue_tail(struct sock *sk, struct sk_buff *skb)
+{
+ __tcp_add_write_queue_tail(sk, skb);
+
+ /* Queue it, remembering where we must start sending. */
+ if (sk->sk_send_head == NULL) {
+ sk->sk_send_head = skb;
+
+ if (tcp_sk(sk)->highest_sack == NULL)
+ tcp_sk(sk)->highest_sack = skb;
+ }
+}
+
+static inline void __tcp_add_write_queue_head(struct sock *sk, struct sk_buff *skb)
+{
+ __skb_queue_head(&sk->sk_write_queue, skb);
+}
+
+/* Insert buff after skb on the write queue of sk. */
+static inline void tcp_insert_write_queue_after(struct sk_buff *skb,
+ struct sk_buff *buff,
+ struct sock *sk)
+{
+ __skb_queue_after(&sk->sk_write_queue, skb, buff);
+}
+
+/* Insert new before skb on the write queue of sk. */
+static inline void tcp_insert_write_queue_before(struct sk_buff *new,
+ struct sk_buff *skb,
+ struct sock *sk)
+{
+ __skb_queue_before(&sk->sk_write_queue, skb, new);
+
+ if (sk->sk_send_head == skb)
+ sk->sk_send_head = new;
+}
+
+static inline void tcp_unlink_write_queue(struct sk_buff *skb, struct sock *sk)
+{
+ __skb_unlink(skb, &sk->sk_write_queue);
+}
+
+static inline int tcp_write_queue_empty(struct sock *sk)
+{
+ return skb_queue_empty(&sk->sk_write_queue);
+}
+
+static inline void tcp_push_pending_frames(struct sock *sk)
+{
+ if (tcp_send_head(sk)) {
+ struct tcp_sock *tp = tcp_sk(sk);
+
+ __tcp_push_pending_frames(sk, tcp_current_mss(sk), tp->nonagle);
+ }
+}
+
+/* Start sequence of the skb just after the highest skb with SACKed
+ * bit, valid only if sacked_out > 0 or when the caller has ensured
+ * validity by itself.
+ */
+static inline u32 tcp_highest_sack_seq(struct tcp_sock *tp)
+{
+ if (!tp->sacked_out)
+ return tp->snd_una;
+
+ if (tp->highest_sack == NULL)
+ return tp->snd_nxt;
+
+ return TCP_SKB_CB(tp->highest_sack)->seq;
+}
+
+static inline void tcp_advance_highest_sack(struct sock *sk, struct sk_buff *skb)
+{
+ tcp_sk(sk)->highest_sack = tcp_skb_is_last(sk, skb) ? NULL :
+ tcp_write_queue_next(sk, skb);
+}
+
+static inline struct sk_buff *tcp_highest_sack(struct sock *sk)
+{
+ return tcp_sk(sk)->highest_sack;
+}
+
+static inline void tcp_highest_sack_reset(struct sock *sk)
+{
+ tcp_sk(sk)->highest_sack = tcp_write_queue_head(sk);
+}
+
+/* Called when old skb is about to be deleted (to be combined with new skb) */
+static inline void tcp_highest_sack_combine(struct sock *sk,
+ struct sk_buff *old,
+ struct sk_buff *new)
+{
+ if (tcp_sk(sk)->sacked_out && (old == tcp_sk(sk)->highest_sack))
+ tcp_sk(sk)->highest_sack = new;
+}
+
+/* Determines whether this is a thin stream (which may suffer from
+ * increased latency). Used to trigger latency-reducing mechanisms.
+ */
+static inline unsigned int tcp_stream_is_thin(struct tcp_sock *tp)
+{
+ return tp->packets_out < 4 && !tcp_in_initial_slowstart(tp);
+}
+
+/* /proc */
+enum tcp_seq_states {
+ TCP_SEQ_STATE_LISTENING,
+ TCP_SEQ_STATE_OPENREQ,
+ TCP_SEQ_STATE_ESTABLISHED,
+ TCP_SEQ_STATE_TIME_WAIT,
+};
+
+int tcp_seq_open(struct inode *inode, struct file *file);
+
+struct tcp_seq_afinfo {
+ char *name;
+ sa_family_t family;
+ const struct file_operations *seq_fops;
+ struct seq_operations seq_ops;
+};
+
+struct tcp_iter_state {
+ struct seq_net_private p;
+ sa_family_t family;
+ enum tcp_seq_states state;
+ struct sock *syn_wait_sk;
+ int bucket, offset, sbucket, num, uid;
+ loff_t last_pos;
+};
+
+extern int tcp_proc_register(struct net *net, struct tcp_seq_afinfo *afinfo);
+extern void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo);
+
+extern struct request_sock_ops tcp_request_sock_ops;
+extern struct request_sock_ops tcp6_request_sock_ops;
+
+extern void tcp_v4_destroy_sock(struct sock *sk);
+
+extern int tcp_v4_gso_send_check(struct sk_buff *skb);
+extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
+ netdev_features_t features);
+extern struct sk_buff **tcp_gro_receive(struct sk_buff **head,
+ struct sk_buff *skb);
+extern struct sk_buff **tcp4_gro_receive(struct sk_buff **head,
+ struct sk_buff *skb);
+extern int tcp_gro_complete(struct sk_buff *skb);
+extern int tcp4_gro_complete(struct sk_buff *skb);
+
+extern int tcp_nuke_addr(struct net *net, struct sockaddr *addr);
+
+#ifdef CONFIG_PROC_FS
+extern int tcp4_proc_init(void);
+extern void tcp4_proc_exit(void);
+#endif
+
+/* TCP af-specific functions */
+struct tcp_sock_af_ops {
+#ifdef CONFIG_TCP_MD5SIG
+ struct tcp_md5sig_key *(*md5_lookup) (struct sock *sk,
+ struct sock *addr_sk);
+ int (*calc_md5_hash) (char *location,
+ struct tcp_md5sig_key *md5,
+ const struct sock *sk,
+ const struct request_sock *req,
+ const struct sk_buff *skb);
+ int (*md5_parse) (struct sock *sk,
+ char __user *optval,
+ int optlen);
+#endif
+};
+
+struct tcp_request_sock_ops {
+#ifdef CONFIG_TCP_MD5SIG
+ struct tcp_md5sig_key *(*md5_lookup) (struct sock *sk,
+ struct request_sock *req);
+ int (*calc_md5_hash) (char *location,
+ struct tcp_md5sig_key *md5,
+ const struct sock *sk,
+ const struct request_sock *req,
+ const struct sk_buff *skb);
+#endif
+};
+
+/* Using SHA1 for now, define some constants.
+ */
+#define COOKIE_DIGEST_WORDS (SHA_DIGEST_WORDS)
+#define COOKIE_MESSAGE_WORDS (SHA_MESSAGE_BYTES / 4)
+#define COOKIE_WORKSPACE_WORDS (COOKIE_DIGEST_WORDS + COOKIE_MESSAGE_WORDS)
+
+extern int tcp_cookie_generator(u32 *bakery);
+
+/**
+ * struct tcp_cookie_values - each socket needs extra space for the
+ * cookies, together with (optional) space for any SYN data.
+ *
+ * A tcp_sock contains a pointer to the current value, and this is
+ * cloned to the tcp_timewait_sock.
+ *
+ * @cookie_pair: variable data from the option exchange.
+ *
+ * @cookie_desired: user specified tcpct_cookie_desired. Zero
+ * indicates default (sysctl_tcp_cookie_size).
+ * After cookie sent, remembers size of cookie.
+ * Range 0, TCP_COOKIE_MIN to TCP_COOKIE_MAX.
+ *
+ * @s_data_desired: user specified tcpct_s_data_desired. When the
+ * constant payload is specified (@s_data_constant),
+ * holds its length instead.
+ * Range 0 to TCP_MSS_DESIRED.
+ *
+ * @s_data_payload: constant data that is to be included in the
+ * payload of SYN or SYNACK segments when the
+ * cookie option is present.
+ */
+struct tcp_cookie_values {
+ struct kref kref;
+ u8 cookie_pair[TCP_COOKIE_PAIR_SIZE];
+ u8 cookie_pair_size;
+ u8 cookie_desired;
+ u16 s_data_desired:11,
+ s_data_constant:1,
+ s_data_in:1,
+ s_data_out:1,
+ s_data_unused:2;
+ u8 s_data_payload[0];
+};
+
+static inline void tcp_cookie_values_release(struct kref *kref)
+{
+ kfree(container_of(kref, struct tcp_cookie_values, kref));
+}
+
+/* The length of constant payload data. Note that s_data_desired is
+ * overloaded, depending on s_data_constant: either the length of constant
+ * data (returned here) or the limit on variable data.
+ */
+static inline int tcp_s_data_size(const struct tcp_sock *tp)
+{
+ return (tp->cookie_values != NULL && tp->cookie_values->s_data_constant)
+ ? tp->cookie_values->s_data_desired
+ : 0;
+}
+
+/**
+ * struct tcp_extend_values - tcp_ipv?.c to tcp_output.c workspace.
+ *
+ * As tcp_request_sock has already been extended in other places, the
+ * only remaining method is to pass stack values along as function
+ * parameters. These parameters are not needed after sending SYNACK.
+ *
+ * @cookie_bakery: cryptographic secret and message workspace.
+ *
+ * @cookie_plus: bytes in authenticator/cookie option, copied from
+ * struct tcp_options_received (above).
+ */
+struct tcp_extend_values {
+ struct request_values rv;
+ u32 cookie_bakery[COOKIE_WORKSPACE_WORDS];
+ u8 cookie_plus:6,
+ cookie_out_never:1,
+ cookie_in_always:1;
+};
+
+static inline struct tcp_extend_values *tcp_xv(struct request_values *rvp)
+{
+ return (struct tcp_extend_values *)rvp;
+}
+
+extern void tcp_v4_init(void);
+extern void tcp_init(void);
+
+#endif /* _TCP_H */
diff --git a/include/net/tcp_memcontrol.h b/include/net/tcp_memcontrol.h
new file mode 100644
index 00000000..48410ff2
--- /dev/null
+++ b/include/net/tcp_memcontrol.h
@@ -0,0 +1,19 @@
+#ifndef _TCP_MEMCG_H
+#define _TCP_MEMCG_H
+
+struct tcp_memcontrol {
+ struct cg_proto cg_proto;
+ /* per-cgroup tcp memory pressure knobs */
+ struct res_counter tcp_memory_allocated;
+ struct percpu_counter tcp_sockets_allocated;
+ /* those two are read-mostly, leave them at the end */
+ long tcp_prot_mem[3];
+ int tcp_memory_pressure;
+};
+
+struct cg_proto *tcp_proto_cgroup(struct mem_cgroup *memcg);
+int tcp_init_cgroup(struct cgroup *cgrp, struct cgroup_subsys *ss);
+void tcp_destroy_cgroup(struct cgroup *cgrp);
+unsigned long long tcp_max_memory(const struct mem_cgroup *memcg);
+void tcp_prot_mem(struct mem_cgroup *memcg, long val, int idx);
+#endif /* _TCP_MEMCG_H */
diff --git a/include/net/tcp_states.h b/include/net/tcp_states.h
new file mode 100644
index 00000000..b0b64598
--- /dev/null
+++ b/include/net/tcp_states.h
@@ -0,0 +1,50 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the TCP protocol sk_state field.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_TCP_STATES_H
+#define _LINUX_TCP_STATES_H
+
+enum {
+ TCP_ESTABLISHED = 1,
+ TCP_SYN_SENT,
+ TCP_SYN_RECV,
+ TCP_FIN_WAIT1,
+ TCP_FIN_WAIT2,
+ TCP_TIME_WAIT,
+ TCP_CLOSE,
+ TCP_CLOSE_WAIT,
+ TCP_LAST_ACK,
+ TCP_LISTEN,
+ TCP_CLOSING, /* Now a valid state */
+
+ TCP_MAX_STATES /* Leave at the end! */
+};
+
+#define TCP_STATE_MASK 0xF
+
+#define TCP_ACTION_FIN (1 << 7)
+
+enum {
+ TCPF_ESTABLISHED = (1 << 1),
+ TCPF_SYN_SENT = (1 << 2),
+ TCPF_SYN_RECV = (1 << 3),
+ TCPF_FIN_WAIT1 = (1 << 4),
+ TCPF_FIN_WAIT2 = (1 << 5),
+ TCPF_TIME_WAIT = (1 << 6),
+ TCPF_CLOSE = (1 << 7),
+ TCPF_CLOSE_WAIT = (1 << 8),
+ TCPF_LAST_ACK = (1 << 9),
+ TCPF_LISTEN = (1 << 10),
+ TCPF_CLOSING = (1 << 11)
+};
+
+#endif /* _LINUX_TCP_STATES_H */
diff --git a/include/net/timewait_sock.h b/include/net/timewait_sock.h
new file mode 100644
index 00000000..8d6689cb
--- /dev/null
+++ b/include/net/timewait_sock.h
@@ -0,0 +1,51 @@
+/*
+ * NET Generic infrastructure for Network protocols.
+ *
+ * Authors: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _TIMEWAIT_SOCK_H
+#define _TIMEWAIT_SOCK_H
+
+#include <linux/slab.h>
+#include <linux/bug.h>
+#include <net/sock.h>
+
+struct timewait_sock_ops {
+ struct kmem_cache *twsk_slab;
+ char *twsk_slab_name;
+ unsigned int twsk_obj_size;
+ int (*twsk_unique)(struct sock *sk,
+ struct sock *sktw, void *twp);
+ void (*twsk_destructor)(struct sock *sk);
+ void *(*twsk_getpeer)(struct sock *sk);
+};
+
+static inline int twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
+{
+ if (sk->sk_prot->twsk_prot->twsk_unique != NULL)
+ return sk->sk_prot->twsk_prot->twsk_unique(sk, sktw, twp);
+ return 0;
+}
+
+static inline void twsk_destructor(struct sock *sk)
+{
+ BUG_ON(sk == NULL);
+ BUG_ON(sk->sk_prot == NULL);
+ BUG_ON(sk->sk_prot->twsk_prot == NULL);
+ if (sk->sk_prot->twsk_prot->twsk_destructor != NULL)
+ sk->sk_prot->twsk_prot->twsk_destructor(sk);
+}
+
+static inline void *twsk_getpeer(struct sock *sk)
+{
+ if (sk->sk_prot->twsk_prot->twsk_getpeer)
+ return sk->sk_prot->twsk_prot->twsk_getpeer(sk);
+ return NULL;
+}
+
+#endif /* _TIMEWAIT_SOCK_H */
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h
new file mode 100644
index 00000000..48b42ea9
--- /dev/null
+++ b/include/net/transp_v6.h
@@ -0,0 +1,61 @@
+#ifndef _TRANSP_V6_H
+#define _TRANSP_V6_H
+
+#include <net/checksum.h>
+
+/*
+ * IPv6 transport protocols
+ */
+
+extern struct proto rawv6_prot;
+extern struct proto udpv6_prot;
+extern struct proto udplitev6_prot;
+extern struct proto tcpv6_prot;
+extern struct proto pingv6_prot;
+
+struct flowi6;
+
+/* extension headers */
+extern int ipv6_exthdrs_init(void);
+extern void ipv6_exthdrs_exit(void);
+extern int ipv6_frag_init(void);
+extern void ipv6_frag_exit(void);
+
+/* transport protocols */
+extern int pingv6_init(void);
+extern void pingv6_exit(void);
+extern int rawv6_init(void);
+extern void rawv6_exit(void);
+extern int udpv6_init(void);
+extern void udpv6_exit(void);
+extern int udplitev6_init(void);
+extern void udplitev6_exit(void);
+extern int tcpv6_init(void);
+extern void tcpv6_exit(void);
+
+extern int udpv6_connect(struct sock *sk,
+ struct sockaddr *uaddr,
+ int addr_len);
+
+extern int datagram_recv_ctl(struct sock *sk,
+ struct msghdr *msg,
+ struct sk_buff *skb);
+
+extern int datagram_send_ctl(struct net *net,
+ struct sock *sk,
+ struct msghdr *msg,
+ struct flowi6 *fl6,
+ struct ipv6_txoptions *opt,
+ int *hlimit, int *tclass,
+ int *dontfrag);
+
+#define LOOPBACK4_IPV6 cpu_to_be32(0x7f000006)
+
+/*
+ * address family specific functions
+ */
+extern const struct inet_connection_sock_af_ops ipv4_specific;
+
+extern void inet6_destroy_sock(struct sock *sk);
+
+#endif
diff --git a/include/net/udp.h b/include/net/udp.h
new file mode 100644
index 00000000..5d606d9d
--- /dev/null
+++ b/include/net/udp.h
@@ -0,0 +1,270 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the UDP module.
+ *
+ * Version: @(#)udp.h 1.0.2 05/07/93
+ *
+ * Authors: Ross Biro
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * Fixes:
+ * Alan Cox : Turned on udp checksums. I don't want to
+ * chase 'memory corruption' bugs that aren't!
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _UDP_H
+#define _UDP_H
+
+#include <linux/list.h>
+#include <linux/bug.h>
+#include <net/inet_sock.h>
+#include <net/sock.h>
+#include <net/snmp.h>
+#include <net/ip.h>
+#include <linux/ipv6.h>
+#include <linux/seq_file.h>
+#include <linux/poll.h>
+
+/**
+ * struct udp_skb_cb - UDP(-Lite) private variables
+ *
+ * @header: private variables used by IPv4/IPv6
+ * @cscov: checksum coverage length (UDP-Lite only)
+ * @partial_cov: if set indicates partial csum coverage
+ */
+struct udp_skb_cb {
+ union {
+ struct inet_skb_parm h4;
+#if IS_ENABLED(CONFIG_IPV6)
+ struct inet6_skb_parm h6;
+#endif
+ } header;
+ __u16 cscov;
+ __u8 partial_cov;
+};
+#define UDP_SKB_CB(__skb) ((struct udp_skb_cb *)((__skb)->cb))
+
+/**
+ * struct udp_hslot - UDP hash slot
+ *
+ * @head: head of list of sockets
+ * @count: number of sockets in 'head' list
+ * @lock: spinlock protecting changes to head/count
+ */
+struct udp_hslot {
+ struct hlist_nulls_head head;
+ int count;
+ spinlock_t lock;
+} __attribute__((aligned(2 * sizeof(long))));
+
+/**
+ * struct udp_table - UDP table
+ *
+ * @hash: hash table, sockets are hashed on (local port)
+ * @hash2: hash table, sockets are hashed on (local port, local address)
+ * @mask: number of slots in hash tables, minus 1
+ * @log: log2(number of slots in hash table)
+ */
+struct udp_table {
+ struct udp_hslot *hash;
+ struct udp_hslot *hash2;
+ unsigned int mask;
+ unsigned int log;
+};
+extern struct udp_table udp_table;
+extern void udp_table_init(struct udp_table *, const char *);
+static inline struct udp_hslot *udp_hashslot(struct udp_table *table,
+ struct net *net, unsigned num)
+{
+ return &table->hash[udp_hashfn(net, num, table->mask)];
+}
+/*
+ * For secondary hash, net_hash_mix() is performed before calling
+ * udp_hashslot2(), this explains difference with udp_hashslot()
+ */
+static inline struct udp_hslot *udp_hashslot2(struct udp_table *table,
+ unsigned int hash)
+{
+ return &table->hash2[hash & table->mask];
+}
+
+/* Note: this must match 'valbool' in sock_setsockopt */
+#define UDP_CSUM_NOXMIT 1
+
+/* Used by SunRPC/xprt layer. */
+#define UDP_CSUM_NORCV 2
+
+/* Default, as per the RFC, is to always do csums. */
+#define UDP_CSUM_DEFAULT 0
+
+extern struct proto udp_prot;
+
+extern atomic_long_t udp_memory_allocated;
+
+/* sysctl variables for udp */
+extern long sysctl_udp_mem[3];
+extern int sysctl_udp_rmem_min;
+extern int sysctl_udp_wmem_min;
+
+struct sk_buff;
+
+/*
+ * Generic checksumming routines for UDP(-Lite) v4 and v6
+ */
+static inline __sum16 __udp_lib_checksum_complete(struct sk_buff *skb)
+{
+ return __skb_checksum_complete_head(skb, UDP_SKB_CB(skb)->cscov);
+}
+
+static inline int udp_lib_checksum_complete(struct sk_buff *skb)
+{
+ return !skb_csum_unnecessary(skb) &&
+ __udp_lib_checksum_complete(skb);
+}
+
+/**
+ * udp_csum_outgoing - compute UDPv4/v6 checksum over fragments
+ * @sk: socket we are writing to
+ * @skb: sk_buff containing the filled-in UDP header
+ * (checksum field must be zeroed out)
+ */
+static inline __wsum udp_csum_outgoing(struct sock *sk, struct sk_buff *skb)
+{
+ __wsum csum = csum_partial(skb_transport_header(skb),
+ sizeof(struct udphdr), 0);
+ skb_queue_walk(&sk->sk_write_queue, skb) {
+ csum = csum_add(csum, skb->csum);
+ }
+ return csum;
+}
+
+static inline __wsum udp_csum(struct sk_buff *skb)
+{
+ __wsum csum = csum_partial(skb_transport_header(skb),
+ sizeof(struct udphdr), skb->csum);
+
+ for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next) {
+ csum = csum_add(csum, skb->csum);
+ }
+ return csum;
+}
+
+/* hash routines shared between UDPv4/6 and UDP-Litev4/6 */
+static inline void udp_lib_hash(struct sock *sk)
+{
+ BUG();
+}
+
+extern void udp_lib_unhash(struct sock *sk);
+extern void udp_lib_rehash(struct sock *sk, u16 new_hash);
+
+static inline void udp_lib_close(struct sock *sk, long timeout)
+{
+ sk_common_release(sk);
+}
+
+extern int udp_lib_get_port(struct sock *sk, unsigned short snum,
+ int (*)(const struct sock *,const struct sock *),
+ unsigned int hash2_nulladdr);
+
+/* net/ipv4/udp.c */
+extern int udp_get_port(struct sock *sk, unsigned short snum,
+ int (*saddr_cmp)(const struct sock *,
+ const struct sock *));
+extern void udp_err(struct sk_buff *, u32);
+extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk,
+ struct msghdr *msg, size_t len);
+extern void udp_flush_pending_frames(struct sock *sk);
+extern int udp_rcv(struct sk_buff *skb);
+extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
+extern int udp_disconnect(struct sock *sk, int flags);
+extern unsigned int udp_poll(struct file *file, struct socket *sock,
+ poll_table *wait);
+extern int udp_lib_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+extern int udp_lib_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, unsigned int optlen,
+ int (*push_pending_frames)(struct sock *));
+extern struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
+ __be32 daddr, __be16 dport,
+ int dif);
+extern struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
+ __be32 daddr, __be16 dport,
+ int dif, struct udp_table *tbl);
+extern struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport,
+ const struct in6_addr *daddr, __be16 dport,
+ int dif);
+extern struct sock *__udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport,
+ const struct in6_addr *daddr, __be16 dport,
+ int dif, struct udp_table *tbl);
+
+/*
+ * SNMP statistics for UDP and UDP-Lite
+ */
+#define UDP_INC_STATS_USER(net, field, is_udplite) do { \
+ if (is_udplite) SNMP_INC_STATS_USER((net)->mib.udplite_statistics, field); \
+ else SNMP_INC_STATS_USER((net)->mib.udp_statistics, field); } while(0)
+#define UDP_INC_STATS_BH(net, field, is_udplite) do { \
+ if (is_udplite) SNMP_INC_STATS_BH((net)->mib.udplite_statistics, field); \
+ else SNMP_INC_STATS_BH((net)->mib.udp_statistics, field); } while(0)
+
+#define UDP6_INC_STATS_BH(net, field, is_udplite) do { \
+ if (is_udplite) SNMP_INC_STATS_BH((net)->mib.udplite_stats_in6, field);\
+ else SNMP_INC_STATS_BH((net)->mib.udp_stats_in6, field); \
+} while(0)
+#define UDP6_INC_STATS_USER(net, field, __lite) do { \
+ if (__lite) SNMP_INC_STATS_USER((net)->mib.udplite_stats_in6, field); \
+ else SNMP_INC_STATS_USER((net)->mib.udp_stats_in6, field); \
+} while(0)
+
+#if IS_ENABLED(CONFIG_IPV6)
+#define UDPX_INC_STATS_BH(sk, field) \
+ do { \
+ if ((sk)->sk_family == AF_INET) \
+ UDP_INC_STATS_BH(sock_net(sk), field, 0); \
+ else \
+ UDP6_INC_STATS_BH(sock_net(sk), field, 0); \
+ } while (0);
+#else
+#define UDPX_INC_STATS_BH(sk, field) UDP_INC_STATS_BH(sock_net(sk), field, 0)
+#endif
+
+/* /proc */
+int udp_seq_open(struct inode *inode, struct file *file);
+
+struct udp_seq_afinfo {
+ char *name;
+ sa_family_t family;
+ struct udp_table *udp_table;
+ const struct file_operations *seq_fops;
+ struct seq_operations seq_ops;
+};
+
+struct udp_iter_state {
+ struct seq_net_private p;
+ sa_family_t family;
+ int bucket;
+ struct udp_table *udp_table;
+};
+
+#ifdef CONFIG_PROC_FS
+extern int udp_proc_register(struct net *net, struct udp_seq_afinfo *afinfo);
+extern void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo);
+
+extern int udp4_proc_init(void);
+extern void udp4_proc_exit(void);
+#endif
+
+extern void udp_init(void);
+
+extern int udp4_ufo_send_check(struct sk_buff *skb);
+extern struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
+ netdev_features_t features);
+#endif /* _UDP_H */
diff --git a/include/net/udplite.h b/include/net/udplite.h
new file mode 100644
index 00000000..71375459
--- /dev/null
+++ b/include/net/udplite.h
@@ -0,0 +1,132 @@
+/*
+ * Definitions for the UDP-Lite (RFC 3828) code.
+ */
+#ifndef _UDPLITE_H
+#define _UDPLITE_H
+
+#include <net/ip6_checksum.h>
+
+/* UDP-Lite socket options */
+#define UDPLITE_SEND_CSCOV 10 /* sender partial coverage (as sent) */
+#define UDPLITE_RECV_CSCOV 11 /* receiver partial coverage (threshold ) */
+
+extern struct proto udplite_prot;
+extern struct udp_table udplite_table;
+
+/*
+ * Checksum computation is all in software, hence simpler getfrag.
+ */
+static __inline__ int udplite_getfrag(void *from, char *to, int offset,
+ int len, int odd, struct sk_buff *skb)
+{
+ return memcpy_fromiovecend(to, (struct iovec *) from, offset, len);
+}
+
+/* Designate sk as UDP-Lite socket */
+static inline int udplite_sk_init(struct sock *sk)
+{
+ udp_sk(sk)->pcflag = UDPLITE_BIT;
+ return 0;
+}
+
+/*
+ * Checksumming routines
+ */
+static inline int udplite_checksum_init(struct sk_buff *skb, struct udphdr *uh)
+{
+ u16 cscov;
+
+ /* In UDPv4 a zero checksum means that the transmitter generated no
+ * checksum. UDP-Lite (like IPv6) mandates checksums, hence packets
+ * with a zero checksum field are illegal. */
+ if (uh->check == 0) {
+ LIMIT_NETDEBUG(KERN_DEBUG "UDPLite: zeroed checksum field\n");
+ return 1;
+ }
+
+ cscov = ntohs(uh->len);
+
+ if (cscov == 0) /* Indicates that full coverage is required. */
+ ;
+ else if (cscov < 8 || cscov > skb->len) {
+ /*
+ * Coverage length violates RFC 3828: log and discard silently.
+ */
+ LIMIT_NETDEBUG(KERN_DEBUG "UDPLite: bad csum coverage %d/%d\n",
+ cscov, skb->len);
+ return 1;
+
+ } else if (cscov < skb->len) {
+ UDP_SKB_CB(skb)->partial_cov = 1;
+ UDP_SKB_CB(skb)->cscov = cscov;
+ if (skb->ip_summed == CHECKSUM_COMPLETE)
+ skb->ip_summed = CHECKSUM_NONE;
+ }
+
+ return 0;
+}
+
+/* Slow-path computation of checksum. Socket is locked. */
+static inline __wsum udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb)
+{
+ const struct udp_sock *up = udp_sk(skb->sk);
+ int cscov = up->len;
+ __wsum csum = 0;
+
+ if (up->pcflag & UDPLITE_SEND_CC) {
+ /*
+ * Sender has set `partial coverage' option on UDP-Lite socket.
+ * The special case "up->pcslen == 0" signifies full coverage.
+ */
+ if (up->pcslen < up->len) {
+ if (0 < up->pcslen)
+ cscov = up->pcslen;
+ udp_hdr(skb)->len = htons(up->pcslen);
+ }
+ /*
+ * NOTE: Causes for the error case `up->pcslen > up->len':
+ * (i) Application error (will not be penalized).
+ * (ii) Payload too big for send buffer: data is split
+ * into several packets, each with its own header.
+ * In this case (e.g. last segment), coverage may
+ * exceed packet length.
+ * Since packets with coverage length > packet length are
+ * illegal, we fall back to the defaults here.
+ */
+ }
+
+ skb->ip_summed = CHECKSUM_NONE; /* no HW support for checksumming */
+
+ skb_queue_walk(&sk->sk_write_queue, skb) {
+ const int off = skb_transport_offset(skb);
+ const int len = skb->len - off;
+
+ csum = skb_checksum(skb, off, (cscov > len)? len : cscov, csum);
+
+ if ((cscov -= len) <= 0)
+ break;
+ }
+ return csum;
+}
+
+/* Fast-path computation of checksum. Socket may not be locked. */
+static inline __wsum udplite_csum(struct sk_buff *skb)
+{
+ const struct udp_sock *up = udp_sk(skb->sk);
+ const int off = skb_transport_offset(skb);
+ int len = skb->len - off;
+
+ if ((up->pcflag & UDPLITE_SEND_CC) && up->pcslen < len) {
+ if (0 < up->pcslen)
+ len = up->pcslen;
+ udp_hdr(skb)->len = htons(up->pcslen);
+ }
+ skb->ip_summed = CHECKSUM_NONE; /* no HW support for checksumming */
+
+ return skb_checksum(skb, off, len, 0);
+}
+
+extern void udplite4_register(void);
+extern int udplite_get_port(struct sock *sk, unsigned short snum,
+ int (*scmp)(const struct sock *, const struct sock *));
+#endif /* _UDPLITE_H */
diff --git a/include/net/wext.h b/include/net/wext.h
new file mode 100644
index 00000000..4f6e7423
--- /dev/null
+++ b/include/net/wext.h
@@ -0,0 +1,60 @@
+#ifndef __NET_WEXT_H
+#define __NET_WEXT_H
+
+#include <net/iw_handler.h>
+
+struct net;
+
+#ifdef CONFIG_WEXT_CORE
+extern int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
+ void __user *arg);
+extern int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
+ unsigned long arg);
+
+extern struct iw_statistics *get_wireless_stats(struct net_device *dev);
+extern int call_commit_handler(struct net_device *dev);
+#else
+static inline int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
+ void __user *arg)
+{
+ return -EINVAL;
+}
+static inline int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
+ unsigned long arg)
+{
+ return -EINVAL;
+}
+#endif
+
+#ifdef CONFIG_WEXT_PROC
+extern int wext_proc_init(struct net *net);
+extern void wext_proc_exit(struct net *net);
+#else
+static inline int wext_proc_init(struct net *net)
+{
+ return 0;
+}
+static inline void wext_proc_exit(struct net *net)
+{
+ return;
+}
+#endif
+
+#ifdef CONFIG_WEXT_PRIV
+int ioctl_private_call(struct net_device *dev, struct iwreq *iwr,
+ unsigned int cmd, struct iw_request_info *info,
+ iw_handler handler);
+int compat_private_call(struct net_device *dev, struct iwreq *iwr,
+ unsigned int cmd, struct iw_request_info *info,
+ iw_handler handler);
+int iw_handler_get_private(struct net_device * dev,
+ struct iw_request_info * info,
+ union iwreq_data * wrqu,
+ char * extra);
+#else
+#define ioctl_private_call NULL
+#define compat_private_call NULL
+#endif
+
+
+#endif /* __NET_WEXT_H */
diff --git a/include/net/wimax.h b/include/net/wimax.h
new file mode 100644
index 00000000..322ff4fb
--- /dev/null
+++ b/include/net/wimax.h
@@ -0,0 +1,519 @@
+/*
+ * Linux WiMAX
+ * Kernel space API for accessing WiMAX devices
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com>
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ *
+ * The WiMAX stack provides an API for controlling and managing the
+ * system's WiMAX devices. This API affects the control plane; the
+ * data plane is accessed via the network stack (netdev).
+ *
+ * Parts of the WiMAX stack API and notifications are exported to
+ * user space via Generic Netlink. In user space, libwimax (part of
+ * the wimax-tools package) provides a shim layer for accessing those
+ * calls.
+ *
+ * The API is standarized for all WiMAX devices and different drivers
+ * implement the backend support for it. However, device-specific
+ * messaging pipes are provided that can be used to issue commands and
+ * receive notifications in free form.
+ *
+ * Currently the messaging pipes are the only means of control as it
+ * is not known (due to the lack of more devices in the market) what
+ * will be a good abstraction layer. Expect this to change as more
+ * devices show in the market. This API is designed to be growable in
+ * order to address this problem.
+ *
+ * USAGE
+ *
+ * Embed a `struct wimax_dev` at the beginning of the the device's
+ * private structure, initialize and register it. For details, see
+ * `struct wimax_dev`s documentation.
+ *
+ * Once this is done, wimax-tools's libwimaxll can be used to
+ * communicate with the driver from user space. You user space
+ * application does not have to forcibily use libwimaxll and can talk
+ * the generic netlink protocol directly if desired.
+ *
+ * Remember this is a very low level API that will to provide all of
+ * WiMAX features. Other daemons and services running in user space
+ * are the expected clients of it. They offer a higher level API that
+ * applications should use (an example of this is the Intel's WiMAX
+ * Network Service for the i2400m).
+ *
+ * DESIGN
+ *
+ * Although not set on final stone, this very basic interface is
+ * mostly completed. Remember this is meant to grow as new common
+ * operations are decided upon. New operations will be added to the
+ * interface, intent being on keeping backwards compatibility as much
+ * as possible.
+ *
+ * This layer implements a set of calls to control a WiMAX device,
+ * exposing a frontend to the rest of the kernel and user space (via
+ * generic netlink) and a backend implementation in the driver through
+ * function pointers.
+ *
+ * WiMAX devices have a state, and a kernel-only API allows the
+ * drivers to manipulate that state. State transitions are atomic, and
+ * only some of them are allowed (see `enum wimax_st`).
+ *
+ * Most API calls will set the state automatically; in most cases
+ * drivers have to only report state changes due to external
+ * conditions.
+ *
+ * All API operations are 'atomic', serialized through a mutex in the
+ * `struct wimax_dev`.
+ *
+ * EXPORTING TO USER SPACE THROUGH GENERIC NETLINK
+ *
+ * The API is exported to user space using generic netlink (other
+ * methods can be added as needed).
+ *
+ * There is a Generic Netlink Family named "WiMAX", where interfaces
+ * supporting the WiMAX interface receive commands and broadcast their
+ * signals over a multicast group named "msg".
+ *
+ * Mapping to the source/destination interface is done by an interface
+ * index attribute.
+ *
+ * For user-to-kernel traffic (commands) we use a function call
+ * marshalling mechanism, where a message X with attributes A, B, C
+ * sent from user space to kernel space means executing the WiMAX API
+ * call wimax_X(A, B, C), sending the results back as a message.
+ *
+ * Kernel-to-user (notifications or signals) communication is sent
+ * over multicast groups. This allows to have multiple applications
+ * monitoring them.
+ *
+ * Each command/signal gets assigned it's own attribute policy. This
+ * way the validator will verify that all the attributes in there are
+ * only the ones that should be for each command/signal. Thing of an
+ * attribute mapping to a type+argumentname for each command/signal.
+ *
+ * If we had a single policy for *all* commands/signals, after running
+ * the validator we'd have to check "does this attribute belong in
+ * here"? for each one. It can be done manually, but it's just easier
+ * to have the validator do that job with multiple policies. As well,
+ * it makes it easier to later expand each command/signal signature
+ * without affecting others and keeping the namespace more or less
+ * sane. Not that it is too complicated, but it makes it even easier.
+ *
+ * No state information is maintained in the kernel for each user
+ * space connection (the connection is stateless).
+ *
+ * TESTING FOR THE INTERFACE AND VERSIONING
+ *
+ * If network interface X is a WiMAX device, there will be a Generic
+ * Netlink family named "WiMAX X" and the device will present a
+ * "wimax" directory in it's network sysfs directory
+ * (/sys/class/net/DEVICE/wimax) [used by HAL].
+ *
+ * The inexistence of any of these means the device does not support
+ * this WiMAX API.
+ *
+ * By querying the generic netlink controller, versioning information
+ * and the multicast groups available can be found. Applications using
+ * the interface can either rely on that or use the generic netlink
+ * controller to figure out which generic netlink commands/signals are
+ * supported.
+ *
+ * NOTE: this versioning is a last resort to avoid hard
+ * incompatibilities. It is the intention of the design of this
+ * stack not to introduce backward incompatible changes.
+ *
+ * The version code has to fit in one byte (restrictions imposed by
+ * generic netlink); we use `version / 10` for the major version and
+ * `version % 10` for the minor. This gives 9 minors for each major
+ * and 25 majors.
+ *
+ * The version change protocol is as follow:
+ *
+ * - Major versions: needs to be increased if an existing message/API
+ * call is changed or removed. Doesn't need to be changed if a new
+ * message is added.
+ *
+ * - Minor version: needs to be increased if new messages/API calls are
+ * being added or some other consideration that doesn't impact the
+ * user-kernel interface too much (like some kind of bug fix) and
+ * that is kind of left up in the air to common sense.
+ *
+ * User space code should not try to work if the major version it was
+ * compiled for differs from what the kernel offers. As well, if the
+ * minor version of the kernel interface is lower than the one user
+ * space is expecting (the one it was compiled for), the kernel
+ * might be missing API calls; user space shall be ready to handle
+ * said condition. Use the generic netlink controller operations to
+ * find which ones are supported and which not.
+ *
+ * libwimaxll:wimaxll_open() takes care of checking versions.
+ *
+ * THE OPERATIONS:
+ *
+ * Each operation is defined in its on file (drivers/net/wimax/op-*.c)
+ * for clarity. The parts needed for an operation are:
+ *
+ * - a function pointer in `struct wimax_dev`: optional, as the
+ * operation might be implemented by the stack and not by the
+ * driver.
+ *
+ * All function pointers are named wimax_dev->op_*(), and drivers
+ * must implement them except where noted otherwise.
+ *
+ * - When exported to user space, a `struct nla_policy` to define the
+ * attributes of the generic netlink command and a `struct genl_ops`
+ * to define the operation.
+ *
+ * All the declarations for the operation codes (WIMAX_GNL_OP_<NAME>)
+ * and generic netlink attributes (WIMAX_GNL_<NAME>_*) are declared in
+ * include/linux/wimax.h; this file is intended to be cloned by user
+ * space to gain access to those declarations.
+ *
+ * A few caveats to remember:
+ *
+ * - Need to define attribute numbers starting in 1; otherwise it
+ * fails.
+ *
+ * - the `struct genl_family` requires a maximum attribute id; when
+ * defining the `struct nla_policy` for each message, it has to have
+ * an array size of WIMAX_GNL_ATTR_MAX+1.
+ *
+ * The op_*() function pointers will not be called if the wimax_dev is
+ * in a state <= %WIMAX_ST_UNINITIALIZED. The exception is:
+ *
+ * - op_reset: can be called at any time after wimax_dev_add() has
+ * been called.
+ *
+ * THE PIPE INTERFACE:
+ *
+ * This interface is kept intentionally simple. The driver can send
+ * and receive free-form messages to/from user space through a
+ * pipe. See drivers/net/wimax/op-msg.c for details.
+ *
+ * The kernel-to-user messages are sent with
+ * wimax_msg(). user-to-kernel messages are delivered via
+ * wimax_dev->op_msg_from_user().
+ *
+ * RFKILL:
+ *
+ * RFKILL support is built into the wimax_dev layer; the driver just
+ * needs to call wimax_report_rfkill_{hw,sw}() to inform of changes in
+ * the hardware or software RF kill switches. When the stack wants to
+ * turn the radio off, it will call wimax_dev->op_rfkill_sw_toggle(),
+ * which the driver implements.
+ *
+ * User space can set the software RF Kill switch by calling
+ * wimax_rfkill().
+ *
+ * The code for now only supports devices that don't require polling;
+ * If the device needs to be polled, create a self-rearming delayed
+ * work struct for polling or look into adding polled support to the
+ * WiMAX stack.
+ *
+ * When initializing the hardware (_probe), after calling
+ * wimax_dev_add(), query the device for it's RF Kill switches status
+ * and feed it back to the WiMAX stack using
+ * wimax_report_rfkill_{hw,sw}(). If any switch is missing, always
+ * report it as ON.
+ *
+ * NOTE: the wimax stack uses an inverted terminology to that of the
+ * RFKILL subsystem:
+ *
+ * - ON: radio is ON, RFKILL is DISABLED or OFF.
+ * - OFF: radio is OFF, RFKILL is ENABLED or ON.
+ *
+ * MISCELLANEOUS OPS:
+ *
+ * wimax_reset() can be used to reset the device to power on state; by
+ * default it issues a warm reset that maintains the same device
+ * node. If that is not possible, it falls back to a cold reset
+ * (device reconnect). The driver implements the backend to this
+ * through wimax_dev->op_reset().
+ */
+
+#ifndef __NET__WIMAX_H__
+#define __NET__WIMAX_H__
+
+#include <linux/wimax.h>
+#include <net/genetlink.h>
+#include <linux/netdevice.h>
+
+struct net_device;
+struct genl_info;
+struct wimax_dev;
+
+/**
+ * struct wimax_dev - Generic WiMAX device
+ *
+ * @net_dev: [fill] Pointer to the &struct net_device this WiMAX
+ * device implements.
+ *
+ * @op_msg_from_user: [fill] Driver-specific operation to
+ * handle a raw message from user space to the driver. The
+ * driver can send messages to user space using with
+ * wimax_msg_to_user().
+ *
+ * @op_rfkill_sw_toggle: [fill] Driver-specific operation to act on
+ * userspace (or any other agent) requesting the WiMAX device to
+ * change the RF Kill software switch (WIMAX_RF_ON or
+ * WIMAX_RF_OFF).
+ * If such hardware support is not present, it is assumed the
+ * radio cannot be switched off and it is always on (and the stack
+ * will error out when trying to switch it off). In such case,
+ * this function pointer can be left as NULL.
+ *
+ * @op_reset: [fill] Driver specific operation to reset the
+ * device.
+ * This operation should always attempt first a warm reset that
+ * does not disconnect the device from the bus and return 0.
+ * If that fails, it should resort to some sort of cold or bus
+ * reset (even if it implies a bus disconnection and device
+ * disappearance). In that case, -ENODEV should be returned to
+ * indicate the device is gone.
+ * This operation has to be synchronous, and return only when the
+ * reset is complete. In case of having had to resort to bus/cold
+ * reset implying a device disconnection, the call is allowed to
+ * return inmediately.
+ * NOTE: wimax_dev->mutex is NOT locked when this op is being
+ * called; however, wimax_dev->mutex_reset IS locked to ensure
+ * serialization of calls to wimax_reset().
+ * See wimax_reset()'s documentation.
+ *
+ * @name: [fill] A way to identify this device. We need to register a
+ * name with many subsystems (rfkill, workqueue creation, etc).
+ * We can't use the network device name as that
+ * might change and in some instances we don't know it yet (until
+ * we don't call register_netdev()). So we generate an unique one
+ * using the driver name and device bus id, place it here and use
+ * it across the board. Recommended naming:
+ * DRIVERNAME-BUSNAME:BUSID (dev->bus->name, dev->bus_id).
+ *
+ * @id_table_node: [private] link to the list of wimax devices kept by
+ * id-table.c. Protected by it's own spinlock.
+ *
+ * @mutex: [private] Serializes all concurrent access and execution of
+ * operations.
+ *
+ * @mutex_reset: [private] Serializes reset operations. Needs to be a
+ * different mutex because as part of the reset operation, the
+ * driver has to call back into the stack to do things such as
+ * state change, that require wimax_dev->mutex.
+ *
+ * @state: [private] Current state of the WiMAX device.
+ *
+ * @rfkill: [private] integration into the RF-Kill infrastructure.
+ *
+ * @rf_sw: [private] State of the software radio switch (OFF/ON)
+ *
+ * @rf_hw: [private] State of the hardware radio switch (OFF/ON)
+ *
+ * @debugfs_dentry: [private] Used to hook up a debugfs entry. This
+ * shows up in the debugfs root as wimax\:DEVICENAME.
+ *
+ * Description:
+ * This structure defines a common interface to access all WiMAX
+ * devices from different vendors and provides a common API as well as
+ * a free-form device-specific messaging channel.
+ *
+ * Usage:
+ * 1. Embed a &struct wimax_dev at *the beginning* the network
+ * device structure so that netdev_priv() points to it.
+ *
+ * 2. memset() it to zero
+ *
+ * 3. Initialize with wimax_dev_init(). This will leave the WiMAX
+ * device in the %__WIMAX_ST_NULL state.
+ *
+ * 4. Fill all the fields marked with [fill]; once called
+ * wimax_dev_add(), those fields CANNOT be modified.
+ *
+ * 5. Call wimax_dev_add() *after* registering the network
+ * device. This will leave the WiMAX device in the %WIMAX_ST_DOWN
+ * state.
+ * Protect the driver's net_device->open() against succeeding if
+ * the wimax device state is lower than %WIMAX_ST_DOWN.
+ *
+ * 6. Select when the device is going to be turned on/initialized;
+ * for example, it could be initialized on 'ifconfig up' (when the
+ * netdev op 'open()' is called on the driver).
+ *
+ * When the device is initialized (at `ifconfig up` time, or right
+ * after calling wimax_dev_add() from _probe(), make sure the
+ * following steps are taken
+ *
+ * a. Move the device to %WIMAX_ST_UNINITIALIZED. This is needed so
+ * some API calls that shouldn't work until the device is ready
+ * can be blocked.
+ *
+ * b. Initialize the device. Make sure to turn the SW radio switch
+ * off and move the device to state %WIMAX_ST_RADIO_OFF when
+ * done. When just initialized, a device should be left in RADIO
+ * OFF state until user space devices to turn it on.
+ *
+ * c. Query the device for the state of the hardware rfkill switch
+ * and call wimax_rfkill_report_hw() and wimax_rfkill_report_sw()
+ * as needed. See below.
+ *
+ * wimax_dev_rm() undoes before unregistering the network device. Once
+ * wimax_dev_add() is called, the driver can get called on the
+ * wimax_dev->op_* function pointers
+ *
+ * CONCURRENCY:
+ *
+ * The stack provides a mutex for each device that will disallow API
+ * calls happening concurrently; thus, op calls into the driver
+ * through the wimax_dev->op*() function pointers will always be
+ * serialized and *never* concurrent.
+ *
+ * For locking, take wimax_dev->mutex is taken; (most) operations in
+ * the API have to check for wimax_dev_is_ready() to return 0 before
+ * continuing (this is done internally).
+ *
+ * REFERENCE COUNTING:
+ *
+ * The WiMAX device is reference counted by the associated network
+ * device. The only operation that can be used to reference the device
+ * is wimax_dev_get_by_genl_info(), and the reference it acquires has
+ * to be released with dev_put(wimax_dev->net_dev).
+ *
+ * RFKILL:
+ *
+ * At startup, both HW and SW radio switchess are assumed to be off.
+ *
+ * At initialization time [after calling wimax_dev_add()], have the
+ * driver query the device for the status of the software and hardware
+ * RF kill switches and call wimax_report_rfkill_hw() and
+ * wimax_rfkill_report_sw() to indicate their state. If any is
+ * missing, just call it to indicate it is ON (radio always on).
+ *
+ * Whenever the driver detects a change in the state of the RF kill
+ * switches, it should call wimax_report_rfkill_hw() or
+ * wimax_report_rfkill_sw() to report it to the stack.
+ */
+struct wimax_dev {
+ struct net_device *net_dev;
+ struct list_head id_table_node;
+ struct mutex mutex; /* Protects all members and API calls */
+ struct mutex mutex_reset;
+ enum wimax_st state;
+
+ int (*op_msg_from_user)(struct wimax_dev *wimax_dev,
+ const char *,
+ const void *, size_t,
+ const struct genl_info *info);
+ int (*op_rfkill_sw_toggle)(struct wimax_dev *wimax_dev,
+ enum wimax_rf_state);
+ int (*op_reset)(struct wimax_dev *wimax_dev);
+
+ struct rfkill *rfkill;
+ unsigned rf_hw;
+ unsigned rf_sw;
+ char name[32];
+
+ struct dentry *debugfs_dentry;
+};
+
+
+
+/*
+ * WiMAX stack public API for device drivers
+ * -----------------------------------------
+ *
+ * These functions are not exported to user space.
+ */
+extern void wimax_dev_init(struct wimax_dev *);
+extern int wimax_dev_add(struct wimax_dev *, struct net_device *);
+extern void wimax_dev_rm(struct wimax_dev *);
+
+static inline
+struct wimax_dev *net_dev_to_wimax(struct net_device *net_dev)
+{
+ return netdev_priv(net_dev);
+}
+
+static inline
+struct device *wimax_dev_to_dev(struct wimax_dev *wimax_dev)
+{
+ return wimax_dev->net_dev->dev.parent;
+}
+
+extern void wimax_state_change(struct wimax_dev *, enum wimax_st);
+extern enum wimax_st wimax_state_get(struct wimax_dev *);
+
+/*
+ * Radio Switch state reporting.
+ *
+ * enum wimax_rf_state is declared in linux/wimax.h so the exports
+ * to user space can use it.
+ */
+extern void wimax_report_rfkill_hw(struct wimax_dev *, enum wimax_rf_state);
+extern void wimax_report_rfkill_sw(struct wimax_dev *, enum wimax_rf_state);
+
+
+/*
+ * Free-form messaging to/from user space
+ *
+ * Sending a message:
+ *
+ * wimax_msg(wimax_dev, pipe_name, buf, buf_size, GFP_KERNEL);
+ *
+ * Broken up:
+ *
+ * skb = wimax_msg_alloc(wimax_dev, pipe_name, buf_size, GFP_KERNEL);
+ * ...fill up skb...
+ * wimax_msg_send(wimax_dev, pipe_name, skb);
+ *
+ * Be sure not to modify skb->data in the middle (ie: don't use
+ * skb_push()/skb_pull()/skb_reserve() on the skb).
+ *
+ * "pipe_name" is any string, than can be interpreted as the name of
+ * the pipe or destinatary; the interpretation of it is driver
+ * specific, so the recipient can multiplex it as wished. It can be
+ * NULL, it won't be used - an example is using a "diagnostics" tag to
+ * send diagnostics information that a device-specific diagnostics
+ * tool would be interested in.
+ */
+extern struct sk_buff *wimax_msg_alloc(struct wimax_dev *, const char *,
+ const void *, size_t, gfp_t);
+extern int wimax_msg_send(struct wimax_dev *, struct sk_buff *);
+extern int wimax_msg(struct wimax_dev *, const char *,
+ const void *, size_t, gfp_t);
+
+extern const void *wimax_msg_data_len(struct sk_buff *, size_t *);
+extern const void *wimax_msg_data(struct sk_buff *);
+extern ssize_t wimax_msg_len(struct sk_buff *);
+
+
+/*
+ * WiMAX stack user space API
+ * --------------------------
+ *
+ * This API is what gets exported to user space for general
+ * operations. As well, they can be called from within the kernel,
+ * (with a properly referenced `struct wimax_dev`).
+ *
+ * Properly referenced means: the 'struct net_device' that embeds the
+ * device's control structure and (as such) the 'struct wimax_dev' is
+ * referenced by the caller.
+ */
+extern int wimax_rfkill(struct wimax_dev *, enum wimax_rf_state);
+extern int wimax_reset(struct wimax_dev *);
+
+#endif /* #ifndef __NET__WIMAX_H__ */
diff --git a/include/net/wpan-phy.h b/include/net/wpan-phy.h
new file mode 100644
index 00000000..ff27f1b0
--- /dev/null
+++ b/include/net/wpan-phy.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 Siemens AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by:
+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
+ */
+
+#ifndef WPAN_PHY_H
+#define WPAN_PHY_H
+
+#include <linux/netdevice.h>
+#include <linux/mutex.h>
+#include <linux/bug.h>
+
+struct wpan_phy {
+ struct mutex pib_lock;
+
+ /*
+ * This is a PIB according to 802.15.4-2006.
+ * We do not provide timing-related variables, as they
+ * aren't used outside of driver
+ */
+ u8 current_channel;
+ u8 current_page;
+ u32 channels_supported[32];
+ u8 transmit_power;
+ u8 cca_mode;
+
+ struct device dev;
+ int idx;
+
+ struct net_device *(*add_iface)(struct wpan_phy *phy,
+ const char *name);
+ void (*del_iface)(struct wpan_phy *phy, struct net_device *dev);
+
+ char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
+};
+
+#define to_phy(_dev) container_of(_dev, struct wpan_phy, dev)
+
+struct wpan_phy *wpan_phy_alloc(size_t priv_size);
+static inline void wpan_phy_set_dev(struct wpan_phy *phy, struct device *dev)
+{
+ phy->dev.parent = dev;
+}
+int wpan_phy_register(struct wpan_phy *phy);
+void wpan_phy_unregister(struct wpan_phy *phy);
+void wpan_phy_free(struct wpan_phy *phy);
+/* Same semantics as for class_for_each_device */
+int wpan_phy_for_each(int (*fn)(struct wpan_phy *phy, void *data), void *data);
+
+static inline void *wpan_phy_priv(struct wpan_phy *phy)
+{
+ BUG_ON(!phy);
+ return &phy->priv;
+}
+
+struct wpan_phy *wpan_phy_find(const char *str);
+
+static inline void wpan_phy_put(struct wpan_phy *phy)
+{
+ put_device(&phy->dev);
+}
+
+static inline const char *wpan_phy_name(struct wpan_phy *phy)
+{
+ return dev_name(&phy->dev);
+}
+#endif
diff --git a/include/net/x25.h b/include/net/x25.h
new file mode 100644
index 00000000..a06119a0
--- /dev/null
+++ b/include/net/x25.h
@@ -0,0 +1,323 @@
+/*
+ * Declarations of X.25 Packet Layer type objects.
+ *
+ * History
+ * nov/17/96 Jonathan Naylor Initial version.
+ * mar/20/00 Daniela Squassoni Disabling/enabling of facilities
+ * negotiation.
+ */
+
+#ifndef _X25_H
+#define _X25_H
+#include <linux/x25.h>
+#include <linux/slab.h>
+#include <net/sock.h>
+
+#define X25_ADDR_LEN 16
+
+#define X25_MAX_L2_LEN 18 /* 802.2 LLC */
+
+#define X25_STD_MIN_LEN 3
+#define X25_EXT_MIN_LEN 4
+
+#define X25_GFI_SEQ_MASK 0x30
+#define X25_GFI_STDSEQ 0x10
+#define X25_GFI_EXTSEQ 0x20
+
+#define X25_Q_BIT 0x80
+#define X25_D_BIT 0x40
+#define X25_STD_M_BIT 0x10
+#define X25_EXT_M_BIT 0x01
+
+#define X25_CALL_REQUEST 0x0B
+#define X25_CALL_ACCEPTED 0x0F
+#define X25_CLEAR_REQUEST 0x13
+#define X25_CLEAR_CONFIRMATION 0x17
+#define X25_DATA 0x00
+#define X25_INTERRUPT 0x23
+#define X25_INTERRUPT_CONFIRMATION 0x27
+#define X25_RR 0x01
+#define X25_RNR 0x05
+#define X25_REJ 0x09
+#define X25_RESET_REQUEST 0x1B
+#define X25_RESET_CONFIRMATION 0x1F
+#define X25_REGISTRATION_REQUEST 0xF3
+#define X25_REGISTRATION_CONFIRMATION 0xF7
+#define X25_RESTART_REQUEST 0xFB
+#define X25_RESTART_CONFIRMATION 0xFF
+#define X25_DIAGNOSTIC 0xF1
+#define X25_ILLEGAL 0xFD
+
+/* Define the various conditions that may exist */
+
+#define X25_COND_ACK_PENDING 0x01
+#define X25_COND_OWN_RX_BUSY 0x02
+#define X25_COND_PEER_RX_BUSY 0x04
+
+/* Define Link State constants. */
+enum {
+ X25_STATE_0, /* Ready */
+ X25_STATE_1, /* Awaiting Call Accepted */
+ X25_STATE_2, /* Awaiting Clear Confirmation */
+ X25_STATE_3, /* Data Transfer */
+ X25_STATE_4 /* Awaiting Reset Confirmation */
+};
+
+enum {
+ X25_LINK_STATE_0,
+ X25_LINK_STATE_1,
+ X25_LINK_STATE_2,
+ X25_LINK_STATE_3
+};
+
+#define X25_DEFAULT_T20 (180 * HZ) /* Default T20 value */
+#define X25_DEFAULT_T21 (200 * HZ) /* Default T21 value */
+#define X25_DEFAULT_T22 (180 * HZ) /* Default T22 value */
+#define X25_DEFAULT_T23 (180 * HZ) /* Default T23 value */
+#define X25_DEFAULT_T2 (3 * HZ) /* Default ack holdback value */
+
+#define X25_DEFAULT_WINDOW_SIZE 2 /* Default Window Size */
+#define X25_DEFAULT_PACKET_SIZE X25_PS128 /* Default Packet Size */
+#define X25_DEFAULT_THROUGHPUT 0x0A /* Deafult Throughput */
+#define X25_DEFAULT_REVERSE 0x00 /* Default Reverse Charging */
+
+#define X25_SMODULUS 8
+#define X25_EMODULUS 128
+
+/*
+ * X.25 Facilities constants.
+ */
+
+#define X25_FAC_CLASS_MASK 0xC0
+
+#define X25_FAC_CLASS_A 0x00
+#define X25_FAC_CLASS_B 0x40
+#define X25_FAC_CLASS_C 0x80
+#define X25_FAC_CLASS_D 0xC0
+
+#define X25_FAC_REVERSE 0x01 /* also fast select */
+#define X25_FAC_THROUGHPUT 0x02
+#define X25_FAC_PACKET_SIZE 0x42
+#define X25_FAC_WINDOW_SIZE 0x43
+
+#define X25_MAX_FAC_LEN 60
+#define X25_MAX_CUD_LEN 128
+
+#define X25_FAC_CALLING_AE 0xCB
+#define X25_FAC_CALLED_AE 0xC9
+
+#define X25_MARKER 0x00
+#define X25_DTE_SERVICES 0x0F
+#define X25_MAX_AE_LEN 40 /* Max num of semi-octets in AE - OSI Nw */
+#define X25_MAX_DTE_FACIL_LEN 21 /* Max length of DTE facility params */
+
+/* Bitset in x25_sock->flags for misc flags */
+#define X25_Q_BIT_FLAG 0
+#define X25_INTERRUPT_FLAG 1
+#define X25_ACCPT_APPRV_FLAG 2
+
+/**
+ * struct x25_route - x25 routing entry
+ * @node - entry in x25_list_lock
+ * @address - Start of address range
+ * @sigdigits - Number of sig digits
+ * @dev - More than one for MLP
+ * @refcnt - reference counter
+ */
+struct x25_route {
+ struct list_head node;
+ struct x25_address address;
+ unsigned int sigdigits;
+ struct net_device *dev;
+ atomic_t refcnt;
+};
+
+struct x25_neigh {
+ struct list_head node;
+ struct net_device *dev;
+ unsigned int state;
+ unsigned int extended;
+ struct sk_buff_head queue;
+ unsigned long t20;
+ struct timer_list t20timer;
+ unsigned long global_facil_mask;
+ atomic_t refcnt;
+};
+
+struct x25_sock {
+ struct sock sk;
+ struct x25_address source_addr, dest_addr;
+ struct x25_neigh *neighbour;
+ unsigned int lci, cudmatchlength;
+ unsigned char state, condition;
+ unsigned short vs, vr, va, vl;
+ unsigned long t2, t21, t22, t23;
+ unsigned short fraglen;
+ unsigned long flags;
+ struct sk_buff_head ack_queue;
+ struct sk_buff_head fragment_queue;
+ struct sk_buff_head interrupt_in_queue;
+ struct sk_buff_head interrupt_out_queue;
+ struct timer_list timer;
+ struct x25_causediag causediag;
+ struct x25_facilities facilities;
+ struct x25_dte_facilities dte_facilities;
+ struct x25_calluserdata calluserdata;
+ unsigned long vc_facil_mask; /* inc_call facilities mask */
+};
+
+struct x25_forward {
+ struct list_head node;
+ unsigned int lci;
+ struct net_device *dev1;
+ struct net_device *dev2;
+ atomic_t refcnt;
+};
+
+static inline struct x25_sock *x25_sk(const struct sock *sk)
+{
+ return (struct x25_sock *)sk;
+}
+
+/* af_x25.c */
+extern int sysctl_x25_restart_request_timeout;
+extern int sysctl_x25_call_request_timeout;
+extern int sysctl_x25_reset_request_timeout;
+extern int sysctl_x25_clear_request_timeout;
+extern int sysctl_x25_ack_holdback_timeout;
+extern int sysctl_x25_forward;
+
+extern int x25_parse_address_block(struct sk_buff *skb,
+ struct x25_address *called_addr,
+ struct x25_address *calling_addr);
+
+extern int x25_addr_ntoa(unsigned char *, struct x25_address *,
+ struct x25_address *);
+extern int x25_addr_aton(unsigned char *, struct x25_address *,
+ struct x25_address *);
+extern struct sock *x25_find_socket(unsigned int, struct x25_neigh *);
+extern void x25_destroy_socket_from_timer(struct sock *);
+extern int x25_rx_call_request(struct sk_buff *, struct x25_neigh *, unsigned int);
+extern void x25_kill_by_neigh(struct x25_neigh *);
+
+/* x25_dev.c */
+extern void x25_send_frame(struct sk_buff *, struct x25_neigh *);
+extern int x25_lapb_receive_frame(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *);
+extern void x25_establish_link(struct x25_neigh *);
+extern void x25_terminate_link(struct x25_neigh *);
+
+/* x25_facilities.c */
+extern int x25_parse_facilities(struct sk_buff *, struct x25_facilities *,
+ struct x25_dte_facilities *, unsigned long *);
+extern int x25_create_facilities(unsigned char *, struct x25_facilities *,
+ struct x25_dte_facilities *, unsigned long);
+extern int x25_negotiate_facilities(struct sk_buff *, struct sock *,
+ struct x25_facilities *,
+ struct x25_dte_facilities *);
+extern void x25_limit_facilities(struct x25_facilities *, struct x25_neigh *);
+
+/* x25_forward.c */
+extern void x25_clear_forward_by_lci(unsigned int lci);
+extern void x25_clear_forward_by_dev(struct net_device *);
+extern int x25_forward_data(int, struct x25_neigh *, struct sk_buff *);
+extern int x25_forward_call(struct x25_address *, struct x25_neigh *,
+ struct sk_buff *, int);
+
+/* x25_in.c */
+extern int x25_process_rx_frame(struct sock *, struct sk_buff *);
+extern int x25_backlog_rcv(struct sock *, struct sk_buff *);
+
+/* x25_link.c */
+extern void x25_link_control(struct sk_buff *, struct x25_neigh *, unsigned short);
+extern void x25_link_device_up(struct net_device *);
+extern void x25_link_device_down(struct net_device *);
+extern void x25_link_established(struct x25_neigh *);
+extern void x25_link_terminated(struct x25_neigh *);
+extern void x25_transmit_clear_request(struct x25_neigh *, unsigned int, unsigned char);
+extern void x25_transmit_link(struct sk_buff *, struct x25_neigh *);
+extern int x25_subscr_ioctl(unsigned int, void __user *);
+extern struct x25_neigh *x25_get_neigh(struct net_device *);
+extern void x25_link_free(void);
+
+/* x25_neigh.c */
+static __inline__ void x25_neigh_hold(struct x25_neigh *nb)
+{
+ atomic_inc(&nb->refcnt);
+}
+
+static __inline__ void x25_neigh_put(struct x25_neigh *nb)
+{
+ if (atomic_dec_and_test(&nb->refcnt))
+ kfree(nb);
+}
+
+/* x25_out.c */
+extern int x25_output(struct sock *, struct sk_buff *);
+extern void x25_kick(struct sock *);
+extern void x25_enquiry_response(struct sock *);
+
+/* x25_route.c */
+extern struct x25_route *x25_get_route(struct x25_address *addr);
+extern struct net_device *x25_dev_get(char *);
+extern void x25_route_device_down(struct net_device *dev);
+extern int x25_route_ioctl(unsigned int, void __user *);
+extern void x25_route_free(void);
+
+static __inline__ void x25_route_hold(struct x25_route *rt)
+{
+ atomic_inc(&rt->refcnt);
+}
+
+static __inline__ void x25_route_put(struct x25_route *rt)
+{
+ if (atomic_dec_and_test(&rt->refcnt))
+ kfree(rt);
+}
+
+/* x25_subr.c */
+extern void x25_clear_queues(struct sock *);
+extern void x25_frames_acked(struct sock *, unsigned short);
+extern void x25_requeue_frames(struct sock *);
+extern int x25_validate_nr(struct sock *, unsigned short);
+extern void x25_write_internal(struct sock *, int);
+extern int x25_decode(struct sock *, struct sk_buff *, int *, int *, int *, int *, int *);
+extern void x25_disconnect(struct sock *, int, unsigned char, unsigned char);
+
+/* x25_timer.c */
+extern void x25_init_timers(struct sock *sk);
+extern void x25_start_heartbeat(struct sock *);
+extern void x25_start_t2timer(struct sock *);
+extern void x25_start_t21timer(struct sock *);
+extern void x25_start_t22timer(struct sock *);
+extern void x25_start_t23timer(struct sock *);
+extern void x25_stop_heartbeat(struct sock *);
+extern void x25_stop_timer(struct sock *);
+extern unsigned long x25_display_timer(struct sock *);
+extern void x25_check_rbuf(struct sock *);
+
+/* sysctl_net_x25.c */
+#ifdef CONFIG_SYSCTL
+extern void x25_register_sysctl(void);
+extern void x25_unregister_sysctl(void);
+#else
+static inline void x25_register_sysctl(void) {};
+static inline void x25_unregister_sysctl(void) {};
+#endif /* CONFIG_SYSCTL */
+
+struct x25_skb_cb {
+ unsigned flags;
+};
+#define X25_SKB_CB(s) ((struct x25_skb_cb *) ((s)->cb))
+
+extern struct hlist_head x25_list;
+extern rwlock_t x25_list_lock;
+extern struct list_head x25_route_list;
+extern rwlock_t x25_route_list_lock;
+extern struct list_head x25_forward_list;
+extern rwlock_t x25_forward_list_lock;
+extern struct list_head x25_neigh_list;
+extern rwlock_t x25_neigh_list_lock;
+
+extern int x25_proc_init(void);
+extern void x25_proc_exit(void);
+#endif
diff --git a/include/net/x25device.h b/include/net/x25device.h
new file mode 100644
index 00000000..1fa08b49
--- /dev/null
+++ b/include/net/x25device.h
@@ -0,0 +1,17 @@
+#ifndef _X25DEVICE_H
+#define _X25DEVICE_H
+
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <linux/if_x25.h>
+#include <linux/skbuff.h>
+
+static inline __be16 x25_type_trans(struct sk_buff *skb, struct net_device *dev)
+{
+ skb->dev = dev;
+ skb_reset_mac_header(skb);
+ skb->pkt_type = PACKET_HOST;
+
+ return htons(ETH_P_X25);
+}
+#endif
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
new file mode 100644
index 00000000..96239e78
--- /dev/null
+++ b/include/net/xfrm.h
@@ -0,0 +1,1693 @@
+#ifndef _NET_XFRM_H
+#define _NET_XFRM_H
+
+#include <linux/compiler.h>
+#include <linux/xfrm.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/skbuff.h>
+#include <linux/socket.h>
+#include <linux/pfkeyv2.h>
+#include <linux/ipsec.h>
+#include <linux/in6.h>
+#include <linux/mutex.h>
+#include <linux/audit.h>
+#include <linux/slab.h>
+
+#include <net/sock.h>
+#include <net/dst.h>
+#include <net/ip.h>
+#include <net/route.h>
+#include <net/ipv6.h>
+#include <net/ip6_fib.h>
+#include <net/flow.h>
+
+#include <linux/interrupt.h>
+
+#ifdef CONFIG_XFRM_STATISTICS
+#include <net/snmp.h>
+#endif
+
+#define XFRM_PROTO_ESP 50
+#define XFRM_PROTO_AH 51
+#define XFRM_PROTO_COMP 108
+#define XFRM_PROTO_IPIP 4
+#define XFRM_PROTO_IPV6 41
+#define XFRM_PROTO_ROUTING IPPROTO_ROUTING
+#define XFRM_PROTO_DSTOPTS IPPROTO_DSTOPTS
+
+#define XFRM_ALIGN4(len) (((len) + 3) & ~3)
+#define XFRM_ALIGN8(len) (((len) + 7) & ~7)
+#define MODULE_ALIAS_XFRM_MODE(family, encap) \
+ MODULE_ALIAS("xfrm-mode-" __stringify(family) "-" __stringify(encap))
+#define MODULE_ALIAS_XFRM_TYPE(family, proto) \
+ MODULE_ALIAS("xfrm-type-" __stringify(family) "-" __stringify(proto))
+
+#ifdef CONFIG_XFRM_STATISTICS
+#define XFRM_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.xfrm_statistics, field)
+#define XFRM_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.xfrm_statistics, field)
+#define XFRM_INC_STATS_USER(net, field) SNMP_INC_STATS_USER((net)-mib.xfrm_statistics, field)
+#else
+#define XFRM_INC_STATS(net, field) ((void)(net))
+#define XFRM_INC_STATS_BH(net, field) ((void)(net))
+#define XFRM_INC_STATS_USER(net, field) ((void)(net))
+#endif
+
+extern struct mutex xfrm_cfg_mutex;
+
+/* Organization of SPD aka "XFRM rules"
+ ------------------------------------
+
+ Basic objects:
+ - policy rule, struct xfrm_policy (=SPD entry)
+ - bundle of transformations, struct dst_entry == struct xfrm_dst (=SA bundle)
+ - instance of a transformer, struct xfrm_state (=SA)
+ - template to clone xfrm_state, struct xfrm_tmpl
+
+ SPD is plain linear list of xfrm_policy rules, ordered by priority.
+ (To be compatible with existing pfkeyv2 implementations,
+ many rules with priority of 0x7fffffff are allowed to exist and
+ such rules are ordered in an unpredictable way, thanks to bsd folks.)
+
+ Lookup is plain linear search until the first match with selector.
+
+ If "action" is "block", then we prohibit the flow, otherwise:
+ if "xfrms_nr" is zero, the flow passes untransformed. Otherwise,
+ policy entry has list of up to XFRM_MAX_DEPTH transformations,
+ described by templates xfrm_tmpl. Each template is resolved
+ to a complete xfrm_state (see below) and we pack bundle of transformations
+ to a dst_entry returned to requestor.
+
+ dst -. xfrm .-> xfrm_state #1
+ |---. child .-> dst -. xfrm .-> xfrm_state #2
+ |---. child .-> dst -. xfrm .-> xfrm_state #3
+ |---. child .-> NULL
+
+ Bundles are cached at xrfm_policy struct (field ->bundles).
+
+
+ Resolution of xrfm_tmpl
+ -----------------------
+ Template contains:
+ 1. ->mode Mode: transport or tunnel
+ 2. ->id.proto Protocol: AH/ESP/IPCOMP
+ 3. ->id.daddr Remote tunnel endpoint, ignored for transport mode.
+ Q: allow to resolve security gateway?
+ 4. ->id.spi If not zero, static SPI.
+ 5. ->saddr Local tunnel endpoint, ignored for transport mode.
+ 6. ->algos List of allowed algos. Plain bitmask now.
+ Q: ealgos, aalgos, calgos. What a mess...
+ 7. ->share Sharing mode.
+ Q: how to implement private sharing mode? To add struct sock* to
+ flow id?
+
+ Having this template we search through SAD searching for entries
+ with appropriate mode/proto/algo, permitted by selector.
+ If no appropriate entry found, it is requested from key manager.
+
+ PROBLEMS:
+ Q: How to find all the bundles referring to a physical path for
+ PMTU discovery? Seems, dst should contain list of all parents...
+ and enter to infinite locking hierarchy disaster.
+ No! It is easier, we will not search for them, let them find us.
+ We add genid to each dst plus pointer to genid of raw IP route,
+ pmtu disc will update pmtu on raw IP route and increase its genid.
+ dst_check() will see this for top level and trigger resyncing
+ metrics. Plus, it will be made via sk->sk_dst_cache. Solved.
+ */
+
+struct xfrm_state_walk {
+ struct list_head all;
+ u8 state;
+ union {
+ u8 dying;
+ u8 proto;
+ };
+ u32 seq;
+};
+
+/* Full description of state of transformer. */
+struct xfrm_state {
+#ifdef CONFIG_NET_NS
+ struct net *xs_net;
+#endif
+ union {
+ struct hlist_node gclist;
+ struct hlist_node bydst;
+ };
+ struct hlist_node bysrc;
+ struct hlist_node byspi;
+
+ atomic_t refcnt;
+ spinlock_t lock;
+
+ struct xfrm_id id;
+ struct xfrm_selector sel;
+ struct xfrm_mark mark;
+ u32 tfcpad;
+
+ u32 genid;
+
+ /* Key manager bits */
+ struct xfrm_state_walk km;
+
+ /* Parameters of this state. */
+ struct {
+ u32 reqid;
+ u8 mode;
+ u8 replay_window;
+ u8 aalgo, ealgo, calgo;
+ u8 flags;
+ u16 family;
+ xfrm_address_t saddr;
+ int header_len;
+ int trailer_len;
+ } props;
+
+ struct xfrm_lifetime_cfg lft;
+
+ /* Data for transformer */
+ struct xfrm_algo_auth *aalg;
+ struct xfrm_algo *ealg;
+ struct xfrm_algo *calg;
+ struct xfrm_algo_aead *aead;
+
+ /* Data for encapsulator */
+ struct xfrm_encap_tmpl *encap;
+
+ /* Data for care-of address */
+ xfrm_address_t *coaddr;
+
+ /* IPComp needs an IPIP tunnel for handling uncompressed packets */
+ struct xfrm_state *tunnel;
+
+ /* If a tunnel, number of users + 1 */
+ atomic_t tunnel_users;
+
+ /* State for replay detection */
+ struct xfrm_replay_state replay;
+ struct xfrm_replay_state_esn *replay_esn;
+
+ /* Replay detection state at the time we sent the last notification */
+ struct xfrm_replay_state preplay;
+ struct xfrm_replay_state_esn *preplay_esn;
+
+ /* The functions for replay detection. */
+ struct xfrm_replay *repl;
+
+ /* internal flag that only holds state for delayed aevent at the
+ * moment
+ */
+ u32 xflags;
+
+ /* Replay detection notification settings */
+ u32 replay_maxage;
+ u32 replay_maxdiff;
+
+ /* Replay detection notification timer */
+ struct timer_list rtimer;
+
+ /* Statistics */
+ struct xfrm_stats stats;
+
+ struct xfrm_lifetime_cur curlft;
+ struct tasklet_hrtimer mtimer;
+
+ /* Last used time */
+ unsigned long lastused;
+
+ /* Reference to data common to all the instances of this
+ * transformer. */
+ const struct xfrm_type *type;
+ struct xfrm_mode *inner_mode;
+ struct xfrm_mode *inner_mode_iaf;
+ struct xfrm_mode *outer_mode;
+
+ /* Security context */
+ struct xfrm_sec_ctx *security;
+
+ /* Private data of this transformer, format is opaque,
+ * interpreted by xfrm_type methods. */
+ void *data;
+};
+
+static inline struct net *xs_net(struct xfrm_state *x)
+{
+ return read_pnet(&x->xs_net);
+}
+
+/* xflags - make enum if more show up */
+#define XFRM_TIME_DEFER 1
+
+enum {
+ XFRM_STATE_VOID,
+ XFRM_STATE_ACQ,
+ XFRM_STATE_VALID,
+ XFRM_STATE_ERROR,
+ XFRM_STATE_EXPIRED,
+ XFRM_STATE_DEAD
+};
+
+/* callback structure passed from either netlink or pfkey */
+struct km_event {
+ union {
+ u32 hard;
+ u32 proto;
+ u32 byid;
+ u32 aevent;
+ u32 type;
+ } data;
+
+ u32 seq;
+ u32 pid;
+ u32 event;
+ struct net *net;
+};
+
+struct xfrm_replay {
+ void (*advance)(struct xfrm_state *x, __be32 net_seq);
+ int (*check)(struct xfrm_state *x,
+ struct sk_buff *skb,
+ __be32 net_seq);
+ void (*notify)(struct xfrm_state *x, int event);
+ int (*overflow)(struct xfrm_state *x, struct sk_buff *skb);
+};
+
+struct net_device;
+struct xfrm_type;
+struct xfrm_dst;
+struct xfrm_policy_afinfo {
+ unsigned short family;
+ struct dst_ops *dst_ops;
+ void (*garbage_collect)(struct net *net);
+ struct dst_entry *(*dst_lookup)(struct net *net, int tos,
+ const xfrm_address_t *saddr,
+ const xfrm_address_t *daddr);
+ int (*get_saddr)(struct net *net, xfrm_address_t *saddr, xfrm_address_t *daddr);
+ void (*decode_session)(struct sk_buff *skb,
+ struct flowi *fl,
+ int reverse);
+ int (*get_tos)(const struct flowi *fl);
+ int (*init_path)(struct xfrm_dst *path,
+ struct dst_entry *dst,
+ int nfheader_len);
+ int (*fill_dst)(struct xfrm_dst *xdst,
+ struct net_device *dev,
+ const struct flowi *fl);
+ struct dst_entry *(*blackhole_route)(struct net *net, struct dst_entry *orig);
+};
+
+extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
+extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
+extern void km_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c);
+extern void km_state_notify(struct xfrm_state *x, const struct km_event *c);
+
+struct xfrm_tmpl;
+extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
+extern void km_state_expired(struct xfrm_state *x, int hard, u32 pid);
+extern int __xfrm_state_delete(struct xfrm_state *x);
+
+struct xfrm_state_afinfo {
+ unsigned int family;
+ unsigned int proto;
+ __be16 eth_proto;
+ struct module *owner;
+ const struct xfrm_type *type_map[IPPROTO_MAX];
+ struct xfrm_mode *mode_map[XFRM_MODE_MAX];
+ int (*init_flags)(struct xfrm_state *x);
+ void (*init_tempsel)(struct xfrm_selector *sel,
+ const struct flowi *fl);
+ void (*init_temprop)(struct xfrm_state *x,
+ const struct xfrm_tmpl *tmpl,
+ const xfrm_address_t *daddr,
+ const xfrm_address_t *saddr);
+ int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
+ int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
+ int (*output)(struct sk_buff *skb);
+ int (*output_finish)(struct sk_buff *skb);
+ int (*extract_input)(struct xfrm_state *x,
+ struct sk_buff *skb);
+ int (*extract_output)(struct xfrm_state *x,
+ struct sk_buff *skb);
+ int (*transport_finish)(struct sk_buff *skb,
+ int async);
+};
+
+extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
+extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
+
+extern void xfrm_state_delete_tunnel(struct xfrm_state *x);
+
+struct xfrm_type {
+ char *description;
+ struct module *owner;
+ u8 proto;
+ u8 flags;
+#define XFRM_TYPE_NON_FRAGMENT 1
+#define XFRM_TYPE_REPLAY_PROT 2
+#define XFRM_TYPE_LOCAL_COADDR 4
+#define XFRM_TYPE_REMOTE_COADDR 8
+
+ int (*init_state)(struct xfrm_state *x);
+ void (*destructor)(struct xfrm_state *);
+ int (*input)(struct xfrm_state *, struct sk_buff *skb);
+ int (*output)(struct xfrm_state *, struct sk_buff *pskb);
+ int (*reject)(struct xfrm_state *, struct sk_buff *,
+ const struct flowi *);
+ int (*hdr_offset)(struct xfrm_state *, struct sk_buff *, u8 **);
+ /* Estimate maximal size of result of transformation of a dgram */
+ u32 (*get_mtu)(struct xfrm_state *, int size);
+};
+
+extern int xfrm_register_type(const struct xfrm_type *type, unsigned short family);
+extern int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family);
+
+struct xfrm_mode {
+ /*
+ * Remove encapsulation header.
+ *
+ * The IP header will be moved over the top of the encapsulation
+ * header.
+ *
+ * On entry, the transport header shall point to where the IP header
+ * should be and the network header shall be set to where the IP
+ * header currently is. skb->data shall point to the start of the
+ * payload.
+ */
+ int (*input2)(struct xfrm_state *x, struct sk_buff *skb);
+
+ /*
+ * This is the actual input entry point.
+ *
+ * For transport mode and equivalent this would be identical to
+ * input2 (which does not need to be set). While tunnel mode
+ * and equivalent would set this to the tunnel encapsulation function
+ * xfrm4_prepare_input that would in turn call input2.
+ */
+ int (*input)(struct xfrm_state *x, struct sk_buff *skb);
+
+ /*
+ * Add encapsulation header.
+ *
+ * On exit, the transport header will be set to the start of the
+ * encapsulation header to be filled in by x->type->output and
+ * the mac header will be set to the nextheader (protocol for
+ * IPv4) field of the extension header directly preceding the
+ * encapsulation header, or in its absence, that of the top IP
+ * header. The value of the network header will always point
+ * to the top IP header while skb->data will point to the payload.
+ */
+ int (*output2)(struct xfrm_state *x,struct sk_buff *skb);
+
+ /*
+ * This is the actual output entry point.
+ *
+ * For transport mode and equivalent this would be identical to
+ * output2 (which does not need to be set). While tunnel mode
+ * and equivalent would set this to a tunnel encapsulation function
+ * (xfrm4_prepare_output or xfrm6_prepare_output) that would in turn
+ * call output2.
+ */
+ int (*output)(struct xfrm_state *x, struct sk_buff *skb);
+
+ struct xfrm_state_afinfo *afinfo;
+ struct module *owner;
+ unsigned int encap;
+ int flags;
+};
+
+/* Flags for xfrm_mode. */
+enum {
+ XFRM_MODE_FLAG_TUNNEL = 1,
+};
+
+extern int xfrm_register_mode(struct xfrm_mode *mode, int family);
+extern int xfrm_unregister_mode(struct xfrm_mode *mode, int family);
+
+static inline int xfrm_af2proto(unsigned int family)
+{
+ switch(family) {
+ case AF_INET:
+ return IPPROTO_IPIP;
+ case AF_INET6:
+ return IPPROTO_IPV6;
+ default:
+ return 0;
+ }
+}
+
+static inline struct xfrm_mode *xfrm_ip2inner_mode(struct xfrm_state *x, int ipproto)
+{
+ if ((ipproto == IPPROTO_IPIP && x->props.family == AF_INET) ||
+ (ipproto == IPPROTO_IPV6 && x->props.family == AF_INET6))
+ return x->inner_mode;
+ else
+ return x->inner_mode_iaf;
+}
+
+struct xfrm_tmpl {
+/* id in template is interpreted as:
+ * daddr - destination of tunnel, may be zero for transport mode.
+ * spi - zero to acquire spi. Not zero if spi is static, then
+ * daddr must be fixed too.
+ * proto - AH/ESP/IPCOMP
+ */
+ struct xfrm_id id;
+
+/* Source address of tunnel. Ignored, if it is not a tunnel. */
+ xfrm_address_t saddr;
+
+ unsigned short encap_family;
+
+ u32 reqid;
+
+/* Mode: transport, tunnel etc. */
+ u8 mode;
+
+/* Sharing mode: unique, this session only, this user only etc. */
+ u8 share;
+
+/* May skip this transfomration if no SA is found */
+ u8 optional;
+
+/* Skip aalgos/ealgos/calgos checks. */
+ u8 allalgs;
+
+/* Bit mask of algos allowed for acquisition */
+ u32 aalgos;
+ u32 ealgos;
+ u32 calgos;
+};
+
+#define XFRM_MAX_DEPTH 6
+
+struct xfrm_policy_walk_entry {
+ struct list_head all;
+ u8 dead;
+};
+
+struct xfrm_policy_walk {
+ struct xfrm_policy_walk_entry walk;
+ u8 type;
+ u32 seq;
+};
+
+struct xfrm_policy {
+#ifdef CONFIG_NET_NS
+ struct net *xp_net;
+#endif
+ struct hlist_node bydst;
+ struct hlist_node byidx;
+
+ /* This lock only affects elements except for entry. */
+ rwlock_t lock;
+ atomic_t refcnt;
+ struct timer_list timer;
+
+ struct flow_cache_object flo;
+ atomic_t genid;
+ u32 priority;
+ u32 index;
+ struct xfrm_mark mark;
+ struct xfrm_selector selector;
+ struct xfrm_lifetime_cfg lft;
+ struct xfrm_lifetime_cur curlft;
+ struct xfrm_policy_walk_entry walk;
+ u8 type;
+ u8 action;
+ u8 flags;
+ u8 xfrm_nr;
+ u16 family;
+ struct xfrm_sec_ctx *security;
+ struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH];
+};
+
+static inline struct net *xp_net(const struct xfrm_policy *xp)
+{
+ return read_pnet(&xp->xp_net);
+}
+
+struct xfrm_kmaddress {
+ xfrm_address_t local;
+ xfrm_address_t remote;
+ u32 reserved;
+ u16 family;
+};
+
+struct xfrm_migrate {
+ xfrm_address_t old_daddr;
+ xfrm_address_t old_saddr;
+ xfrm_address_t new_daddr;
+ xfrm_address_t new_saddr;
+ u8 proto;
+ u8 mode;
+ u16 reserved;
+ u32 reqid;
+ u16 old_family;
+ u16 new_family;
+};
+
+#define XFRM_KM_TIMEOUT 30
+/* which seqno */
+#define XFRM_REPLAY_SEQ 1
+#define XFRM_REPLAY_OSEQ 2
+#define XFRM_REPLAY_SEQ_MASK 3
+/* what happened */
+#define XFRM_REPLAY_UPDATE XFRM_AE_CR
+#define XFRM_REPLAY_TIMEOUT XFRM_AE_CE
+
+/* default aevent timeout in units of 100ms */
+#define XFRM_AE_ETIME 10
+/* Async Event timer multiplier */
+#define XFRM_AE_ETH_M 10
+/* default seq threshold size */
+#define XFRM_AE_SEQT_SIZE 2
+
+struct xfrm_mgr {
+ struct list_head list;
+ char *id;
+ int (*notify)(struct xfrm_state *x, const struct km_event *c);
+ int (*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir);
+ struct xfrm_policy *(*compile_policy)(struct sock *sk, int opt, u8 *data, int len, int *dir);
+ int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
+ int (*notify_policy)(struct xfrm_policy *x, int dir, const struct km_event *c);
+ int (*report)(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
+ int (*migrate)(const struct xfrm_selector *sel,
+ u8 dir, u8 type,
+ const struct xfrm_migrate *m,
+ int num_bundles,
+ const struct xfrm_kmaddress *k);
+};
+
+extern int xfrm_register_km(struct xfrm_mgr *km);
+extern int xfrm_unregister_km(struct xfrm_mgr *km);
+
+/*
+ * This structure is used for the duration where packets are being
+ * transformed by IPsec. As soon as the packet leaves IPsec the
+ * area beyond the generic IP part may be overwritten.
+ */
+struct xfrm_skb_cb {
+ union {
+ struct inet_skb_parm h4;
+ struct inet6_skb_parm h6;
+ } header;
+
+ /* Sequence number for replay protection. */
+ union {
+ struct {
+ __u32 low;
+ __u32 hi;
+ } output;
+ struct {
+ __be32 low;
+ __be32 hi;
+ } input;
+ } seq;
+};
+
+#define XFRM_SKB_CB(__skb) ((struct xfrm_skb_cb *)&((__skb)->cb[0]))
+
+/*
+ * This structure is used by the afinfo prepare_input/prepare_output functions
+ * to transmit header information to the mode input/output functions.
+ */
+struct xfrm_mode_skb_cb {
+ union {
+ struct inet_skb_parm h4;
+ struct inet6_skb_parm h6;
+ } header;
+
+ /* Copied from header for IPv4, always set to zero and DF for IPv6. */
+ __be16 id;
+ __be16 frag_off;
+
+ /* IP header length (excluding options or extension headers). */
+ u8 ihl;
+
+ /* TOS for IPv4, class for IPv6. */
+ u8 tos;
+
+ /* TTL for IPv4, hop limitfor IPv6. */
+ u8 ttl;
+
+ /* Protocol for IPv4, NH for IPv6. */
+ u8 protocol;
+
+ /* Option length for IPv4, zero for IPv6. */
+ u8 optlen;
+
+ /* Used by IPv6 only, zero for IPv4. */
+ u8 flow_lbl[3];
+};
+
+#define XFRM_MODE_SKB_CB(__skb) ((struct xfrm_mode_skb_cb *)&((__skb)->cb[0]))
+
+/*
+ * This structure is used by the input processing to locate the SPI and
+ * related information.
+ */
+struct xfrm_spi_skb_cb {
+ union {
+ struct inet_skb_parm h4;
+ struct inet6_skb_parm h6;
+ } header;
+
+ unsigned int daddroff;
+ unsigned int family;
+};
+
+#define XFRM_SPI_SKB_CB(__skb) ((struct xfrm_spi_skb_cb *)&((__skb)->cb[0]))
+
+/* Audit Information */
+struct xfrm_audit {
+ u32 secid;
+ uid_t loginuid;
+ u32 sessionid;
+};
+
+#ifdef CONFIG_AUDITSYSCALL
+static inline struct audit_buffer *xfrm_audit_start(const char *op)
+{
+ struct audit_buffer *audit_buf = NULL;
+
+ if (audit_enabled == 0)
+ return NULL;
+ audit_buf = audit_log_start(current->audit_context, GFP_ATOMIC,
+ AUDIT_MAC_IPSEC_EVENT);
+ if (audit_buf == NULL)
+ return NULL;
+ audit_log_format(audit_buf, "op=%s", op);
+ return audit_buf;
+}
+
+static inline void xfrm_audit_helper_usrinfo(uid_t auid, u32 ses, u32 secid,
+ struct audit_buffer *audit_buf)
+{
+ char *secctx;
+ u32 secctx_len;
+
+ audit_log_format(audit_buf, " auid=%u ses=%u", auid, ses);
+ if (secid != 0 &&
+ security_secid_to_secctx(secid, &secctx, &secctx_len) == 0) {
+ audit_log_format(audit_buf, " subj=%s", secctx);
+ security_release_secctx(secctx, secctx_len);
+ } else
+ audit_log_task_context(audit_buf);
+}
+
+extern void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
+ u32 auid, u32 ses, u32 secid);
+extern void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result,
+ u32 auid, u32 ses, u32 secid);
+extern void xfrm_audit_state_add(struct xfrm_state *x, int result,
+ u32 auid, u32 ses, u32 secid);
+extern void xfrm_audit_state_delete(struct xfrm_state *x, int result,
+ u32 auid, u32 ses, u32 secid);
+extern void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
+ struct sk_buff *skb);
+extern void xfrm_audit_state_replay(struct xfrm_state *x,
+ struct sk_buff *skb, __be32 net_seq);
+extern void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family);
+extern void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
+ __be32 net_spi, __be32 net_seq);
+extern void xfrm_audit_state_icvfail(struct xfrm_state *x,
+ struct sk_buff *skb, u8 proto);
+#else
+
+static inline void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
+ u32 auid, u32 ses, u32 secid)
+{
+}
+
+static inline void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result,
+ u32 auid, u32 ses, u32 secid)
+{
+}
+
+static inline void xfrm_audit_state_add(struct xfrm_state *x, int result,
+ u32 auid, u32 ses, u32 secid)
+{
+}
+
+static inline void xfrm_audit_state_delete(struct xfrm_state *x, int result,
+ u32 auid, u32 ses, u32 secid)
+{
+}
+
+static inline void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
+ struct sk_buff *skb)
+{
+}
+
+static inline void xfrm_audit_state_replay(struct xfrm_state *x,
+ struct sk_buff *skb, __be32 net_seq)
+{
+}
+
+static inline void xfrm_audit_state_notfound_simple(struct sk_buff *skb,
+ u16 family)
+{
+}
+
+static inline void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
+ __be32 net_spi, __be32 net_seq)
+{
+}
+
+static inline void xfrm_audit_state_icvfail(struct xfrm_state *x,
+ struct sk_buff *skb, u8 proto)
+{
+}
+#endif /* CONFIG_AUDITSYSCALL */
+
+static inline void xfrm_pol_hold(struct xfrm_policy *policy)
+{
+ if (likely(policy != NULL))
+ atomic_inc(&policy->refcnt);
+}
+
+extern void xfrm_policy_destroy(struct xfrm_policy *policy);
+
+static inline void xfrm_pol_put(struct xfrm_policy *policy)
+{
+ if (atomic_dec_and_test(&policy->refcnt))
+ xfrm_policy_destroy(policy);
+}
+
+static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols)
+{
+ int i;
+ for (i = npols - 1; i >= 0; --i)
+ xfrm_pol_put(pols[i]);
+}
+
+extern void __xfrm_state_destroy(struct xfrm_state *);
+
+static inline void __xfrm_state_put(struct xfrm_state *x)
+{
+ atomic_dec(&x->refcnt);
+}
+
+static inline void xfrm_state_put(struct xfrm_state *x)
+{
+ if (atomic_dec_and_test(&x->refcnt))
+ __xfrm_state_destroy(x);
+}
+
+static inline void xfrm_state_hold(struct xfrm_state *x)
+{
+ atomic_inc(&x->refcnt);
+}
+
+static inline bool addr_match(const void *token1, const void *token2,
+ int prefixlen)
+{
+ const __be32 *a1 = token1;
+ const __be32 *a2 = token2;
+ int pdw;
+ int pbi;
+
+ pdw = prefixlen >> 5; /* num of whole u32 in prefix */
+ pbi = prefixlen & 0x1f; /* num of bits in incomplete u32 in prefix */
+
+ if (pdw)
+ if (memcmp(a1, a2, pdw << 2))
+ return false;
+
+ if (pbi) {
+ __be32 mask;
+
+ mask = htonl((0xffffffff) << (32 - pbi));
+
+ if ((a1[pdw] ^ a2[pdw]) & mask)
+ return false;
+ }
+
+ return true;
+}
+
+static inline bool addr4_match(__be32 a1, __be32 a2, u8 prefixlen)
+{
+ /* C99 6.5.7 (3): u32 << 32 is undefined behaviour */
+ if (prefixlen == 0)
+ return true;
+ return !((a1 ^ a2) & htonl(0xFFFFFFFFu << (32 - prefixlen)));
+}
+
+static __inline__
+__be16 xfrm_flowi_sport(const struct flowi *fl, const union flowi_uli *uli)
+{
+ __be16 port;
+ switch(fl->flowi_proto) {
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+ case IPPROTO_UDPLITE:
+ case IPPROTO_SCTP:
+ port = uli->ports.sport;
+ break;
+ case IPPROTO_ICMP:
+ case IPPROTO_ICMPV6:
+ port = htons(uli->icmpt.type);
+ break;
+ case IPPROTO_MH:
+ port = htons(uli->mht.type);
+ break;
+ case IPPROTO_GRE:
+ port = htons(ntohl(uli->gre_key) >> 16);
+ break;
+ default:
+ port = 0; /*XXX*/
+ }
+ return port;
+}
+
+static __inline__
+__be16 xfrm_flowi_dport(const struct flowi *fl, const union flowi_uli *uli)
+{
+ __be16 port;
+ switch(fl->flowi_proto) {
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+ case IPPROTO_UDPLITE:
+ case IPPROTO_SCTP:
+ port = uli->ports.dport;
+ break;
+ case IPPROTO_ICMP:
+ case IPPROTO_ICMPV6:
+ port = htons(uli->icmpt.code);
+ break;
+ case IPPROTO_GRE:
+ port = htons(ntohl(uli->gre_key) & 0xffff);
+ break;
+ default:
+ port = 0; /*XXX*/
+ }
+ return port;
+}
+
+extern int xfrm_selector_match(const struct xfrm_selector *sel,
+ const struct flowi *fl,
+ unsigned short family);
+
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+/* If neither has a context --> match
+ * Otherwise, both must have a context and the sids, doi, alg must match
+ */
+static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ctx *s2)
+{
+ return ((!s1 && !s2) ||
+ (s1 && s2 &&
+ (s1->ctx_sid == s2->ctx_sid) &&
+ (s1->ctx_doi == s2->ctx_doi) &&
+ (s1->ctx_alg == s2->ctx_alg)));
+}
+#else
+static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ctx *s2)
+{
+ return 1;
+}
+#endif
+
+/* A struct encoding bundle of transformations to apply to some set of flow.
+ *
+ * dst->child points to the next element of bundle.
+ * dst->xfrm points to an instanse of transformer.
+ *
+ * Due to unfortunate limitations of current routing cache, which we
+ * have no time to fix, it mirrors struct rtable and bound to the same
+ * routing key, including saddr,daddr. However, we can have many of
+ * bundles differing by session id. All the bundles grow from a parent
+ * policy rule.
+ */
+struct xfrm_dst {
+ union {
+ struct dst_entry dst;
+ struct rtable rt;
+ struct rt6_info rt6;
+ } u;
+ struct dst_entry *route;
+ struct flow_cache_object flo;
+ struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
+ int num_pols, num_xfrms;
+#ifdef CONFIG_XFRM_SUB_POLICY
+ struct flowi *origin;
+ struct xfrm_selector *partner;
+#endif
+ u32 xfrm_genid;
+ u32 policy_genid;
+ u32 route_mtu_cached;
+ u32 child_mtu_cached;
+ u32 route_cookie;
+ u32 path_cookie;
+};
+
+#ifdef CONFIG_XFRM
+static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
+{
+ xfrm_pols_put(xdst->pols, xdst->num_pols);
+ dst_release(xdst->route);
+ if (likely(xdst->u.dst.xfrm))
+ xfrm_state_put(xdst->u.dst.xfrm);
+#ifdef CONFIG_XFRM_SUB_POLICY
+ kfree(xdst->origin);
+ xdst->origin = NULL;
+ kfree(xdst->partner);
+ xdst->partner = NULL;
+#endif
+}
+#endif
+
+extern void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
+
+struct sec_path {
+ atomic_t refcnt;
+ int len;
+ struct xfrm_state *xvec[XFRM_MAX_DEPTH];
+};
+
+static inline int secpath_exists(struct sk_buff *skb)
+{
+#ifdef CONFIG_XFRM
+ return skb->sp != NULL;
+#else
+ return 0;
+#endif
+}
+
+static inline struct sec_path *
+secpath_get(struct sec_path *sp)
+{
+ if (sp)
+ atomic_inc(&sp->refcnt);
+ return sp;
+}
+
+extern void __secpath_destroy(struct sec_path *sp);
+
+static inline void
+secpath_put(struct sec_path *sp)
+{
+ if (sp && atomic_dec_and_test(&sp->refcnt))
+ __secpath_destroy(sp);
+}
+
+extern struct sec_path *secpath_dup(struct sec_path *src);
+
+static inline void
+secpath_reset(struct sk_buff *skb)
+{
+#ifdef CONFIG_XFRM
+ secpath_put(skb->sp);
+ skb->sp = NULL;
+#endif
+}
+
+static inline int
+xfrm_addr_any(const xfrm_address_t *addr, unsigned short family)
+{
+ switch (family) {
+ case AF_INET:
+ return addr->a4 == 0;
+ case AF_INET6:
+ return ipv6_addr_any((struct in6_addr *)&addr->a6);
+ }
+ return 0;
+}
+
+static inline int
+__xfrm4_state_addr_cmp(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x)
+{
+ return (tmpl->saddr.a4 &&
+ tmpl->saddr.a4 != x->props.saddr.a4);
+}
+
+static inline int
+__xfrm6_state_addr_cmp(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x)
+{
+ return (!ipv6_addr_any((struct in6_addr*)&tmpl->saddr) &&
+ ipv6_addr_cmp((struct in6_addr *)&tmpl->saddr, (struct in6_addr*)&x->props.saddr));
+}
+
+static inline int
+xfrm_state_addr_cmp(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x, unsigned short family)
+{
+ switch (family) {
+ case AF_INET:
+ return __xfrm4_state_addr_cmp(tmpl, x);
+ case AF_INET6:
+ return __xfrm6_state_addr_cmp(tmpl, x);
+ }
+ return !0;
+}
+
+#ifdef CONFIG_XFRM
+extern int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb, unsigned short family);
+
+static inline int __xfrm_policy_check2(struct sock *sk, int dir,
+ struct sk_buff *skb,
+ unsigned int family, int reverse)
+{
+ struct net *net = dev_net(skb->dev);
+ int ndir = dir | (reverse ? XFRM_POLICY_MASK + 1 : 0);
+
+ if (sk && sk->sk_policy[XFRM_POLICY_IN])
+ return __xfrm_policy_check(sk, ndir, skb, family);
+
+ return (!net->xfrm.policy_count[dir] && !skb->sp) ||
+ (skb_dst(skb)->flags & DST_NOPOLICY) ||
+ __xfrm_policy_check(sk, ndir, skb, family);
+}
+
+static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family)
+{
+ return __xfrm_policy_check2(sk, dir, skb, family, 0);
+}
+
+static inline int xfrm4_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
+{
+ return xfrm_policy_check(sk, dir, skb, AF_INET);
+}
+
+static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
+{
+ return xfrm_policy_check(sk, dir, skb, AF_INET6);
+}
+
+static inline int xfrm4_policy_check_reverse(struct sock *sk, int dir,
+ struct sk_buff *skb)
+{
+ return __xfrm_policy_check2(sk, dir, skb, AF_INET, 1);
+}
+
+static inline int xfrm6_policy_check_reverse(struct sock *sk, int dir,
+ struct sk_buff *skb)
+{
+ return __xfrm_policy_check2(sk, dir, skb, AF_INET6, 1);
+}
+
+extern int __xfrm_decode_session(struct sk_buff *skb, struct flowi *fl,
+ unsigned int family, int reverse);
+
+static inline int xfrm_decode_session(struct sk_buff *skb, struct flowi *fl,
+ unsigned int family)
+{
+ return __xfrm_decode_session(skb, fl, family, 0);
+}
+
+static inline int xfrm_decode_session_reverse(struct sk_buff *skb,
+ struct flowi *fl,
+ unsigned int family)
+{
+ return __xfrm_decode_session(skb, fl, family, 1);
+}
+
+extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family);
+
+static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
+{
+ struct net *net = dev_net(skb->dev);
+
+ return !net->xfrm.policy_count[XFRM_POLICY_OUT] ||
+ (skb_dst(skb)->flags & DST_NOXFRM) ||
+ __xfrm_route_forward(skb, family);
+}
+
+static inline int xfrm4_route_forward(struct sk_buff *skb)
+{
+ return xfrm_route_forward(skb, AF_INET);
+}
+
+static inline int xfrm6_route_forward(struct sk_buff *skb)
+{
+ return xfrm_route_forward(skb, AF_INET6);
+}
+
+extern int __xfrm_sk_clone_policy(struct sock *sk);
+
+static inline int xfrm_sk_clone_policy(struct sock *sk)
+{
+ if (unlikely(sk->sk_policy[0] || sk->sk_policy[1]))
+ return __xfrm_sk_clone_policy(sk);
+ return 0;
+}
+
+extern int xfrm_policy_delete(struct xfrm_policy *pol, int dir);
+
+static inline void xfrm_sk_free_policy(struct sock *sk)
+{
+ if (unlikely(sk->sk_policy[0] != NULL)) {
+ xfrm_policy_delete(sk->sk_policy[0], XFRM_POLICY_MAX);
+ sk->sk_policy[0] = NULL;
+ }
+ if (unlikely(sk->sk_policy[1] != NULL)) {
+ xfrm_policy_delete(sk->sk_policy[1], XFRM_POLICY_MAX+1);
+ sk->sk_policy[1] = NULL;
+ }
+}
+
+#else
+
+static inline void xfrm_sk_free_policy(struct sock *sk) {}
+static inline int xfrm_sk_clone_policy(struct sock *sk) { return 0; }
+static inline int xfrm6_route_forward(struct sk_buff *skb) { return 1; }
+static inline int xfrm4_route_forward(struct sk_buff *skb) { return 1; }
+static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
+{
+ return 1;
+}
+static inline int xfrm4_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
+{
+ return 1;
+}
+static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family)
+{
+ return 1;
+}
+static inline int xfrm_decode_session_reverse(struct sk_buff *skb,
+ struct flowi *fl,
+ unsigned int family)
+{
+ return -ENOSYS;
+}
+static inline int xfrm4_policy_check_reverse(struct sock *sk, int dir,
+ struct sk_buff *skb)
+{
+ return 1;
+}
+static inline int xfrm6_policy_check_reverse(struct sock *sk, int dir,
+ struct sk_buff *skb)
+{
+ return 1;
+}
+#endif
+
+static __inline__
+xfrm_address_t *xfrm_flowi_daddr(const struct flowi *fl, unsigned short family)
+{
+ switch (family){
+ case AF_INET:
+ return (xfrm_address_t *)&fl->u.ip4.daddr;
+ case AF_INET6:
+ return (xfrm_address_t *)&fl->u.ip6.daddr;
+ }
+ return NULL;
+}
+
+static __inline__
+xfrm_address_t *xfrm_flowi_saddr(const struct flowi *fl, unsigned short family)
+{
+ switch (family){
+ case AF_INET:
+ return (xfrm_address_t *)&fl->u.ip4.saddr;
+ case AF_INET6:
+ return (xfrm_address_t *)&fl->u.ip6.saddr;
+ }
+ return NULL;
+}
+
+static __inline__
+void xfrm_flowi_addr_get(const struct flowi *fl,
+ xfrm_address_t *saddr, xfrm_address_t *daddr,
+ unsigned short family)
+{
+ switch(family) {
+ case AF_INET:
+ memcpy(&saddr->a4, &fl->u.ip4.saddr, sizeof(saddr->a4));
+ memcpy(&daddr->a4, &fl->u.ip4.daddr, sizeof(daddr->a4));
+ break;
+ case AF_INET6:
+ *(struct in6_addr *)saddr->a6 = fl->u.ip6.saddr;
+ *(struct in6_addr *)daddr->a6 = fl->u.ip6.daddr;
+ break;
+ }
+}
+
+static __inline__ int
+__xfrm4_state_addr_check(const struct xfrm_state *x,
+ const xfrm_address_t *daddr, const xfrm_address_t *saddr)
+{
+ if (daddr->a4 == x->id.daddr.a4 &&
+ (saddr->a4 == x->props.saddr.a4 || !saddr->a4 || !x->props.saddr.a4))
+ return 1;
+ return 0;
+}
+
+static __inline__ int
+__xfrm6_state_addr_check(const struct xfrm_state *x,
+ const xfrm_address_t *daddr, const xfrm_address_t *saddr)
+{
+ if (!ipv6_addr_cmp((struct in6_addr *)daddr, (struct in6_addr *)&x->id.daddr) &&
+ (!ipv6_addr_cmp((struct in6_addr *)saddr, (struct in6_addr *)&x->props.saddr)||
+ ipv6_addr_any((struct in6_addr *)saddr) ||
+ ipv6_addr_any((struct in6_addr *)&x->props.saddr)))
+ return 1;
+ return 0;
+}
+
+static __inline__ int
+xfrm_state_addr_check(const struct xfrm_state *x,
+ const xfrm_address_t *daddr, const xfrm_address_t *saddr,
+ unsigned short family)
+{
+ switch (family) {
+ case AF_INET:
+ return __xfrm4_state_addr_check(x, daddr, saddr);
+ case AF_INET6:
+ return __xfrm6_state_addr_check(x, daddr, saddr);
+ }
+ return 0;
+}
+
+static __inline__ int
+xfrm_state_addr_flow_check(const struct xfrm_state *x, const struct flowi *fl,
+ unsigned short family)
+{
+ switch (family) {
+ case AF_INET:
+ return __xfrm4_state_addr_check(x,
+ (const xfrm_address_t *)&fl->u.ip4.daddr,
+ (const xfrm_address_t *)&fl->u.ip4.saddr);
+ case AF_INET6:
+ return __xfrm6_state_addr_check(x,
+ (const xfrm_address_t *)&fl->u.ip6.daddr,
+ (const xfrm_address_t *)&fl->u.ip6.saddr);
+ }
+ return 0;
+}
+
+static inline int xfrm_state_kern(const struct xfrm_state *x)
+{
+ return atomic_read(&x->tunnel_users);
+}
+
+static inline int xfrm_id_proto_match(u8 proto, u8 userproto)
+{
+ return (!userproto || proto == userproto ||
+ (userproto == IPSEC_PROTO_ANY && (proto == IPPROTO_AH ||
+ proto == IPPROTO_ESP ||
+ proto == IPPROTO_COMP)));
+}
+
+/*
+ * xfrm algorithm information
+ */
+struct xfrm_algo_aead_info {
+ u16 icv_truncbits;
+};
+
+struct xfrm_algo_auth_info {
+ u16 icv_truncbits;
+ u16 icv_fullbits;
+};
+
+struct xfrm_algo_encr_info {
+ u16 blockbits;
+ u16 defkeybits;
+};
+
+struct xfrm_algo_comp_info {
+ u16 threshold;
+};
+
+struct xfrm_algo_desc {
+ char *name;
+ char *compat;
+ u8 available:1;
+ union {
+ struct xfrm_algo_aead_info aead;
+ struct xfrm_algo_auth_info auth;
+ struct xfrm_algo_encr_info encr;
+ struct xfrm_algo_comp_info comp;
+ } uinfo;
+ struct sadb_alg desc;
+};
+
+/* XFRM tunnel handlers. */
+struct xfrm_tunnel {
+ int (*handler)(struct sk_buff *skb);
+ int (*err_handler)(struct sk_buff *skb, u32 info);
+
+ struct xfrm_tunnel __rcu *next;
+ int priority;
+};
+
+struct xfrm6_tunnel {
+ int (*handler)(struct sk_buff *skb);
+ int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ u8 type, u8 code, int offset, __be32 info);
+ struct xfrm6_tunnel __rcu *next;
+ int priority;
+};
+
+extern void xfrm_init(void);
+extern void xfrm4_init(int rt_hash_size);
+extern int xfrm_state_init(struct net *net);
+extern void xfrm_state_fini(struct net *net);
+extern void xfrm4_state_init(void);
+#ifdef CONFIG_XFRM
+extern int xfrm6_init(void);
+extern void xfrm6_fini(void);
+extern int xfrm6_state_init(void);
+extern void xfrm6_state_fini(void);
+#else
+static inline int xfrm6_init(void)
+{
+ return 0;
+}
+static inline void xfrm6_fini(void)
+{
+ ;
+}
+#endif
+
+#ifdef CONFIG_XFRM_STATISTICS
+extern int xfrm_proc_init(struct net *net);
+extern void xfrm_proc_fini(struct net *net);
+#endif
+
+extern int xfrm_sysctl_init(struct net *net);
+#ifdef CONFIG_SYSCTL
+extern void xfrm_sysctl_fini(struct net *net);
+#else
+static inline void xfrm_sysctl_fini(struct net *net)
+{
+}
+#endif
+
+extern void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto);
+extern int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
+ int (*func)(struct xfrm_state *, int, void*), void *);
+extern void xfrm_state_walk_done(struct xfrm_state_walk *walk);
+extern struct xfrm_state *xfrm_state_alloc(struct net *net);
+extern struct xfrm_state *xfrm_state_find(const xfrm_address_t *daddr,
+ const xfrm_address_t *saddr,
+ const struct flowi *fl,
+ struct xfrm_tmpl *tmpl,
+ struct xfrm_policy *pol, int *err,
+ unsigned short family);
+extern struct xfrm_state *xfrm_stateonly_find(struct net *net, u32 mark,
+ xfrm_address_t *daddr,
+ xfrm_address_t *saddr,
+ unsigned short family,
+ u8 mode, u8 proto, u32 reqid);
+extern int xfrm_state_check_expire(struct xfrm_state *x);
+extern void xfrm_state_insert(struct xfrm_state *x);
+extern int xfrm_state_add(struct xfrm_state *x);
+extern int xfrm_state_update(struct xfrm_state *x);
+extern struct xfrm_state *xfrm_state_lookup(struct net *net, u32 mark,
+ const xfrm_address_t *daddr, __be32 spi,
+ u8 proto, unsigned short family);
+extern struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, u32 mark,
+ const xfrm_address_t *daddr,
+ const xfrm_address_t *saddr,
+ u8 proto,
+ unsigned short family);
+#ifdef CONFIG_XFRM_SUB_POLICY
+extern int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
+ int n, unsigned short family);
+extern int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src,
+ int n, unsigned short family);
+#else
+static inline int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
+ int n, unsigned short family)
+{
+ return -ENOSYS;
+}
+
+static inline int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src,
+ int n, unsigned short family)
+{
+ return -ENOSYS;
+}
+#endif
+
+struct xfrmk_sadinfo {
+ u32 sadhcnt; /* current hash bkts */
+ u32 sadhmcnt; /* max allowed hash bkts */
+ u32 sadcnt; /* current running count */
+};
+
+struct xfrmk_spdinfo {
+ u32 incnt;
+ u32 outcnt;
+ u32 fwdcnt;
+ u32 inscnt;
+ u32 outscnt;
+ u32 fwdscnt;
+ u32 spdhcnt;
+ u32 spdhmcnt;
+};
+
+extern struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark,
+ u32 seq);
+extern int xfrm_state_delete(struct xfrm_state *x);
+extern int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info);
+extern void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
+extern void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si);
+extern u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq);
+extern int xfrm_init_replay(struct xfrm_state *x);
+extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
+extern int __xfrm_init_state(struct xfrm_state *x, bool init_replay);
+extern int xfrm_init_state(struct xfrm_state *x);
+extern int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb);
+extern int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi,
+ int encap_type);
+extern int xfrm_input_resume(struct sk_buff *skb, int nexthdr);
+extern int xfrm_output_resume(struct sk_buff *skb, int err);
+extern int xfrm_output(struct sk_buff *skb);
+extern int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb);
+extern int xfrm4_extract_header(struct sk_buff *skb);
+extern int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb);
+extern int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
+ int encap_type);
+extern int xfrm4_transport_finish(struct sk_buff *skb, int async);
+extern int xfrm4_rcv(struct sk_buff *skb);
+
+static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
+{
+ return xfrm4_rcv_encap(skb, nexthdr, spi, 0);
+}
+
+extern int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb);
+extern int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
+extern int xfrm4_output(struct sk_buff *skb);
+extern int xfrm4_output_finish(struct sk_buff *skb);
+extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
+extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
+extern int xfrm6_extract_header(struct sk_buff *skb);
+extern int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb);
+extern int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi);
+extern int xfrm6_transport_finish(struct sk_buff *skb, int async);
+extern int xfrm6_rcv(struct sk_buff *skb);
+extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
+ xfrm_address_t *saddr, u8 proto);
+extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family);
+extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family);
+extern __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr);
+extern __be32 xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr);
+extern int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb);
+extern int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
+extern int xfrm6_output(struct sk_buff *skb);
+extern int xfrm6_output_finish(struct sk_buff *skb);
+extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
+ u8 **prevhdr);
+
+#ifdef CONFIG_XFRM
+extern int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb);
+extern int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen);
+#else
+static inline int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen)
+{
+ return -ENOPROTOOPT;
+}
+
+static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
+{
+ /* should not happen */
+ kfree_skb(skb);
+ return 0;
+}
+#endif
+
+struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp);
+
+extern void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type);
+extern int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk,
+ int (*func)(struct xfrm_policy *, int, int, void*), void *);
+extern void xfrm_policy_walk_done(struct xfrm_policy_walk *walk);
+int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
+struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark,
+ u8 type, int dir,
+ struct xfrm_selector *sel,
+ struct xfrm_sec_ctx *ctx, int delete,
+ int *err);
+struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8, int dir, u32 id, int delete, int *err);
+int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info);
+u32 xfrm_get_acqseq(void);
+extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
+struct xfrm_state *xfrm_find_acq(struct net *net, struct xfrm_mark *mark,
+ u8 mode, u32 reqid, u8 proto,
+ const xfrm_address_t *daddr,
+ const xfrm_address_t *saddr, int create,
+ unsigned short family);
+extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
+
+#ifdef CONFIG_XFRM_MIGRATE
+extern int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
+ const struct xfrm_migrate *m, int num_bundles,
+ const struct xfrm_kmaddress *k);
+extern struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m);
+extern struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x,
+ struct xfrm_migrate *m);
+extern int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
+ struct xfrm_migrate *m, int num_bundles,
+ struct xfrm_kmaddress *k);
+#endif
+
+extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
+extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid);
+extern int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
+
+extern void xfrm_input_init(void);
+extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq);
+
+extern void xfrm_probe_algs(void);
+extern int xfrm_count_auth_supported(void);
+extern int xfrm_count_enc_supported(void);
+extern struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx);
+extern struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx);
+extern struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id);
+extern struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id);
+extern struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id);
+extern struct xfrm_algo_desc *xfrm_aalg_get_byname(const char *name, int probe);
+extern struct xfrm_algo_desc *xfrm_ealg_get_byname(const char *name, int probe);
+extern struct xfrm_algo_desc *xfrm_calg_get_byname(const char *name, int probe);
+extern struct xfrm_algo_desc *xfrm_aead_get_byname(const char *name, int icv_len,
+ int probe);
+
+static inline int xfrm_addr_cmp(const xfrm_address_t *a,
+ const xfrm_address_t *b,
+ int family)
+{
+ switch (family) {
+ default:
+ case AF_INET:
+ return (__force u32)a->a4 - (__force u32)b->a4;
+ case AF_INET6:
+ return ipv6_addr_cmp((const struct in6_addr *)a,
+ (const struct in6_addr *)b);
+ }
+}
+
+static inline int xfrm_policy_id2dir(u32 index)
+{
+ return index & 7;
+}
+
+#ifdef CONFIG_XFRM
+static inline int xfrm_aevent_is_on(struct net *net)
+{
+ struct sock *nlsk;
+ int ret = 0;
+
+ rcu_read_lock();
+ nlsk = rcu_dereference(net->xfrm.nlsk);
+ if (nlsk)
+ ret = netlink_has_listeners(nlsk, XFRMNLGRP_AEVENTS);
+ rcu_read_unlock();
+ return ret;
+}
+#endif
+
+static inline int xfrm_alg_len(const struct xfrm_algo *alg)
+{
+ return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
+}
+
+static inline int xfrm_alg_auth_len(const struct xfrm_algo_auth *alg)
+{
+ return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
+}
+
+static inline int xfrm_replay_state_esn_len(struct xfrm_replay_state_esn *replay_esn)
+{
+ return sizeof(*replay_esn) + replay_esn->bmp_len * sizeof(__u32);
+}
+
+#ifdef CONFIG_XFRM_MIGRATE
+static inline int xfrm_replay_clone(struct xfrm_state *x,
+ struct xfrm_state *orig)
+{
+ x->replay_esn = kzalloc(xfrm_replay_state_esn_len(orig->replay_esn),
+ GFP_KERNEL);
+ if (!x->replay_esn)
+ return -ENOMEM;
+
+ x->replay_esn->bmp_len = orig->replay_esn->bmp_len;
+ x->replay_esn->replay_window = orig->replay_esn->replay_window;
+
+ x->preplay_esn = kmemdup(x->replay_esn,
+ xfrm_replay_state_esn_len(x->replay_esn),
+ GFP_KERNEL);
+ if (!x->preplay_esn) {
+ kfree(x->replay_esn);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static inline struct xfrm_algo *xfrm_algo_clone(struct xfrm_algo *orig)
+{
+ return kmemdup(orig, xfrm_alg_len(orig), GFP_KERNEL);
+}
+
+static inline struct xfrm_algo_auth *xfrm_algo_auth_clone(struct xfrm_algo_auth *orig)
+{
+ return kmemdup(orig, xfrm_alg_auth_len(orig), GFP_KERNEL);
+}
+
+static inline void xfrm_states_put(struct xfrm_state **states, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ xfrm_state_put(*(states + i));
+}
+
+static inline void xfrm_states_delete(struct xfrm_state **states, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ xfrm_state_delete(*(states + i));
+}
+#endif
+
+#ifdef CONFIG_XFRM
+static inline struct xfrm_state *xfrm_input_state(struct sk_buff *skb)
+{
+ return skb->sp->xvec[skb->sp->len - 1];
+}
+#endif
+
+static inline int xfrm_mark_get(struct nlattr **attrs, struct xfrm_mark *m)
+{
+ if (attrs[XFRMA_MARK])
+ memcpy(m, nla_data(attrs[XFRMA_MARK]), sizeof(struct xfrm_mark));
+ else
+ m->v = m->m = 0;
+
+ return m->v & m->m;
+}
+
+static inline int xfrm_mark_put(struct sk_buff *skb, const struct xfrm_mark *m)
+{
+ if (m->m | m->v)
+ NLA_PUT(skb, XFRMA_MARK, sizeof(struct xfrm_mark), m);
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
+#endif /* _NET_XFRM_H */