diff options
Diffstat (limited to 'include/net')
77 files changed, 2345 insertions, 831 deletions
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index d2df55b0c21..008711e8e78 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h @@ -241,10 +241,10 @@ enum p9_open_mode_t { /** * enum p9_perm_t - 9P permissions - * @P9_DMDIR: mode bite for directories + * @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 bite for mount points + * @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) @@ -362,7 +362,7 @@ struct p9_qid { }; /** - * struct p9_stat - file system metadata information + * 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) @@ -687,10 +687,10 @@ struct p9_rwstat { * @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 currentposition in buffer + * @offset: used by marshalling routines to track current position in buffer * @capacity: used by marshalling routines to track total malloc'd capacity * @pubuf: Payload user buffer given by the caller - * @pubuf: Payload kernel buffer given by the caller + * @pkbuf: Payload kernel buffer given by the caller * @pbuf_size: pubuf/pkbuf(only one will be !NULL) size to be read/write. * @private: For transport layer's use. * @sdata: payload @@ -714,7 +714,7 @@ struct p9_fcall { size_t pbuf_size; void *private; - uint8_t *sdata; + u8 *sdata; }; struct p9_idpool; @@ -728,7 +728,6 @@ void p9_idpool_put(int id, struct p9_idpool *p); int p9_idpool_check(int id, struct p9_idpool *p); int p9_error_init(void); -int p9_errstr2errno(char *, int); int 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 index 051a99f7976..d26d5e98a17 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -60,7 +60,7 @@ enum p9_trans_status { }; /** - * enum p9_req_status_t - virtio request status + * 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 diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h index 8f08c736c4c..d8549fb9c74 100644 --- a/include/net/9p/transport.h +++ b/include/net/9p/transport.h @@ -41,6 +41,7 @@ * @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) * @@ -48,7 +49,7 @@ * transport module with the 9P core network module and used by the client * to instantiate a new connection on a transport. * - * BUGS: the transport module list isn't protected. + * The transport module list is protected by v9fs_trans_lock. */ struct p9_trans_module { diff --git a/include/net/act_api.h b/include/net/act_api.h index bab385f13ac..c739531e156 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -72,7 +72,7 @@ struct tcf_act_hdr { struct tc_action { void *priv; - struct tc_action_ops *ops; + const struct tc_action_ops *ops; __u32 type; /* for backward compat(TCA_OLD_COMPAT) */ __u32 order; struct tc_action *next; @@ -86,7 +86,7 @@ struct tc_action_ops { __u32 type; /* TBD to match kind */ __u32 capab; /* capabilities includes 4 bit version */ struct module *owner; - int (*act)(struct sk_buff *, struct tc_action *, struct tcf_result *); + 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); @@ -115,7 +115,7 @@ 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, struct tc_action *a, struct tcf_result *res); +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); diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 23710aa6a18..582e4ae7075 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -42,8 +42,6 @@ struct prefix_info { }; -#ifdef __KERNEL__ - #include <linux/netdevice.h> #include <net/if_inet6.h> #include <net/ipv6.h> @@ -61,16 +59,16 @@ extern int addrconf_set_dstaddr(struct net *net, void __user *arg); extern int ipv6_chk_addr(struct net *net, - struct in6_addr *addr, + 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, - struct in6_addr *addr); + const struct in6_addr *addr); #endif -extern int ipv6_chk_prefix(struct in6_addr *addr, +extern int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev); extern struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, @@ -89,9 +87,9 @@ extern int ipv6_get_lladdr(struct net_device *dev, extern int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2); extern void addrconf_join_solict(struct net_device *dev, - struct in6_addr *addr); + const struct in6_addr *addr); extern void addrconf_leave_solict(struct inet6_dev *idev, - struct in6_addr *addr); + const struct in6_addr *addr); static inline unsigned long addrconf_timeout_fixup(u32 timeout, unsigned unit) @@ -158,15 +156,15 @@ extern void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len); /* * anycast prototypes (anycast.c) */ -extern int ipv6_sock_ac_join(struct sock *sk,int ifindex,struct in6_addr *addr); -extern int ipv6_sock_ac_drop(struct sock *sk,int ifindex,struct in6_addr *addr); +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 inet6_ac_check(struct sock *sk, struct in6_addr *addr, int ifindex); +extern int inet6_ac_check(struct sock *sk, const struct in6_addr *addr, int ifindex); -extern int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr); -extern int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr); +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, - struct in6_addr *addr); + const struct in6_addr *addr); /* Device notifier */ @@ -285,4 +283,3 @@ extern void if6_proc_exit(void); #endif #endif -#endif diff --git a/include/net/af_rxrpc.h b/include/net/af_rxrpc.h index 00c2eaa07c2..03e6e945362 100644 --- a/include/net/af_rxrpc.h +++ b/include/net/af_rxrpc.h @@ -12,8 +12,6 @@ #ifndef _NET_RXRPC_H #define _NET_RXRPC_H -#ifdef __KERNEL__ - #include <linux/rxrpc.h> struct rxrpc_call; @@ -53,5 +51,4 @@ extern struct rxrpc_call *rxrpc_kernel_accept_call(struct socket *, unsigned long); extern int rxrpc_kernel_reject_call(struct socket *); -#endif /* __KERNEL__ */ #endif /* _NET_RXRPC_H */ diff --git a/include/net/af_unix.h b/include/net/af_unix.h index 18e5c3f6758..91ab5b01678 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -41,7 +41,6 @@ struct unix_skb_parms { spin_lock_nested(&unix_sk(s)->lock, \ SINGLE_DEPTH_NESTING) -#ifdef __KERNEL__ /* The AF_UNIX socket */ struct unix_sock { /* WARNING: sk has to be the first member */ @@ -72,4 +71,3 @@ static inline int unix_sysctl_register(struct net *net) { return 0; } static inline void unix_sysctl_unregister(struct net *net) {} #endif #endif -#endif diff --git a/include/net/arp.h b/include/net/arp.h index 91f0568a04e..4979af8b155 100644 --- a/include/net/arp.h +++ b/include/net/arp.h @@ -8,6 +8,36 @@ 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 neigh_table *tbl, 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(tbl->nht); + hash_val = arp_hashfn(key, 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)) { + 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); @@ -15,7 +45,6 @@ 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_bind_neighbour(struct dst_entry *dst); extern int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir); extern void arp_ifdown(struct net_device *dev); diff --git a/include/net/atmclip.h b/include/net/atmclip.h index 467c531b8a7..497ef6444a7 100644 --- a/include/net/atmclip.h +++ b/include/net/atmclip.h @@ -54,8 +54,6 @@ struct clip_priv { }; -#ifdef __KERNEL__ extern struct neigh_table *clip_tbl_hook; -#endif #endif diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 43750439c52..e727555d4ee 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -56,6 +56,7 @@ #define BT_SECURITY 4 struct bt_security { __u8 level; + __u8 key_size; }; #define BT_SECURITY_SDP 0 #define BT_SECURITY_LOW 1 @@ -69,9 +70,19 @@ struct bt_security { #define BT_FLUSHABLE_OFF 0 #define BT_FLUSHABLE_ON 1 -#define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg) -#define BT_ERR(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg) -#define BT_DBG(fmt, arg...) pr_debug("%s: " fmt "\n" , __func__ , ## arg) +#define BT_POWER 9 +struct bt_power { + __u8 force_active; +}; +#define BT_POWER_FORCE_ACTIVE_OFF 0 +#define BT_POWER_FORCE_ACTIVE_ON 1 + +__attribute__((format (printf, 2, 3))) +int bt_printk(const char *level, const char *fmt, ...); + +#define BT_INFO(fmt, arg...) bt_printk(KERN_INFO, pr_fmt(fmt), ##arg) +#define BT_ERR(fmt, arg...) bt_printk(KERN_ERR, pr_fmt(fmt), ##arg) +#define BT_DBG(fmt, arg...) pr_debug(fmt "\n", ##arg) /* Connection and socket states */ enum { @@ -130,7 +141,8 @@ 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_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); @@ -150,6 +162,7 @@ struct bt_skb_cb { __u8 retries; __u8 sar; unsigned short channel; + __u8 force_active; }; #define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb)) @@ -164,8 +177,8 @@ static inline struct sk_buff *bt_skb_alloc(unsigned int len, gfp_t how) return skb; } -static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk, unsigned long len, - int nb, int *err) +static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk, + unsigned long len, int nb, int *err) { struct sk_buff *skb; @@ -195,7 +208,7 @@ out: return NULL; } -int bt_err(__u16 code); +int bt_to_errno(__u16 code); extern int hci_sock_init(void); extern void hci_sock_cleanup(void); diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 2c0d309c738..be30aabe7b8 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -211,11 +211,16 @@ enum { #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_LE 0x02 /* Connection modes */ #define HCI_CM_ACTIVE 0x0000 @@ -246,6 +251,19 @@ enum { #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 */ +#define HCI_LK_SMP_LTK 0x81 +#define HCI_LK_SMP_IRK 0x82 +#define HCI_LK_SMP_CSRK 0x83 + /* ----- HCI Commands ---- */ #define HCI_OP_NOP 0x0000 @@ -428,6 +446,18 @@ struct hci_rp_user_confirm_reply { #define HCI_OP_USER_CONFIRM_NEG_REPLY 0x042d +#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; @@ -537,15 +567,17 @@ struct hci_cp_delete_stored_link_key { __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[248]; + __u8 name[HCI_MAX_NAME_LENGTH]; } __packed; #define HCI_OP_READ_LOCAL_NAME 0x0c14 struct hci_rp_read_local_name { __u8 status; - __u8 name[248]; + __u8 name[HCI_MAX_NAME_LENGTH]; } __packed; #define HCI_OP_WRITE_CA_TIMEOUT 0x0c16 @@ -602,6 +634,14 @@ struct hci_cp_host_buffer_size { #define HCI_OP_WRITE_INQUIRY_MODE 0x0c45 +#define HCI_MAX_EIR_LENGTH 240 + +#define HCI_OP_WRITE_EIR 0x0c52 +struct hci_cp_write_eir { + uint8_t fec; + uint8_t data[HCI_MAX_EIR_LENGTH]; +} __packed; + #define HCI_OP_READ_SSP_MODE 0x0c55 struct hci_rp_read_ssp_mode { __u8 status; @@ -613,8 +653,21 @@ 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_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; @@ -638,6 +691,9 @@ struct hci_rp_read_local_features { } __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; @@ -672,6 +728,12 @@ struct hci_rp_le_read_buffer_size { __u8 le_max_pkt; } __packed; +#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; @@ -701,6 +763,33 @@ struct hci_cp_le_conn_update { __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 @@ -747,7 +836,7 @@ struct hci_ev_auth_complete { struct hci_ev_remote_name { __u8 status; bdaddr_t bdaddr; - __u8 name[248]; + __u8 name[HCI_MAX_NAME_LENGTH]; } __packed; #define HCI_EV_ENCRYPT_CHANGE 0x08 @@ -955,6 +1044,11 @@ struct hci_ev_user_confirm_req { __le32 passkey; } __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; @@ -986,6 +1080,32 @@ struct hci_ev_le_conn_complete { __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 { @@ -1033,7 +1153,6 @@ struct hci_sco_hdr { __u8 dlen; } __packed; -#ifdef __KERNEL__ #include <linux/skbuff.h> static inline struct hci_event_hdr *hci_event_hdr(const struct sk_buff *skb) { @@ -1049,7 +1168,6 @@ static inline struct hci_sco_hdr *hci_sco_hdr(const struct sk_buff *skb) { return (struct hci_sco_hdr *) skb->data; } -#endif /* Command opcode pack/unpack */ #define hci_opcode_pack(ogf, ocf) (__u16) ((ocf & 0x03ff)|(ogf << 10)) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 441dadbf6a8..8f441b8b296 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -25,6 +25,7 @@ #ifndef __HCI_CORE_H #define __HCI_CORE_H +#include <linux/interrupt.h> #include <net/bluetooth/hci.h> /* HCI upper protocols */ @@ -74,12 +75,41 @@ struct bt_uuid { u8 svc_hint; }; +struct key_master_id { + __le16 ediv; + u8 rand[8]; +} __packed; + +struct link_key_data { + bdaddr_t bdaddr; + u8 type; + u8 val[16]; + u8 pin_len; + u8 dlen; + u8 data[0]; +} __packed; + struct link_key { struct list_head list; bdaddr_t bdaddr; u8 type; u8 val[16]; u8 pin_len; + u8 dlen; + u8 data[0]; +}; + +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; }; #define NUM_REASSEMBLY 4 @@ -94,11 +124,13 @@ struct hci_dev { __u8 bus; __u8 dev_type; bdaddr_t bdaddr; - __u8 dev_name[248]; + __u8 dev_name[HCI_MAX_NAME_LENGTH]; + __u8 eir[HCI_MAX_EIR_LENGTH]; __u8 dev_class[3]; __u8 major_class; __u8 minor_class; __u8 features[8]; + __u8 extfeatures[8]; __u8 commands[64]; __u8 ssp_mode; __u8 hci_ver; @@ -118,6 +150,8 @@ struct hci_dev { __u16 sniff_min_interval; __u16 sniff_max_interval; + unsigned int auto_accept_delay; + unsigned long quirks; atomic_t cmd_cnt; @@ -161,6 +195,8 @@ struct hci_dev { __u16 init_last_cmd; + struct crypto_blkcipher *tfm; + struct inquiry_cache inq_cache; struct hci_conn_hash conn_hash; struct list_head blacklist; @@ -169,6 +205,11 @@ struct hci_dev { struct list_head link_keys; + struct list_head remote_oob_data; + + struct list_head adv_entries; + struct timer_list adv_timer; + struct hci_dev_stats stat; struct sk_buff_head driver_init; @@ -200,9 +241,9 @@ struct hci_conn { struct list_head list; atomic_t refcnt; - spinlock_t lock; bdaddr_t dst; + __u8 dst_type; __u16 handle; __u16 state; __u8 mode; @@ -216,10 +257,12 @@ struct hci_conn { __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; __u8 power_save; __u16 disc_timeout; @@ -235,6 +278,7 @@ struct hci_conn { struct timer_list disc_timer; struct timer_list idle_timer; + struct timer_list auto_accept_timer; struct work_struct work_add; struct work_struct work_del; @@ -245,7 +289,6 @@ struct hci_conn { struct hci_dev *hdev; void *l2cap_data; void *sco_data; - void *priv; struct hci_conn *link; @@ -293,12 +336,14 @@ 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(struct hci_dev *hdev, + bdaddr_t *bdaddr); void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data); /* ----- HCI Connections ----- */ enum { HCI_CONN_AUTH_PEND, + HCI_CONN_REAUTH_PEND, HCI_CONN_ENCRYPT_PEND, HCI_CONN_RSWITCH_PEND, HCI_CONN_MODE_CHANGE_PEND, @@ -406,13 +451,15 @@ 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_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type); +struct hci_conn *hci_connect(struct hci_dev *hdev, int 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); +void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active); void hci_conn_enter_sniff_mode(struct hci_conn *conn); void hci_conn_hold_device(struct hci_conn *conn); @@ -434,10 +481,12 @@ static inline void hci_conn_put(struct hci_conn *conn) timeo = msecs_to_jiffies(conn->disc_timeout); if (!conn->out) timeo *= 2; - } else + } else { timeo = msecs_to_jiffies(10); - } else + } + } else { timeo = msecs_to_jiffies(10); + } mod_timer(&conn->disc_timer, jiffies + timeo); } } @@ -496,15 +545,35 @@ 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); +int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr); 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, int new_key, bdaddr_t *bdaddr, - u8 *key, u8 type, u8 pin_len); +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 link_key *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]); +struct link_key *hci_find_link_key_type(struct hci_dev *hdev, + bdaddr_t *bdaddr, u8 type); +int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, + u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16]); 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); @@ -531,6 +600,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn); #define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH) #define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE) +/* ----- Extended LMP capabilities ----- */ +#define lmp_host_le_capable(dev) ((dev)->extfeatures[0] & LMP_HOST_LE) + /* ----- HCI protocols ----- */ struct hci_proto { char *name; @@ -539,16 +611,20 @@ struct hci_proto { void *priv; - int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type); + int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr, + __u8 type); int (*connect_cfm) (struct hci_conn *conn, __u8 status); int (*disconn_ind) (struct hci_conn *conn); int (*disconn_cfm) (struct hci_conn *conn, __u8 reason); - int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb, __u16 flags); + int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb, + __u16 flags); int (*recv_scodata) (struct hci_conn *conn, struct sk_buff *skb); - int (*security_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt); + int (*security_cfm) (struct hci_conn *conn, __u8 status, + __u8 encrypt); }; -static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type) +static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, + __u8 type) { register struct hci_proto *hp; int mask = 0; @@ -634,7 +710,8 @@ static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status) conn->security_cfm_cb(conn, status); } -static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt) +static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, + __u8 encrypt) { register struct hci_proto *hp; @@ -659,7 +736,8 @@ struct hci_cb { char *name; - void (*security_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt); + 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); }; @@ -685,13 +763,17 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status) read_unlock_bh(&hci_cb_list_lock); } -static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt) +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_bh(&hci_cb_list_lock); @@ -716,7 +798,8 @@ static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status) read_unlock_bh(&hci_cb_list_lock); } -static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, __u8 role) +static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, + __u8 role) { struct list_head *p; @@ -754,19 +837,27 @@ int mgmt_index_removed(u16 index); int mgmt_powered(u16 index, u8 powered); int mgmt_discoverable(u16 index, u8 discoverable); int mgmt_connectable(u16 index, u8 connectable); -int mgmt_new_key(u16 index, struct link_key *key, u8 old_key_type); +int mgmt_new_key(u16 index, struct link_key *key, u8 persistent); int mgmt_connected(u16 index, bdaddr_t *bdaddr); int mgmt_disconnected(u16 index, bdaddr_t *bdaddr); int mgmt_disconnect_failed(u16 index); int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status); -int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr); +int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure); int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); -int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value); +int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value, + u8 confirm_hint); int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status); +int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status); +int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, + u8 status); +int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, + u8 *eir); +int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name); +int mgmt_discovering(u16 index, u8 discovering); /* HCI info for socket */ #define hci_pi(sk) ((struct hci_pinfo *) sk) @@ -800,4 +891,9 @@ 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); + #endif /* __HCI_CORE_H */ diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 4f4bff1eaed..4f34ad25e75 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -37,7 +37,6 @@ #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_LOCAL_BUSY_TRIES 12 #define L2CAP_LE_DEFAULT_MTU 23 #define L2CAP_CONN_TIMEOUT (40000) /* 40 seconds */ @@ -130,6 +129,12 @@ struct l2cap_conninfo { #define L2CAP_SDU_END 0x8000 #define L2CAP_SDU_CONTINUE 0xC000 +/* 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; @@ -144,8 +149,19 @@ struct l2cap_cmd_hdr { } __packed; #define L2CAP_CMD_HDR_SIZE 4 -struct l2cap_cmd_rej { +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 { @@ -276,63 +292,21 @@ struct l2cap_conn_param_update_rsp { #define L2CAP_CONN_PARAM_ACCEPTED 0x0000 #define L2CAP_CONN_PARAM_REJECTED 0x0001 -/* ----- L2CAP connections ----- */ -struct l2cap_chan_list { - struct sock *head; - rwlock_t lock; - long num; -}; - -struct l2cap_conn { - struct hci_conn *hcon; - - bdaddr_t *dst; - bdaddr_t *src; - - unsigned int mtu; - - __u32 feat_mask; - - __u8 info_state; - __u8 info_ident; - - struct timer_list info_timer; - - spinlock_t lock; - - struct sk_buff *rx_skb; - __u32 rx_len; - __u8 rx_ident; - __u8 tx_ident; - - __u8 disc_reason; - - struct l2cap_chan_list chan_list; +/* ----- L2CAP channels and connections ----- */ +struct srej_list { + __u8 tx_seq; + struct list_head list; }; -struct sock_del_list { +struct l2cap_chan { struct sock *sk; - struct list_head list; -}; -#define L2CAP_INFO_CL_MTU_REQ_SENT 0x01 -#define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x04 -#define L2CAP_INFO_FEAT_MASK_REQ_DONE 0x08 + struct l2cap_conn *conn; -/* ----- L2CAP channel and socket info ----- */ -#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) -#define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue) -#define SREJ_QUEUE(sk) (&l2cap_pi(sk)->srej_queue) -#define BUSY_QUEUE(sk) (&l2cap_pi(sk)->busy_queue) -#define SREJ_LIST(sk) (&l2cap_pi(sk)->srej_l.list) + __u8 state; -struct srej_list { - __u8 tx_seq; - struct list_head list; -}; + atomic_t refcnt; -struct l2cap_pinfo { - struct bt_sock bt; __le16 psm; __u16 dcid; __u16 scid; @@ -341,19 +315,33 @@ struct l2cap_pinfo { __u16 omtu; __u16 flush_to; __u8 mode; - __u8 num_conf_req; - __u8 num_conf_rsp; + __u8 chan_type; + + __le16 sport; - __u8 fcs; __u8 sec_level; __u8 role_switch; __u8 force_reliable; __u8 flushable; + __u8 force_active; + + __u8 ident; __u8 conf_req[64]; __u8 conf_len; - __u8 conf_state; - __u16 conn_state; + __u8 num_conf_req; + __u8 num_conf_rsp; + + __u8 fcs; + + __u8 tx_win; + __u8 max_tx; + __u16 retrans_timeout; + __u16 monitor_timeout; + __u16 mps; + + unsigned long conf_state; + unsigned long conn_state; __u8 next_tx_seq; __u8 expected_ack_seq; @@ -369,74 +357,137 @@ struct l2cap_pinfo { __u16 partial_sdu_len; struct sk_buff *sdu; - __u8 ident; - - __u8 tx_win; - __u8 max_tx; __u8 remote_tx_win; __u8 remote_max_tx; - __u16 retrans_timeout; - __u16 monitor_timeout; __u16 remote_mps; - __u16 mps; - - __le16 sport; + struct timer_list chan_timer; struct timer_list retrans_timer; struct timer_list monitor_timer; struct timer_list ack_timer; - struct sk_buff_head tx_queue; - struct sk_buff_head srej_queue; - struct sk_buff_head busy_queue; - struct work_struct busy_work; - struct srej_list srej_l; - struct l2cap_conn *conn; - struct sock *next_c; - struct sock *prev_c; + 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 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); }; -#define L2CAP_CONF_REQ_SENT 0x01 -#define L2CAP_CONF_INPUT_DONE 0x02 -#define L2CAP_CONF_OUTPUT_DONE 0x04 -#define L2CAP_CONF_MTU_DONE 0x08 -#define L2CAP_CONF_MODE_DONE 0x10 -#define L2CAP_CONF_CONNECT_PEND 0x20 -#define L2CAP_CONF_NO_FCS_RECV 0x40 -#define L2CAP_CONF_STATE2_DEVICE 0x80 +struct l2cap_conn { + struct hci_conn *hcon; + + bdaddr_t *dst; + bdaddr_t *src; + + unsigned int mtu; + + __u32 feat_mask; + + __u8 info_state; + __u8 info_ident; + + struct timer_list info_timer; + + spinlock_t lock; + + struct sk_buff *rx_skb; + __u32 rx_len; + __u8 tx_ident; + + __u8 disc_reason; + + __u8 preq[7]; /* SMP Pairing Request */ + __u8 prsp[7]; /* SMP Pairing Response */ + __u8 prnd[16]; /* SMP Pairing Random */ + __u8 pcnf[16]; /* SMP Pairing Confirm */ + __u8 tk[16]; /* SMP Temporary Key */ + __u8 smp_key_size; + + struct timer_list security_timer; + + struct list_head chan_l; + rwlock_t 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, +}; #define L2CAP_CONF_MAX_CONF_REQ 2 #define L2CAP_CONF_MAX_CONF_RSP 2 -#define L2CAP_CONN_SAR_SDU 0x0001 -#define L2CAP_CONN_SREJ_SENT 0x0002 -#define L2CAP_CONN_WAIT_F 0x0004 -#define L2CAP_CONN_SREJ_ACT 0x0008 -#define L2CAP_CONN_SEND_PBIT 0x0010 -#define L2CAP_CONN_REMOTE_BUSY 0x0020 -#define L2CAP_CONN_LOCAL_BUSY 0x0040 -#define L2CAP_CONN_REJ_ACT 0x0080 -#define L2CAP_CONN_SEND_FBIT 0x0100 -#define L2CAP_CONN_RNR_SENT 0x0200 -#define L2CAP_CONN_SAR_RETRY 0x0400 - -#define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \ - jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); -#define __mod_monitor_timer() mod_timer(&l2cap_pi(sk)->monitor_timer, \ - jiffies + msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO)); -#define __mod_ack_timer() mod_timer(&l2cap_pi(sk)->ack_timer, \ - jiffies + msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO)); - -static inline int l2cap_tx_window_full(struct sock *sk) +enum { + CONN_SAR_SDU, + 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, +}; + +#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, \ + 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, \ + 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, \ + L2CAP_DEFAULT_ACK_TO); +#define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer) + +static inline int l2cap_tx_window_full(struct l2cap_chan *ch) { - struct l2cap_pinfo *pi = l2cap_pi(sk); int sub; - sub = (pi->next_tx_seq - pi->expected_ack_seq) % 64; + sub = (ch->next_tx_seq - ch->expected_ack_seq) % 64; if (sub < 0) sub += 64; - return sub == pi->remote_tx_win; + return sub == ch->remote_tx_win; } #define __get_txseq(ctrl) (((ctrl) & L2CAP_CTRL_TXSEQ) >> 1) @@ -446,34 +497,21 @@ static inline int l2cap_tx_window_full(struct sock *sk) #define __is_sar_start(ctrl) (((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START) extern int disable_ertm; -extern const struct proto_ops l2cap_sock_ops; -extern struct bt_sock_list l2cap_sk_list; int l2cap_init_sockets(void); void l2cap_cleanup_sockets(void); -u8 l2cap_get_ident(struct l2cap_conn *conn); -void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data); -int l2cap_build_conf_req(struct sock *sk, void *data); +void __l2cap_connect_rsp_defer(struct l2cap_chan *chan); int __l2cap_wait_ack(struct sock *sk); -struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len); -struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len); -struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen); -int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len); -void l2cap_do_send(struct sock *sk, struct sk_buff *skb); -void l2cap_streaming_send(struct sock *sk); -int l2cap_ertm_send(struct sock *sk); - -void l2cap_sock_set_timer(struct sock *sk, long timeout); -void l2cap_sock_clear_timer(struct sock *sk); -void __l2cap_sock_close(struct sock *sk, int reason); -void l2cap_sock_kill(struct sock *sk); -void l2cap_sock_init(struct sock *sk, struct sock *parent); -struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, - int proto, gfp_t prio); -void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err); -void l2cap_chan_del(struct sock *sk, int err); -int l2cap_do_connect(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); +int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len); +void l2cap_chan_busy(struct l2cap_chan *chan, int busy); #endif /* __L2CAP_H */ diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 5fabfa886b3..5428fd32cce 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -41,6 +41,10 @@ struct mgmt_rp_read_index_list { __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_OP_READ_INFO 0x0004 struct mgmt_rp_read_info { __u8 type; @@ -55,6 +59,7 @@ struct mgmt_rp_read_info { __u16 manufacturer; __u8 hci_ver; __u16 hci_rev; + __u8 name[MGMT_MAX_NAME_LENGTH]; } __packed; struct mgmt_mode { @@ -96,6 +101,8 @@ struct mgmt_key_info { u8 type; u8 val[16]; u8 pin_len; + u8 dlen; + u8 data[0]; } __packed; #define MGMT_OP_LOAD_KEYS 0x000D @@ -167,6 +174,43 @@ struct mgmt_rp_user_confirm_reply { #define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x0016 +#define MGMT_OP_SET_LOCAL_NAME 0x0017 +struct mgmt_cp_set_local_name { + __u8 name[MGMT_MAX_NAME_LENGTH]; +} __packed; + +#define MGMT_OP_READ_LOCAL_OOB_DATA 0x0018 +struct mgmt_rp_read_local_oob_data { + __u8 hash[16]; + __u8 randomizer[16]; +} __packed; + +#define MGMT_OP_ADD_REMOTE_OOB_DATA 0x0019 +struct mgmt_cp_add_remote_oob_data { + bdaddr_t bdaddr; + __u8 hash[16]; + __u8 randomizer[16]; +} __packed; + +#define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x001A +struct mgmt_cp_remove_remote_oob_data { + bdaddr_t bdaddr; +} __packed; + +#define MGMT_OP_START_DISCOVERY 0x001B + +#define MGMT_OP_STOP_DISCOVERY 0x001C + +#define MGMT_OP_BLOCK_DEVICE 0x001D +struct mgmt_cp_block_device { + bdaddr_t bdaddr; +} __packed; + +#define MGMT_OP_UNBLOCK_DEVICE 0x001E +struct mgmt_cp_unblock_device { + bdaddr_t bdaddr; +} __packed; + #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; @@ -198,8 +242,8 @@ struct mgmt_ev_controller_error { #define MGMT_EV_NEW_KEY 0x000A struct mgmt_ev_new_key { + __u8 store_hint; struct mgmt_key_info key; - __u8 old_key_type; } __packed; #define MGMT_EV_CONNECTED 0x000B @@ -221,11 +265,13 @@ struct mgmt_ev_connect_failed { #define MGMT_EV_PIN_CODE_REQUEST 0x000E struct mgmt_ev_pin_code_request { bdaddr_t bdaddr; + __u8 secure; } __packed; #define MGMT_EV_USER_CONFIRM_REQUEST 0x000F struct mgmt_ev_user_confirm_request { bdaddr_t bdaddr; + __u8 confirm_hint; __le32 value; } __packed; @@ -234,3 +280,24 @@ struct mgmt_ev_auth_failed { bdaddr_t bdaddr; __u8 status; } __packed; + +#define MGMT_EV_LOCAL_NAME_CHANGED 0x0011 +struct mgmt_ev_local_name_changed { + __u8 name[MGMT_MAX_NAME_LENGTH]; +} __packed; + +#define MGMT_EV_DEVICE_FOUND 0x0012 +struct mgmt_ev_device_found { + bdaddr_t bdaddr; + __u8 dev_class[3]; + __s8 rssi; + __u8 eir[HCI_MAX_EIR_LENGTH]; +} __packed; + +#define MGMT_EV_REMOTE_NAME 0x0013 +struct mgmt_ev_remote_name { + bdaddr_t bdaddr; + __u8 name[MGMT_MAX_NAME_LENGTH]; +} __packed; + +#define MGMT_EV_DISCOVERING 0x0014 diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index 6eac4a760c3..d5eee2093b1 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h @@ -234,7 +234,8 @@ int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci, /* ---- 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_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); @@ -271,7 +272,8 @@ static inline void rfcomm_dlc_unthrottle(struct rfcomm_dlc *d) } /* ---- RFCOMM sessions ---- */ -void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, bdaddr_t *dst); +void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, + bdaddr_t *dst); static inline void rfcomm_session_hold(struct rfcomm_session *s) { @@ -312,7 +314,8 @@ struct rfcomm_pinfo { int rfcomm_init_sockets(void); void rfcomm_cleanup_sockets(void); -int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc **d); +int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, + struct rfcomm_dlc **d); /* ---- RFCOMM TTY ---- */ #define RFCOMM_MAX_DEV 256 diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h index 8f2edbf979d..46c45761230 100644 --- a/include/net/bluetooth/smp.h +++ b/include/net/bluetooth/smp.h @@ -1,3 +1,25 @@ +/* + 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 @@ -16,6 +38,23 @@ struct smp_cmd_pairing { __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]; @@ -73,4 +112,12 @@ struct smp_cmd_security_req { #define SMP_UNSPECIFIED 0x08 #define SMP_REPEATED_ATTEMPTS 0x09 +#define SMP_MIN_ENC_KEY_SIZE 7 +#define SMP_MAX_ENC_KEY_SIZE 16 + +/* 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); + #endif /* __SMP_H */ diff --git a/include/net/caif/caif_dev.h b/include/net/caif/caif_dev.h index 8eff83b9536..c011281d92c 100644 --- a/include/net/caif/caif_dev.h +++ b/include/net/caif/caif_dev.h @@ -11,6 +11,7 @@ #include <net/caif/cfcnfg.h> #include <linux/caif/caif_socket.h> #include <linux/if.h> +#include <linux/net.h> /** * struct caif_param - CAIF parameters. @@ -62,46 +63,45 @@ struct caif_connect_request { * 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 caif_connect_request *conn_req, +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 removed. + * @client_layer: Client layer to be disconnected. */ -int caif_disconnect_client(struct cflayer *client_layer); +int caif_disconnect_client(struct net *net, struct cflayer *client_layer); + /** - * caif_release_client - Release adaptation layer reference to client. + * caif_client_register_refcnt - register ref-count functions provided by client. * - * @client_layer: Client layer. + * @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 * - * Releases a client/adaptation layer use of the caif stack. - * This function must be used after caif_disconnect_client to - * decrease the reference count of the service layer. - */ -void caif_release_client(struct cflayer *client_layer); - -/** - * connect_req_to_link_param - Translate configuration parameters - * from socket format to internal format. - * @cnfg: Pointer to configuration handler - * @con_req: Configuration parameters supplied in function - * caif_connect_client - * @channel_setup_param: Parameters supplied to the CAIF Core stack for - * setting up channels. + * 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. */ -int connect_req_to_link_param(struct cfcnfg *cnfg, - struct caif_connect_request *con_req, - struct cfctrl_link_param *channel_setup_param); +void caif_client_register_refcnt(struct cflayer *adapt_layer, + void (*hold)(struct cflayer *lyr), + void (*put)(struct cflayer *lyr)); /** - * get_caif_conf() - Get the configuration handler. + * 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. */ -struct cfcnfg *get_caif_conf(void); - +void caif_free_client(struct cflayer *adap_layer); #endif /* CAIF_DEV_H_ */ diff --git a/include/net/caif/caif_hsi.h b/include/net/caif/caif_hsi.h new file mode 100644 index 00000000000..c5dedd87b4c --- /dev/null +++ b/include/net/caif/caif_hsi.h @@ -0,0 +1,145 @@ +/* + * 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. + */ +/* TODO: 4096 is temporary... */ +#define CFHSI_MAX_PAYLOAD_SZ (CFHSI_MAX_PKTS * 4096) + +/* 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_PENDING_RX 4 +#define CFHSI_SHUTDOWN 6 +#define CFHSI_FLUSH_FIFO 7 + +#ifndef CFHSI_INACTIVITY_TOUT +#define CFHSI_INACTIVITY_TOUT (1 * HZ) +#endif /* CFHSI_INACTIVITY_TOUT */ + +#ifndef CFHSI_WAKEUP_TOUT +#define CFHSI_WAKEUP_TOUT (3 * HZ) +#endif /* CFHSI_WAKEUP_TOUT */ + + +/* 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_fifo_occupancy)(struct cfhsi_dev *dev, size_t *occupancy); + int (*cfhsi_rx_cancel)(struct cfhsi_dev *dev); + struct cfhsi_drv *drv; +}; + +/* 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; + int rx_state; + int rx_len; + u8 *rx_ptr; + u8 *tx_buf; + u8 *rx_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 rx_done_work; + struct work_struct tx_done_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; + 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 index c8b07a904e7..35bc7883cf9 100644 --- a/include/net/caif/caif_layer.h +++ b/include/net/caif/caif_layer.h @@ -15,7 +15,6 @@ struct cfpktq; struct caif_payload_info; struct caif_packet_funcs; - #define CAIF_LAYER_NAME_SZ 16 /** @@ -33,7 +32,6 @@ do { \ } \ } while (0) - /** * enum caif_ctrlcmd - CAIF Stack Control Signaling sent in layer.ctrlcmd(). * @@ -141,7 +139,7 @@ enum caif_direction { * - 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 private data. + * - 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); @@ -155,16 +153,23 @@ struct cflayer { struct list_head node; /* - * receive() - Receive Function. + * 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) cannot be accessed after - * passing it to the next layer using up->receive(). + * - 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 -1 returned from the function. + * 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. + * the function must return a value >= 0. * * Returns result < 0 indicates an error, 0 or positive value * indicates success. @@ -176,7 +181,7 @@ struct cflayer { int (*receive)(struct cflayer *layr, struct cfpkt *cfpkt); /* - * transmit() - Transmit Function. + * transmit() - Transmit Function (non-blocking). * Contract: Each layer must implement a transmit function passing the * CAIF packet downwards in the stack. * Packet handling rules: @@ -185,15 +190,16 @@ struct cflayer { * cannot be accessed after passing it to the below * layer using dn->transmit(). * - * - If transmit fails, however, the ownership is returned - * to thecaller. The caller of "dn->transmit()" must - * destroy or resend packet. + * - 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. * - * result < 0 indicates an error, 0 or positive value - * indicate success. + * 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). @@ -202,7 +208,7 @@ struct cflayer { int (*transmit) (struct cflayer *layr, struct cfpkt *cfpkt); /* - * cttrlcmd() - Control Function upwards in CAIF Stack. + * 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) * diff --git a/include/net/caif/cfcnfg.h b/include/net/caif/cfcnfg.h index f33d3634113..3e93a4a4b67 100644 --- a/include/net/caif/cfcnfg.h +++ b/include/net/caif/cfcnfg.h @@ -46,6 +46,12 @@ enum cfcnfg_phy_preference { }; /** + * 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); @@ -65,17 +71,15 @@ void cfcnfg_remove(struct cfcnfg *cfg); * @dev: Pointer to link layer device * @phy_layer: Specify the physical layer. The transmit function * MUST be set in the structure. - * @phyid: The assigned physical ID for this layer, used in - * cfcnfg_add_adapt_layer to specify PHY for the link. * @pref: The phy (link layer) preference. * @fcs: Specify if checksum is used in CAIF Framing Layer. - * @stx: Specify if Start Of Frame extension is used. + * @stx: Specify if Start Of Frame eXtention is used. */ void cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, struct net_device *dev, struct cflayer *phy_layer, - u16 *phyid, enum cfcnfg_phy_preference pref, + enum cfcnfg_phy_preference pref, bool fcs, bool stx); /** @@ -88,61 +92,12 @@ cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer); /** - * cfcnfg_disconn_adapt_layer - Disconnects an adaptation layer. - * - * @cnfg: Pointer to a CAIF configuration object, created by - * cfcnfg_create(). - * @adap_layer: Adaptation layer to be removed. - */ -int cfcnfg_disconn_adapt_layer(struct cfcnfg *cnfg, - struct cflayer *adap_layer); - -/** - * cfcnfg_release_adap_layer - Used by client to release the adaptation layer. - * - * @adap_layer: Adaptation layer. - */ -void cfcnfg_release_adap_layer(struct cflayer *adap_layer); - -/** - * cfcnfg_add_adaptation_layer - Add an adaptation layer to the CAIF stack. - * - * The adaptation Layer is where the interface to application or higher-level - * driver functionality is implemented. - * - * @cnfg: Pointer to a CAIF configuration object, created by - * cfcnfg_create(). - * @param: Link setup parameters. - * @adap_layer: Specify the adaptation layer; the receive and - * flow-control functions MUST be set in the structure. - * @ifindex: Link layer interface index used for this connection. - * @proto_head: Protocol head-space needed by CAIF protocol, - * excluding link layer. - * @proto_tail: Protocol tail-space needed by CAIF protocol, - * excluding link layer. - */ -int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, - struct cfctrl_link_param *param, - struct cflayer *adap_layer, - int *ifindex, - int *proto_head, - int *proto_tail); - -/** - * cfcnfg_get_phyid() - Get physical ID, given type. - * Returns one of the physical interfaces matching the given type. - * Zero if no match is found. + * cfcnfg_set_phy_state() - Set the state of the physical interface device. * @cnfg: Configuration object - * @phy_pref: Caif Link Layer preference + * @phy_layer: Physical Layer representation + * @up: State of device */ -struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg, - enum cfcnfg_phy_preference phy_pref); +int cfcnfg_set_phy_state(struct cfcnfg *cnfg, struct cflayer *phy_layer, + bool up); -/** - * cfcnfg_get_id_from_ifi() - Get the Physical Identifier of ifindex, - * it matches caif physical id with the kernel interface id. - * @cnfg: Configuration object - * @ifi: ifindex obtained from socket.c bindtodevice. - */ -int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi); #endif /* CFCNFG_H_ */ diff --git a/include/net/caif/cfctrl.h b/include/net/caif/cfctrl.h index e54f6396fa4..9e5425b4a1d 100644 --- a/include/net/caif/cfctrl.h +++ b/include/net/caif/cfctrl.h @@ -121,19 +121,10 @@ int cfctrl_linkup_request(struct cflayer *cfctrl, struct cflayer *user_layer); int cfctrl_linkdown_req(struct cflayer *cfctrl, u8 linkid, struct cflayer *client); -void cfctrl_sleep_req(struct cflayer *cfctrl); -void cfctrl_wake_req(struct cflayer *cfctrl); -void cfctrl_getstartreason_req(struct cflayer *cfctrl); + struct cflayer *cfctrl_create(void); -void cfctrl_set_dnlayer(struct cflayer *this, struct cflayer *dn); -void cfctrl_set_uplayer(struct cflayer *this, struct cflayer *up); struct cfctrl_rsp *cfctrl_get_respfuncs(struct cflayer *layer); -bool cfctrl_req_eq(struct cfctrl_request_info *r1, - struct cfctrl_request_info *r2); -void cfctrl_insert_req(struct cfctrl *ctrl, - struct cfctrl_request_info *req); -struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl, - struct cfctrl_request_info *req); -void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_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 index 3f14d2e1ce6..afac1a48cce 100644 --- a/include/net/caif/cffrml.h +++ b/include/net/caif/cffrml.h @@ -7,10 +7,15 @@ #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 DoFCS); +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 index 4e1b4f33423..5847a196b8a 100644 --- a/include/net/caif/cfmuxl.h +++ b/include/net/caif/cfmuxl.h @@ -16,7 +16,5 @@ 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); -bool cfmuxl_is_phy_inuse(struct cflayer *layr, u8 phyid); -u8 cfmuxl_get_phyid(struct cflayer *layr, u8 channel_id); #endif /* CFMUXL_H_ */ diff --git a/include/net/caif/cfpkt.h b/include/net/caif/cfpkt.h index fbc681beff5..6bd200a4754 100644 --- a/include/net/caif/cfpkt.h +++ b/include/net/caif/cfpkt.h @@ -16,12 +16,6 @@ struct cfpkt; */ struct cfpkt *cfpkt_create(u16 len); -/* Create a CAIF packet. - * data Data to copy. - * len Length of packet to be created - * @return New packet. - */ -struct cfpkt *cfpkt_create_uplink(const unsigned char *data, unsigned int len); /* * Destroy a CAIF Packet. * pkt Packet to be destoyed. @@ -181,22 +175,6 @@ u16 cfpkt_iterate(struct cfpkt *pkt, u16 (*iter_func)(u16 chks, void *buf, u16 len), u16 data); -/* Append by giving user access to packet buffer - * cfpkt Packet to append to - * buf Buffer inside pkt that user shall copy data into - * buflen Length of buffer and number of bytes added to packet - * @return 0 on error, 1 on success - */ -int cfpkt_raw_append(struct cfpkt *cfpkt, void **buf, unsigned int buflen); - -/* Extract by giving user access to packet buffer - * cfpkt Packet to extract from - * buf Buffer inside pkt that user shall copy data from - * buflen Length of buffer and number of bytes removed from packet - * @return 0 on error, 1 on success - */ -int cfpkt_raw_extract(struct cfpkt *cfpkt, void **buf, unsigned int buflen); - /* 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 @@ -210,59 +188,6 @@ struct cfpkt *cfpkt_fromnative(enum caif_direction dir, void *nativepkt); */ void *cfpkt_tonative(struct cfpkt *pkt); -/* - * Insert a packet in the packet queue. - * pktq Packet queue to insert into - * pkt Packet to be inserted in queue - * prio Priority of packet - */ -void cfpkt_queue(struct cfpktq *pktq, struct cfpkt *pkt, - unsigned short prio); - -/* - * Remove a packet from the packet queue. - * pktq Packet queue to fetch packets from. - * @return Dequeued packet. - */ -struct cfpkt *cfpkt_dequeue(struct cfpktq *pktq); - -/* - * Peek into a packet from the packet queue. - * pktq Packet queue to fetch packets from. - * @return Peeked packet. - */ -struct cfpkt *cfpkt_qpeek(struct cfpktq *pktq); - -/* - * Initiates the packet queue. - * @return Pointer to new packet queue. - */ -struct cfpktq *cfpktq_create(void); - -/* - * Get the number of packets in the queue. - * pktq Packet queue to fetch count from. - * @return Number of packets in queue. - */ -int cfpkt_qcount(struct cfpktq *pktq); - -/* - * Put content of packet into buffer for debuging purposes. - * pkt Packet to copy data from - * buf Buffer to copy data into - * buflen Length of data to copy - * @return Pointer to copied data - */ -char *cfpkt_log_pkt(struct cfpkt *pkt, char *buf, int buflen); - -/* - * Clones a packet and releases the original packet. - * This is used for taking ownership of a packet e.g queueing. - * pkt Packet to clone and release. - * @return Cloned packet. - */ -struct cfpkt *cfpkt_clone_release(struct cfpkt *pkt); - /* * Returns packet information for a packet. @@ -270,5 +195,4 @@ struct cfpkt *cfpkt_clone_release(struct cfpkt *pkt); * @return Packet information */ struct caif_payload_info *cfpkt_info(struct cfpkt *pkt); -/*! @} */ #endif /* CFPKT_H_ */ diff --git a/include/net/caif/cfsrvl.h b/include/net/caif/cfsrvl.h index b1fa87ee099..0f590524184 100644 --- a/include/net/caif/cfsrvl.h +++ b/include/net/caif/cfsrvl.h @@ -10,6 +10,7 @@ #include <linux/stddef.h> #include <linux/types.h> #include <linux/kref.h> +#include <linux/rculist.h> struct cfsrvl { struct cflayer layer; @@ -17,12 +18,13 @@ struct cfsrvl { bool phy_flow_on; bool modem_flow_on; bool supports_flowctrl; - void (*release)(struct kref *); + void (*release)(struct cflayer *layer); struct dev_info dev_info; - struct kref ref; + void (*hold)(struct cflayer *lyr); + void (*put)(struct cflayer *lyr); + struct rcu_head rcu; }; -void cfsrvl_release(struct kref *kref); 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); @@ -30,8 +32,12 @@ 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 cfservl_destroy(struct cflayer *layer); + void cfsrvl_init(struct cfsrvl *service, u8 channel_id, struct dev_info *dev_info, @@ -41,23 +47,19 @@ u8 cfsrvl_getphyid(struct cflayer *layer); static inline void cfsrvl_get(struct cflayer *layr) { - struct cfsrvl *s; - if (layr == NULL) + struct cfsrvl *s = container_of(layr, struct cfsrvl, layer); + if (layr == NULL || layr->up == NULL || s->hold == NULL) return; - s = container_of(layr, struct cfsrvl, layer); - kref_get(&s->ref); + + s->hold(layr->up); } static inline void cfsrvl_put(struct cflayer *layr) { - struct cfsrvl *s; - if (layr == NULL) + struct cfsrvl *s = container_of(layr, struct cfsrvl, layer); + if (layr == NULL || layr->up == NULL || s->hold == NULL) return; - s = container_of(layr, struct cfsrvl, layer); - WARN_ON(!s->release); - if (s->release) - kref_put(&s->ref, s->release); + s->put(layr->up); } - #endif /* CFSRVL_H_ */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index b2b9d28cb4a..5390e3245a1 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -387,6 +387,7 @@ enum plink_actions { * @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 */ struct station_parameters { @@ -397,6 +398,7 @@ struct station_parameters { u16 aid; u8 supported_rates_len; u8 plink_action; + u8 plink_state; struct ieee80211_ht_cap *ht_capa; }; @@ -422,6 +424,8 @@ struct station_parameters { * @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 */ enum station_info_flags { STATION_INFO_INACTIVE_TIME = 1<<0, @@ -439,6 +443,8 @@ enum station_info_flags { 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 }; /** @@ -473,11 +479,43 @@ struct rate_info { }; /** + * 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 @@ -493,6 +531,7 @@ struct rate_info { * @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 @@ -500,6 +539,7 @@ struct rate_info { */ struct station_info { u32 filled; + u32 connected_time; u32 inactive_time; u32 rx_bytes; u32 tx_bytes; @@ -515,6 +555,7 @@ struct station_info { u32 tx_retries; u32 tx_failed; u32 rx_dropped_misc; + struct sta_bss_parameters bss_param; int generation; }; @@ -655,8 +696,10 @@ struct mesh_config { * @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 - * @vendor_ie: vendor information elements (optional) - * @vendor_ie_len: length of vendor information elements + * @ie: vendor information elements (optional) + * @ie_len: length of vendor information elements + * @is_authenticated: this mesh requires authentication + * @is_secure: this mesh uses security * * These parameters are fixed when the mesh is created. */ @@ -665,8 +708,10 @@ struct mesh_setup { u8 mesh_id_len; u8 path_sel_proto; u8 path_metric; - const u8 *vendor_ie; - u8 vendor_ie_len; + const u8 *ie; + u8 ie_len; + bool is_authenticated; + bool is_secure; }; /** @@ -753,6 +798,35 @@ struct cfg80211_scan_request { }; /** + * 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 + * @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; + + /* 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 @@ -1048,6 +1122,50 @@ struct cfg80211_pmksa { }; /** + * 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 + */ +struct cfg80211_wowlan { + bool any, disconnect, magic_pkt; + 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 @@ -1060,7 +1178,9 @@ struct cfg80211_pmksa { * 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 + * @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, @@ -1089,6 +1209,8 @@ struct cfg80211_pmksa { * * @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 + * * @add_beacon: Add a beacon with given parameters, @head, @interval * and @dtim_period will be valid, @tail is optional. * @set_beacon: Change the beacon parameters for an access point mode @@ -1176,6 +1298,12 @@ struct cfg80211_pmksa { * 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 * @@ -1187,6 +1315,10 @@ struct cfg80211_pmksa { * @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 @@ -1204,7 +1336,7 @@ struct cfg80211_pmksa { * @get_ringparam: Get tx and rx ring current and maximum sizes. */ struct cfg80211_ops { - int (*suspend)(struct wiphy *wiphy); + int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); int (*resume)(struct wiphy *wiphy); struct net_device * (*add_virtual_intf)(struct wiphy *wiphy, @@ -1321,6 +1453,9 @@ struct cfg80211_ops { #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, @@ -1373,6 +1508,14 @@ struct cfg80211_ops { 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); }; /* @@ -1404,6 +1547,10 @@ struct cfg80211_ops { * 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 @@ -1415,8 +1562,9 @@ struct cfg80211_ops { * 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_SUPPORTS_SEPARATE_DEFAULT_KEYS: The device supports separate - * unicast and multicast TX keys. + * @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. */ enum wiphy_flags { WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), @@ -1428,7 +1576,83 @@ enum wiphy_flags { WIPHY_FLAG_4ADDR_STATION = BIT(6), WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7), WIPHY_FLAG_IBSS_RSN = BIT(8), - WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS= BIT(9), + WIPHY_FLAG_MESH_AUTH = BIT(10), + WIPHY_FLAG_SUPPORTS_SCHED_SCAN = BIT(11), + WIPHY_FLAG_ENFORCE_COMBINATIONS = BIT(12), +}; + +/** + * 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 { @@ -1440,6 +1664,38 @@ struct ieee80211_txrx_stypes { }; /** + * 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 + */ +enum wiphy_wowlan_support_flags { + WIPHY_WOWLAN_ANY = BIT(0), + WIPHY_WOWLAN_MAGIC_PKT = BIT(1), + WIPHY_WOWLAN_DISCONNECT = BIT(2), +}; + +/** + * 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() @@ -1476,6 +1732,11 @@ struct ieee80211_txrx_stypes { * @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 * @bss_priv_size: each BSS struct has private data allocated with it, * this variable determines its size @@ -1506,6 +1767,8 @@ struct ieee80211_txrx_stypes { * * @max_remain_on_channel_duration: Maximum time a remain-on-channel operation * may request, if implemented. + * + * @wowlan: WoWLAN support information */ struct wiphy { /* assign these fields before you register the wiphy */ @@ -1518,6 +1781,10 @@ struct wiphy { 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_...) */ @@ -1543,6 +1810,8 @@ struct wiphy { char fw_version[ETHTOOL_BUSINFO_LEN]; u32 hw_version; + struct wiphy_wowlan_support wowlan; + u16 max_remain_on_channel_duration; u8 max_num_pmkids; @@ -1726,6 +1995,8 @@ struct cfg80211_cached_keys; * @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; @@ -1766,6 +2037,8 @@ struct wireless_dev { bool ps; int ps_timeout; + int beacon_interval; + #ifdef CONFIG_CFG80211_WEXT /* wext data */ struct { @@ -1991,10 +2264,12 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, * @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); + const unsigned int extra_headroom, + bool has_80211_header); /** * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame @@ -2214,6 +2489,24 @@ int cfg80211_wext_siwpmksa(struct net_device *dev, 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 @@ -2421,7 +2714,7 @@ void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf, * @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) + * @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 * @@ -2450,6 +2743,22 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr, 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, @@ -2566,8 +2875,10 @@ struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy, 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 /** @@ -2596,6 +2907,7 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, * 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 @@ -2606,7 +2918,9 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, * 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, const u8 *bssid, +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); @@ -2667,6 +2981,15 @@ 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 @@ -2727,6 +3050,16 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, 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); + /* Logging, debugging and troubleshooting/diagnostic helpers. */ /* wiphy_printk helpers, similar to dev_printk */ diff --git a/include/net/compat.h b/include/net/compat.h index 28d5428ec6a..9ee75edcc29 100644 --- a/include/net/compat.h +++ b/include/net/compat.h @@ -43,6 +43,8 @@ extern int compat_sock_get_timestampns(struct sock *, struct timespec __user *); extern int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *); extern int verify_compat_iovec(struct msghdr *, struct iovec *, struct sockaddr *, 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, diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h index e5983c9053d..f5aa39997f0 100644 --- a/include/net/dcbnl.h +++ b/include/net/dcbnl.h @@ -28,8 +28,16 @@ struct dcb_app_type { struct list_head list; }; -u8 dcb_setapp(struct net_device *, struct dcb_app *); +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 @@ -43,6 +51,7 @@ struct dcbnl_rtnl_ops { 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 *); diff --git a/include/net/dst.h b/include/net/dst.h index 75b95df4afe..29e255796ce 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -16,13 +16,6 @@ #include <net/neighbour.h> #include <asm/processor.h> -/* - * 0 - no debugging messages - * 1 - rare events and bugs (default) - * 2 - trace mode. - */ -#define RT_CACHE_DEBUG 0 - #define DST_GC_MIN (HZ/10) #define DST_GC_INC (HZ/2) #define DST_GC_MAX (120*HZ) @@ -44,8 +37,7 @@ struct dst_entry { unsigned long _metrics; unsigned long expires; struct dst_entry *path; - struct neighbour *neighbour; - struct hh_cache *hh; + struct neighbour *_neighbour; #ifdef CONFIG_XFRM struct xfrm_state *xfrm; #else @@ -54,6 +46,14 @@ struct dst_entry { 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 + short error; short obsolete; unsigned short header_len; /* more space at head required */ @@ -69,7 +69,7 @@ struct dst_entry { * (L1_CACHE_SIZE would be too much) */ #ifdef CONFIG_64BIT - long __pad_to_align_refcnt[1]; + long __pad_to_align_refcnt[2]; #endif /* * __refcnt wants to be on a different cache line from @@ -78,12 +78,6 @@ struct dst_entry { atomic_t __refcnt; /* client references */ int __use; unsigned long lastuse; - int flags; -#define DST_HOST 0x0001 -#define DST_NOXFRM 0x0002 -#define DST_NOPOLICY 0x0004 -#define DST_NOHASH 0x0008 -#define DST_NOCACHE 0x0010 union { struct dst_entry *next; struct rtable __rcu *rt_next; @@ -92,7 +86,15 @@ struct dst_entry { }; }; -#ifdef __KERNEL__ +static inline struct neighbour *dst_get_neighbour(struct dst_entry *dst) +{ + return dst->_neighbour; +} + +static inline void dst_set_neighbour(struct dst_entry *dst, struct neighbour *neigh) +{ + dst->_neighbour = neigh; +} extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); extern const u32 dst_default_metrics[RTAX_MAX]; @@ -120,6 +122,8 @@ 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); @@ -352,7 +356,8 @@ static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb) } extern int dst_discard(struct sk_buff *skb); -extern void *dst_alloc(struct dst_ops * ops, int initial_ref); +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); @@ -376,8 +381,15 @@ static inline void dst_rcu_free(struct rcu_head *head) static inline void dst_confirm(struct dst_entry *dst) { - if (dst) - neigh_confirm(dst->neighbour); + if (dst) { + struct neighbour *n = dst_get_neighbour(dst); + neigh_confirm(n); + } +} + +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) @@ -438,6 +450,5 @@ 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 #endif /* _NET_DST_H */ diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h index dc074632894..9adb99845a5 100644 --- a/include/net/dst_ops.h +++ b/include/net/dst_ops.h @@ -26,6 +26,7 @@ struct dst_ops { 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; diff --git a/include/net/flow.h b/include/net/flow.h index 7fe5a0f9483..c6d5fe5ec1b 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -26,8 +26,8 @@ struct flowi_common { union flowi_uli { struct { - __be16 sport; __be16 dport; + __be16 sport; } ports; struct { @@ -36,8 +36,8 @@ union flowi_uli { } icmpt; struct { - __le16 sport; __le16 dport; + __le16 sport; } dnports; __be32 spi; @@ -70,6 +70,27 @@ struct flowi4 { #define fl4_gre_key uli.gre_key }; +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, __be32 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; +} + + struct flowi6 { struct flowi_common __fl_common; #define flowi6_oif __fl_common.flowic_oif diff --git a/include/net/garp.h b/include/net/garp.h index f4c295984c4..834d8add9e5 100644 --- a/include/net/garp.h +++ b/include/net/garp.h @@ -104,10 +104,12 @@ struct garp_applicant { 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); diff --git a/include/net/genetlink.h b/include/net/genetlink.h index b4c7c1cbcf4..82d8d09faa4 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h @@ -160,6 +160,38 @@ static inline void *genlmsg_put(struct sk_buff *skb, u32 pid, u32 seq, } /** + * 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 @@ -260,7 +292,7 @@ static inline int genlmsg_reply(struct sk_buff *skb, struct genl_info *info) /** * gennlmsg_data - head of message payload - * @gnlh: genetlink messsage header + * @gnlh: genetlink message header */ static inline void *genlmsg_data(const struct genlmsghdr *gnlh) { diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index fccc2180c61..11cf373970a 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h @@ -30,8 +30,6 @@ #define IF_PREFIX_ONLINK 0x01 #define IF_PREFIX_AUTOCONF 0x02 -#ifdef __KERNEL__ - enum { INET6_IFADDR_STATE_DAD, INET6_IFADDR_STATE_POSTDAD, @@ -156,8 +154,8 @@ struct ifacaddr6 { struct ipv6_devstat { struct proc_dir_entry *proc_dir_entry; DEFINE_SNMP_STAT(struct ipstats_mib, ipv6); - DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6); - DEFINE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg); + DEFINE_SNMP_STAT_ATOMIC(struct icmpv6_mib_device, icmpv6dev); + DEFINE_SNMP_STAT_ATOMIC(struct icmpv6msg_mib_device, icmpv6msgdev); }; struct inet6_dev { @@ -196,7 +194,7 @@ struct inet6_dev { struct rcu_head rcu; }; -static inline void ipv6_eth_mc_map(struct in6_addr *addr, char *buf) +static inline void ipv6_eth_mc_map(const struct in6_addr *addr, char *buf) { /* * +-------+-------+-------+-------+-------+-------+ @@ -210,7 +208,7 @@ static inline void ipv6_eth_mc_map(struct in6_addr *addr, char *buf) memcpy(buf + 2, &addr->s6_addr32[3], sizeof(__u32)); } -static inline void ipv6_tr_mc_map(struct in6_addr *addr, char *buf) +static inline void ipv6_tr_mc_map(const struct in6_addr *addr, char *buf) { /* All nodes FF01::1, FF02::1, FF02::1:FFxx:xxxx */ @@ -303,4 +301,3 @@ static inline int ipv6_ipgre_mc_map(const struct in6_addr *addr, } #endif -#endif diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h index ff013505236..3207e58ee01 100644 --- a/include/net/inet6_connection_sock.h +++ b/include/net/inet6_connection_sock.h @@ -41,5 +41,5 @@ extern void inet6_csk_reqsk_queue_hash_add(struct sock *sk, extern void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr); -extern int inet6_csk_xmit(struct sk_buff *skb); +extern int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl); #endif /* _INET6_CONNECTION_SOCK_H */ diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 6ac4e3b5007..e6db62e756d 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -36,7 +36,7 @@ struct tcp_congestion_ops; * (i.e. things that depend on the address family) */ struct inet_connection_sock_af_ops { - int (*queue_xmit)(struct sk_buff *skb); + int (*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); @@ -249,7 +249,11 @@ extern int inet_csk_bind_conflict(const struct sock *sk, 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, diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 7a37369f8ea..caaff5f5f39 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -57,7 +57,15 @@ struct ip_options { unsigned char __data[0]; }; -#define optlength(opt) (sizeof(struct ip_options) + opt->optlen) +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; @@ -78,7 +86,7 @@ struct inet_request_sock { acked : 1, no_srccheck: 1; kmemcheck_bitfield_end(flags); - struct ip_options *opt; + struct ip_options_rcu *opt; }; static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk) @@ -88,17 +96,21 @@ static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk) struct inet_cork { unsigned int flags; - unsigned int fragsize; + __be32 addr; struct ip_options *opt; + unsigned int fragsize; struct dst_entry *dst; int length; /* Total length of all frames */ - __be32 addr; - struct flowi fl; 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; @@ -140,7 +152,7 @@ struct inet_sock { __be16 inet_sport; __u16 inet_id; - struct ip_options *opt; + struct ip_options_rcu __rcu *inet_opt; __u8 tos; __u8 min_ttl; __u8 mc_ttl; @@ -156,7 +168,7 @@ struct inet_sock { int mc_index; __be32 mc_addr; struct ip_mc_socklist __rcu *mc_list; - struct inet_cork cork; + struct inet_cork_full cork; }; #define IPCORK_OPT 1 /* ip-options has been held in ipcork.opt */ diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h index e6dd8da6b2a..4233e6f9841 100644 --- a/include/net/inetpeer.h +++ b/include/net/inetpeer.h @@ -32,13 +32,17 @@ struct inet_peer { struct inet_peer __rcu *avl_left, *avl_right; struct inetpeer_addr daddr; __u32 avl_height; - struct list_head unused; - __u32 dtime; /* the time of last use of not - * referenced entries */ - atomic_t refcnt; + + 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; /* * Once inet_peer is queued for deletion (refcnt == -1), following fields - * are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp, metrics + * 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 { @@ -47,16 +51,14 @@ struct inet_peer { atomic_t ip_id_count; /* IP ID for the next packet */ __u32 tcp_ts; __u32 tcp_ts_stamp; - 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; }; 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; @@ -69,7 +71,7 @@ static inline bool inet_metrics_new(const struct inet_peer *p) } /* can be called with or without local BH being disabled */ -struct inet_peer *inet_getpeer(struct inetpeer_addr *daddr, int create); +struct inet_peer *inet_getpeer(const struct inetpeer_addr *daddr, int create); static inline struct inet_peer *inet_getpeer_v4(__be32 v4daddr, int create) { @@ -80,7 +82,7 @@ static inline struct inet_peer *inet_getpeer_v4(__be32 v4daddr, int create) return inet_getpeer(&daddr, create); } -static inline struct inet_peer *inet_getpeer_v6(struct in6_addr *v6daddr, int create) +static inline struct inet_peer *inet_getpeer_v6(const struct in6_addr *v6daddr, int create) { struct inetpeer_addr daddr; @@ -104,11 +106,18 @@ static inline void inet_peer_refcheck(const struct inet_peer *p) /* can be called with or without local BH being disabled */ -static inline __u16 inet_getid(struct inet_peer *p, int more) +static inline int inet_getid(struct inet_peer *p, int more) { + int old, new; more++; inet_peer_refcheck(p); - return atomic_add_return(more, &p->ip_id_count) - more; + 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 index 7c416583b71..aa76c7a4d9c 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -52,7 +52,7 @@ static inline unsigned int ip_hdrlen(const struct sk_buff *skb) struct ipcm_cookie { __be32 addr; int oif; - struct ip_options *opt; + struct ip_options_rcu *opt; __u8 tx_flags; }; @@ -92,7 +92,7 @@ extern int igmp_mc_proc_init(void); extern int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, __be32 saddr, __be32 daddr, - struct ip_options *opt); + 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); @@ -104,9 +104,9 @@ 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); +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, +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, @@ -114,15 +114,17 @@ extern int ip_append_data(struct sock *sk, 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 page *page, +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); +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, @@ -130,9 +132,9 @@ extern struct sk_buff *ip_make_skb(struct sock *sk, struct rtable **rtp, unsigned int flags); -static inline struct sk_buff *ip_finish_skb(struct sock *sk) +static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4) { - return __ip_make_skb(sk, &sk->sk_write_queue, &inet_sk(sk)->cork); + return __ip_make_skb(sk, fl4, &sk->sk_write_queue, &inet_sk(sk)->cork.base); } /* datagram.c */ @@ -172,8 +174,8 @@ 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, struct ip_reply_arg *arg, - unsigned int len); +void ip_send_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr, + struct ip_reply_arg *arg, unsigned int len); struct ipv4_config { int log_martians; @@ -226,8 +228,6 @@ extern struct ctl_path net_ipv4_ctl_path[]; extern int inet_peer_threshold; extern int inet_peer_minttl; extern int inet_peer_maxttl; -extern int inet_peer_gc_mintime; -extern int inet_peer_gc_maxtime; /* From ip_output.c */ extern int sysctl_ip_dynaddr; @@ -236,6 +236,11 @@ 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> @@ -399,7 +404,8 @@ enum ip_defrag_users { __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_VS_FWD, + IP_DEFRAG_AF_PACKET, }; int ip_defrag(struct sk_buff *skb, u32 user); @@ -416,14 +422,15 @@ 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 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 **optp, +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 **optp, +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); diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index bc3cde0a810..5735a0f979c 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -13,8 +13,6 @@ #ifndef _IP6_FIB_H #define _IP6_FIB_H -#ifdef __KERNEL__ - #include <linux/ipv6_route.h> #include <linux/rtnetlink.h> #include <linux/spinlock.h> @@ -42,6 +40,7 @@ struct fib6_config { struct in6_addr fc_dst; struct in6_addr fc_src; + struct in6_addr fc_prefsrc; struct in6_addr fc_gateway; unsigned long fc_expires; @@ -88,7 +87,6 @@ struct rt6_info { struct dst_entry dst; #define rt6i_dev dst.dev -#define rt6i_nexthop dst.neighbour #define rt6i_expires dst.expires /* @@ -107,6 +105,7 @@ struct rt6_info { 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; @@ -196,12 +195,12 @@ extern struct dst_entry *fib6_rule_lookup(struct net *net, pol_lookup_t lookup); extern struct fib6_node *fib6_lookup(struct fib6_node *root, - struct in6_addr *daddr, - struct in6_addr *saddr); + const struct in6_addr *daddr, + const struct in6_addr *saddr); struct fib6_node *fib6_locate(struct fib6_node *root, - struct in6_addr *daddr, int dst_len, - struct in6_addr *saddr, int src_len); + const struct in6_addr *daddr, int dst_len, + const struct in6_addr *saddr, int src_len); extern void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg), @@ -238,4 +237,3 @@ static inline void fib6_rules_cleanup(void) } #endif #endif -#endif diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index c850e5fb967..5e91b72fc71 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -21,8 +21,6 @@ struct route_info { __u8 prefix[0]; /* 0,8 or 16 */ }; -#ifdef __KERNEL__ - #include <net/flow.h> #include <net/ip6_fib.h> #include <net/sock.h> @@ -84,6 +82,12 @@ 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, @@ -106,9 +110,9 @@ extern int ip6_dst_hoplimit(struct dst_entry *dst); * support functions for ND * */ -extern struct rt6_info * rt6_get_dflt_router(struct in6_addr *addr, +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(struct in6_addr *gwaddr, +extern struct rt6_info * rt6_add_dflt_router(const struct in6_addr *gwaddr, struct net_device *dev, unsigned int pref); @@ -116,17 +120,17 @@ extern void rt6_purge_dflt_routers(struct net *net); extern int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, - struct in6_addr *gwaddr); + const struct in6_addr *gwaddr); -extern void rt6_redirect(struct in6_addr *dest, - struct in6_addr *src, - struct in6_addr *saddr, +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(struct in6_addr *daddr, - struct in6_addr *saddr, +extern void rt6_pmtu_discovery(const struct in6_addr *daddr, + const struct in6_addr *saddr, struct net_device *dev, u32 pmtu); @@ -141,6 +145,7 @@ struct rt6_rtnl_dump_arg { 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); /* @@ -186,4 +191,3 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb) } #endif -#endif diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index e5d66ec88cf..10422ef14e2 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -160,7 +160,8 @@ struct fib_table { struct hlist_node tb_hlist; u32 tb_id; int tb_default; - unsigned char tb_data[0]; + int tb_num_default; + unsigned long tb_data[0]; }; extern int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, @@ -227,9 +228,9 @@ extern struct fib_table *fib_get_table(struct net *net, u32 id); /* Exported by fib_frontend.c */ extern const struct nla_policy rtm_ipv4_policy[]; extern void ip_fib_init(void); -extern int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, - struct net_device *dev, __be32 *spec_dst, - u32 *itag, u32 mark); +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 */ diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 86aefed6140..b1370c4015b 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -8,9 +8,6 @@ #include <linux/ip_vs.h> /* definitions shared with userland */ -/* old ipvsadm versions still include this file directly */ -#ifdef __KERNEL__ - #include <asm/types.h> /* for __uXX types */ #include <linux/sysctl.h> /* for ctl_path */ @@ -668,9 +665,7 @@ struct ip_vs_dest { struct dst_entry *dst_cache; /* destination cache entry */ u32 dst_rtos; /* RT_TOS(tos) for dst */ u32 dst_cookie; -#ifdef CONFIG_IP_VS_IPV6 - struct in6_addr dst_saddr; -#endif + union nf_inet_addr dst_saddr; /* for virtual service */ struct ip_vs_service *svc; /* service it belongs to */ @@ -802,7 +797,8 @@ struct netns_ipvs { 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]; @@ -840,8 +836,6 @@ struct netns_ipvs { int num_services; /* no of virtual services */ rwlock_t rs_lock; /* real services table */ - /* semaphore for IPVS sockopts. And, [gs]etsockopt may sleep. */ - struct lock_class_key ctl_key; /* ctl_mutex debuging */ /* Trash for destinations */ struct list_head dest_trash; /* Service counters */ @@ -1093,19 +1087,19 @@ ip_vs_control_add(struct ip_vs_conn *cp, struct ip_vs_conn *ctl_cp) /* * IPVS netns init & cleanup functions */ -extern int __ip_vs_estimator_init(struct net *net); -extern int __ip_vs_control_init(struct net *net); -extern int __ip_vs_protocol_init(struct net *net); -extern int __ip_vs_app_init(struct net *net); -extern int __ip_vs_conn_init(struct net *net); -extern int __ip_vs_sync_init(struct net *net); -extern void __ip_vs_conn_cleanup(struct net *net); -extern void __ip_vs_app_cleanup(struct net *net); -extern void __ip_vs_protocol_cleanup(struct net *net); -extern void __ip_vs_control_cleanup(struct net *net); -extern void __ip_vs_estimator_cleanup(struct net *net); -extern void __ip_vs_sync_cleanup(struct net *net); -extern void __ip_vs_service_cleanup(struct net *net); +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 @@ -1123,8 +1117,6 @@ 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); -extern int ip_vs_app_init(void); -extern void ip_vs_app_cleanup(void); 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); @@ -1227,15 +1219,11 @@ 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); -extern int ip_vs_sync_init(void); -extern void ip_vs_sync_cleanup(void); /* * IPVS rate estimator prototypes (from ip_vs_est.c) */ -extern int ip_vs_estimator_init(void); -extern void ip_vs_estimator_cleanup(void); 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); @@ -1256,7 +1244,8 @@ extern int ip_vs_tunnel_xmit 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); +(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 @@ -1270,7 +1259,7 @@ 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); + int offset, unsigned int hooknum); #endif #ifdef CONFIG_SYSCTL @@ -1432,6 +1421,4 @@ ip_vs_dest_conn_overhead(struct ip_vs_dest *dest) atomic_read(&dest->inactconns); } -#endif /* __KERNEL__ */ - #endif /* _NET_IP_VS_H */ diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 34200f9e680..3b5ac1fbff3 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -77,11 +77,9 @@ /* * Addr scopes */ -#ifdef __KERNEL__ #define IPV6_ADDR_MC_SCOPE(a) \ ((a)->s6_addr[1] & 0x0f) /* nonstandard */ #define __IPV6_ADDR_SCOPE_INVALID -1 -#endif #define IPV6_ADDR_SCOPE_NODELOCAL 0x01 #define IPV6_ADDR_SCOPE_LINKLOCAL 0x02 #define IPV6_ADDR_SCOPE_SITELOCAL 0x05 @@ -91,14 +89,12 @@ /* * Addr flags */ -#ifdef __KERNEL__ #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) -#endif /* * fragmentation header @@ -113,8 +109,6 @@ struct frag_hdr { #define IP6_MF 0x0001 -#ifdef __KERNEL__ - #include <net/sock.h> /* sysctls */ @@ -129,6 +123,15 @@ extern struct ctl_path net_ipv6_ctl_path[]; 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));\ +}) + #define _DEVADD(net, statname, modifier, idev, field, val) \ ({ \ struct inet6_dev *_idev = (idev); \ @@ -160,16 +163,16 @@ extern struct ctl_path net_ipv6_ctl_path[]; #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) \ - _DEVINC(net, icmpv6, , idev, field) + _DEVINCATOMIC(net, icmpv6, , idev, field) #define ICMP6_INC_STATS_BH(net, idev, field) \ - _DEVINC(net, icmpv6, _BH, idev, field) + _DEVINCATOMIC(net, icmpv6, _BH, idev, field) #define ICMP6MSGOUT_INC_STATS(net, idev, field) \ - _DEVINC(net, icmpv6msg, , idev, field +256) + _DEVINCATOMIC(net, icmpv6msg, , idev, field +256) #define ICMP6MSGOUT_INC_STATS_BH(net, idev, field) \ - _DEVINC(net, icmpv6msg, _BH, idev, field +256) + _DEVINCATOMIC(net, icmpv6msg, _BH, idev, field +256) #define ICMP6MSGIN_INC_STATS_BH(net, idev, field) \ - _DEVINC(net, icmpv6msg, _BH, idev, field) + _DEVINCATOMIC(net, icmpv6msg, _BH, idev, field) struct ip6_ra_chain { struct ip6_ra_chain *next; @@ -376,8 +379,8 @@ enum ip6_defrag_users { struct ip6_create_arg { __be32 id; u32 user; - struct in6_addr *src; - struct in6_addr *dst; + const struct in6_addr *src; + const struct in6_addr *dst; }; void ip6_frag_init(struct inet_frag_queue *q, void *a); @@ -460,17 +463,7 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr)); } -static __inline__ void ipv6_select_ident(struct frag_hdr *fhdr) -{ - static u32 ipv6_fragmentation_id = 1; - static DEFINE_SPINLOCK(ip6_id_lock); - - spin_lock_bh(&ip6_id_lock); - fhdr->identification = htonl(ipv6_fragmentation_id); - if (++ipv6_fragmentation_id == 0) - ipv6_fragmentation_id = 1; - spin_unlock_bh(&ip6_id_lock); -} +extern void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt); /* * Prototypes exported by ipv6 @@ -667,5 +660,4 @@ extern int ipv6_static_sysctl_register(void); extern void ipv6_static_sysctl_unregister(void); #endif -#endif /* __KERNEL__ */ #endif /* _NET_IPV6_H */ diff --git a/include/net/ipx.h b/include/net/ipx.h index 05d7e4a88b4..c1fec6b464c 100644 --- a/include/net/ipx.h +++ b/include/net/ipx.h @@ -80,7 +80,6 @@ struct ipx_route { atomic_t refcnt; }; -#ifdef __KERNEL__ struct ipx_cb { u8 ipx_tctrl; __be32 ipx_dest_net; @@ -116,7 +115,6 @@ static inline struct ipx_sock *ipx_sk(struct sock *sk) } #define IPX_SKB_CB(__skb) ((struct ipx_cb *)&((__skb)->cb[0])) -#endif #define IPX_MIN_EPHEMERAL_SOCKET 0x4000 #define IPX_MAX_EPHEMERAL_SOCKET 0x7fff diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 025d4cc7bbf..ea2c8c36477 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -20,6 +20,7 @@ #include <linux/device.h> #include <linux/ieee80211.h> #include <net/cfg80211.h> +#include <asm/unaligned.h> /** * DOC: Introduction @@ -193,6 +194,17 @@ enum ieee80211_bss_change { #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 @@ -537,6 +549,21 @@ struct ieee80211_tx_info { }; }; +/** + * 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; @@ -918,6 +945,7 @@ enum set_key_cmd { * @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. */ @@ -926,6 +954,7 @@ struct ieee80211_sta { u8 addr[ETH_ALEN]; u16 aid; struct ieee80211_sta_ht_cap ht_cap; + bool wme; /* must be last */ u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); @@ -945,21 +974,6 @@ enum sta_notify_cmd { }; /** - * enum ieee80211_tkip_key_type - get tkip key - * - * Used by drivers which need to get a tkip key for skb. Some drivers need a - * phase 1 key, others need a phase 2 key. A single function allows the driver - * to get the key, this enum indicates what type of key is required. - * - * @IEEE80211_TKIP_P1_KEY: the driver needs a phase 1 key - * @IEEE80211_TKIP_P2_KEY: the driver needs a phase 2 key - */ -enum ieee80211_tkip_key_type { - IEEE80211_TKIP_P1_KEY, - IEEE80211_TKIP_P2_KEY, -}; - -/** * enum ieee80211_hw_flags - hardware flags * * These flags are used to indicate hardware capabilities to @@ -1606,6 +1620,22 @@ enum ieee80211_ampdu_mlme_action { * 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. @@ -1667,6 +1697,12 @@ enum ieee80211_ampdu_mlme_action { * 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 @@ -1681,6 +1717,21 @@ enum ieee80211_ampdu_mlme_action { * 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. @@ -1782,6 +1833,7 @@ enum ieee80211_ampdu_mlme_action { * * @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 @@ -1819,11 +1871,24 @@ enum ieee80211_ampdu_mlme_action { * @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. */ struct ieee80211_ops { void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); 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, @@ -1852,8 +1917,19 @@ struct ieee80211_ops { 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, @@ -1885,6 +1961,9 @@ struct ieee80211_ops { 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, @@ -1906,6 +1985,11 @@ struct ieee80211_ops { 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); }; /** @@ -2223,6 +2307,19 @@ static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta, #define IEEE80211_TX_STATUS_HEADROOM 13 /** + * ieee80211_sta_set_tim - set the TIM bit for a sleeping station + * @sta: &struct ieee80211_sta pointer for the sleeping station + * + * If a driver buffers frames for a powersave station instead of passing + * them back to mac80211 for retransmission, the station needs to be told + * to wake up using the TIM bitmap in the beacon. + * + * This function sets the station's TIM bit - it will be cleared when the + * station wakes up. + */ +void ieee80211_sta_set_tim(struct ieee80211_sta *sta); + +/** * ieee80211_tx_status - transmit status callback * * Call this function for all transmitted frames after they have been @@ -2276,6 +2373,17 @@ 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. @@ -2472,21 +2580,122 @@ struct sk_buff * ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_vif *vif); /** - * ieee80211_get_tkip_key - get a TKIP rc4 for skb + * ieee80211_get_tkip_p1k_iv - get a TKIP phase 1 key for IV32 * - * This function computes a TKIP rc4 key for an skb. It computes - * a phase 1 key if needed (iv16 wraps around). This function is to - * be used by drivers which can do HW encryption but need to compute - * to phase 1/2 key in SW. + * This function returns the TKIP phase 1 key for the given IV32. * * @keyconf: the parameter passed with the set key - * @skb: the skb for which the key is needed - * @type: TBD - * @key: a buffer to which the key will be written + * @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_key(struct ieee80211_key_conf *keyconf, - struct sk_buff *skb, - enum ieee80211_tkip_key_type type, u8 *key); +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_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(). @@ -2545,6 +2754,28 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw); 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 @@ -2730,6 +2961,29 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, bool block); /** + * 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. + */ +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. @@ -2770,6 +3024,29 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif); 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. @@ -2816,6 +3093,16 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, 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 @@ -2865,6 +3152,23 @@ void ieee80211_ready_on_channel(struct ieee80211_hw *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); + /* Rate control API */ /** @@ -3050,4 +3354,9 @@ 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); #endif /* MAC80211_H */ diff --git a/include/net/ndisc.h b/include/net/ndisc.h index e0e594f8e9d..62beeb97c4b 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h @@ -42,8 +42,6 @@ enum { #define ND_REACHABLE_TIME (30*HZ) #define ND_RETRANS_TIMER HZ -#ifdef __KERNEL__ - #include <linux/compiler.h> #include <linux/icmpv6.h> #include <linux/in6.h> @@ -102,7 +100,8 @@ extern void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, const struct in6_addr *target); -extern int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir); +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, @@ -155,8 +154,4 @@ static inline struct neighbour * ndisc_get_neigh(struct net_device *dev, const s return ERR_PTR(-ENODEV); } - -#endif /* __KERNEL__ */ - - #endif diff --git a/include/net/neighbour.h b/include/net/neighbour.h index 4014b623880..4ba8521490b 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h @@ -108,8 +108,8 @@ struct neighbour { __u8 dead; seqlock_t ha_lock; unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))]; - struct hh_cache *hh; - int (*output)(struct sk_buff *skb); + struct hh_cache hh; + int (*output)(struct neighbour *, struct sk_buff *); const struct neigh_ops *ops; struct rcu_head rcu; struct net_device *dev; @@ -118,12 +118,10 @@ struct neighbour { struct neigh_ops { int family; - void (*solicit)(struct neighbour *, struct sk_buff*); - void (*error_report)(struct neighbour *, struct sk_buff*); - int (*output)(struct sk_buff*); - int (*connected_output)(struct sk_buff*); - int (*hh_output)(struct sk_buff*); - int (*queue_xmit)(struct sk_buff*); + 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 { @@ -142,7 +140,7 @@ struct pneigh_entry { struct neigh_hash_table { struct neighbour __rcu **hash_buckets; - unsigned int hash_mask; + unsigned int hash_shift; __u32 hash_rnd; struct rcu_head rcu; }; @@ -205,9 +203,10 @@ 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 sk_buff *skb); -extern int neigh_connected_output(struct sk_buff *skb); -extern int neigh_compat_output(struct sk_buff *skb); +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); @@ -341,7 +340,16 @@ static inline int neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb) } while (read_seqretry(&hh->hh_lock, seq)); skb_push(skb, hh_len); - return hh->hh_output(skb); + 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 * diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 3ae491932bc..1ab1aec209a 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -7,6 +7,7 @@ #include <asm/atomic.h> #include <linux/workqueue.h> #include <linux/list.h> +#include <linux/sysctl.h> #include <net/netns/core.h> #include <net/netns/mib.h> @@ -34,8 +35,11 @@ struct netns_ipvs; #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 freed. + * namespace should be shut down. */ #ifdef NETNS_REFCNT_DEBUG atomic_t use_count; /* To track references we @@ -61,6 +65,7 @@ struct net { 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; @@ -119,6 +124,7 @@ static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns) 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); @@ -152,6 +158,9 @@ 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) @@ -173,6 +182,8 @@ int net_eq(const struct net *net1, const struct net *net2) { return 1; } + +#define net_drop_ns NULL #endif diff --git a/include/net/net_ratelimit.h b/include/net/net_ratelimit.h new file mode 100644 index 00000000000..7727b4247da --- /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/netevent.h b/include/net/netevent.h index 22b239c17ea..086f8a5b59d 100644 --- a/include/net/netevent.h +++ b/include/net/netevent.h @@ -10,7 +10,6 @@ * * Changes: */ -#ifdef __KERNEL__ struct dst_entry; @@ -29,4 +28,3 @@ extern int unregister_netevent_notifier(struct notifier_block *nb); extern int call_netevent_notifiers(unsigned long val, void *v); #endif -#endif diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index d0d13378991..5d4f8e586e3 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -14,7 +14,6 @@ #include <linux/netfilter/nf_conntrack_common.h> -#ifdef __KERNEL__ #include <linux/bitops.h> #include <linux/compiler.h> #include <asm/atomic.h> @@ -308,6 +307,12 @@ 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; +} + 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; @@ -326,5 +331,4 @@ do { \ #define MODULE_ALIAS_NFCT_HELPER(helper) \ MODULE_ALIAS("nfct-helper-" helper) -#endif /* __KERNEL__ */ #endif /* _NF_CONNTRACK_H */ diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h index 4ee44c84a30..7ca6bdd5bae 100644 --- a/include/net/netfilter/nf_conntrack_tuple.h +++ b/include/net/netfilter/nf_conntrack_tuple.h @@ -104,8 +104,6 @@ struct nf_conntrack_tuple_mask { } src; }; -#ifdef __KERNEL__ - static inline void nf_ct_dump_tuple_ip(const struct nf_conntrack_tuple *t) { #ifdef DEBUG @@ -148,8 +146,6 @@ struct nf_conntrack_tuple_hash { struct nf_conntrack_tuple tuple; }; -#endif /* __KERNEL__ */ - static inline bool __nf_ct_tuple_src_equal(const struct nf_conntrack_tuple *t1, const struct nf_conntrack_tuple *t2) { diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index aff80b190c1..0346b007086 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h @@ -48,7 +48,6 @@ struct nf_nat_multi_range_compat { struct nf_nat_range range[1]; }; -#ifdef __KERNEL__ #include <linux/list.h> #include <linux/netfilter/nf_conntrack_pptp.h> #include <net/netfilter/nf_conntrack_extend.h> @@ -93,7 +92,4 @@ static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct) #endif } -#else /* !__KERNEL__: iptables wants this to compile. */ -#define nf_nat_multi_range nf_nat_multi_range_compat -#endif /*__KERNEL__*/ #endif diff --git a/include/net/netlink.h b/include/net/netlink.h index 8a3906a08f5..98c185441be 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -290,7 +290,7 @@ static inline int nlmsg_padlen(int payload) /** * nlmsg_data - head of message payload - * @nlh: netlink messsage header + * @nlh: netlink message header */ static inline void *nlmsg_data(const struct nlmsghdr *nlh) { @@ -638,6 +638,30 @@ static inline int nlmsg_unicast(struct sock *sk, struct sk_buff *skb, u32 pid) 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 **************************************************************************/ diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 542195d9469..d786b4fc02a 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -54,6 +54,8 @@ struct netns_ipv4 { int sysctl_rt_cache_rebuild_count; int current_rt_cache_rebuild_count; + unsigned int sysctl_ping_group_range[2]; + atomic_t rt_genid; atomic_t dev_addr_genid; diff --git a/include/net/nfc.h b/include/net/nfc.h new file mode 100644 index 00000000000..cc0130312f7 --- /dev/null +++ b/include/net/nfc.h @@ -0,0 +1,156 @@ +/* + * 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/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 (*start_poll)(struct nfc_dev *dev, u32 protocols); + void (*stop_poll)(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); +}; + +struct nfc_target { + u32 idx; + u32 supported_protocols; + u16 sens_res; + u8 sel_res; +}; + +struct nfc_genl_data { + u32 poll_req_pid; + struct mutex genl_data_mutex; +}; + +struct nfc_dev { + unsigned idx; + unsigned target_idx; + struct nfc_target *targets; + int n_targets; + int targets_generation; + spinlock_t targets_lock; + struct device dev; + bool polling; + struct nfc_genl_data genl_data; + u32 supported_protocols; + + 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); + +/** + * 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_skb(unsigned int size, gfp_t gfp); + +int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets, + int ntargets); + +#endif /* __NET_NFC_H */ diff --git a/include/net/phonet/pn_dev.h b/include/net/phonet/pn_dev.h index 13649eb5741..8639de5750f 100644 --- a/include/net/phonet/pn_dev.h +++ b/include/net/phonet/pn_dev.h @@ -51,7 +51,7 @@ 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(struct net *net, u8 daddr); +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 diff --git a/include/net/ping.h b/include/net/ping.h new file mode 100644 index 00000000000..682b5ae9af5 --- /dev/null +++ b/include/net/ping.h @@ -0,0 +1,55 @@ +/* + * 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/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) + +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 void ping_rcv(struct sk_buff *); +extern void ping_err(struct sk_buff *, u32 info); + +#ifdef CONFIG_PROC_FS +extern int __init ping_proc_init(void); +extern void ping_proc_exit(void); +#endif + +void __init ping_init(void); + + +#endif /* _PING_H */ diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index 65afc496620..fffdc603f4c 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -99,9 +99,9 @@ static inline void qdisc_run(struct Qdisc *q) __qdisc_run(q); } -extern int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp, +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, struct tcf_proto *tp, +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 diff --git a/include/net/rawv6.h b/include/net/rawv6.h index f6b9b830df8..cf757723445 100644 --- a/include/net/rawv6.h +++ b/include/net/rawv6.h @@ -1,8 +1,6 @@ #ifndef _NET_RAWV6_H #define _NET_RAWV6_H -#ifdef __KERNEL__ - #include <net/protocol.h> void raw6_icmp_error(struct sk_buff *, int nexthdr, @@ -20,5 +18,3 @@ int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock, #endif #endif - -#endif diff --git a/include/net/route.h b/include/net/route.h index 8fce0621cad..db7b3432f07 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -35,16 +35,8 @@ #include <linux/cache.h> #include <linux/security.h> -#ifndef __KERNEL__ -#warning This file is not supposed to be used outside of kernel. -#endif - #define RTO_ONLINK 0x01 -#define RTO_CONN 0 -/* RTO_CONN is not used (being alias for 0), but preserved not to break - * some modules referring to it. */ - #define RT_CONN_FLAGS(sk) (RT_TOS(inet_sk(sk)->tos) | sock_flag(sk, SOCK_LOCALROUTE)) struct fib_nh; @@ -60,7 +52,7 @@ struct rtable { int rt_genid; unsigned rt_flags; __u16 rt_type; - __u8 rt_tos; + __u8 rt_key_tos; __be32 rt_dst; /* Path destination */ __be32 rt_src; /* Path source */ @@ -123,7 +115,7 @@ 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 *, const struct flowi4 *flp); +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); @@ -145,40 +137,33 @@ static inline struct rtable *ip_route_output(struct net *net, __be32 daddr, return ip_route_output_key(net, &fl4); } -static inline struct rtable *ip_route_output_ports(struct net *net, struct sock *sk, +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) { - struct flowi4 fl4 = { - .flowi4_oif = oif, - .flowi4_flags = sk ? inet_sk_flowi_flags(sk) : 0, - .flowi4_mark = sk ? sk->sk_mark : 0, - .daddr = daddr, - .saddr = saddr, - .flowi4_tos = tos, - .flowi4_proto = proto, - .fl4_dport = dport, - .fl4_sport = sport, - }; + 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); + 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, +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) { - struct flowi4 fl4 = { - .flowi4_oif = oif, - .daddr = daddr, - .saddr = saddr, - .flowi4_tos = tos, - .flowi4_proto = IPPROTO_GRE, - .fl4_gre_key = gre_key, - }; - return ip_route_output_key(net, &fl4); + 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, @@ -196,14 +181,15 @@ static inline int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 s return ip_route_input_common(skb, dst, src, tos, devin, true); } -extern unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph, unsigned short new_mtu, struct net_device *dev); +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 rtable *rt); +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; @@ -225,78 +211,93 @@ static inline char rt_tos2priority(u8 tos) return ip_tos2prio[IPTOS_TOS(tos)>>1]; } -static inline struct rtable *ip_route_connect(__be32 dst, __be32 src, u32 tos, +/* 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 flowi4 fl4 = { - .flowi4_oif = oif, - .flowi4_mark = sk->sk_mark, - .daddr = dst, - .saddr = src, - .flowi4_tos = tos, - .flowi4_proto = protocol, - .fl4_sport = sport, - .fl4_dport = dport, - }; struct net *net = sock_net(sk); struct rtable *rt; - if (inet_sk(sk)->transparent) - fl4.flowi4_flags |= FLOWI_FLAG_ANYSRC; - if (protocol == IPPROTO_TCP) - fl4.flowi4_flags |= FLOWI_FLAG_PRECOW_METRICS; - if (can_sleep) - fl4.flowi4_flags |= FLOWI_FLAG_CAN_SLEEP; + 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); + rt = __ip_route_output_key(net, fl4); if (IS_ERR(rt)) return rt; - fl4.daddr = rt->rt_dst; - fl4.saddr = rt->rt_src; ip_rt_put(rt); } - security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); - return ip_route_output_flow(net, &fl4, sk); + 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 rtable *rt, - u8 protocol, __be16 orig_sport, - __be16 orig_dport, __be16 sport, - __be16 dport, struct sock *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) { - struct flowi4 fl4 = { - .flowi4_oif = rt->rt_oif, - .flowi4_mark = rt->rt_mark, - .daddr = rt->rt_dst, - .saddr = rt->rt_src, - .flowi4_tos = rt->rt_tos, - .flowi4_proto = protocol, - .fl4_sport = sport, - .fl4_dport = dport - }; - if (inet_sk(sk)->transparent) - fl4.flowi4_flags |= FLOWI_FLAG_ANYSRC; - if (protocol == IPPROTO_TCP) - fl4.flowi4_flags |= FLOWI_FLAG_PRECOW_METRICS; + fl4->fl4_dport = dport; + fl4->fl4_sport = sport; ip_rt_put(rt); - security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); - return ip_route_output_flow(sock_net(sk), &fl4, sk); + 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, int create); +extern void rt_bind_peer(struct rtable *rt, __be32 daddr, int create); -static inline struct inet_peer *rt_get_peer(struct rtable *rt) +static inline struct inet_peer *rt_get_peer(struct rtable *rt, __be32 daddr) { if (rt->peer) return rt->peer; - rt_bind_peer(rt, 0); + rt_bind_peer(rt, daddr, 0); return rt->peer; } diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index 4093ca78cf6..678f1ffaf84 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h @@ -6,11 +6,14 @@ 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 *); extern int __rtnl_register(int protocol, int msgtype, - rtnl_doit_func, rtnl_dumpit_func); + rtnl_doit_func, rtnl_dumpit_func, + rtnl_calcit_func); extern void rtnl_register(int protocol, int msgtype, - rtnl_doit_func, rtnl_dumpit_func); + rtnl_doit_func, rtnl_dumpit_func, + rtnl_calcit_func); extern int rtnl_unregister(int protocol, int msgtype); extern void rtnl_unregister_all(int protocol); diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index b931f021d7a..4fc88f3ccd5 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -181,8 +181,9 @@ struct tcf_proto_ops { struct tcf_proto_ops *next; char kind[IFNAMSIZ]; - int (*classify)(struct sk_buff*, struct tcf_proto*, - struct tcf_result *); + int (*classify)(struct sk_buff *, + const struct tcf_proto *, + struct tcf_result *); int (*init)(struct tcf_proto*); void (*destroy)(struct tcf_proto*); @@ -205,8 +206,9 @@ struct tcf_proto { /* Fast access part */ struct tcf_proto *next; void *root; - int (*classify)(struct sk_buff*, struct tcf_proto*, - struct tcf_result *); + int (*classify)(struct sk_buff *, + const struct tcf_proto *, + struct tcf_result *); __be16 protocol; /* All the rest */ @@ -214,7 +216,7 @@ struct tcf_proto { u32 classid; struct Qdisc *q; void *data; - struct tcf_proto_ops *ops; + const struct tcf_proto_ops *ops; }; struct qdisc_skb_cb { diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h index c01dc99def0..6506458ccd3 100644 --- a/include/net/sctp/command.h +++ b/include/net/sctp/command.h @@ -63,6 +63,7 @@ typedef enum { 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. */ @@ -73,7 +74,6 @@ typedef enum { 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_TRANSMIT, /* Transmit the outqueue. */ 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. */ @@ -108,6 +108,7 @@ typedef enum { 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_LAST } sctp_verb_t; diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h index c70d8ccc55c..942b864f613 100644 --- a/include/net/sctp/constants.h +++ b/include/net/sctp/constants.h @@ -150,7 +150,6 @@ SCTP_SUBTYPE_CONSTRUCTOR(OTHER, sctp_event_other_t, other) SCTP_SUBTYPE_CONSTRUCTOR(PRIMITIVE, sctp_event_primitive_t, primitive) -#define sctp_chunk_is_control(a) (a->chunk_hdr->type != SCTP_CID_DATA) #define sctp_chunk_is_data(a) (a->chunk_hdr->type == SCTP_CID_DATA) /* Calculate the actual data size in a data chunk */ @@ -188,15 +187,14 @@ typedef enum { /* SCTP state defines for internal state machine */ typedef enum { - SCTP_STATE_EMPTY = 0, - SCTP_STATE_CLOSED = 1, - SCTP_STATE_COOKIE_WAIT = 2, - SCTP_STATE_COOKIE_ECHOED = 3, - SCTP_STATE_ESTABLISHED = 4, - SCTP_STATE_SHUTDOWN_PENDING = 5, - SCTP_STATE_SHUTDOWN_SENT = 6, - SCTP_STATE_SHUTDOWN_RECEIVED = 7, - SCTP_STATE_SHUTDOWN_ACK_SENT = 8, + 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; diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 01e094c6d0a..6a72a58cde5 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -120,6 +120,7 @@ extern int sctp_copy_local_addr_list(struct sctp_bind_addr *, 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 @@ -134,6 +135,7 @@ 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 @@ -285,20 +287,21 @@ do { \ pr_cont(fmt, ##args); \ } while (0) #define SCTP_DEBUG_PRINTK_IPADDR(fmt_lead, fmt_trail, \ - args_lead, saddr, args_trail...) \ + args_lead, addr, args_trail...) \ do { \ + const union sctp_addr *_addr = (addr); \ if (sctp_debug_flag) { \ - if (saddr->sa.sa_family == AF_INET6) { \ + if (_addr->sa.sa_family == AF_INET6) { \ printk(KERN_DEBUG \ pr_fmt(fmt_lead "%pI6" fmt_trail), \ args_lead, \ - &saddr->v6.sin6_addr, \ + &_addr->v6.sin6_addr, \ args_trail); \ } else { \ printk(KERN_DEBUG \ pr_fmt(fmt_lead "%pI4" fmt_trail), \ args_lead, \ - &saddr->v4.sin_addr.s_addr, \ + &_addr->v4.sin_addr.s_addr, \ args_trail); \ } \ } \ @@ -530,7 +533,6 @@ _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 - sizeof(sctp_paramhdr_t) &&\ 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))) @@ -541,7 +543,6 @@ _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 - sizeof(sctp_errhdr_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)))) @@ -600,7 +601,7 @@ static inline int ipver2af(__u8 ipver) return AF_INET6; default: return 0; - }; + } } /* Convert from an address parameter type to an address family. */ @@ -613,7 +614,7 @@ static inline int param_type2af(__be16 type) return AF_INET6; default: return 0; - }; + } } /* Perform some sanity checks. */ diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 9352d12f02d..9148632b820 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -165,6 +165,7 @@ 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; @@ -232,9 +233,7 @@ 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 *, - const void *payload, - const size_t paylen); + const struct sctp_transport *); struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *, const struct sctp_chunk *, const void *payload, diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 0f6e60a9c30..31d7ea2e1d2 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -205,6 +205,11 @@ extern struct sctp_globals { * 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; @@ -264,6 +269,11 @@ extern struct sctp_globals { #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) @@ -341,6 +351,8 @@ struct sctp_sock { 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) @@ -564,19 +576,15 @@ struct sctp_af { int optname, char __user *optval, int __user *optlen); - struct dst_entry *(*get_dst) (struct sctp_association *asoc, - union sctp_addr *daddr, - union sctp_addr *saddr); + 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_association *asoc, - struct dst_entry *dst, - union sctp_addr *daddr, - union sctp_addr *saddr); + struct sctp_transport *t, + struct flowi *fl); void (*copy_addrlist) (struct list_head *, struct net_device *); - void (*dst_saddr) (union sctp_addr *saddr, - struct dst_entry *dst, - __be16 port); int (*cmp_addr) (const union sctp_addr *addr1, const union sctp_addr *addr2); void (*addr_copy) (union sctp_addr *dst, @@ -796,6 +804,8 @@ struct sctp_sockaddr_entry { __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 @@ -898,6 +908,7 @@ struct sctp_transport { /* Is this structure kfree()able? */ malloced:1; + struct flowi fl; /* This is the peer's IP address and port. */ union sctp_addr ipaddr; @@ -1061,7 +1072,7 @@ 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 *); +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 *); @@ -1239,6 +1250,7 @@ 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? */ @@ -1400,7 +1412,7 @@ int sctp_has_association(const union sctp_addr *laddr, 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 *, sctp_cid_t cid, +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 *); @@ -1901,6 +1913,8 @@ struct sctp_association { * after reaching 4294967295. */ __u32 addip_serial; + union sctp_addr *asconf_addr_del_pending; + int src_out_of_asoc_ok; /* SCTP AUTH: list of the endpoint shared keys. These * keys are provided out of band by the user applicaton @@ -1996,7 +2010,7 @@ 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); diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h index 7ea12e8e667..ca4693b4e09 100644 --- a/include/net/sctp/ulpevent.h +++ b/include/net/sctp/ulpevent.h @@ -80,7 +80,7 @@ static inline struct sctp_ulpevent *sctp_skb2event(struct sk_buff *skb) void sctp_ulpevent_free(struct sctp_ulpevent *); int sctp_ulpevent_is_notification(const struct sctp_ulpevent *); -void sctp_queue_purge_ulpevents(struct sk_buff_head *list); +unsigned int sctp_queue_purge_ulpevents(struct sk_buff_head *list); struct sctp_ulpevent *sctp_ulpevent_make_assoc_change( const struct sctp_association *asoc, @@ -132,6 +132,9 @@ 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); diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index e73ebdae323..0842ef00b2f 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h @@ -91,6 +91,8 @@ typedef __s32 sctp_assoc_t; #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. @@ -353,6 +355,20 @@ struct sctp_authkey_event { 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 @@ -368,6 +384,7 @@ struct sctp_event_subscribe { __u8 sctp_partial_delivery_event; __u8 sctp_adaptation_layer_event; __u8 sctp_authentication_event; + __u8 sctp_sender_dry_event; }; /* @@ -391,6 +408,7 @@ union sctp_notification { 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 @@ -407,7 +425,9 @@ enum sctp_sn_type { SCTP_SHUTDOWN_EVENT, SCTP_PARTIAL_DELIVERY_EVENT, SCTP_ADAPTATION_INDICATION, - SCTP_AUTHENTICATION_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 @@ -669,6 +689,18 @@ struct sctp_authchunks { }; /* + * 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 diff --git a/include/net/snmp.h b/include/net/snmp.h index 27461d6dd46..8f0f9ac0307 100644 --- a/include/net/snmp.h +++ b/include/net/snmp.h @@ -72,14 +72,24 @@ struct icmpmsg_mib { /* 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 { unsigned long mibs[ICMP6MSG_MIB_MAX]; }; +/* per device counters, (shared on all cpus) */ +struct icmpv6msg_mib_device { + atomic_long_t mibs[ICMP6MSG_MIB_MAX]; +}; /* TCP */ @@ -106,53 +116,51 @@ struct linux_xfrm_mib { unsigned long mibs[LINUX_MIB_XFRMMAX]; }; -/* - * FIXME: On x86 and some other CPUs the split into user and softirq parts - * is not needed because addl $1,memory is atomic against interrupts (but - * atomic_inc would be overkill because of the lock cycles). Wants new - * nonlocked_atomic_inc() primitives -AK - */ +#define SNMP_ARRAY_SZ 1 + #define DEFINE_SNMP_STAT(type, name) \ - __typeof__(type) __percpu *name[2] + __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[2] - -#define SNMP_STAT_BHPTR(name) (name[0]) -#define SNMP_STAT_USRPTR(name) (name[1]) + 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[1]->mibs[field]) + irqsafe_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[!in_softirq()]->mibs[field]) + irqsafe_cpu_inc(mib[0]->mibs[field]) + #define SNMP_DEC_STATS(mib, field) \ - this_cpu_dec(mib[!in_softirq()]->mibs[field]) + irqsafe_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[1]->mibs[field], addend) + irqsafe_cpu_add(mib[0]->mibs[field], addend) + #define SNMP_ADD_STATS(mib, field, addend) \ - this_cpu_add(mib[!in_softirq()]->mibs[field], addend) + irqsafe_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 { \ - __typeof__(*mib[0]) *ptr; \ - preempt_disable(); \ - ptr = this_cpu_ptr((mib)[!in_softirq()]); \ - ptr->mibs[basefield##PKTS]++; \ - ptr->mibs[basefield##OCTETS] += addend;\ - preempt_enable(); \ + irqsafe_cpu_inc(mib[0]->mibs[basefield##PKTS]); \ + irqsafe_cpu_add(mib[0]->mibs[basefield##OCTETS], addend); \ } while (0) #define SNMP_UPD_PO_STATS_BH(mib, basefield, addend) \ do { \ - __typeof__(*mib[0]) *ptr = \ - __this_cpu_ptr((mib)[0]); \ - ptr->mibs[basefield##PKTS]++; \ - ptr->mibs[basefield##OCTETS] += addend;\ + __this_cpu_inc(mib[0]->mibs[basefield##PKTS]); \ + __this_cpu_add(mib[0]->mibs[basefield##OCTETS], addend); \ } while (0) @@ -165,40 +173,20 @@ struct linux_xfrm_mib { ptr->mibs[field] += addend; \ u64_stats_update_end(&ptr->syncp); \ } while (0) + #define SNMP_ADD_STATS64_USER(mib, field, addend) \ do { \ - __typeof__(*mib[0]) *ptr; \ - preempt_disable(); \ - ptr = __this_cpu_ptr((mib)[1]); \ - u64_stats_update_begin(&ptr->syncp); \ - ptr->mibs[field] += addend; \ - u64_stats_update_end(&ptr->syncp); \ - preempt_enable(); \ + local_bh_disable(); \ + SNMP_ADD_STATS64_BH(mib, field, addend); \ + local_bh_enable(); \ } while (0) + #define SNMP_ADD_STATS64(mib, field, addend) \ - do { \ - __typeof__(*mib[0]) *ptr; \ - preempt_disable(); \ - ptr = __this_cpu_ptr((mib)[!in_softirq()]); \ - u64_stats_update_begin(&ptr->syncp); \ - ptr->mibs[field] += addend; \ - u64_stats_update_end(&ptr->syncp); \ - preempt_enable(); \ - } while (0) + 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(mib, basefield, addend) \ - do { \ - __typeof__(*mib[0]) *ptr; \ - preempt_disable(); \ - ptr = __this_cpu_ptr((mib)[!in_softirq()]); \ - u64_stats_update_begin(&ptr->syncp); \ - ptr->mibs[basefield##PKTS]++; \ - ptr->mibs[basefield##OCTETS] += addend; \ - u64_stats_update_end(&ptr->syncp); \ - preempt_enable(); \ - } while (0) #define SNMP_UPD_PO_STATS64_BH(mib, basefield, addend) \ do { \ __typeof__(*mib[0]) *ptr; \ @@ -208,6 +196,12 @@ struct linux_xfrm_mib { 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) diff --git a/include/net/sock.h b/include/net/sock.h index 01810a3f19d..396f735e0cd 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -40,6 +40,7 @@ #ifndef _SOCK_H #define _SOCK_H +#include <linux/hardirq.h> #include <linux/kernel.h> #include <linux/list.h> #include <linux/list_nulls.h> @@ -52,6 +53,7 @@ #include <linux/mm.h> #include <linux/security.h> #include <linux/slab.h> +#include <linux/uaccess.h> #include <linux/filter.h> #include <linux/rculist_nulls.h> @@ -177,7 +179,6 @@ struct sock_common { * @sk_dst_cache: destination cache * @sk_dst_lock: destination cache lock * @sk_policy: flow policy - * @sk_rmem_alloc: receive queue bytes committed * @sk_receive_queue: incoming packets * @sk_wmem_alloc: transmit queue bytes committed * @sk_write_queue: Packet sending queue @@ -562,6 +563,7 @@ enum sock_flags { SOCK_TIMESTAMPING_SYS_HARDWARE, /* %SOF_TIMESTAMPING_SYS_HARDWARE */ SOCK_FASYNC, /* fasync() active */ SOCK_RXQ_OVFL, + SOCK_ZEROCOPY, /* buffers from userspace */ }; static inline void sock_copy_flags(struct sock *nsk, struct sock *osk) @@ -1389,6 +1391,59 @@ static inline void sk_nocaps_add(struct sock *sk, int 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) diff --git a/include/net/tcp.h b/include/net/tcp.h index cda30ea354a..149a415d1e0 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -122,7 +122,13 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); #endif #define TCP_RTO_MAX ((unsigned)(120*HZ)) #define TCP_RTO_MIN ((unsigned)(HZ/5)) -#define TCP_TIMEOUT_INIT ((unsigned)(3*HZ)) /* RFC 1122 initial RTO value */ +#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. @@ -295,7 +301,7 @@ static inline void tcp_synq_overflow(struct sock *sk) 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_INIT); + return time_after(jiffies, last_overflow + TCP_TIMEOUT_FALLBACK); } extern struct proto tcp_prot; @@ -508,6 +514,7 @@ extern void tcp_initialize_rcv_mss(struct sock *sk); extern int tcp_mtu_to_mss(struct sock *sk, int pmtu); extern int tcp_mss_to_mtu(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) { diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index a8122dc5641..5271a741c3a 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h @@ -7,8 +7,6 @@ * IPv6 transport protocols */ -#ifdef __KERNEL__ - extern struct proto rawv6_prot; extern struct proto udpv6_prot; extern struct proto udplitev6_prot; @@ -57,5 +55,3 @@ extern const struct inet_connection_sock_af_ops ipv4_specific; extern void inet6_destroy_sock(struct sock *sk); #endif - -#endif diff --git a/include/net/wimax.h b/include/net/wimax.h index c799ba7b708..322ff4fbdb4 100644 --- a/include/net/wimax.h +++ b/include/net/wimax.h @@ -250,7 +250,6 @@ #ifndef __NET__WIMAX_H__ #define __NET__WIMAX_H__ -#ifdef __KERNEL__ #include <linux/wimax.h> #include <net/genetlink.h> @@ -424,7 +423,6 @@ struct wimax_dev { int (*op_reset)(struct wimax_dev *wimax_dev); struct rfkill *rfkill; - struct input_dev *rfkill_input; unsigned rf_hw; unsigned rf_sw; char name[32]; @@ -518,8 +516,4 @@ extern ssize_t wimax_msg_len(struct sk_buff *); extern int wimax_rfkill(struct wimax_dev *, enum wimax_rf_state); extern int wimax_reset(struct wimax_dev *); -#else -/* You might be looking for linux/wimax.h */ -#error This file should not be included from user space. -#endif /* #ifdef __KERNEL__ */ #endif /* #ifndef __NET__WIMAX_H__ */ diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 20afeaa3939..b203e14d26b 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -958,6 +958,15 @@ struct sec_path { 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) { @@ -1468,7 +1477,7 @@ extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, 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, 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); @@ -1563,8 +1572,8 @@ static inline int xfrm_addr_cmp(const xfrm_address_t *a, case AF_INET: return (__force u32)a->a4 - (__force u32)b->a4; case AF_INET6: - return ipv6_addr_cmp((struct in6_addr *)a, - (struct in6_addr *)b); + return ipv6_addr_cmp((const struct in6_addr *)a, + (const struct in6_addr *)b); } } |