diff options
Diffstat (limited to 'net')
317 files changed, 7132 insertions, 3792 deletions
diff --git a/net/802/fc.c b/net/802/fc.c index b324e31..05eea6b 100644 --- a/net/802/fc.c +++ b/net/802/fc.c @@ -35,7 +35,7 @@ static int fc_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, - const void *daddr, const void *saddr, unsigned len) + const void *daddr, const void *saddr, unsigned int len) { struct fch_hdr *fch; int hdr_len; diff --git a/net/802/fddi.c b/net/802/fddi.c index 5ab25cd..9cda406 100644 --- a/net/802/fddi.c +++ b/net/802/fddi.c @@ -51,7 +51,7 @@ static int fddi_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, - const void *daddr, const void *saddr, unsigned len) + const void *daddr, const void *saddr, unsigned int len) { int hl = FDDI_K_SNAP_HLEN; struct fddihdr *fddi; diff --git a/net/802/garp.c b/net/802/garp.c index a5c2248..8456f5d 100644 --- a/net/802/garp.c +++ b/net/802/garp.c @@ -157,9 +157,9 @@ static struct garp_attr *garp_attr_lookup(const struct garp_applicant *app, while (parent) { attr = rb_entry(parent, struct garp_attr, node); d = garp_attr_cmp(attr, data, len, type); - if (d < 0) + if (d > 0) parent = parent->rb_left; - else if (d > 0) + else if (d < 0) parent = parent->rb_right; else return attr; @@ -178,9 +178,9 @@ static struct garp_attr *garp_attr_create(struct garp_applicant *app, parent = *p; attr = rb_entry(parent, struct garp_attr, node); d = garp_attr_cmp(attr, data, len, type); - if (d < 0) + if (d > 0) p = &parent->rb_left; - else if (d > 0) + else if (d < 0) p = &parent->rb_right; else { /* The attribute already exists; re-use it. */ diff --git a/net/802/hippi.c b/net/802/hippi.c index 056794e..51a1f53 100644 --- a/net/802/hippi.c +++ b/net/802/hippi.c @@ -45,7 +45,7 @@ static int hippi_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, - const void *daddr, const void *saddr, unsigned len) + const void *daddr, const void *saddr, unsigned int len) { struct hippi_hdr *hip = (struct hippi_hdr *)skb_push(skb, HIPPI_HLEN); struct hippi_cb *hcb = (struct hippi_cb *) skb->cb; diff --git a/net/802/tr.c b/net/802/tr.c index b9a3a14..e65f0b8 100644 --- a/net/802/tr.c +++ b/net/802/tr.c @@ -101,7 +101,7 @@ static inline unsigned long rif_hash(const unsigned char *addr) static int tr_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, - const void *daddr, const void *saddr, unsigned len) + const void *daddr, const void *saddr, unsigned int len) { struct trh_hdr *trh; int hdr_len; @@ -193,7 +193,7 @@ __be16 tr_type_trans(struct sk_buff *skb, struct net_device *dev) struct trh_hdr *trh; struct trllc *trllc; - unsigned riflen=0; + unsigned int riflen=0; skb->dev = dev; skb_reset_mac_header(skb); diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c index 5071136..708c80e 100644 --- a/net/8021q/vlan_netlink.c +++ b/net/8021q/vlan_netlink.c @@ -166,11 +166,13 @@ static int vlan_fill_info(struct sk_buff *skb, const struct net_device *dev) struct nlattr *nest; unsigned int i; - NLA_PUT_U16(skb, IFLA_VLAN_ID, vlan_dev_priv(dev)->vlan_id); + if (nla_put_u16(skb, IFLA_VLAN_ID, vlan_dev_priv(dev)->vlan_id)) + goto nla_put_failure; if (vlan->flags) { f.flags = vlan->flags; f.mask = ~0; - NLA_PUT(skb, IFLA_VLAN_FLAGS, sizeof(f), &f); + if (nla_put(skb, IFLA_VLAN_FLAGS, sizeof(f), &f)) + goto nla_put_failure; } if (vlan->nr_ingress_mappings) { nest = nla_nest_start(skb, IFLA_VLAN_INGRESS_QOS); @@ -183,8 +185,9 @@ static int vlan_fill_info(struct sk_buff *skb, const struct net_device *dev) m.from = i; m.to = vlan->ingress_priority_map[i]; - NLA_PUT(skb, IFLA_VLAN_QOS_MAPPING, - sizeof(m), &m); + if (nla_put(skb, IFLA_VLAN_QOS_MAPPING, + sizeof(m), &m)) + goto nla_put_failure; } nla_nest_end(skb, nest); } @@ -202,8 +205,9 @@ static int vlan_fill_info(struct sk_buff *skb, const struct net_device *dev) m.from = pm->priority; m.to = (pm->vlan_qos >> 13) & 0x7; - NLA_PUT(skb, IFLA_VLAN_QOS_MAPPING, - sizeof(m), &m); + if (nla_put(skb, IFLA_VLAN_QOS_MAPPING, + sizeof(m), &m)) + goto nla_put_failure; } } nla_nest_end(skb, nest); diff --git a/net/9p/client.c b/net/9p/client.c index b23a17c..a170893 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -1530,7 +1530,7 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", - fid->fid, (long long unsigned) offset, count); + fid->fid, (unsigned long long) offset, count); err = 0; clnt = fid->clnt; @@ -1605,7 +1605,7 @@ p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, struct p9_req_t *req; p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d\n", - fid->fid, (long long unsigned) offset, count); + fid->fid, (unsigned long long) offset, count); err = 0; clnt = fid->clnt; @@ -2040,7 +2040,7 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) char *dataptr; p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n", - fid->fid, (long long unsigned) offset, count); + fid->fid, (unsigned long long) offset, count); err = 0; clnt = fid->clnt; diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index fccae26..6449bae 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -513,7 +513,7 @@ error: clear_bit(Wworksched, &m->wsched); } -static int p9_pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key) +static int p9_pollwake(wait_queue_t *wait, unsigned int mode, int sync, void *key) { struct p9_poll_wait *pwait = container_of(wait, struct p9_poll_wait, wait); diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index bfa9ab9..0301b32 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -63,7 +63,7 @@ #include <net/tcp_states.h> #include <net/route.h> #include <linux/atalk.h> -#include "../core/kmap_skb.h" +#include <linux/highmem.h> struct datalink_proto *ddp_dl, *aarp_dl; static const struct proto_ops atalk_dgram_ops; @@ -960,10 +960,10 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset, if (copy > len) copy = len; - vaddr = kmap_skb_frag(frag); + vaddr = kmap_atomic(skb_frag_page(frag)); sum = atalk_sum_partial(vaddr + frag->page_offset + offset - start, copy, sum); - kunmap_skb_frag(vaddr); + kunmap_atomic(vaddr); if (!(len -= copy)) return sum; diff --git a/net/atm/br2684.c b/net/atm/br2684.c index 353fccf..4819d315 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -73,7 +73,7 @@ struct br2684_vcc { #ifdef CONFIG_ATM_BR2684_IPFILTER struct br2684_filter filter; #endif /* CONFIG_ATM_BR2684_IPFILTER */ - unsigned copies_needed, copies_failed; + unsigned int copies_needed, copies_failed; }; struct br2684_dev { diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c index 53e5002..5bdd300 100644 --- a/net/atm/mpoa_proc.c +++ b/net/atm/mpoa_proc.c @@ -207,7 +207,7 @@ static ssize_t proc_mpc_write(struct file *file, const char __user *buff, size_t nbytes, loff_t *ppos) { char *page, *p; - unsigned len; + unsigned int len; if (nbytes == 0) return 0; diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c index 614d3fc..ce1e59f 100644 --- a/net/atm/pppoatm.c +++ b/net/atm/pppoatm.c @@ -62,12 +62,25 @@ struct pppoatm_vcc { void (*old_pop)(struct atm_vcc *, struct sk_buff *); /* keep old push/pop for detaching */ enum pppoatm_encaps encaps; + atomic_t inflight; + unsigned long blocked; int flags; /* SC_COMP_PROT - compress protocol */ struct ppp_channel chan; /* interface to generic ppp layer */ struct tasklet_struct wakeup_tasklet; }; /* + * We want to allow two packets in the queue. The one that's currently in + * flight, and *one* queued up ready for the ATM device to send immediately + * from its TX done IRQ. We want to be able to use atomic_inc_not_zero(), so + * inflight == -2 represents an empty queue, -1 one packet, and zero means + * there are two packets in the queue. + */ +#define NONE_INFLIGHT -2 + +#define BLOCKED 0 + +/* * Header used for LLC Encapsulated PPP (4 bytes) followed by the LCP protocol * ID (0xC021) used in autodetection */ @@ -102,16 +115,30 @@ static void pppoatm_wakeup_sender(unsigned long arg) static void pppoatm_pop(struct atm_vcc *atmvcc, struct sk_buff *skb) { struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc); + pvcc->old_pop(atmvcc, skb); + atomic_dec(&pvcc->inflight); + /* - * We don't really always want to do this since it's - * really inefficient - it would be much better if we could - * test if we had actually throttled the generic layer. - * Unfortunately then there would be a nasty SMP race where - * we could clear that flag just as we refuse another packet. - * For now we do the safe thing. + * We always used to run the wakeup tasklet unconditionally here, for + * fear of race conditions where we clear the BLOCKED flag just as we + * refuse another packet in pppoatm_send(). This was quite inefficient. + * + * In fact it's OK. The PPP core will only ever call pppoatm_send() + * while holding the channel->downl lock. And ppp_output_wakeup() as + * called by the tasklet will *also* grab that lock. So even if another + * CPU is in pppoatm_send() right now, the tasklet isn't going to race + * with it. The wakeup *will* happen after the other CPU is safely out + * of pppoatm_send() again. + * + * So if the CPU in pppoatm_send() has already set the BLOCKED bit and + * it about to return, that's fine. We trigger a wakeup which will + * happen later. And if the CPU in pppoatm_send() *hasn't* set the + * BLOCKED bit yet, that's fine too because of the double check in + * pppoatm_may_send() which is commented there. */ - tasklet_schedule(&pvcc->wakeup_tasklet); + if (test_and_clear_bit(BLOCKED, &pvcc->blocked)) + tasklet_schedule(&pvcc->wakeup_tasklet); } /* @@ -184,6 +211,51 @@ error: ppp_input_error(&pvcc->chan, 0); } +static inline int pppoatm_may_send(struct pppoatm_vcc *pvcc, int size) +{ + /* + * It's not clear that we need to bother with using atm_may_send() + * to check we don't exceed sk->sk_sndbuf. If userspace sets a + * value of sk_sndbuf which is lower than the MTU, we're going to + * block for ever. But the code always did that before we introduced + * the packet count limit, so... + */ + if (atm_may_send(pvcc->atmvcc, size) && + atomic_inc_not_zero_hint(&pvcc->inflight, NONE_INFLIGHT)) + return 1; + + /* + * We use test_and_set_bit() rather than set_bit() here because + * we need to ensure there's a memory barrier after it. The bit + * *must* be set before we do the atomic_inc() on pvcc->inflight. + * There's no smp_mb__after_set_bit(), so it's this or abuse + * smp_mb__after_clear_bit(). + */ + test_and_set_bit(BLOCKED, &pvcc->blocked); + + /* + * We may have raced with pppoatm_pop(). If it ran for the + * last packet in the queue, *just* before we set the BLOCKED + * bit, then it might never run again and the channel could + * remain permanently blocked. Cope with that race by checking + * *again*. If it did run in that window, we'll have space on + * the queue now and can return success. It's harmless to leave + * the BLOCKED flag set, since it's only used as a trigger to + * run the wakeup tasklet. Another wakeup will never hurt. + * If pppoatm_pop() is running but hasn't got as far as making + * space on the queue yet, then it hasn't checked the BLOCKED + * flag yet either, so we're safe in that case too. It'll issue + * an "immediate" wakeup... where "immediate" actually involves + * taking the PPP channel's ->downl lock, which is held by the + * code path that calls pppoatm_send(), and is thus going to + * wait for us to finish. + */ + if (atm_may_send(pvcc->atmvcc, size) && + atomic_inc_not_zero(&pvcc->inflight)) + return 1; + + return 0; +} /* * Called by the ppp_generic.c to send a packet - returns true if packet * was accepted. If we return false, then it's our job to call @@ -207,7 +279,7 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb) struct sk_buff *n; n = skb_realloc_headroom(skb, LLC_LEN); if (n != NULL && - !atm_may_send(pvcc->atmvcc, n->truesize)) { + !pppoatm_may_send(pvcc, n->truesize)) { kfree_skb(n); goto nospace; } @@ -215,12 +287,12 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb) skb = n; if (skb == NULL) return DROP_PACKET; - } else if (!atm_may_send(pvcc->atmvcc, skb->truesize)) + } else if (!pppoatm_may_send(pvcc, skb->truesize)) goto nospace; memcpy(skb_push(skb, LLC_LEN), pppllc, LLC_LEN); break; case e_vc: - if (!atm_may_send(pvcc->atmvcc, skb->truesize)) + if (!pppoatm_may_send(pvcc, skb->truesize)) goto nospace; break; case e_autodetect: @@ -285,6 +357,9 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg) if (pvcc == NULL) return -ENOMEM; pvcc->atmvcc = atmvcc; + + /* Maximum is zero, so that we can use atomic_inc_not_zero() */ + atomic_set(&pvcc->inflight, NONE_INFLIGHT); pvcc->old_push = atmvcc->push; pvcc->old_pop = atmvcc->pop; pvcc->encaps = (enum pppoatm_encaps) be.encaps; diff --git a/net/atm/signaling.c b/net/atm/signaling.c index 509c8ac..86767ca 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c @@ -166,7 +166,7 @@ void sigd_enq2(struct atm_vcc *vcc, enum atmsvc_msg_type type, { struct sk_buff *skb; struct atmsvc_msg *msg; - static unsigned session = 0; + static unsigned int session = 0; pr_debug("%d (0x%p)\n", (int)type, vcc); while (!(skb = alloc_skb(sizeof(struct atmsvc_msg), GFP_KERNEL))) diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c index 846ae4e..67de6b3 100644 --- a/net/ax25/ax25_ip.c +++ b/net/ax25/ax25_ip.c @@ -48,7 +48,7 @@ int ax25_hard_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, const void *daddr, - const void *saddr, unsigned len) + const void *saddr, unsigned int len) { unsigned char *buff; @@ -219,7 +219,7 @@ put: int ax25_hard_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, const void *daddr, - const void *saddr, unsigned len) + const void *saddr, unsigned int len) { return -AX25_HEADER_LEN; } diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig index 2b68d06..53f5244 100644 --- a/net/batman-adv/Kconfig +++ b/net/batman-adv/Kconfig @@ -7,19 +7,28 @@ config BATMAN_ADV depends on NET select CRC16 default n - ---help--- + help + B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is + a routing protocol for multi-hop ad-hoc mesh networks. The + networks may be wired or wireless. See + http://www.open-mesh.org/ for more information and user space + tools. - B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is - a routing protocol for multi-hop ad-hoc mesh networks. The - networks may be wired or wireless. See - http://www.open-mesh.org/ for more information and user space - tools. +config BATMAN_ADV_BLA + bool "Bridge Loop Avoidance" + depends on BATMAN_ADV && INET + default y + help + This option enables BLA (Bridge Loop Avoidance), a mechanism + to avoid Ethernet frames looping when mesh nodes are connected + to both the same LAN and the same mesh. If you will never use + more than one mesh node in the same LAN, you can safely remove + this feature and save some space. config BATMAN_ADV_DEBUG bool "B.A.T.M.A.N. debugging" - depends on BATMAN_ADV != n - ---help--- - + depends on BATMAN_ADV + help This is an option for use by developers; most people should say N here. This enables compilation of support for outputting debugging information to the kernel log. The diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile index 4e392eb..6d5c194 100644 --- a/net/batman-adv/Makefile +++ b/net/batman-adv/Makefile @@ -23,6 +23,7 @@ batman-adv-y += bat_debugfs.o batman-adv-y += bat_iv_ogm.o batman-adv-y += bat_sysfs.o batman-adv-y += bitarray.o +batman-adv-$(CONFIG_BATMAN_ADV_BLA) += bridge_loop_avoidance.o batman-adv-y += gateway_client.o batman-adv-y += gateway_common.o batman-adv-y += hard-interface.o diff --git a/net/batman-adv/bat_debugfs.c b/net/batman-adv/bat_debugfs.c index c3b0548..916380c 100644 --- a/net/batman-adv/bat_debugfs.c +++ b/net/batman-adv/bat_debugfs.c @@ -32,6 +32,7 @@ #include "soft-interface.h" #include "vis.h" #include "icmp_socket.h" +#include "bridge_loop_avoidance.h" static struct dentry *bat_debugfs; @@ -238,17 +239,19 @@ static int gateways_open(struct inode *inode, struct file *file) return single_open(file, gw_client_seq_print_text, net_dev); } -static int softif_neigh_open(struct inode *inode, struct file *file) +static int transtable_global_open(struct inode *inode, struct file *file) { struct net_device *net_dev = (struct net_device *)inode->i_private; - return single_open(file, softif_neigh_seq_print_text, net_dev); + return single_open(file, tt_global_seq_print_text, net_dev); } -static int transtable_global_open(struct inode *inode, struct file *file) +#ifdef CONFIG_BATMAN_ADV_BLA +static int bla_claim_table_open(struct inode *inode, struct file *file) { struct net_device *net_dev = (struct net_device *)inode->i_private; - return single_open(file, tt_global_seq_print_text, net_dev); + return single_open(file, bla_claim_table_seq_print_text, net_dev); } +#endif static int transtable_local_open(struct inode *inode, struct file *file) { @@ -282,16 +285,20 @@ struct bat_debuginfo bat_debuginfo_##_name = { \ static BAT_DEBUGINFO(routing_algos, S_IRUGO, bat_algorithms_open); static BAT_DEBUGINFO(originators, S_IRUGO, originators_open); static BAT_DEBUGINFO(gateways, S_IRUGO, gateways_open); -static BAT_DEBUGINFO(softif_neigh, S_IRUGO, softif_neigh_open); static BAT_DEBUGINFO(transtable_global, S_IRUGO, transtable_global_open); +#ifdef CONFIG_BATMAN_ADV_BLA +static BAT_DEBUGINFO(bla_claim_table, S_IRUGO, bla_claim_table_open); +#endif static BAT_DEBUGINFO(transtable_local, S_IRUGO, transtable_local_open); static BAT_DEBUGINFO(vis_data, S_IRUGO, vis_data_open); static struct bat_debuginfo *mesh_debuginfos[] = { &bat_debuginfo_originators, &bat_debuginfo_gateways, - &bat_debuginfo_softif_neigh, &bat_debuginfo_transtable_global, +#ifdef CONFIG_BATMAN_ADV_BLA + &bat_debuginfo_bla_claim_table, +#endif &bat_debuginfo_transtable_local, &bat_debuginfo_vis_data, NULL, diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index a6d5d63..fab1071 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -850,9 +850,9 @@ static int bat_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, hlist_for_each_entry_rcu(tmp_neigh_node, node, &orig_node->neigh_list, list) { - is_duplicate |= get_bit_status(tmp_neigh_node->real_bits, - orig_node->last_real_seqno, - batman_ogm_packet->seqno); + is_duplicate |= bat_test_bit(tmp_neigh_node->real_bits, + orig_node->last_real_seqno, + batman_ogm_packet->seqno); if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) && (tmp_neigh_node->if_incoming == if_incoming)) @@ -866,7 +866,8 @@ static int bat_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, seq_diff, set_mark); tmp_neigh_node->real_packet_count = - bit_packet_count(tmp_neigh_node->real_bits); + bitmap_weight(tmp_neigh_node->real_bits, + TQ_LOCAL_WINDOW_SIZE); } rcu_read_unlock(); @@ -998,11 +999,11 @@ static void bat_iv_ogm_process(const struct ethhdr *ethhdr, spin_lock_bh(&orig_neigh_node->ogm_cnt_lock); word = &(orig_neigh_node->bcast_own[offset]); - bit_mark(word, - if_incoming_seqno - + bat_set_bit(word, + if_incoming_seqno - batman_ogm_packet->seqno - 2); orig_neigh_node->bcast_own_sum[if_incoming->if_num] = - bit_packet_count(word); + bitmap_weight(word, TQ_LOCAL_WINDOW_SIZE); spin_unlock_bh(&orig_neigh_node->ogm_cnt_lock); } diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c index 68ff759..2c81688 100644 --- a/net/batman-adv/bat_sysfs.c +++ b/net/batman-adv/bat_sysfs.c @@ -149,7 +149,7 @@ static int store_bool_attr(char *buff, size_t count, atomic_read(attr) == 1 ? "enabled" : "disabled", enabled == 1 ? "enabled" : "disabled"); - atomic_set(attr, (unsigned)enabled); + atomic_set(attr, (unsigned int)enabled); return count; } @@ -268,7 +268,7 @@ static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr, "client" : "server", vis_mode_tmp == VIS_TYPE_CLIENT_UPDATE ? "client" : "server"); - atomic_set(&bat_priv->vis_mode, (unsigned)vis_mode_tmp); + atomic_set(&bat_priv->vis_mode, (unsigned int)vis_mode_tmp); return count; } @@ -354,7 +354,7 @@ static ssize_t store_gw_mode(struct kobject *kobj, struct attribute *attr, curr_gw_mode_str, buff); gw_deselect(bat_priv); - atomic_set(&bat_priv->gw_mode, (unsigned)gw_mode_tmp); + atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp); return count; } @@ -386,6 +386,9 @@ static ssize_t store_gw_bwidth(struct kobject *kobj, struct attribute *attr, BAT_ATTR_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL); BAT_ATTR_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); +#ifdef CONFIG_BATMAN_ADV_BLA +BAT_ATTR_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL); +#endif BAT_ATTR_BOOL(fragmentation, S_IRUGO | S_IWUSR, update_min_mtu); BAT_ATTR_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL); static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode); @@ -398,12 +401,15 @@ BAT_ATTR_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, TQ_MAX_VALUE, static BAT_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, show_gw_bwidth, store_gw_bwidth); #ifdef CONFIG_BATMAN_ADV_DEBUG -BAT_ATTR_UINT(log_level, S_IRUGO | S_IWUSR, 0, 7, NULL); +BAT_ATTR_UINT(log_level, S_IRUGO | S_IWUSR, 0, 15, NULL); #endif static struct bat_attribute *mesh_attrs[] = { &bat_attr_aggregated_ogms, &bat_attr_bonding, +#ifdef CONFIG_BATMAN_ADV_BLA + &bat_attr_bridge_loop_avoidance, +#endif &bat_attr_fragmentation, &bat_attr_ap_isolation, &bat_attr_vis_mode, diff --git a/net/batman-adv/bitarray.c b/net/batman-adv/bitarray.c index 6d0aa21..07ae6e1 100644 --- a/net/batman-adv/bitarray.c +++ b/net/batman-adv/bitarray.c @@ -24,100 +24,13 @@ #include <linux/bitops.h> -/* returns true if the corresponding bit in the given seq_bits indicates true - * and curr_seqno is within range of last_seqno */ -int get_bit_status(const unsigned long *seq_bits, uint32_t last_seqno, - uint32_t curr_seqno) -{ - int32_t diff, word_offset, word_num; - - diff = last_seqno - curr_seqno; - if (diff < 0 || diff >= TQ_LOCAL_WINDOW_SIZE) { - return 0; - } else { - /* which word */ - word_num = (last_seqno - curr_seqno) / WORD_BIT_SIZE; - /* which position in the selected word */ - word_offset = (last_seqno - curr_seqno) % WORD_BIT_SIZE; - - if (test_bit(word_offset, &seq_bits[word_num])) - return 1; - else - return 0; - } -} - -/* turn corresponding bit on, so we can remember that we got the packet */ -void bit_mark(unsigned long *seq_bits, int32_t n) -{ - int32_t word_offset, word_num; - - /* if too old, just drop it */ - if (n < 0 || n >= TQ_LOCAL_WINDOW_SIZE) - return; - - /* which word */ - word_num = n / WORD_BIT_SIZE; - /* which position in the selected word */ - word_offset = n % WORD_BIT_SIZE; - - set_bit(word_offset, &seq_bits[word_num]); /* turn the position on */ -} - /* shift the packet array by n places. */ -static void bit_shift(unsigned long *seq_bits, int32_t n) +static void bat_bitmap_shift_left(unsigned long *seq_bits, int32_t n) { - int32_t word_offset, word_num; - int32_t i; - if (n <= 0 || n >= TQ_LOCAL_WINDOW_SIZE) return; - word_offset = n % WORD_BIT_SIZE;/* shift how much inside each word */ - word_num = n / WORD_BIT_SIZE; /* shift over how much (full) words */ - - for (i = NUM_WORDS - 1; i > word_num; i--) { - /* going from old to new, so we don't overwrite the data we copy - * from. - * - * left is high, right is low: FEDC BA98 7654 3210 - * ^^ ^^ - * vvvv - * ^^^^ = from, vvvvv =to, we'd have word_num==1 and - * word_offset==WORD_BIT_SIZE/2 ????? in this example. - * (=24 bits) - * - * our desired output would be: 9876 5432 1000 0000 - * */ - - seq_bits[i] = - (seq_bits[i - word_num] << word_offset) + - /* take the lower port from the left half, shift it left - * to its final position */ - (seq_bits[i - word_num - 1] >> - (WORD_BIT_SIZE-word_offset)); - /* and the upper part of the right half and shift it left to - * its position */ - /* for our example that would be: word[0] = 9800 + 0076 = - * 9876 */ - } - /* now for our last word, i==word_num, we only have its "left" half. - * that's the 1000 word in our example.*/ - - seq_bits[i] = (seq_bits[i - word_num] << word_offset); - - /* pad the rest with 0, if there is anything */ - i--; - - for (; i >= 0; i--) - seq_bits[i] = 0; -} - -static void bit_reset_window(unsigned long *seq_bits) -{ - int i; - for (i = 0; i < NUM_WORDS; i++) - seq_bits[i] = 0; + bitmap_shift_left(seq_bits, seq_bits, n, TQ_LOCAL_WINDOW_SIZE); } @@ -137,7 +50,7 @@ int bit_get_packet(void *priv, unsigned long *seq_bits, if ((seq_num_diff <= 0) && (seq_num_diff > -TQ_LOCAL_WINDOW_SIZE)) { if (set_mark) - bit_mark(seq_bits, -seq_num_diff); + bat_set_bit(seq_bits, -seq_num_diff); return 0; } @@ -145,10 +58,10 @@ int bit_get_packet(void *priv, unsigned long *seq_bits, * set the mark if required */ if ((seq_num_diff > 0) && (seq_num_diff < TQ_LOCAL_WINDOW_SIZE)) { - bit_shift(seq_bits, seq_num_diff); + bat_bitmap_shift_left(seq_bits, seq_num_diff); if (set_mark) - bit_mark(seq_bits, 0); + bat_set_bit(seq_bits, 0); return 1; } @@ -159,9 +72,9 @@ int bit_get_packet(void *priv, unsigned long *seq_bits, bat_dbg(DBG_BATMAN, bat_priv, "We missed a lot of packets (%i) !\n", seq_num_diff - 1); - bit_reset_window(seq_bits); + bitmap_zero(seq_bits, TQ_LOCAL_WINDOW_SIZE); if (set_mark) - bit_mark(seq_bits, 0); + bat_set_bit(seq_bits, 0); return 1; } @@ -176,9 +89,9 @@ int bit_get_packet(void *priv, unsigned long *seq_bits, bat_dbg(DBG_BATMAN, bat_priv, "Other host probably restarted!\n"); - bit_reset_window(seq_bits); + bitmap_zero(seq_bits, TQ_LOCAL_WINDOW_SIZE); if (set_mark) - bit_mark(seq_bits, 0); + bat_set_bit(seq_bits, 0); return 1; } @@ -186,16 +99,3 @@ int bit_get_packet(void *priv, unsigned long *seq_bits, /* never reached */ return 0; } - -/* count the hamming weight, how many good packets did we receive? just count - * the 1's. - */ -int bit_packet_count(const unsigned long *seq_bits) -{ - int i, hamming = 0; - - for (i = 0; i < NUM_WORDS; i++) - hamming += hweight_long(seq_bits[i]); - - return hamming; -} diff --git a/net/batman-adv/bitarray.h b/net/batman-adv/bitarray.h index c613572..1835c15 100644 --- a/net/batman-adv/bitarray.h +++ b/net/batman-adv/bitarray.h @@ -22,23 +22,33 @@ #ifndef _NET_BATMAN_ADV_BITARRAY_H_ #define _NET_BATMAN_ADV_BITARRAY_H_ -#define WORD_BIT_SIZE (sizeof(unsigned long) * 8) - /* returns true if the corresponding bit in the given seq_bits indicates true * and curr_seqno is within range of last_seqno */ -int get_bit_status(const unsigned long *seq_bits, uint32_t last_seqno, - uint32_t curr_seqno); +static inline int bat_test_bit(const unsigned long *seq_bits, + uint32_t last_seqno, uint32_t curr_seqno) +{ + int32_t diff; + + diff = last_seqno - curr_seqno; + if (diff < 0 || diff >= TQ_LOCAL_WINDOW_SIZE) + return 0; + else + return test_bit(diff, seq_bits); +} /* turn corresponding bit on, so we can remember that we got the packet */ -void bit_mark(unsigned long *seq_bits, int32_t n); +static inline void bat_set_bit(unsigned long *seq_bits, int32_t n) +{ + /* if too old, just drop it */ + if (n < 0 || n >= TQ_LOCAL_WINDOW_SIZE) + return; + set_bit(n, seq_bits); /* turn the position on */ +} /* receive and process one packet, returns 1 if received seq_num is considered * new, 0 if old */ int bit_get_packet(void *priv, unsigned long *seq_bits, int32_t seq_num_diff, int set_mark); -/* count the hamming weight, how many good packets did we receive? */ -int bit_packet_count(const unsigned long *seq_bits); - #endif /* _NET_BATMAN_ADV_BITARRAY_H_ */ diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c new file mode 100644 index 0000000..1cf18ac --- /dev/null +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -0,0 +1,1583 @@ +/* + * Copyright (C) 2011 B.A.T.M.A.N. contributors: + * + * Simon Wunderlich + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "main.h" +#include "hash.h" +#include "hard-interface.h" +#include "originator.h" +#include "bridge_loop_avoidance.h" +#include "translation-table.h" +#include "send.h" + +#include <linux/etherdevice.h> +#include <linux/crc16.h> +#include <linux/if_arp.h> +#include <net/arp.h> +#include <linux/if_vlan.h> + +static const uint8_t announce_mac[4] = {0x43, 0x05, 0x43, 0x05}; + +static void bla_periodic_work(struct work_struct *work); +static void bla_send_announce(struct bat_priv *bat_priv, + struct backbone_gw *backbone_gw); + +/* return the index of the claim */ +static inline uint32_t choose_claim(const void *data, uint32_t size) +{ + const unsigned char *key = data; + uint32_t hash = 0; + size_t i; + + for (i = 0; i < ETH_ALEN + sizeof(short); i++) { + hash += key[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + + return hash % size; +} + +/* return the index of the backbone gateway */ +static inline uint32_t choose_backbone_gw(const void *data, uint32_t size) +{ + const unsigned char *key = data; + uint32_t hash = 0; + size_t i; + + for (i = 0; i < ETH_ALEN + sizeof(short); i++) { + hash += key[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + + return hash % size; +} + + +/* compares address and vid of two backbone gws */ +static int compare_backbone_gw(const struct hlist_node *node, const void *data2) +{ + const void *data1 = container_of(node, struct backbone_gw, + hash_entry); + + return (memcmp(data1, data2, ETH_ALEN + sizeof(short)) == 0 ? 1 : 0); +} + +/* compares address and vid of two claims */ +static int compare_claim(const struct hlist_node *node, const void *data2) +{ + const void *data1 = container_of(node, struct claim, + hash_entry); + + return (memcmp(data1, data2, ETH_ALEN + sizeof(short)) == 0 ? 1 : 0); +} + +/* free a backbone gw */ +static void backbone_gw_free_ref(struct backbone_gw *backbone_gw) +{ + if (atomic_dec_and_test(&backbone_gw->refcount)) + kfree_rcu(backbone_gw, rcu); +} + +/* finally deinitialize the claim */ +static void claim_free_rcu(struct rcu_head *rcu) +{ + struct claim *claim; + + claim = container_of(rcu, struct claim, rcu); + + backbone_gw_free_ref(claim->backbone_gw); + kfree(claim); +} + +/* free a claim, call claim_free_rcu if its the last reference */ +static void claim_free_ref(struct claim *claim) +{ + if (atomic_dec_and_test(&claim->refcount)) + call_rcu(&claim->rcu, claim_free_rcu); +} + +/** + * @bat_priv: the bat priv with all the soft interface information + * @data: search data (may be local/static data) + * + * looks for a claim in the hash, and returns it if found + * or NULL otherwise. + */ +static struct claim *claim_hash_find(struct bat_priv *bat_priv, + struct claim *data) +{ + struct hashtable_t *hash = bat_priv->claim_hash; + struct hlist_head *head; + struct hlist_node *node; + struct claim *claim; + struct claim *claim_tmp = NULL; + int index; + + if (!hash) + return NULL; + + index = choose_claim(data, hash->size); + head = &hash->table[index]; + + rcu_read_lock(); + hlist_for_each_entry_rcu(claim, node, head, hash_entry) { + if (!compare_claim(&claim->hash_entry, data)) + continue; + + if (!atomic_inc_not_zero(&claim->refcount)) + continue; + + claim_tmp = claim; + break; + } + rcu_read_unlock(); + + return claim_tmp; +} + +/** + * @bat_priv: the bat priv with all the soft interface information + * @addr: the address of the originator + * @vid: the VLAN ID + * + * looks for a claim in the hash, and returns it if found + * or NULL otherwise. + */ +static struct backbone_gw *backbone_hash_find(struct bat_priv *bat_priv, + uint8_t *addr, short vid) +{ + struct hashtable_t *hash = bat_priv->backbone_hash; + struct hlist_head *head; + struct hlist_node *node; + struct backbone_gw search_entry, *backbone_gw; + struct backbone_gw *backbone_gw_tmp = NULL; + int index; + + if (!hash) + return NULL; + + memcpy(search_entry.orig, addr, ETH_ALEN); + search_entry.vid = vid; + + index = choose_backbone_gw(&search_entry, hash->size); + head = &hash->table[index]; + + rcu_read_lock(); + hlist_for_each_entry_rcu(backbone_gw, node, head, hash_entry) { + if (!compare_backbone_gw(&backbone_gw->hash_entry, + &search_entry)) + continue; + + if (!atomic_inc_not_zero(&backbone_gw->refcount)) + continue; + + backbone_gw_tmp = backbone_gw; + break; + } + rcu_read_unlock(); + + return backbone_gw_tmp; +} + +/* delete all claims for a backbone */ +static void bla_del_backbone_claims(struct backbone_gw *backbone_gw) +{ + struct hashtable_t *hash; + struct hlist_node *node, *node_tmp; + struct hlist_head *head; + struct claim *claim; + int i; + spinlock_t *list_lock; /* protects write access to the hash lists */ + + hash = backbone_gw->bat_priv->claim_hash; + if (!hash) + return; + + for (i = 0; i < hash->size; i++) { + head = &hash->table[i]; + list_lock = &hash->list_locks[i]; + + spin_lock_bh(list_lock); + hlist_for_each_entry_safe(claim, node, node_tmp, + head, hash_entry) { + + if (claim->backbone_gw != backbone_gw) + continue; + + claim_free_ref(claim); + hlist_del_rcu(node); + } + spin_unlock_bh(list_lock); + } + + /* all claims gone, intialize CRC */ + backbone_gw->crc = BLA_CRC_INIT; +} + +/** + * @bat_priv: the bat priv with all the soft interface information + * @orig: the mac address to be announced within the claim + * @vid: the VLAN ID + * @claimtype: the type of the claim (CLAIM, UNCLAIM, ANNOUNCE, ...) + * + * sends a claim frame according to the provided info. + */ +static void bla_send_claim(struct bat_priv *bat_priv, uint8_t *mac, + short vid, int claimtype) +{ + struct sk_buff *skb; + struct ethhdr *ethhdr; + struct hard_iface *primary_if; + struct net_device *soft_iface; + uint8_t *hw_src; + struct bla_claim_dst local_claim_dest; + uint32_t zeroip = 0; + + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + return; + + memcpy(&local_claim_dest, &bat_priv->claim_dest, + sizeof(local_claim_dest)); + local_claim_dest.type = claimtype; + + soft_iface = primary_if->soft_iface; + + skb = arp_create(ARPOP_REPLY, ETH_P_ARP, + /* IP DST: 0.0.0.0 */ + zeroip, + primary_if->soft_iface, + /* IP SRC: 0.0.0.0 */ + zeroip, + /* Ethernet DST: Broadcast */ + NULL, + /* Ethernet SRC/HW SRC: originator mac */ + primary_if->net_dev->dev_addr, + /* HW DST: FF:43:05:XX:00:00 + * with XX = claim type + * and YY:YY = group id + */ + (uint8_t *)&local_claim_dest); + + if (!skb) + goto out; + + ethhdr = (struct ethhdr *)skb->data; + hw_src = (uint8_t *)ethhdr + + sizeof(struct ethhdr) + + sizeof(struct arphdr); + + /* now we pretend that the client would have sent this ... */ + switch (claimtype) { + case CLAIM_TYPE_ADD: + /* normal claim frame + * set Ethernet SRC to the clients mac + */ + memcpy(ethhdr->h_source, mac, ETH_ALEN); + bat_dbg(DBG_BLA, bat_priv, + "bla_send_claim(): CLAIM %pM on vid %d\n", mac, vid); + break; + case CLAIM_TYPE_DEL: + /* unclaim frame + * set HW SRC to the clients mac + */ + memcpy(hw_src, mac, ETH_ALEN); + bat_dbg(DBG_BLA, bat_priv, + "bla_send_claim(): UNCLAIM %pM on vid %d\n", mac, vid); + break; + case CLAIM_TYPE_ANNOUNCE: + /* announcement frame + * set HW SRC to the special mac containg the crc + */ + memcpy(hw_src, mac, ETH_ALEN); + bat_dbg(DBG_BLA, bat_priv, + "bla_send_claim(): ANNOUNCE of %pM on vid %d\n", + ethhdr->h_source, vid); + break; + case CLAIM_TYPE_REQUEST: + /* request frame + * set HW SRC to the special mac containg the crc + */ + memcpy(hw_src, mac, ETH_ALEN); + memcpy(ethhdr->h_dest, mac, ETH_ALEN); + bat_dbg(DBG_BLA, bat_priv, + "bla_send_claim(): REQUEST of %pM to %pMon vid %d\n", + ethhdr->h_source, ethhdr->h_dest, vid); + break; + + } + + if (vid != -1) + skb = vlan_insert_tag(skb, vid); + + skb_reset_mac_header(skb); + skb->protocol = eth_type_trans(skb, soft_iface); + bat_priv->stats.rx_packets++; + bat_priv->stats.rx_bytes += skb->len + sizeof(struct ethhdr); + soft_iface->last_rx = jiffies; + + netif_rx(skb); +out: + if (primary_if) + hardif_free_ref(primary_if); +} + +/** + * @bat_priv: the bat priv with all the soft interface information + * @orig: the mac address of the originator + * @vid: the VLAN ID + * + * searches for the backbone gw or creates a new one if it could not + * be found. + */ +static struct backbone_gw *bla_get_backbone_gw(struct bat_priv *bat_priv, + uint8_t *orig, short vid) +{ + struct backbone_gw *entry; + struct orig_node *orig_node; + int hash_added; + + entry = backbone_hash_find(bat_priv, orig, vid); + + if (entry) + return entry; + + bat_dbg(DBG_BLA, bat_priv, + "bla_get_backbone_gw(): not found (%pM, %d), creating new entry\n", + orig, vid); + + entry = kzalloc(sizeof(*entry), GFP_ATOMIC); + if (!entry) + return NULL; + + entry->vid = vid; + entry->lasttime = jiffies; + entry->crc = BLA_CRC_INIT; + entry->bat_priv = bat_priv; + atomic_set(&entry->request_sent, 0); + memcpy(entry->orig, orig, ETH_ALEN); + + /* one for the hash, one for returning */ + atomic_set(&entry->refcount, 2); + + hash_added = hash_add(bat_priv->backbone_hash, compare_backbone_gw, + choose_backbone_gw, entry, &entry->hash_entry); + + if (unlikely(hash_added != 0)) { + /* hash failed, free the structure */ + kfree(entry); + return NULL; + } + + /* this is a gateway now, remove any tt entries */ + orig_node = orig_hash_find(bat_priv, orig); + if (orig_node) { + tt_global_del_orig(bat_priv, orig_node, + "became a backbone gateway"); + orig_node_free_ref(orig_node); + } + return entry; +} + +/* update or add the own backbone gw to make sure we announce + * where we receive other backbone gws + */ +static void bla_update_own_backbone_gw(struct bat_priv *bat_priv, + struct hard_iface *primary_if, + short vid) +{ + struct backbone_gw *backbone_gw; + + backbone_gw = bla_get_backbone_gw(bat_priv, + primary_if->net_dev->dev_addr, vid); + if (unlikely(!backbone_gw)) + return; + + backbone_gw->lasttime = jiffies; + backbone_gw_free_ref(backbone_gw); +} + +/** + * @bat_priv: the bat priv with all the soft interface information + * @vid: the vid where the request came on + * + * Repeat all of our own claims, and finally send an ANNOUNCE frame + * to allow the requester another check if the CRC is correct now. + */ +static void bla_answer_request(struct bat_priv *bat_priv, + struct hard_iface *primary_if, short vid) +{ + struct hlist_node *node; + struct hlist_head *head; + struct hashtable_t *hash; + struct claim *claim; + struct backbone_gw *backbone_gw; + int i; + + bat_dbg(DBG_BLA, bat_priv, + "bla_answer_request(): received a claim request, send all of our own claims again\n"); + + backbone_gw = backbone_hash_find(bat_priv, + primary_if->net_dev->dev_addr, vid); + if (!backbone_gw) + return; + + hash = bat_priv->claim_hash; + for (i = 0; i < hash->size; i++) { + head = &hash->table[i]; + + rcu_read_lock(); + hlist_for_each_entry_rcu(claim, node, head, hash_entry) { + /* only own claims are interesting */ + if (claim->backbone_gw != backbone_gw) + continue; + + bla_send_claim(bat_priv, claim->addr, claim->vid, + CLAIM_TYPE_ADD); + } + rcu_read_unlock(); + } + + /* finally, send an announcement frame */ + bla_send_announce(bat_priv, backbone_gw); + backbone_gw_free_ref(backbone_gw); +} + +/** + * @backbone_gw: the backbone gateway from whom we are out of sync + * + * When the crc is wrong, ask the backbone gateway for a full table update. + * After the request, it will repeat all of his own claims and finally + * send an announcement claim with which we can check again. + */ +static void bla_send_request(struct backbone_gw *backbone_gw) +{ + /* first, remove all old entries */ + bla_del_backbone_claims(backbone_gw); + + bat_dbg(DBG_BLA, backbone_gw->bat_priv, + "Sending REQUEST to %pM\n", + backbone_gw->orig); + + /* send request */ + bla_send_claim(backbone_gw->bat_priv, backbone_gw->orig, + backbone_gw->vid, CLAIM_TYPE_REQUEST); + + /* no local broadcasts should be sent or received, for now. */ + if (!atomic_read(&backbone_gw->request_sent)) { + atomic_inc(&backbone_gw->bat_priv->bla_num_requests); + atomic_set(&backbone_gw->request_sent, 1); + } +} + +/** + * @bat_priv: the bat priv with all the soft interface information + * @backbone_gw: our backbone gateway which should be announced + * + * This function sends an announcement. It is called from multiple + * places. + */ +static void bla_send_announce(struct bat_priv *bat_priv, + struct backbone_gw *backbone_gw) +{ + uint8_t mac[ETH_ALEN]; + uint16_t crc; + + memcpy(mac, announce_mac, 4); + crc = htons(backbone_gw->crc); + memcpy(&mac[4], (uint8_t *)&crc, 2); + + bla_send_claim(bat_priv, mac, backbone_gw->vid, CLAIM_TYPE_ANNOUNCE); + +} + +/** + * @bat_priv: the bat priv with all the soft interface information + * @mac: the mac address of the claim + * @vid: the VLAN ID of the frame + * @backbone_gw: the backbone gateway which claims it + * + * Adds a claim in the claim hash. + */ +static void bla_add_claim(struct bat_priv *bat_priv, const uint8_t *mac, + const short vid, struct backbone_gw *backbone_gw) +{ + struct claim *claim; + struct claim search_claim; + int hash_added; + + memcpy(search_claim.addr, mac, ETH_ALEN); + search_claim.vid = vid; + claim = claim_hash_find(bat_priv, &search_claim); + + /* create a new claim entry if it does not exist yet. */ + if (!claim) { + claim = kzalloc(sizeof(*claim), GFP_ATOMIC); + if (!claim) + return; + + memcpy(claim->addr, mac, ETH_ALEN); + claim->vid = vid; + claim->lasttime = jiffies; + claim->backbone_gw = backbone_gw; + + atomic_set(&claim->refcount, 2); + bat_dbg(DBG_BLA, bat_priv, + "bla_add_claim(): adding new entry %pM, vid %d to hash ...\n", + mac, vid); + hash_added = hash_add(bat_priv->claim_hash, compare_claim, + choose_claim, claim, &claim->hash_entry); + + if (unlikely(hash_added != 0)) { + /* only local changes happened. */ + kfree(claim); + return; + } + } else { + claim->lasttime = jiffies; + if (claim->backbone_gw == backbone_gw) + /* no need to register a new backbone */ + goto claim_free_ref; + + bat_dbg(DBG_BLA, bat_priv, + "bla_add_claim(): changing ownership for %pM, vid %d\n", + mac, vid); + + claim->backbone_gw->crc ^= + crc16(0, claim->addr, ETH_ALEN); + backbone_gw_free_ref(claim->backbone_gw); + + } + /* set (new) backbone gw */ + atomic_inc(&backbone_gw->refcount); + claim->backbone_gw = backbone_gw; + + backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN); + backbone_gw->lasttime = jiffies; + +claim_free_ref: + claim_free_ref(claim); +} + +/* Delete a claim from the claim hash which has the + * given mac address and vid. + */ +static void bla_del_claim(struct bat_priv *bat_priv, const uint8_t *mac, + const short vid) +{ + struct claim search_claim, *claim; + + memcpy(search_claim.addr, mac, ETH_ALEN); + search_claim.vid = vid; + claim = claim_hash_find(bat_priv, &search_claim); + if (!claim) + return; + + bat_dbg(DBG_BLA, bat_priv, "bla_del_claim(): %pM, vid %d\n", mac, vid); + + hash_remove(bat_priv->claim_hash, compare_claim, choose_claim, claim); + claim_free_ref(claim); /* reference from the hash is gone */ + + claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN); + + /* don't need the reference from hash_find() anymore */ + claim_free_ref(claim); +} + +/* check for ANNOUNCE frame, return 1 if handled */ +static int handle_announce(struct bat_priv *bat_priv, + uint8_t *an_addr, uint8_t *backbone_addr, short vid) +{ + struct backbone_gw *backbone_gw; + uint16_t crc; + + if (memcmp(an_addr, announce_mac, 4) != 0) + return 0; + + backbone_gw = bla_get_backbone_gw(bat_priv, backbone_addr, vid); + + if (unlikely(!backbone_gw)) + return 1; + + + /* handle as ANNOUNCE frame */ + backbone_gw->lasttime = jiffies; + crc = ntohs(*((uint16_t *)(&an_addr[4]))); + + bat_dbg(DBG_BLA, bat_priv, + "handle_announce(): ANNOUNCE vid %d (sent by %pM)... CRC = %04x\n", + vid, backbone_gw->orig, crc); + + if (backbone_gw->crc != crc) { + bat_dbg(DBG_BLA, backbone_gw->bat_priv, + "handle_announce(): CRC FAILED for %pM/%d (my = %04x, sent = %04x)\n", + backbone_gw->orig, backbone_gw->vid, backbone_gw->crc, + crc); + + bla_send_request(backbone_gw); + } else { + /* if we have sent a request and the crc was OK, + * we can allow traffic again. + */ + if (atomic_read(&backbone_gw->request_sent)) { + atomic_dec(&backbone_gw->bat_priv->bla_num_requests); + atomic_set(&backbone_gw->request_sent, 0); + } + } + + backbone_gw_free_ref(backbone_gw); + return 1; +} + +/* check for REQUEST frame, return 1 if handled */ +static int handle_request(struct bat_priv *bat_priv, + struct hard_iface *primary_if, + uint8_t *backbone_addr, + struct ethhdr *ethhdr, short vid) +{ + /* check for REQUEST frame */ + if (!compare_eth(backbone_addr, ethhdr->h_dest)) + return 0; + + /* sanity check, this should not happen on a normal switch, + * we ignore it in this case. + */ + if (!compare_eth(ethhdr->h_dest, primary_if->net_dev->dev_addr)) + return 1; + + bat_dbg(DBG_BLA, bat_priv, + "handle_request(): REQUEST vid %d (sent by %pM)...\n", + vid, ethhdr->h_source); + + bla_answer_request(bat_priv, primary_if, vid); + return 1; +} + +/* check for UNCLAIM frame, return 1 if handled */ +static int handle_unclaim(struct bat_priv *bat_priv, + struct hard_iface *primary_if, + uint8_t *backbone_addr, + uint8_t *claim_addr, short vid) +{ + struct backbone_gw *backbone_gw; + + /* unclaim in any case if it is our own */ + if (primary_if && compare_eth(backbone_addr, + primary_if->net_dev->dev_addr)) + bla_send_claim(bat_priv, claim_addr, vid, CLAIM_TYPE_DEL); + + backbone_gw = backbone_hash_find(bat_priv, backbone_addr, vid); + + if (!backbone_gw) + return 1; + + /* this must be an UNCLAIM frame */ + bat_dbg(DBG_BLA, bat_priv, + "handle_unclaim(): UNCLAIM %pM on vid %d (sent by %pM)...\n", + claim_addr, vid, backbone_gw->orig); + + bla_del_claim(bat_priv, claim_addr, vid); + backbone_gw_free_ref(backbone_gw); + return 1; +} + +/* check for CLAIM frame, return 1 if handled */ +static int handle_claim(struct bat_priv *bat_priv, + struct hard_iface *primary_if, uint8_t *backbone_addr, + uint8_t *claim_addr, short vid) +{ + struct backbone_gw *backbone_gw; + + /* register the gateway if not yet available, and add the claim. */ + + backbone_gw = bla_get_backbone_gw(bat_priv, backbone_addr, vid); + + if (unlikely(!backbone_gw)) + return 1; + + /* this must be a CLAIM frame */ + bla_add_claim(bat_priv, claim_addr, vid, backbone_gw); + if (compare_eth(backbone_addr, primary_if->net_dev->dev_addr)) + bla_send_claim(bat_priv, claim_addr, vid, CLAIM_TYPE_ADD); + + /* TODO: we could call something like tt_local_del() here. */ + + backbone_gw_free_ref(backbone_gw); + return 1; +} + +/** + * @bat_priv: the bat priv with all the soft interface information + * @bat_priv: the bat priv with all the soft interface information + * @hw_src: the Hardware source in the ARP Header + * @hw_dst: the Hardware destination in the ARP Header + * @ethhdr: pointer to the Ethernet header of the claim frame + * + * checks if it is a claim packet and if its on the same group. + * This function also applies the group ID of the sender + * if it is in the same mesh. + * + * returns: + * 2 - if it is a claim packet and on the same group + * 1 - if is a claim packet from another group + * 0 - if it is not a claim packet + */ +static int check_claim_group(struct bat_priv *bat_priv, + struct hard_iface *primary_if, + uint8_t *hw_src, uint8_t *hw_dst, + struct ethhdr *ethhdr) +{ + uint8_t *backbone_addr; + struct orig_node *orig_node; + struct bla_claim_dst *bla_dst, *bla_dst_own; + + bla_dst = (struct bla_claim_dst *)hw_dst; + bla_dst_own = &bat_priv->claim_dest; + + /* check if it is a claim packet in general */ + if (memcmp(bla_dst->magic, bla_dst_own->magic, + sizeof(bla_dst->magic)) != 0) + return 0; + + /* if announcement packet, use the source, + * otherwise assume it is in the hw_src + */ + switch (bla_dst->type) { + case CLAIM_TYPE_ADD: + backbone_addr = hw_src; + break; + case CLAIM_TYPE_REQUEST: + case CLAIM_TYPE_ANNOUNCE: + case CLAIM_TYPE_DEL: + backbone_addr = ethhdr->h_source; + break; + default: + return 0; + } + + /* don't accept claim frames from ourselves */ + if (compare_eth(backbone_addr, primary_if->net_dev->dev_addr)) + return 0; + + /* if its already the same group, it is fine. */ + if (bla_dst->group == bla_dst_own->group) + return 2; + + /* lets see if this originator is in our mesh */ + orig_node = orig_hash_find(bat_priv, backbone_addr); + + /* dont accept claims from gateways which are not in + * the same mesh or group. + */ + if (!orig_node) + return 1; + + /* if our mesh friends mac is bigger, use it for ourselves. */ + if (ntohs(bla_dst->group) > ntohs(bla_dst_own->group)) { + bat_dbg(DBG_BLA, bat_priv, + "taking other backbones claim group: %04x\n", + ntohs(bla_dst->group)); + bla_dst_own->group = bla_dst->group; + } + + orig_node_free_ref(orig_node); + + return 2; +} + + +/** + * @bat_priv: the bat priv with all the soft interface information + * @skb: the frame to be checked + * + * Check if this is a claim frame, and process it accordingly. + * + * returns 1 if it was a claim frame, otherwise return 0 to + * tell the callee that it can use the frame on its own. + */ +static int bla_process_claim(struct bat_priv *bat_priv, + struct hard_iface *primary_if, + struct sk_buff *skb) +{ + struct ethhdr *ethhdr; + struct vlan_ethhdr *vhdr; + struct arphdr *arphdr; + uint8_t *hw_src, *hw_dst; + struct bla_claim_dst *bla_dst; + uint16_t proto; + int headlen; + short vid = -1; + int ret; + + ethhdr = (struct ethhdr *)skb_mac_header(skb); + + if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) { + vhdr = (struct vlan_ethhdr *)ethhdr; + vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK; + proto = ntohs(vhdr->h_vlan_encapsulated_proto); + headlen = sizeof(*vhdr); + } else { + proto = ntohs(ethhdr->h_proto); + headlen = sizeof(*ethhdr); + } + + if (proto != ETH_P_ARP) + return 0; /* not a claim frame */ + + /* this must be a ARP frame. check if it is a claim. */ + + if (unlikely(!pskb_may_pull(skb, headlen + arp_hdr_len(skb->dev)))) + return 0; + + /* pskb_may_pull() may have modified the pointers, get ethhdr again */ + ethhdr = (struct ethhdr *)skb_mac_header(skb); + arphdr = (struct arphdr *)((uint8_t *)ethhdr + headlen); + + /* Check whether the ARP frame carries a valid + * IP information + */ + + if (arphdr->ar_hrd != htons(ARPHRD_ETHER)) + return 0; + if (arphdr->ar_pro != htons(ETH_P_IP)) + return 0; + if (arphdr->ar_hln != ETH_ALEN) + return 0; + if (arphdr->ar_pln != 4) + return 0; + + hw_src = (uint8_t *)arphdr + sizeof(struct arphdr); + hw_dst = hw_src + ETH_ALEN + 4; + bla_dst = (struct bla_claim_dst *)hw_dst; + + /* check if it is a claim frame. */ + ret = check_claim_group(bat_priv, primary_if, hw_src, hw_dst, ethhdr); + if (ret == 1) + bat_dbg(DBG_BLA, bat_priv, + "bla_process_claim(): received a claim frame from another group. From: %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n", + ethhdr->h_source, vid, hw_src, hw_dst); + + if (ret < 2) + return ret; + + /* become a backbone gw ourselves on this vlan if not happened yet */ + bla_update_own_backbone_gw(bat_priv, primary_if, vid); + + /* check for the different types of claim frames ... */ + switch (bla_dst->type) { + case CLAIM_TYPE_ADD: + if (handle_claim(bat_priv, primary_if, hw_src, + ethhdr->h_source, vid)) + return 1; + break; + case CLAIM_TYPE_DEL: + if (handle_unclaim(bat_priv, primary_if, + ethhdr->h_source, hw_src, vid)) + return 1; + break; + + case CLAIM_TYPE_ANNOUNCE: + if (handle_announce(bat_priv, hw_src, ethhdr->h_source, vid)) + return 1; + break; + case CLAIM_TYPE_REQUEST: + if (handle_request(bat_priv, primary_if, hw_src, ethhdr, vid)) + return 1; + break; + } + + bat_dbg(DBG_BLA, bat_priv, + "bla_process_claim(): ERROR - this looks like a claim frame, but is useless. eth src %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n", + ethhdr->h_source, vid, hw_src, hw_dst); + return 1; +} + +/* Check when we last heard from other nodes, and remove them in case of + * a time out, or clean all backbone gws if now is set. + */ +static void bla_purge_backbone_gw(struct bat_priv *bat_priv, int now) +{ + struct backbone_gw *backbone_gw; + struct hlist_node *node, *node_tmp; + struct hlist_head *head; + struct hashtable_t *hash; + spinlock_t *list_lock; /* protects write access to the hash lists */ + int i; + + hash = bat_priv->backbone_hash; + if (!hash) + return; + + for (i = 0; i < hash->size; i++) { + head = &hash->table[i]; + list_lock = &hash->list_locks[i]; + + spin_lock_bh(list_lock); + hlist_for_each_entry_safe(backbone_gw, node, node_tmp, + head, hash_entry) { + if (now) + goto purge_now; + if (!has_timed_out(backbone_gw->lasttime, + BLA_BACKBONE_TIMEOUT)) + continue; + + bat_dbg(DBG_BLA, backbone_gw->bat_priv, + "bla_purge_backbone_gw(): backbone gw %pM timed out\n", + backbone_gw->orig); + +purge_now: + /* don't wait for the pending request anymore */ + if (atomic_read(&backbone_gw->request_sent)) + atomic_dec(&bat_priv->bla_num_requests); + + bla_del_backbone_claims(backbone_gw); + + hlist_del_rcu(node); + backbone_gw_free_ref(backbone_gw); + } + spin_unlock_bh(list_lock); + } +} + +/** + * @bat_priv: the bat priv with all the soft interface information + * @primary_if: the selected primary interface, may be NULL if now is set + * @now: whether the whole hash shall be wiped now + * + * Check when we heard last time from our own claims, and remove them in case of + * a time out, or clean all claims if now is set + */ +static void bla_purge_claims(struct bat_priv *bat_priv, + struct hard_iface *primary_if, int now) +{ + struct claim *claim; + struct hlist_node *node; + struct hlist_head *head; + struct hashtable_t *hash; + int i; + + hash = bat_priv->claim_hash; + if (!hash) + return; + + for (i = 0; i < hash->size; i++) { + head = &hash->table[i]; + + rcu_read_lock(); + hlist_for_each_entry_rcu(claim, node, head, hash_entry) { + if (now) + goto purge_now; + if (!compare_eth(claim->backbone_gw->orig, + primary_if->net_dev->dev_addr)) + continue; + if (!has_timed_out(claim->lasttime, + BLA_CLAIM_TIMEOUT)) + continue; + + bat_dbg(DBG_BLA, bat_priv, + "bla_purge_claims(): %pM, vid %d, time out\n", + claim->addr, claim->vid); + +purge_now: + handle_unclaim(bat_priv, primary_if, + claim->backbone_gw->orig, + claim->addr, claim->vid); + } + rcu_read_unlock(); + } +} + +/** + * @bat_priv: the bat priv with all the soft interface information + * @primary_if: the new selected primary_if + * @oldif: the old primary interface, may be NULL + * + * Update the backbone gateways when the own orig address changes. + * + */ +void bla_update_orig_address(struct bat_priv *bat_priv, + struct hard_iface *primary_if, + struct hard_iface *oldif) +{ + struct backbone_gw *backbone_gw; + struct hlist_node *node; + struct hlist_head *head; + struct hashtable_t *hash; + int i; + + /* reset bridge loop avoidance group id */ + bat_priv->claim_dest.group = + htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN)); + + if (!oldif) { + bla_purge_claims(bat_priv, NULL, 1); + bla_purge_backbone_gw(bat_priv, 1); + return; + } + + hash = bat_priv->backbone_hash; + if (!hash) + return; + + for (i = 0; i < hash->size; i++) { + head = &hash->table[i]; + + rcu_read_lock(); + hlist_for_each_entry_rcu(backbone_gw, node, head, hash_entry) { + /* own orig still holds the old value. */ + if (!compare_eth(backbone_gw->orig, + oldif->net_dev->dev_addr)) + continue; + + memcpy(backbone_gw->orig, + primary_if->net_dev->dev_addr, ETH_ALEN); + /* send an announce frame so others will ask for our + * claims and update their tables. + */ + bla_send_announce(bat_priv, backbone_gw); + } + rcu_read_unlock(); + } +} + + + +/* (re)start the timer */ +static void bla_start_timer(struct bat_priv *bat_priv) +{ + INIT_DELAYED_WORK(&bat_priv->bla_work, bla_periodic_work); + queue_delayed_work(bat_event_workqueue, &bat_priv->bla_work, + msecs_to_jiffies(BLA_PERIOD_LENGTH)); +} + +/* periodic work to do: + * * purge structures when they are too old + * * send announcements + */ +static void bla_periodic_work(struct work_struct *work) +{ + struct delayed_work *delayed_work = + container_of(work, struct delayed_work, work); + struct bat_priv *bat_priv = + container_of(delayed_work, struct bat_priv, bla_work); + struct hlist_node *node; + struct hlist_head *head; + struct backbone_gw *backbone_gw; + struct hashtable_t *hash; + struct hard_iface *primary_if; + int i; + + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + goto out; + + bla_purge_claims(bat_priv, primary_if, 0); + bla_purge_backbone_gw(bat_priv, 0); + + if (!atomic_read(&bat_priv->bridge_loop_avoidance)) + goto out; + + hash = bat_priv->backbone_hash; + if (!hash) + goto out; + + for (i = 0; i < hash->size; i++) { + head = &hash->table[i]; + + rcu_read_lock(); + hlist_for_each_entry_rcu(backbone_gw, node, head, hash_entry) { + if (!compare_eth(backbone_gw->orig, + primary_if->net_dev->dev_addr)) + continue; + + backbone_gw->lasttime = jiffies; + + bla_send_announce(bat_priv, backbone_gw); + } + rcu_read_unlock(); + } +out: + if (primary_if) + hardif_free_ref(primary_if); + + bla_start_timer(bat_priv); +} + +/* initialize all bla structures */ +int bla_init(struct bat_priv *bat_priv) +{ + int i; + uint8_t claim_dest[ETH_ALEN] = {0xff, 0x43, 0x05, 0x00, 0x00, 0x00}; + struct hard_iface *primary_if; + + bat_dbg(DBG_BLA, bat_priv, "bla hash registering\n"); + + /* setting claim destination address */ + memcpy(&bat_priv->claim_dest.magic, claim_dest, 3); + bat_priv->claim_dest.type = 0; + primary_if = primary_if_get_selected(bat_priv); + if (primary_if) { + bat_priv->claim_dest.group = + htons(crc16(0, primary_if->net_dev->dev_addr, + ETH_ALEN)); + hardif_free_ref(primary_if); + } else { + bat_priv->claim_dest.group = 0; /* will be set later */ + } + + /* initialize the duplicate list */ + for (i = 0; i < DUPLIST_SIZE; i++) + bat_priv->bcast_duplist[i].entrytime = + jiffies - msecs_to_jiffies(DUPLIST_TIMEOUT); + bat_priv->bcast_duplist_curr = 0; + + if (bat_priv->claim_hash) + return 1; + + bat_priv->claim_hash = hash_new(128); + bat_priv->backbone_hash = hash_new(32); + + if (!bat_priv->claim_hash || !bat_priv->backbone_hash) + return -1; + + bat_dbg(DBG_BLA, bat_priv, "bla hashes initialized\n"); + + bla_start_timer(bat_priv); + return 1; +} + +/** + * @bat_priv: the bat priv with all the soft interface information + * @bcast_packet: originator mac address + * @hdr_size: maximum length of the frame + * + * check if it is on our broadcast list. Another gateway might + * have sent the same packet because it is connected to the same backbone, + * so we have to remove this duplicate. + * + * This is performed by checking the CRC, which will tell us + * with a good chance that it is the same packet. If it is furthermore + * sent by another host, drop it. We allow equal packets from + * the same host however as this might be intended. + * + **/ + +int bla_check_bcast_duplist(struct bat_priv *bat_priv, + struct bcast_packet *bcast_packet, + int hdr_size) +{ + int i, length, curr; + uint8_t *content; + uint16_t crc; + struct bcast_duplist_entry *entry; + + length = hdr_size - sizeof(*bcast_packet); + content = (uint8_t *)bcast_packet; + content += sizeof(*bcast_packet); + + /* calculate the crc ... */ + crc = crc16(0, content, length); + + for (i = 0 ; i < DUPLIST_SIZE; i++) { + curr = (bat_priv->bcast_duplist_curr + i) % DUPLIST_SIZE; + entry = &bat_priv->bcast_duplist[curr]; + + /* we can stop searching if the entry is too old ; + * later entries will be even older + */ + if (has_timed_out(entry->entrytime, DUPLIST_TIMEOUT)) + break; + + if (entry->crc != crc) + continue; + + if (compare_eth(entry->orig, bcast_packet->orig)) + continue; + + /* this entry seems to match: same crc, not too old, + * and from another gw. therefore return 1 to forbid it. + */ + return 1; + } + /* not found, add a new entry (overwrite the oldest entry) */ + curr = (bat_priv->bcast_duplist_curr + DUPLIST_SIZE - 1) % DUPLIST_SIZE; + entry = &bat_priv->bcast_duplist[curr]; + entry->crc = crc; + entry->entrytime = jiffies; + memcpy(entry->orig, bcast_packet->orig, ETH_ALEN); + bat_priv->bcast_duplist_curr = curr; + + /* allow it, its the first occurence. */ + return 0; +} + + + +/** + * @bat_priv: the bat priv with all the soft interface information + * @orig: originator mac address + * + * check if the originator is a gateway for any VLAN ID. + * + * returns 1 if it is found, 0 otherwise + * + */ + +int bla_is_backbone_gw_orig(struct bat_priv *bat_priv, uint8_t *orig) +{ + struct hashtable_t *hash = bat_priv->backbone_hash; + struct hlist_head *head; + struct hlist_node *node; + struct backbone_gw *backbone_gw; + int i; + + if (!atomic_read(&bat_priv->bridge_loop_avoidance)) + return 0; + + if (!hash) + return 0; + + for (i = 0; i < hash->size; i++) { + head = &hash->table[i]; + + rcu_read_lock(); + hlist_for_each_entry_rcu(backbone_gw, node, head, hash_entry) { + if (compare_eth(backbone_gw->orig, orig)) { + rcu_read_unlock(); + return 1; + } + } + rcu_read_unlock(); + } + + return 0; +} + + +/** + * @skb: the frame to be checked + * @orig_node: the orig_node of the frame + * @hdr_size: maximum length of the frame + * + * bla_is_backbone_gw inspects the skb for the VLAN ID and returns 1 + * if the orig_node is also a gateway on the soft interface, otherwise it + * returns 0. + * + */ +int bla_is_backbone_gw(struct sk_buff *skb, + struct orig_node *orig_node, int hdr_size) +{ + struct ethhdr *ethhdr; + struct vlan_ethhdr *vhdr; + struct backbone_gw *backbone_gw; + short vid = -1; + + if (!atomic_read(&orig_node->bat_priv->bridge_loop_avoidance)) + return 0; + + /* first, find out the vid. */ + if (!pskb_may_pull(skb, hdr_size + sizeof(struct ethhdr))) + return 0; + + ethhdr = (struct ethhdr *)(((uint8_t *)skb->data) + hdr_size); + + if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) { + if (!pskb_may_pull(skb, hdr_size + sizeof(struct vlan_ethhdr))) + return 0; + + vhdr = (struct vlan_ethhdr *)(((uint8_t *)skb->data) + + hdr_size); + vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK; + } + + /* see if this originator is a backbone gw for this VLAN */ + + backbone_gw = backbone_hash_find(orig_node->bat_priv, + orig_node->orig, vid); + if (!backbone_gw) + return 0; + + backbone_gw_free_ref(backbone_gw); + return 1; +} + +/* free all bla structures (for softinterface free or module unload) */ +void bla_free(struct bat_priv *bat_priv) +{ + struct hard_iface *primary_if; + + cancel_delayed_work_sync(&bat_priv->bla_work); + primary_if = primary_if_get_selected(bat_priv); + + if (bat_priv->claim_hash) { + bla_purge_claims(bat_priv, primary_if, 1); + hash_destroy(bat_priv->claim_hash); + bat_priv->claim_hash = NULL; + } + if (bat_priv->backbone_hash) { + bla_purge_backbone_gw(bat_priv, 1); + hash_destroy(bat_priv->backbone_hash); + bat_priv->backbone_hash = NULL; + } + if (primary_if) + hardif_free_ref(primary_if); +} + +/** + * @bat_priv: the bat priv with all the soft interface information + * @skb: the frame to be checked + * @vid: the VLAN ID of the frame + * + * bla_rx avoidance checks if: + * * we have to race for a claim + * * if the frame is allowed on the LAN + * + * in these cases, the skb is further handled by this function and + * returns 1, otherwise it returns 0 and the caller shall further + * process the skb. + * + */ +int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid) +{ + struct ethhdr *ethhdr; + struct claim search_claim, *claim = NULL; + struct hard_iface *primary_if; + int ret; + + ethhdr = (struct ethhdr *)skb_mac_header(skb); + + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + goto handled; + + if (!atomic_read(&bat_priv->bridge_loop_avoidance)) + goto allow; + + + if (unlikely(atomic_read(&bat_priv->bla_num_requests))) + /* don't allow broadcasts while requests are in flight */ + if (is_multicast_ether_addr(ethhdr->h_dest)) + goto handled; + + memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN); + search_claim.vid = vid; + claim = claim_hash_find(bat_priv, &search_claim); + + if (!claim) { + /* possible optimization: race for a claim */ + /* No claim exists yet, claim it for us! + */ + handle_claim(bat_priv, primary_if, + primary_if->net_dev->dev_addr, + ethhdr->h_source, vid); + goto allow; + } + + /* if it is our own claim ... */ + if (compare_eth(claim->backbone_gw->orig, + primary_if->net_dev->dev_addr)) { + /* ... allow it in any case */ + claim->lasttime = jiffies; + goto allow; + } + + /* if it is a broadcast ... */ + if (is_multicast_ether_addr(ethhdr->h_dest)) { + /* ... drop it. the responsible gateway is in charge. */ + goto handled; + } else { + /* seems the client considers us as its best gateway. + * send a claim and update the claim table + * immediately. + */ + handle_claim(bat_priv, primary_if, + primary_if->net_dev->dev_addr, + ethhdr->h_source, vid); + goto allow; + } +allow: + bla_update_own_backbone_gw(bat_priv, primary_if, vid); + ret = 0; + goto out; + +handled: + kfree_skb(skb); + ret = 1; + +out: + if (primary_if) + hardif_free_ref(primary_if); + if (claim) + claim_free_ref(claim); + return ret; +} + +/** + * @bat_priv: the bat priv with all the soft interface information + * @skb: the frame to be checked + * @vid: the VLAN ID of the frame + * + * bla_tx checks if: + * * a claim was received which has to be processed + * * the frame is allowed on the mesh + * + * in these cases, the skb is further handled by this function and + * returns 1, otherwise it returns 0 and the caller shall further + * process the skb. + * + */ +int bla_tx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid) +{ + struct ethhdr *ethhdr; + struct claim search_claim, *claim = NULL; + struct hard_iface *primary_if; + int ret = 0; + + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + goto out; + + if (!atomic_read(&bat_priv->bridge_loop_avoidance)) + goto allow; + + /* in VLAN case, the mac header might not be set. */ + skb_reset_mac_header(skb); + + if (bla_process_claim(bat_priv, primary_if, skb)) + goto handled; + + ethhdr = (struct ethhdr *)skb_mac_header(skb); + + if (unlikely(atomic_read(&bat_priv->bla_num_requests))) + /* don't allow broadcasts while requests are in flight */ + if (is_multicast_ether_addr(ethhdr->h_dest)) + goto handled; + + memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN); + search_claim.vid = vid; + + claim = claim_hash_find(bat_priv, &search_claim); + + /* if no claim exists, allow it. */ + if (!claim) + goto allow; + + /* check if we are responsible. */ + if (compare_eth(claim->backbone_gw->orig, + primary_if->net_dev->dev_addr)) { + /* if yes, the client has roamed and we have + * to unclaim it. + */ + handle_unclaim(bat_priv, primary_if, + primary_if->net_dev->dev_addr, + ethhdr->h_source, vid); + goto allow; + } + + /* check if it is a multicast/broadcast frame */ + if (is_multicast_ether_addr(ethhdr->h_dest)) { + /* drop it. the responsible gateway has forwarded it into + * the backbone network. + */ + goto handled; + } else { + /* we must allow it. at least if we are + * responsible for the DESTINATION. + */ + goto allow; + } +allow: + bla_update_own_backbone_gw(bat_priv, primary_if, vid); + ret = 0; + goto out; +handled: + ret = 1; +out: + if (primary_if) + hardif_free_ref(primary_if); + if (claim) + claim_free_ref(claim); + return ret; +} + +int bla_claim_table_seq_print_text(struct seq_file *seq, void *offset) +{ + struct net_device *net_dev = (struct net_device *)seq->private; + struct bat_priv *bat_priv = netdev_priv(net_dev); + struct hashtable_t *hash = bat_priv->claim_hash; + struct claim *claim; + struct hard_iface *primary_if; + struct hlist_node *node; + struct hlist_head *head; + uint32_t i; + bool is_own; + int ret = 0; + + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) { + ret = seq_printf(seq, + "BATMAN mesh %s disabled - please specify interfaces to enable it\n", + net_dev->name); + goto out; + } + + if (primary_if->if_status != IF_ACTIVE) { + ret = seq_printf(seq, + "BATMAN mesh %s disabled - primary interface not active\n", + net_dev->name); + goto out; + } + + seq_printf(seq, + "Claims announced for the mesh %s (orig %pM, group id %04x)\n", + net_dev->name, primary_if->net_dev->dev_addr, + ntohs(bat_priv->claim_dest.group)); + seq_printf(seq, " %-17s %-5s %-17s [o] (%-4s)\n", + "Client", "VID", "Originator", "CRC"); + for (i = 0; i < hash->size; i++) { + head = &hash->table[i]; + + rcu_read_lock(); + hlist_for_each_entry_rcu(claim, node, head, hash_entry) { + is_own = compare_eth(claim->backbone_gw->orig, + primary_if->net_dev->dev_addr); + seq_printf(seq, " * %pM on % 5d by %pM [%c] (%04x)\n", + claim->addr, claim->vid, + claim->backbone_gw->orig, + (is_own ? 'x' : ' '), + claim->backbone_gw->crc); + } + rcu_read_unlock(); + } +out: + if (primary_if) + hardif_free_ref(primary_if); + return ret; +} diff --git a/net/batman-adv/bridge_loop_avoidance.h b/net/batman-adv/bridge_loop_avoidance.h new file mode 100644 index 0000000..4a8e4fc --- /dev/null +++ b/net/batman-adv/bridge_loop_avoidance.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2011 B.A.T.M.A.N. contributors: + * + * Simon Wunderlich + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#ifndef _NET_BATMAN_ADV_BLA_H_ +#define _NET_BATMAN_ADV_BLA_H_ + +#ifdef CONFIG_BATMAN_ADV_BLA +int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid); +int bla_tx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid); +int bla_is_backbone_gw(struct sk_buff *skb, + struct orig_node *orig_node, int hdr_size); +int bla_claim_table_seq_print_text(struct seq_file *seq, void *offset); +int bla_is_backbone_gw_orig(struct bat_priv *bat_priv, uint8_t *orig); +int bla_check_bcast_duplist(struct bat_priv *bat_priv, + struct bcast_packet *bcast_packet, int hdr_size); +void bla_update_orig_address(struct bat_priv *bat_priv, + struct hard_iface *primary_if, + struct hard_iface *oldif); +int bla_init(struct bat_priv *bat_priv); +void bla_free(struct bat_priv *bat_priv); + +#define BLA_CRC_INIT 0 +#else /* ifdef CONFIG_BATMAN_ADV_BLA */ + +static inline int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, + short vid) +{ + return 0; +} + +static inline int bla_tx(struct bat_priv *bat_priv, struct sk_buff *skb, + short vid) +{ + return 0; +} + +static inline int bla_is_backbone_gw(struct sk_buff *skb, + struct orig_node *orig_node, + int hdr_size) +{ + return 0; +} + +static inline int bla_claim_table_seq_print_text(struct seq_file *seq, + void *offset) +{ + return 0; +} + +static inline int bla_is_backbone_gw_orig(struct bat_priv *bat_priv, + uint8_t *orig) +{ + return 0; +} + +static inline int bla_check_bcast_duplist(struct bat_priv *bat_priv, + struct bcast_packet *bcast_packet, + int hdr_size) +{ + return 0; +} + +static inline void bla_update_orig_address(struct bat_priv *bat_priv, + struct hard_iface *primary_if, + struct hard_iface *oldif) +{ +} + +static inline int bla_init(struct bat_priv *bat_priv) +{ + return 1; +} + +static inline void bla_free(struct bat_priv *bat_priv) +{ +} + +#endif /* ifdef CONFIG_BATMAN_ADV_BLA */ + +#endif /* ifndef _NET_BATMAN_ADV_BLA_H_ */ diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 3778977..8c4b790 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -28,6 +28,7 @@ #include "bat_sysfs.h" #include "originator.h" #include "hash.h" +#include "bridge_loop_avoidance.h" #include <linux/if_arp.h> @@ -107,7 +108,8 @@ out: return hard_iface; } -static void primary_if_update_addr(struct bat_priv *bat_priv) +static void primary_if_update_addr(struct bat_priv *bat_priv, + struct hard_iface *oldif) { struct vis_packet *vis_packet; struct hard_iface *primary_if; @@ -122,6 +124,7 @@ static void primary_if_update_addr(struct bat_priv *bat_priv) memcpy(vis_packet->sender_orig, primary_if->net_dev->dev_addr, ETH_ALEN); + bla_update_orig_address(bat_priv, primary_if, oldif); out: if (primary_if) hardif_free_ref(primary_if); @@ -140,14 +143,15 @@ static void primary_if_select(struct bat_priv *bat_priv, curr_hard_iface = rcu_dereference_protected(bat_priv->primary_if, 1); rcu_assign_pointer(bat_priv->primary_if, new_hard_iface); - if (curr_hard_iface) - hardif_free_ref(curr_hard_iface); - if (!new_hard_iface) - return; + goto out; bat_priv->bat_algo_ops->bat_ogm_init_primary(new_hard_iface); - primary_if_update_addr(bat_priv); + primary_if_update_addr(bat_priv, curr_hard_iface); + +out: + if (curr_hard_iface) + hardif_free_ref(curr_hard_iface); } static bool hardif_is_iface_up(const struct hard_iface *hard_iface) @@ -531,7 +535,7 @@ static int hard_if_event(struct notifier_block *this, goto hardif_put; if (hard_iface == primary_if) - primary_if_update_addr(bat_priv); + primary_if_update_addr(bat_priv, NULL); break; default: break; diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 6d51caa..e67ca96 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -30,6 +30,7 @@ #include "translation-table.h" #include "hard-interface.h" #include "gateway_client.h" +#include "bridge_loop_avoidance.h" #include "vis.h" #include "hash.h" #include "bat_algo.h" @@ -96,13 +97,10 @@ int mesh_init(struct net_device *soft_iface) spin_lock_init(&bat_priv->gw_list_lock); spin_lock_init(&bat_priv->vis_hash_lock); spin_lock_init(&bat_priv->vis_list_lock); - spin_lock_init(&bat_priv->softif_neigh_lock); - spin_lock_init(&bat_priv->softif_neigh_vid_lock); INIT_HLIST_HEAD(&bat_priv->forw_bat_list); INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); INIT_HLIST_HEAD(&bat_priv->gw_list); - INIT_HLIST_HEAD(&bat_priv->softif_neigh_vids); INIT_LIST_HEAD(&bat_priv->tt_changes_list); INIT_LIST_HEAD(&bat_priv->tt_req_list); INIT_LIST_HEAD(&bat_priv->tt_roam_list); @@ -118,6 +116,9 @@ int mesh_init(struct net_device *soft_iface) if (vis_init(bat_priv) < 1) goto err; + if (bla_init(bat_priv) < 1) + goto err; + atomic_set(&bat_priv->gw_reselect, 0); atomic_set(&bat_priv->mesh_state, MESH_ACTIVE); goto end; @@ -145,7 +146,7 @@ void mesh_free(struct net_device *soft_iface) tt_free(bat_priv); - softif_neigh_purge(bat_priv); + bla_free(bat_priv); atomic_set(&bat_priv->mesh_state, MESH_INACTIVE); } diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 94fa1c2..d9832ac 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -65,7 +65,7 @@ #define NULL_IFINDEX 0 /* dummy ifindex used to avoid iface checks */ -#define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE) +#define NUM_WORDS BITS_TO_LONGS(TQ_LOCAL_WINDOW_SIZE) #define LOG_BUF_LEN 8192 /* has to be a power of 2 */ @@ -80,8 +80,12 @@ #define MAX_AGGREGATION_BYTES 512 #define MAX_AGGREGATION_MS 100 -#define SOFTIF_NEIGH_TIMEOUT 180000 /* 3 minutes */ +#define BLA_PERIOD_LENGTH 10000 /* 10 seconds */ +#define BLA_BACKBONE_TIMEOUT (BLA_PERIOD_LENGTH * 3) +#define BLA_CLAIM_TIMEOUT (BLA_PERIOD_LENGTH * 10) +#define DUPLIST_SIZE 16 +#define DUPLIST_TIMEOUT 500 /* 500 ms */ /* don't reset again within 30 seconds */ #define RESET_PROTECTION_MS 30000 #define EXPECTED_SEQNO_RANGE 65536 @@ -119,7 +123,8 @@ enum dbg_level { DBG_BATMAN = 1 << 0, DBG_ROUTES = 1 << 1, /* route added / changed / deleted */ DBG_TT = 1 << 2, /* translation table operations */ - DBG_ALL = 7 + DBG_BLA = 1 << 3, /* bridge loop avoidance */ + DBG_ALL = 15 }; /* Kernel headers */ diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 43c0a4f..ce49698 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -28,6 +28,7 @@ #include "hard-interface.h" #include "unicast.h" #include "soft-interface.h" +#include "bridge_loop_avoidance.h" static void purge_orig(struct work_struct *work); @@ -375,8 +376,6 @@ static void _purge_orig(struct bat_priv *bat_priv) gw_node_purge(bat_priv); gw_election(bat_priv); - - softif_neigh_purge(bat_priv); } static void purge_orig(struct work_struct *work) diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index 441f3db..59800e8 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h @@ -90,6 +90,23 @@ enum tt_client_flags { TT_CLIENT_PENDING = 1 << 10 }; +/* claim frame types for the bridge loop avoidance */ +enum bla_claimframe { + CLAIM_TYPE_ADD = 0x00, + CLAIM_TYPE_DEL = 0x01, + CLAIM_TYPE_ANNOUNCE = 0x02, + CLAIM_TYPE_REQUEST = 0x03 +}; + +/* the destination hardware field in the ARP frame is used to + * transport the claim type and the group id + */ +struct bla_claim_dst { + uint8_t magic[3]; /* FF:43:05 */ + uint8_t type; /* bla_claimframe */ + uint16_t group; /* group id */ +} __packed; + struct batman_header { uint8_t packet_type; uint8_t version; /* batman version field */ @@ -100,8 +117,8 @@ struct batman_ogm_packet { struct batman_header header; uint8_t flags; /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */ uint32_t seqno; - uint8_t orig[6]; - uint8_t prev_sender[6]; + uint8_t orig[ETH_ALEN]; + uint8_t prev_sender[ETH_ALEN]; uint8_t gw_flags; /* flags related to gateway class */ uint8_t tq; uint8_t tt_num_changes; @@ -114,8 +131,8 @@ struct batman_ogm_packet { struct icmp_packet { struct batman_header header; uint8_t msg_type; /* see ICMP message types above */ - uint8_t dst[6]; - uint8_t orig[6]; + uint8_t dst[ETH_ALEN]; + uint8_t orig[ETH_ALEN]; uint16_t seqno; uint8_t uid; uint8_t reserved; @@ -128,8 +145,8 @@ struct icmp_packet { struct icmp_packet_rr { struct batman_header header; uint8_t msg_type; /* see ICMP message types above */ - uint8_t dst[6]; - uint8_t orig[6]; + uint8_t dst[ETH_ALEN]; + uint8_t orig[ETH_ALEN]; uint16_t seqno; uint8_t uid; uint8_t rr_cur; @@ -139,16 +156,16 @@ struct icmp_packet_rr { struct unicast_packet { struct batman_header header; uint8_t ttvn; /* destination translation table version number */ - uint8_t dest[6]; + uint8_t dest[ETH_ALEN]; } __packed; struct unicast_frag_packet { struct batman_header header; uint8_t ttvn; /* destination translation table version number */ - uint8_t dest[6]; + uint8_t dest[ETH_ALEN]; uint8_t flags; uint8_t align; - uint8_t orig[6]; + uint8_t orig[ETH_ALEN]; uint16_t seqno; } __packed; @@ -156,7 +173,7 @@ struct bcast_packet { struct batman_header header; uint8_t reserved; uint32_t seqno; - uint8_t orig[6]; + uint8_t orig[ETH_ALEN]; } __packed; struct vis_packet { @@ -165,9 +182,9 @@ struct vis_packet { uint32_t seqno; /* sequence number */ uint8_t entries; /* number of entries behind this struct */ uint8_t reserved; - uint8_t vis_orig[6]; /* originator that announces its neighbors */ - uint8_t target_orig[6]; /* who should receive this packet */ - uint8_t sender_orig[6]; /* who sent or rebroadcasted this packet */ + uint8_t vis_orig[ETH_ALEN]; /* originator reporting its neighbors */ + uint8_t target_orig[ETH_ALEN]; /* who should receive this packet */ + uint8_t sender_orig[ETH_ALEN]; /* who sent or forwarded this packet */ } __packed; struct tt_query_packet { diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 7f8e158..78eddc9 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -29,6 +29,10 @@ #include "originator.h" #include "vis.h" #include "unicast.h" +#include "bridge_loop_avoidance.h" + +static int route_unicast_packet(struct sk_buff *skb, + struct hard_iface *recv_if); void slide_own_bcast_window(struct hard_iface *hard_iface) { @@ -52,7 +56,7 @@ void slide_own_bcast_window(struct hard_iface *hard_iface) bit_get_packet(bat_priv, word, 1, 0); orig_node->bcast_own_sum[hard_iface->if_num] = - bit_packet_count(word); + bitmap_weight(word, TQ_LOCAL_WINDOW_SIZE); spin_unlock_bh(&orig_node->ogm_cnt_lock); } rcu_read_unlock(); @@ -669,6 +673,13 @@ int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if) if (!is_my_mac(roam_adv_packet->dst)) return route_unicast_packet(skb, recv_if); + /* check if it is a backbone gateway. we don't accept + * roaming advertisement from it, as it has the same + * entries as we have. + */ + if (bla_is_backbone_gw_orig(bat_priv, roam_adv_packet->src)) + goto out; + orig_node = orig_hash_find(bat_priv, roam_adv_packet->src); if (!orig_node) goto out; @@ -798,7 +809,7 @@ static int check_unicast_packet(struct sk_buff *skb, int hdr_size) return 0; } -int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) +static int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) { struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); struct orig_node *orig_node = NULL; @@ -1047,8 +1058,8 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if) spin_lock_bh(&orig_node->bcast_seqno_lock); /* check whether the packet is a duplicate */ - if (get_bit_status(orig_node->bcast_bits, orig_node->last_bcast_seqno, - ntohl(bcast_packet->seqno))) + if (bat_test_bit(orig_node->bcast_bits, orig_node->last_bcast_seqno, + ntohl(bcast_packet->seqno))) goto spin_unlock; seq_diff = ntohl(bcast_packet->seqno) - orig_node->last_bcast_seqno; @@ -1065,9 +1076,19 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if) spin_unlock_bh(&orig_node->bcast_seqno_lock); + /* check whether this has been sent by another originator before */ + if (bla_check_bcast_duplist(bat_priv, bcast_packet, hdr_size)) + goto out; + /* rebroadcast packet */ add_bcast_packet_to_list(bat_priv, skb, 1); + /* don't hand the broadcast up if it is from an originator + * from the same backbone. + */ + if (bla_is_backbone_gw(skb, orig_node, hdr_size)) + goto out; + /* broadcast for me */ interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size); ret = NET_RX_SUCCESS; diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h index 92ac100..3d729cb 100644 --- a/net/batman-adv/routing.h +++ b/net/batman-adv/routing.h @@ -25,7 +25,6 @@ void slide_own_bcast_window(struct hard_iface *hard_iface); void update_route(struct bat_priv *bat_priv, struct orig_node *orig_node, struct neigh_node *neigh_node); -int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if); int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if); diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index a5590f4..efe0fba 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -36,6 +36,7 @@ #include <linux/etherdevice.h> #include <linux/if_vlan.h> #include "unicast.h" +#include "bridge_loop_avoidance.h" static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd); @@ -73,439 +74,6 @@ int my_skb_head_push(struct sk_buff *skb, unsigned int len) return 0; } -static void softif_neigh_free_ref(struct softif_neigh *softif_neigh) -{ - if (atomic_dec_and_test(&softif_neigh->refcount)) - kfree_rcu(softif_neigh, rcu); -} - -static void softif_neigh_vid_free_rcu(struct rcu_head *rcu) -{ - struct softif_neigh_vid *softif_neigh_vid; - struct softif_neigh *softif_neigh; - struct hlist_node *node, *node_tmp; - struct bat_priv *bat_priv; - - softif_neigh_vid = container_of(rcu, struct softif_neigh_vid, rcu); - bat_priv = softif_neigh_vid->bat_priv; - - spin_lock_bh(&bat_priv->softif_neigh_lock); - hlist_for_each_entry_safe(softif_neigh, node, node_tmp, - &softif_neigh_vid->softif_neigh_list, list) { - hlist_del_rcu(&softif_neigh->list); - softif_neigh_free_ref(softif_neigh); - } - spin_unlock_bh(&bat_priv->softif_neigh_lock); - - kfree(softif_neigh_vid); -} - -static void softif_neigh_vid_free_ref(struct softif_neigh_vid *softif_neigh_vid) -{ - if (atomic_dec_and_test(&softif_neigh_vid->refcount)) - call_rcu(&softif_neigh_vid->rcu, softif_neigh_vid_free_rcu); -} - -static struct softif_neigh_vid *softif_neigh_vid_get(struct bat_priv *bat_priv, - short vid) -{ - struct softif_neigh_vid *softif_neigh_vid; - struct hlist_node *node; - - rcu_read_lock(); - hlist_for_each_entry_rcu(softif_neigh_vid, node, - &bat_priv->softif_neigh_vids, list) { - if (softif_neigh_vid->vid != vid) - continue; - - if (!atomic_inc_not_zero(&softif_neigh_vid->refcount)) - continue; - - goto out; - } - - softif_neigh_vid = kzalloc(sizeof(*softif_neigh_vid), GFP_ATOMIC); - if (!softif_neigh_vid) - goto out; - - softif_neigh_vid->vid = vid; - softif_neigh_vid->bat_priv = bat_priv; - - /* initialize with 2 - caller decrements counter by one */ - atomic_set(&softif_neigh_vid->refcount, 2); - INIT_HLIST_HEAD(&softif_neigh_vid->softif_neigh_list); - INIT_HLIST_NODE(&softif_neigh_vid->list); - spin_lock_bh(&bat_priv->softif_neigh_vid_lock); - hlist_add_head_rcu(&softif_neigh_vid->list, - &bat_priv->softif_neigh_vids); - spin_unlock_bh(&bat_priv->softif_neigh_vid_lock); - -out: - rcu_read_unlock(); - return softif_neigh_vid; -} - -static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv, - const uint8_t *addr, short vid) -{ - struct softif_neigh_vid *softif_neigh_vid; - struct softif_neigh *softif_neigh = NULL; - struct hlist_node *node; - - softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); - if (!softif_neigh_vid) - goto out; - - rcu_read_lock(); - hlist_for_each_entry_rcu(softif_neigh, node, - &softif_neigh_vid->softif_neigh_list, - list) { - if (!compare_eth(softif_neigh->addr, addr)) - continue; - - if (!atomic_inc_not_zero(&softif_neigh->refcount)) - continue; - - softif_neigh->last_seen = jiffies; - goto unlock; - } - - softif_neigh = kzalloc(sizeof(*softif_neigh), GFP_ATOMIC); - if (!softif_neigh) - goto unlock; - - memcpy(softif_neigh->addr, addr, ETH_ALEN); - softif_neigh->last_seen = jiffies; - /* initialize with 2 - caller decrements counter by one */ - atomic_set(&softif_neigh->refcount, 2); - - INIT_HLIST_NODE(&softif_neigh->list); - spin_lock_bh(&bat_priv->softif_neigh_lock); - hlist_add_head_rcu(&softif_neigh->list, - &softif_neigh_vid->softif_neigh_list); - spin_unlock_bh(&bat_priv->softif_neigh_lock); - -unlock: - rcu_read_unlock(); -out: - if (softif_neigh_vid) - softif_neigh_vid_free_ref(softif_neigh_vid); - return softif_neigh; -} - -static struct softif_neigh *softif_neigh_get_selected( - struct softif_neigh_vid *softif_neigh_vid) -{ - struct softif_neigh *softif_neigh; - - rcu_read_lock(); - softif_neigh = rcu_dereference(softif_neigh_vid->softif_neigh); - - if (softif_neigh && !atomic_inc_not_zero(&softif_neigh->refcount)) - softif_neigh = NULL; - - rcu_read_unlock(); - return softif_neigh; -} - -static struct softif_neigh *softif_neigh_vid_get_selected( - struct bat_priv *bat_priv, - short vid) -{ - struct softif_neigh_vid *softif_neigh_vid; - struct softif_neigh *softif_neigh = NULL; - - softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); - if (!softif_neigh_vid) - goto out; - - softif_neigh = softif_neigh_get_selected(softif_neigh_vid); -out: - if (softif_neigh_vid) - softif_neigh_vid_free_ref(softif_neigh_vid); - return softif_neigh; -} - -static void softif_neigh_vid_select(struct bat_priv *bat_priv, - struct softif_neigh *new_neigh, - short vid) -{ - struct softif_neigh_vid *softif_neigh_vid; - struct softif_neigh *curr_neigh; - - softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); - if (!softif_neigh_vid) - goto out; - - spin_lock_bh(&bat_priv->softif_neigh_lock); - - if (new_neigh && !atomic_inc_not_zero(&new_neigh->refcount)) - new_neigh = NULL; - - curr_neigh = rcu_dereference_protected(softif_neigh_vid->softif_neigh, - 1); - rcu_assign_pointer(softif_neigh_vid->softif_neigh, new_neigh); - - if ((curr_neigh) && (!new_neigh)) - bat_dbg(DBG_ROUTES, bat_priv, - "Removing mesh exit point on vid: %d (prev: %pM).\n", - vid, curr_neigh->addr); - else if ((curr_neigh) && (new_neigh)) - bat_dbg(DBG_ROUTES, bat_priv, - "Changing mesh exit point on vid: %d from %pM to %pM.\n", - vid, curr_neigh->addr, new_neigh->addr); - else if ((!curr_neigh) && (new_neigh)) - bat_dbg(DBG_ROUTES, bat_priv, - "Setting mesh exit point on vid: %d to %pM.\n", - vid, new_neigh->addr); - - if (curr_neigh) - softif_neigh_free_ref(curr_neigh); - - spin_unlock_bh(&bat_priv->softif_neigh_lock); - -out: - if (softif_neigh_vid) - softif_neigh_vid_free_ref(softif_neigh_vid); -} - -static void softif_neigh_vid_deselect(struct bat_priv *bat_priv, - struct softif_neigh_vid *softif_neigh_vid) -{ - struct softif_neigh *curr_neigh; - struct softif_neigh *softif_neigh = NULL, *softif_neigh_tmp; - struct hard_iface *primary_if = NULL; - struct hlist_node *node; - - primary_if = primary_if_get_selected(bat_priv); - if (!primary_if) - goto out; - - /* find new softif_neigh immediately to avoid temporary loops */ - rcu_read_lock(); - curr_neigh = rcu_dereference(softif_neigh_vid->softif_neigh); - - hlist_for_each_entry_rcu(softif_neigh_tmp, node, - &softif_neigh_vid->softif_neigh_list, - list) { - if (softif_neigh_tmp == curr_neigh) - continue; - - /* we got a neighbor but its mac is 'bigger' than ours */ - if (memcmp(primary_if->net_dev->dev_addr, - softif_neigh_tmp->addr, ETH_ALEN) < 0) - continue; - - if (!atomic_inc_not_zero(&softif_neigh_tmp->refcount)) - continue; - - softif_neigh = softif_neigh_tmp; - goto unlock; - } - -unlock: - rcu_read_unlock(); -out: - softif_neigh_vid_select(bat_priv, softif_neigh, softif_neigh_vid->vid); - - if (primary_if) - hardif_free_ref(primary_if); - if (softif_neigh) - softif_neigh_free_ref(softif_neigh); -} - -int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) -{ - struct net_device *net_dev = (struct net_device *)seq->private; - struct bat_priv *bat_priv = netdev_priv(net_dev); - struct softif_neigh_vid *softif_neigh_vid; - struct softif_neigh *softif_neigh; - struct hard_iface *primary_if; - struct hlist_node *node, *node_tmp; - struct softif_neigh *curr_softif_neigh; - int ret = 0, last_seen_secs, last_seen_msecs; - - primary_if = primary_if_get_selected(bat_priv); - if (!primary_if) { - ret = seq_printf(seq, - "BATMAN mesh %s disabled - please specify interfaces to enable it\n", - net_dev->name); - goto out; - } - - if (primary_if->if_status != IF_ACTIVE) { - ret = seq_printf(seq, - "BATMAN mesh %s disabled - primary interface not active\n", - net_dev->name); - goto out; - } - - seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name); - - rcu_read_lock(); - hlist_for_each_entry_rcu(softif_neigh_vid, node, - &bat_priv->softif_neigh_vids, list) { - seq_printf(seq, " %-15s %s on vid: %d\n", - "Originator", "last-seen", softif_neigh_vid->vid); - - curr_softif_neigh = softif_neigh_get_selected(softif_neigh_vid); - - hlist_for_each_entry_rcu(softif_neigh, node_tmp, - &softif_neigh_vid->softif_neigh_list, - list) { - last_seen_secs = jiffies_to_msecs(jiffies - - softif_neigh->last_seen) / 1000; - last_seen_msecs = jiffies_to_msecs(jiffies - - softif_neigh->last_seen) % 1000; - seq_printf(seq, "%s %pM %3i.%03is\n", - curr_softif_neigh == softif_neigh - ? "=>" : " ", softif_neigh->addr, - last_seen_secs, last_seen_msecs); - } - - if (curr_softif_neigh) - softif_neigh_free_ref(curr_softif_neigh); - - seq_printf(seq, "\n"); - } - rcu_read_unlock(); - -out: - if (primary_if) - hardif_free_ref(primary_if); - return ret; -} - -void softif_neigh_purge(struct bat_priv *bat_priv) -{ - struct softif_neigh *softif_neigh, *curr_softif_neigh; - struct softif_neigh_vid *softif_neigh_vid; - struct hlist_node *node, *node_tmp, *node_tmp2; - int do_deselect; - - rcu_read_lock(); - hlist_for_each_entry_rcu(softif_neigh_vid, node, - &bat_priv->softif_neigh_vids, list) { - if (!atomic_inc_not_zero(&softif_neigh_vid->refcount)) - continue; - - curr_softif_neigh = softif_neigh_get_selected(softif_neigh_vid); - do_deselect = 0; - - spin_lock_bh(&bat_priv->softif_neigh_lock); - hlist_for_each_entry_safe(softif_neigh, node_tmp, node_tmp2, - &softif_neigh_vid->softif_neigh_list, - list) { - if ((!has_timed_out(softif_neigh->last_seen, - SOFTIF_NEIGH_TIMEOUT)) && - (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)) - continue; - - if (curr_softif_neigh == softif_neigh) { - bat_dbg(DBG_ROUTES, bat_priv, - "Current mesh exit point on vid: %d '%pM' vanished.\n", - softif_neigh_vid->vid, - softif_neigh->addr); - do_deselect = 1; - } - - hlist_del_rcu(&softif_neigh->list); - softif_neigh_free_ref(softif_neigh); - } - spin_unlock_bh(&bat_priv->softif_neigh_lock); - - /* soft_neigh_vid_deselect() needs to acquire the - * softif_neigh_lock */ - if (do_deselect) - softif_neigh_vid_deselect(bat_priv, softif_neigh_vid); - - if (curr_softif_neigh) - softif_neigh_free_ref(curr_softif_neigh); - - softif_neigh_vid_free_ref(softif_neigh_vid); - } - rcu_read_unlock(); - - spin_lock_bh(&bat_priv->softif_neigh_vid_lock); - hlist_for_each_entry_safe(softif_neigh_vid, node, node_tmp, - &bat_priv->softif_neigh_vids, list) { - if (!hlist_empty(&softif_neigh_vid->softif_neigh_list)) - continue; - - hlist_del_rcu(&softif_neigh_vid->list); - softif_neigh_vid_free_ref(softif_neigh_vid); - } - spin_unlock_bh(&bat_priv->softif_neigh_vid_lock); - -} - -static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, - short vid) -{ - struct bat_priv *bat_priv = netdev_priv(dev); - struct ethhdr *ethhdr = (struct ethhdr *)skb->data; - struct batman_ogm_packet *batman_ogm_packet; - struct softif_neigh *softif_neigh = NULL; - struct hard_iface *primary_if = NULL; - struct softif_neigh *curr_softif_neigh = NULL; - - if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) - batman_ogm_packet = (struct batman_ogm_packet *) - (skb->data + ETH_HLEN + VLAN_HLEN); - else - batman_ogm_packet = (struct batman_ogm_packet *) - (skb->data + ETH_HLEN); - - if (batman_ogm_packet->header.version != COMPAT_VERSION) - goto out; - - if (batman_ogm_packet->header.packet_type != BAT_OGM) - goto out; - - if (!(batman_ogm_packet->flags & PRIMARIES_FIRST_HOP)) - goto out; - - if (is_my_mac(batman_ogm_packet->orig)) - goto out; - - softif_neigh = softif_neigh_get(bat_priv, batman_ogm_packet->orig, vid); - if (!softif_neigh) - goto out; - - curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); - if (curr_softif_neigh == softif_neigh) - goto out; - - primary_if = primary_if_get_selected(bat_priv); - if (!primary_if) - goto out; - - /* we got a neighbor but its mac is 'bigger' than ours */ - if (memcmp(primary_if->net_dev->dev_addr, - softif_neigh->addr, ETH_ALEN) < 0) - goto out; - - /* close own batX device and use softif_neigh as exit node */ - if (!curr_softif_neigh) { - softif_neigh_vid_select(bat_priv, softif_neigh, vid); - goto out; - } - - /* switch to new 'smallest neighbor' */ - if (memcmp(softif_neigh->addr, curr_softif_neigh->addr, ETH_ALEN) < 0) - softif_neigh_vid_select(bat_priv, softif_neigh, vid); - -out: - kfree_skb(skb); - if (softif_neigh) - softif_neigh_free_ref(softif_neigh); - if (curr_softif_neigh) - softif_neigh_free_ref(curr_softif_neigh); - if (primary_if) - hardif_free_ref(primary_if); - return; -} - static int interface_open(struct net_device *dev) { netif_start_queue(dev); @@ -562,10 +130,11 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) struct hard_iface *primary_if = NULL; struct bcast_packet *bcast_packet; struct vlan_ethhdr *vhdr; - struct softif_neigh *curr_softif_neigh = NULL; + static const uint8_t stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00, 0x00, + 0x00}; unsigned int header_len = 0; int data_len = skb->len, ret; - short vid = -1; + short vid __maybe_unused = -1; bool do_bcast = false; if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) @@ -583,21 +152,21 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) /* fall through */ case ETH_P_BATMAN: - softif_batman_recv(skb, soft_iface, vid); - goto end; + goto dropped; } - /** - * if we have a another chosen mesh exit node in range - * it will transport the packets to the mesh - */ - curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); - if (curr_softif_neigh) + if (bla_tx(bat_priv, skb, vid)) goto dropped; /* Register the client MAC in the transtable */ tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif); + /* don't accept stp packets. STP does not help in meshes. + * better use the bridge loop avoidance ... + */ + if (compare_eth(ethhdr->h_dest, stp_addr)) + goto dropped; + if (is_multicast_ether_addr(ethhdr->h_dest)) { do_bcast = true; @@ -675,8 +244,6 @@ dropped: dropped_freed: bat_priv->stats.tx_dropped++; end: - if (curr_softif_neigh) - softif_neigh_free_ref(curr_softif_neigh); if (primary_if) hardif_free_ref(primary_if); return NETDEV_TX_OK; @@ -687,12 +254,9 @@ void interface_rx(struct net_device *soft_iface, int hdr_size) { struct bat_priv *bat_priv = netdev_priv(soft_iface); - struct unicast_packet *unicast_packet; struct ethhdr *ethhdr; struct vlan_ethhdr *vhdr; - struct softif_neigh *curr_softif_neigh = NULL; - short vid = -1; - int ret; + short vid __maybe_unused = -1; /* check if enough space is available for pulling, and pull */ if (!pskb_may_pull(skb, hdr_size)) @@ -716,30 +280,6 @@ void interface_rx(struct net_device *soft_iface, goto dropped; } - /** - * if we have a another chosen mesh exit node in range - * it will transport the packets to the non-mesh network - */ - curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); - if (curr_softif_neigh) { - skb_push(skb, hdr_size); - unicast_packet = (struct unicast_packet *)skb->data; - - if ((unicast_packet->header.packet_type != BAT_UNICAST) && - (unicast_packet->header.packet_type != BAT_UNICAST_FRAG)) - goto dropped; - - skb_reset_mac_header(skb); - - memcpy(unicast_packet->dest, - curr_softif_neigh->addr, ETH_ALEN); - ret = route_unicast_packet(skb, recv_if); - if (ret == NET_RX_DROP) - goto dropped; - - goto out; - } - /* skb->dev & skb->pkt_type are set here */ if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) goto dropped; @@ -759,14 +299,18 @@ void interface_rx(struct net_device *soft_iface, if (is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest)) goto dropped; + /* Let the bridge loop avoidance check the packet. If will + * not handle it, we can safely push it up. + */ + if (bla_rx(bat_priv, skb, vid)) + goto out; + netif_rx(skb); goto out; dropped: kfree_skb(skb); out: - if (curr_softif_neigh) - softif_neigh_free_ref(curr_softif_neigh); return; } @@ -828,13 +372,14 @@ struct net_device *softif_create(const char *name) atomic_set(&bat_priv->aggregated_ogms, 1); atomic_set(&bat_priv->bonding, 0); + atomic_set(&bat_priv->bridge_loop_avoidance, 0); atomic_set(&bat_priv->ap_isolation, 0); atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); atomic_set(&bat_priv->gw_mode, GW_MODE_OFF); atomic_set(&bat_priv->gw_sel_class, 20); atomic_set(&bat_priv->gw_bandwidth, 41); atomic_set(&bat_priv->orig_interval, 1000); - atomic_set(&bat_priv->hop_penalty, 10); + atomic_set(&bat_priv->hop_penalty, 30); atomic_set(&bat_priv->log_level, 0); atomic_set(&bat_priv->fragmentation, 1); atomic_set(&bat_priv->bcast_queue_left, BCAST_QUEUE_LEN); @@ -845,6 +390,7 @@ struct net_device *softif_create(const char *name) atomic_set(&bat_priv->ttvn, 0); atomic_set(&bat_priv->tt_local_changes, 0); atomic_set(&bat_priv->tt_ogm_append_cnt, 0); + atomic_set(&bat_priv->bla_num_requests, 0); bat_priv->tt_buff = NULL; bat_priv->tt_buff_len = 0; diff --git a/net/batman-adv/soft-interface.h b/net/batman-adv/soft-interface.h index 756eab5..0203006 100644 --- a/net/batman-adv/soft-interface.h +++ b/net/batman-adv/soft-interface.h @@ -23,8 +23,6 @@ #define _NET_BATMAN_ADV_SOFT_INTERFACE_H_ int my_skb_head_push(struct sk_buff *skb, unsigned int len); -int softif_neigh_seq_print_text(struct seq_file *seq, void *offset); -void softif_neigh_purge(struct bat_priv *bat_priv); void interface_rx(struct net_device *soft_iface, struct sk_buff *skb, struct hard_iface *recv_if, int hdr_size); diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 1f86921..e16a369 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -27,13 +27,14 @@ #include "hash.h" #include "originator.h" #include "routing.h" +#include "bridge_loop_avoidance.h" #include <linux/crc16.h> -static void _tt_global_del(struct bat_priv *bat_priv, - struct tt_global_entry *tt_global_entry, - const char *message); +static void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client, + struct orig_node *orig_node); static void tt_purge(struct work_struct *work); +static void tt_global_del_orig_list(struct tt_global_entry *tt_global_entry); /* returns 1 if they are the same mac addr */ static int compare_tt(const struct hlist_node *node, const void *data2) @@ -123,17 +124,31 @@ static void tt_global_entry_free_rcu(struct rcu_head *rcu) tt_global_entry = container_of(tt_common_entry, struct tt_global_entry, common); - if (tt_global_entry->orig_node) - orig_node_free_ref(tt_global_entry->orig_node); - kfree(tt_global_entry); } static void tt_global_entry_free_ref(struct tt_global_entry *tt_global_entry) { - if (atomic_dec_and_test(&tt_global_entry->common.refcount)) + if (atomic_dec_and_test(&tt_global_entry->common.refcount)) { + tt_global_del_orig_list(tt_global_entry); call_rcu(&tt_global_entry->common.rcu, tt_global_entry_free_rcu); + } +} + +static void tt_orig_list_entry_free_rcu(struct rcu_head *rcu) +{ + struct tt_orig_list_entry *orig_entry; + + orig_entry = container_of(rcu, struct tt_orig_list_entry, rcu); + atomic_dec(&orig_entry->orig_node->tt_size); + orig_node_free_ref(orig_entry->orig_node); + kfree(orig_entry); +} + +static void tt_orig_list_entry_free_ref(struct tt_orig_list_entry *orig_entry) +{ + call_rcu(&orig_entry->rcu, tt_orig_list_entry_free_rcu); } static void tt_local_event(struct bat_priv *bat_priv, const uint8_t *addr, @@ -182,6 +197,9 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, struct bat_priv *bat_priv = netdev_priv(soft_iface); struct tt_local_entry *tt_local_entry = NULL; struct tt_global_entry *tt_global_entry = NULL; + struct hlist_head *head; + struct hlist_node *node; + struct tt_orig_list_entry *orig_entry; int hash_added; tt_local_entry = tt_local_hash_find(bat_priv, addr); @@ -232,14 +250,21 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, /* Check whether it is a roaming! */ if (tt_global_entry) { - /* This node is probably going to update its tt table */ - tt_global_entry->orig_node->tt_poss_change = true; - /* The global entry has to be marked as ROAMING and has to be - * kept for consistency purpose */ + /* These node are probably going to update their tt table */ + head = &tt_global_entry->orig_list; + rcu_read_lock(); + hlist_for_each_entry_rcu(orig_entry, node, head, list) { + orig_entry->orig_node->tt_poss_change = true; + + send_roam_adv(bat_priv, tt_global_entry->common.addr, + orig_entry->orig_node); + } + rcu_read_unlock(); + /* The global entry has to be marked as ROAMING and + * has to be kept for consistency purpose + */ tt_global_entry->common.flags |= TT_CLIENT_ROAM; tt_global_entry->roam_at = jiffies; - send_roam_adv(bat_priv, tt_global_entry->common.addr, - tt_global_entry->orig_node); } out: if (tt_local_entry) @@ -490,33 +515,76 @@ static void tt_changes_list_free(struct bat_priv *bat_priv) spin_unlock_bh(&bat_priv->tt_changes_list_lock); } +/* find out if an orig_node is already in the list of a tt_global_entry. + * returns 1 if found, 0 otherwise + */ +static bool tt_global_entry_has_orig(const struct tt_global_entry *entry, + const struct orig_node *orig_node) +{ + struct tt_orig_list_entry *tmp_orig_entry; + const struct hlist_head *head; + struct hlist_node *node; + bool found = false; + + rcu_read_lock(); + head = &entry->orig_list; + hlist_for_each_entry_rcu(tmp_orig_entry, node, head, list) { + if (tmp_orig_entry->orig_node == orig_node) { + found = true; + break; + } + } + rcu_read_unlock(); + return found; +} + +static void tt_global_add_orig_entry(struct tt_global_entry *tt_global_entry, + struct orig_node *orig_node, + int ttvn) +{ + struct tt_orig_list_entry *orig_entry; + + orig_entry = kzalloc(sizeof(*orig_entry), GFP_ATOMIC); + if (!orig_entry) + return; + + INIT_HLIST_NODE(&orig_entry->list); + atomic_inc(&orig_node->refcount); + atomic_inc(&orig_node->tt_size); + orig_entry->orig_node = orig_node; + orig_entry->ttvn = ttvn; + + spin_lock_bh(&tt_global_entry->list_lock); + hlist_add_head_rcu(&orig_entry->list, + &tt_global_entry->orig_list); + spin_unlock_bh(&tt_global_entry->list_lock); +} + /* caller must hold orig_node refcount */ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, const unsigned char *tt_addr, uint8_t ttvn, bool roaming, bool wifi) { - struct tt_global_entry *tt_global_entry; - struct orig_node *orig_node_tmp; + struct tt_global_entry *tt_global_entry = NULL; int ret = 0; int hash_added; tt_global_entry = tt_global_hash_find(bat_priv, tt_addr); if (!tt_global_entry) { - tt_global_entry = - kmalloc(sizeof(*tt_global_entry), - GFP_ATOMIC); + tt_global_entry = kzalloc(sizeof(*tt_global_entry), + GFP_ATOMIC); if (!tt_global_entry) goto out; memcpy(tt_global_entry->common.addr, tt_addr, ETH_ALEN); + tt_global_entry->common.flags = NO_FLAGS; - atomic_set(&tt_global_entry->common.refcount, 2); - /* Assign the new orig_node */ - atomic_inc(&orig_node->refcount); - tt_global_entry->orig_node = orig_node; - tt_global_entry->ttvn = ttvn; tt_global_entry->roam_at = 0; + atomic_set(&tt_global_entry->common.refcount, 2); + + INIT_HLIST_HEAD(&tt_global_entry->orig_list); + spin_lock_init(&tt_global_entry->list_lock); hash_added = hash_add(bat_priv->tt_global_hash, compare_tt, choose_orig, &tt_global_entry->common, @@ -527,19 +595,27 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, tt_global_entry_free_ref(tt_global_entry); goto out_remove; } - atomic_inc(&orig_node->tt_size); + + tt_global_add_orig_entry(tt_global_entry, orig_node, ttvn); } else { - if (tt_global_entry->orig_node != orig_node) { - atomic_dec(&tt_global_entry->orig_node->tt_size); - orig_node_tmp = tt_global_entry->orig_node; - atomic_inc(&orig_node->refcount); - tt_global_entry->orig_node = orig_node; - orig_node_free_ref(orig_node_tmp); - atomic_inc(&orig_node->tt_size); + /* there is already a global entry, use this one. */ + + /* If there is the TT_CLIENT_ROAM flag set, there is only one + * originator left in the list and we previously received a + * delete + roaming change for this originator. + * + * We should first delete the old originator before adding the + * new one. + */ + if (tt_global_entry->common.flags & TT_CLIENT_ROAM) { + tt_global_del_orig_list(tt_global_entry); + tt_global_entry->common.flags &= ~TT_CLIENT_ROAM; + tt_global_entry->roam_at = 0; } - tt_global_entry->common.flags = NO_FLAGS; - tt_global_entry->ttvn = ttvn; - tt_global_entry->roam_at = 0; + + if (!tt_global_entry_has_orig(tt_global_entry, orig_node)) + tt_global_add_orig_entry(tt_global_entry, orig_node, + ttvn); } if (wifi) @@ -560,6 +636,34 @@ out: return ret; } +/* print all orig nodes who announce the address for this global entry. + * it is assumed that the caller holds rcu_read_lock(); + */ +static void tt_global_print_entry(struct tt_global_entry *tt_global_entry, + struct seq_file *seq) +{ + struct hlist_head *head; + struct hlist_node *node; + struct tt_orig_list_entry *orig_entry; + struct tt_common_entry *tt_common_entry; + uint16_t flags; + uint8_t last_ttvn; + + tt_common_entry = &tt_global_entry->common; + + head = &tt_global_entry->orig_list; + + hlist_for_each_entry_rcu(orig_entry, node, head, list) { + flags = tt_common_entry->flags; + last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn); + seq_printf(seq, " * %pM (%3u) via %pM (%3u) [%c%c]\n", + tt_global_entry->common.addr, orig_entry->ttvn, + orig_entry->orig_node->orig, last_ttvn, + (flags & TT_CLIENT_ROAM ? 'R' : '.'), + (flags & TT_CLIENT_WIFI ? 'W' : '.')); + } +} + int tt_global_seq_print_text(struct seq_file *seq, void *offset) { struct net_device *net_dev = (struct net_device *)seq->private; @@ -603,18 +707,7 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset) tt_global_entry = container_of(tt_common_entry, struct tt_global_entry, common); - seq_printf(seq, - " * %pM (%3u) via %pM (%3u) [%c%c]\n", - tt_global_entry->common.addr, - tt_global_entry->ttvn, - tt_global_entry->orig_node->orig, - (uint8_t) atomic_read( - &tt_global_entry->orig_node-> - last_ttvn), - (tt_global_entry->common.flags & - TT_CLIENT_ROAM ? 'R' : '.'), - (tt_global_entry->common.flags & - TT_CLIENT_WIFI ? 'W' : '.')); + tt_global_print_entry(tt_global_entry, seq); } rcu_read_unlock(); } @@ -624,59 +717,150 @@ out: return ret; } -static void _tt_global_del(struct bat_priv *bat_priv, - struct tt_global_entry *tt_global_entry, - const char *message) +/* deletes the orig list of a tt_global_entry */ +static void tt_global_del_orig_list(struct tt_global_entry *tt_global_entry) { - if (!tt_global_entry) - goto out; + struct hlist_head *head; + struct hlist_node *node, *safe; + struct tt_orig_list_entry *orig_entry; - bat_dbg(DBG_TT, bat_priv, - "Deleting global tt entry %pM (via %pM): %s\n", - tt_global_entry->common.addr, tt_global_entry->orig_node->orig, - message); + spin_lock_bh(&tt_global_entry->list_lock); + head = &tt_global_entry->orig_list; + hlist_for_each_entry_safe(orig_entry, node, safe, head, list) { + hlist_del_rcu(node); + tt_orig_list_entry_free_ref(orig_entry); + } + spin_unlock_bh(&tt_global_entry->list_lock); - atomic_dec(&tt_global_entry->orig_node->tt_size); +} + +static void tt_global_del_orig_entry(struct bat_priv *bat_priv, + struct tt_global_entry *tt_global_entry, + struct orig_node *orig_node, + const char *message) +{ + struct hlist_head *head; + struct hlist_node *node, *safe; + struct tt_orig_list_entry *orig_entry; + + spin_lock_bh(&tt_global_entry->list_lock); + head = &tt_global_entry->orig_list; + hlist_for_each_entry_safe(orig_entry, node, safe, head, list) { + if (orig_entry->orig_node == orig_node) { + bat_dbg(DBG_TT, bat_priv, + "Deleting %pM from global tt entry %pM: %s\n", + orig_node->orig, tt_global_entry->common.addr, + message); + hlist_del_rcu(node); + tt_orig_list_entry_free_ref(orig_entry); + } + } + spin_unlock_bh(&tt_global_entry->list_lock); +} + +static void tt_global_del_struct(struct bat_priv *bat_priv, + struct tt_global_entry *tt_global_entry, + const char *message) +{ + bat_dbg(DBG_TT, bat_priv, + "Deleting global tt entry %pM: %s\n", + tt_global_entry->common.addr, message); hash_remove(bat_priv->tt_global_hash, compare_tt, choose_orig, tt_global_entry->common.addr); -out: - if (tt_global_entry) - tt_global_entry_free_ref(tt_global_entry); + tt_global_entry_free_ref(tt_global_entry); + } -void tt_global_del(struct bat_priv *bat_priv, - struct orig_node *orig_node, const unsigned char *addr, - const char *message, bool roaming) +/* If the client is to be deleted, we check if it is the last origantor entry + * within tt_global entry. If yes, we set the TT_CLIENT_ROAM flag and the timer, + * otherwise we simply remove the originator scheduled for deletion. + */ +static void tt_global_del_roaming(struct bat_priv *bat_priv, + struct tt_global_entry *tt_global_entry, + struct orig_node *orig_node, + const char *message) +{ + bool last_entry = true; + struct hlist_head *head; + struct hlist_node *node; + struct tt_orig_list_entry *orig_entry; + + /* no local entry exists, case 1: + * Check if this is the last one or if other entries exist. + */ + + rcu_read_lock(); + head = &tt_global_entry->orig_list; + hlist_for_each_entry_rcu(orig_entry, node, head, list) { + if (orig_entry->orig_node != orig_node) { + last_entry = false; + break; + } + } + rcu_read_unlock(); + + if (last_entry) { + /* its the last one, mark for roaming. */ + tt_global_entry->common.flags |= TT_CLIENT_ROAM; + tt_global_entry->roam_at = jiffies; + } else + /* there is another entry, we can simply delete this + * one and can still use the other one. + */ + tt_global_del_orig_entry(bat_priv, tt_global_entry, + orig_node, message); +} + + + +static void tt_global_del(struct bat_priv *bat_priv, + struct orig_node *orig_node, + const unsigned char *addr, + const char *message, bool roaming) { struct tt_global_entry *tt_global_entry = NULL; struct tt_local_entry *tt_local_entry = NULL; tt_global_entry = tt_global_hash_find(bat_priv, addr); - if (!tt_global_entry || tt_global_entry->orig_node != orig_node) + if (!tt_global_entry) goto out; - if (!roaming) - goto out_del; + if (!roaming) { + tt_global_del_orig_entry(bat_priv, tt_global_entry, orig_node, + message); + + if (hlist_empty(&tt_global_entry->orig_list)) + tt_global_del_struct(bat_priv, tt_global_entry, + message); + + goto out; + } /* if we are deleting a global entry due to a roam * event, there are two possibilities: - * 1) the client roamed from node A to node B => we mark + * 1) the client roamed from node A to node B => if there + * is only one originator left for this client, we mark * it with TT_CLIENT_ROAM, we start a timer and we * wait for node B to claim it. In case of timeout * the entry is purged. + * + * If there are other originators left, we directly delete + * the originator. * 2) the client roamed to us => we can directly delete * the global entry, since it is useless now. */ + tt_local_entry = tt_local_hash_find(bat_priv, tt_global_entry->common.addr); - if (!tt_local_entry) { - tt_global_entry->common.flags |= TT_CLIENT_ROAM; - tt_global_entry->roam_at = jiffies; - goto out; - } + if (tt_local_entry) { + /* local entry exists, case 2: client roamed to us. */ + tt_global_del_orig_list(tt_global_entry); + tt_global_del_struct(bat_priv, tt_global_entry, message); + } else + /* no local entry exists, case 1: check for roaming */ + tt_global_del_roaming(bat_priv, tt_global_entry, orig_node, + message); -out_del: - _tt_global_del(bat_priv, tt_global_entry, message); out: if (tt_global_entry) @@ -709,11 +893,14 @@ void tt_global_del_orig(struct bat_priv *bat_priv, tt_global_entry = container_of(tt_common_entry, struct tt_global_entry, common); - if (tt_global_entry->orig_node == orig_node) { + + tt_global_del_orig_entry(bat_priv, tt_global_entry, + orig_node, message); + + if (hlist_empty(&tt_global_entry->orig_list)) { bat_dbg(DBG_TT, bat_priv, - "Deleting global tt entry %pM (via %pM): %s\n", + "Deleting global tt entry %pM: %s\n", tt_global_entry->common.addr, - tt_global_entry->orig_node->orig, message); hlist_del_rcu(node); tt_global_entry_free_ref(tt_global_entry); @@ -754,7 +941,7 @@ static void tt_global_roam_purge(struct bat_priv *bat_priv) bat_dbg(DBG_TT, bat_priv, "Deleting global tt entry (%pM): Roaming timeout\n", tt_global_entry->common.addr); - atomic_dec(&tt_global_entry->orig_node->tt_size); + hlist_del_rcu(node); tt_global_entry_free_ref(tt_global_entry); } @@ -817,6 +1004,11 @@ struct orig_node *transtable_search(struct bat_priv *bat_priv, struct tt_local_entry *tt_local_entry = NULL; struct tt_global_entry *tt_global_entry = NULL; struct orig_node *orig_node = NULL; + struct neigh_node *router = NULL; + struct hlist_head *head; + struct hlist_node *node; + struct tt_orig_list_entry *orig_entry; + int best_tq; if (src && atomic_read(&bat_priv->ap_isolation)) { tt_local_entry = tt_local_hash_find(bat_priv, src); @@ -833,11 +1025,25 @@ struct orig_node *transtable_search(struct bat_priv *bat_priv, if (tt_local_entry && _is_ap_isolated(tt_local_entry, tt_global_entry)) goto out; - if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount)) - goto out; + best_tq = 0; - orig_node = tt_global_entry->orig_node; + rcu_read_lock(); + head = &tt_global_entry->orig_list; + hlist_for_each_entry_rcu(orig_entry, node, head, list) { + router = orig_node_get_router(orig_entry->orig_node); + if (!router) + continue; + if (router->tq_avg > best_tq) { + orig_node = orig_entry->orig_node; + best_tq = router->tq_avg; + } + neigh_node_free_ref(router); + } + /* found anything? */ + if (orig_node && !atomic_inc_not_zero(&orig_node->refcount)) + orig_node = NULL; + rcu_read_unlock(); out: if (tt_global_entry) tt_global_entry_free_ref(tt_global_entry); @@ -848,7 +1054,8 @@ out: } /* Calculates the checksum of the local table of a given orig_node */ -uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node) +static uint16_t tt_global_crc(struct bat_priv *bat_priv, + struct orig_node *orig_node) { uint16_t total = 0, total_one; struct hashtable_t *hash = bat_priv->tt_global_hash; @@ -868,20 +1075,26 @@ uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node) tt_global_entry = container_of(tt_common_entry, struct tt_global_entry, common); - if (compare_eth(tt_global_entry->orig_node, - orig_node)) { - /* Roaming clients are in the global table for - * consistency only. They don't have to be - * taken into account while computing the - * global crc */ - if (tt_common_entry->flags & TT_CLIENT_ROAM) - continue; - total_one = 0; - for (j = 0; j < ETH_ALEN; j++) - total_one = crc16_byte(total_one, - tt_common_entry->addr[j]); - total ^= total_one; - } + /* Roaming clients are in the global table for + * consistency only. They don't have to be + * taken into account while computing the + * global crc + */ + if (tt_global_entry->common.flags & TT_CLIENT_ROAM) + continue; + + /* find out if this global entry is announced by this + * originator + */ + if (!tt_global_entry_has_orig(tt_global_entry, + orig_node)) + continue; + + total_one = 0; + for (j = 0; j < ETH_ALEN; j++) + total_one = crc16_byte(total_one, + tt_global_entry->common.addr[j]); + total ^= total_one; } rcu_read_unlock(); } @@ -936,8 +1149,10 @@ static void tt_req_list_free(struct bat_priv *bat_priv) spin_unlock_bh(&bat_priv->tt_req_list_lock); } -void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node, - const unsigned char *tt_buff, uint8_t tt_num_changes) +static void tt_save_orig_buffer(struct bat_priv *bat_priv, + struct orig_node *orig_node, + const unsigned char *tt_buff, + uint8_t tt_num_changes) { uint16_t tt_buff_len = tt_len(tt_num_changes); @@ -1020,7 +1235,7 @@ static int tt_global_valid_entry(const void *entry_ptr, const void *data_ptr) tt_global_entry = container_of(tt_common_entry, struct tt_global_entry, common); - return (tt_global_entry->orig_node == orig_node); + return tt_global_entry_has_orig(tt_global_entry, orig_node); } static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn, @@ -1401,10 +1616,15 @@ out: bool send_tt_response(struct bat_priv *bat_priv, struct tt_query_packet *tt_request) { - if (is_my_mac(tt_request->dst)) + if (is_my_mac(tt_request->dst)) { + /* don't answer backbone gws! */ + if (bla_is_backbone_gw_orig(bat_priv, tt_request->src)) + return true; + return send_my_tt_response(bat_priv, tt_request); - else + } else { return send_other_tt_response(bat_priv, tt_request); + } } static void _tt_update_changes(struct bat_priv *bat_priv, @@ -1508,6 +1728,10 @@ void handle_tt_response(struct bat_priv *bat_priv, tt_response->src, tt_response->ttvn, tt_response->tt_data, (tt_response->flags & TT_FULL_TABLE ? 'F' : '.')); + /* we should have never asked a backbone gw */ + if (bla_is_backbone_gw_orig(bat_priv, tt_response->src)) + goto out; + orig_node = orig_hash_find(bat_priv, tt_response->src); if (!orig_node) goto out; @@ -1627,8 +1851,8 @@ unlock: return ret; } -void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client, - struct orig_node *orig_node) +static void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client, + struct orig_node *orig_node) { struct neigh_node *neigh_node = NULL; struct sk_buff *skb = NULL; @@ -1796,6 +2020,8 @@ void tt_commit_changes(struct bat_priv *bat_priv) /* Increment the TTVN only once per OGM interval */ atomic_inc(&bat_priv->ttvn); + bat_dbg(DBG_TT, bat_priv, "Local changes committed, updating to ttvn %u\n", + (uint8_t)atomic_read(&bat_priv->ttvn)); bat_priv->tt_poss_change = false; } @@ -1836,6 +2062,10 @@ void tt_update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); bool full_table = true; + /* don't care about a backbone gateways updates. */ + if (bla_is_backbone_gw_orig(bat_priv, orig_node->orig)) + return; + /* orig table not initialised AND first diff is in the OGM OR the ttvn * increased by one -> we can apply the attached changes */ if ((!orig_node->tt_initialised && ttvn == 1) || @@ -1873,6 +2103,7 @@ void tt_update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, } else { /* if we missed more than one change or our tables are not * in sync anymore -> request fresh tt data */ + if (!orig_node->tt_initialised || ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) { request_table: diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h index c753633..bfebe26 100644 --- a/net/batman-adv/translation-table.h +++ b/net/batman-adv/translation-table.h @@ -39,23 +39,15 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, int tt_global_seq_print_text(struct seq_file *seq, void *offset); void tt_global_del_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, const char *message); -void tt_global_del(struct bat_priv *bat_priv, - struct orig_node *orig_node, const unsigned char *addr, - const char *message, bool roaming); struct orig_node *transtable_search(struct bat_priv *bat_priv, const uint8_t *src, const uint8_t *addr); -void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node, - const unsigned char *tt_buff, uint8_t tt_num_changes); uint16_t tt_local_crc(struct bat_priv *bat_priv); -uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node); void tt_free(struct bat_priv *bat_priv); bool send_tt_response(struct bat_priv *bat_priv, struct tt_query_packet *tt_request); bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr); void handle_tt_response(struct bat_priv *bat_priv, struct tt_query_packet *tt_response); -void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client, - struct orig_node *orig_node); void tt_commit_changes(struct bat_priv *bat_priv); bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst); void tt_update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 302efb5..a5b1a63 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -90,7 +90,7 @@ struct orig_node { bool tt_poss_change; uint32_t last_real_seqno; uint8_t last_ttl; - unsigned long bcast_bits[NUM_WORDS]; + DECLARE_BITMAP(bcast_bits, TQ_LOCAL_WINDOW_SIZE); uint32_t last_bcast_seqno; struct hlist_head neigh_list; struct list_head frag_list; @@ -132,7 +132,7 @@ struct neigh_node { uint8_t last_ttl; struct list_head bonding_list; unsigned long last_valid; - unsigned long real_bits[NUM_WORDS]; + DECLARE_BITMAP(real_bits, TQ_LOCAL_WINDOW_SIZE); atomic_t refcount; struct rcu_head rcu; struct orig_node *orig_node; @@ -140,6 +140,13 @@ struct neigh_node { spinlock_t tq_lock; /* protects: tq_recv, tq_index */ }; +#ifdef CONFIG_BATMAN_ADV_BLA +struct bcast_duplist_entry { + uint8_t orig[ETH_ALEN]; + uint16_t crc; + unsigned long entrytime; +}; +#endif struct bat_priv { atomic_t mesh_state; @@ -148,6 +155,7 @@ struct bat_priv { atomic_t bonding; /* boolean */ atomic_t fragmentation; /* boolean */ atomic_t ap_isolation; /* boolean */ + atomic_t bridge_loop_avoidance; /* boolean */ atomic_t vis_mode; /* VIS_TYPE_* */ atomic_t gw_mode; /* GW_MODE_* */ atomic_t gw_sel_class; /* uint */ @@ -161,6 +169,7 @@ struct bat_priv { atomic_t ttvn; /* translation table version number */ atomic_t tt_ogm_append_cnt; atomic_t tt_local_changes; /* changes registered in a OGM interval */ + atomic_t bla_num_requests; /* number of bla requests in flight */ /* The tt_poss_change flag is used to detect an ongoing roaming phase. * If true, then I received a Roaming_adv and I have to inspect every * packet directed to me to check whether I am still the true @@ -174,15 +183,23 @@ struct bat_priv { struct hlist_head forw_bat_list; struct hlist_head forw_bcast_list; struct hlist_head gw_list; - struct hlist_head softif_neigh_vids; struct list_head tt_changes_list; /* tracks changes in a OGM int */ struct list_head vis_send_list; struct hashtable_t *orig_hash; struct hashtable_t *tt_local_hash; struct hashtable_t *tt_global_hash; +#ifdef CONFIG_BATMAN_ADV_BLA + struct hashtable_t *claim_hash; + struct hashtable_t *backbone_hash; +#endif struct list_head tt_req_list; /* list of pending tt_requests */ struct list_head tt_roam_list; struct hashtable_t *vis_hash; +#ifdef CONFIG_BATMAN_ADV_BLA + struct bcast_duplist_entry bcast_duplist[DUPLIST_SIZE]; + int bcast_duplist_curr; + struct bla_claim_dst claim_dest; +#endif spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ spinlock_t forw_bcast_list_lock; /* protects */ spinlock_t tt_changes_list_lock; /* protects tt_changes */ @@ -191,8 +208,6 @@ struct bat_priv { spinlock_t gw_list_lock; /* protects gw_list and curr_gw */ spinlock_t vis_hash_lock; /* protects vis_hash */ spinlock_t vis_list_lock; /* protects vis_info::recv_list */ - spinlock_t softif_neigh_lock; /* protects soft-interface neigh list */ - spinlock_t softif_neigh_vid_lock; /* protects soft-interface vid list */ atomic_t num_local_tt; /* Checksum of the local table, recomputed before sending a new OGM */ atomic_t tt_crc; @@ -202,6 +217,7 @@ struct bat_priv { struct delayed_work tt_work; struct delayed_work orig_work; struct delayed_work vis_work; + struct delayed_work bla_work; struct gw_node __rcu *curr_gw; /* rcu protected pointer */ atomic_t gw_reselect; struct hard_iface __rcu *primary_if; /* rcu protected pointer */ @@ -239,10 +255,41 @@ struct tt_local_entry { struct tt_global_entry { struct tt_common_entry common; + struct hlist_head orig_list; + spinlock_t list_lock; /* protects the list */ + unsigned long roam_at; /* time at which TT_GLOBAL_ROAM was set */ +}; + +struct tt_orig_list_entry { struct orig_node *orig_node; uint8_t ttvn; - unsigned long roam_at; /* time at which TT_GLOBAL_ROAM was set */ + struct rcu_head rcu; + struct hlist_node list; +}; + +#ifdef CONFIG_BATMAN_ADV_BLA +struct backbone_gw { + uint8_t orig[ETH_ALEN]; + short vid; /* used VLAN ID */ + struct hlist_node hash_entry; + struct bat_priv *bat_priv; + unsigned long lasttime; /* last time we heard of this backbone gw */ + atomic_t request_sent; + atomic_t refcount; + struct rcu_head rcu; + uint16_t crc; /* crc checksum over all claims */ +}; + +struct claim { + uint8_t addr[ETH_ALEN]; + short vid; + struct backbone_gw *backbone_gw; + unsigned long lasttime; /* last time we heard of claim (locals only) */ + struct rcu_head rcu; + atomic_t refcount; + struct hlist_node hash_entry; }; +#endif struct tt_change_node { struct list_head list; @@ -327,24 +374,6 @@ struct recvlist_node { uint8_t mac[ETH_ALEN]; }; -struct softif_neigh_vid { - struct hlist_node list; - struct bat_priv *bat_priv; - short vid; - atomic_t refcount; - struct softif_neigh __rcu *softif_neigh; - struct rcu_head rcu; - struct hlist_head softif_neigh_list; -}; - -struct softif_neigh { - struct hlist_node list; - uint8_t addr[ETH_ALEN]; - unsigned long last_seen; - atomic_t refcount; - struct rcu_head rcu; -}; - struct bat_algo_ops { struct hlist_node list; char *name; diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index ba829de..d6e5929 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -317,6 +317,9 @@ static const struct net_device_ops br_netdev_ops = { .ndo_add_slave = br_add_slave, .ndo_del_slave = br_del_slave, .ndo_fix_features = br_fix_features, + .ndo_fdb_add = br_fdb_add, + .ndo_fdb_del = br_fdb_delete, + .ndo_fdb_dump = br_fdb_dump, }; static void br_dev_free(struct net_device *dev) diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 5ba0c84..5945c54 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -487,14 +487,14 @@ static int fdb_fill_info(struct sk_buff *skb, const struct net_bridge *br, ndm->ndm_ifindex = fdb->dst ? fdb->dst->dev->ifindex : br->dev->ifindex; ndm->ndm_state = fdb_to_nud(fdb); - NLA_PUT(skb, NDA_LLADDR, ETH_ALEN, &fdb->addr); - + if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->addr)) + goto nla_put_failure; ci.ndm_used = jiffies_to_clock_t(now - fdb->used); ci.ndm_confirmed = 0; ci.ndm_updated = jiffies_to_clock_t(now - fdb->updated); ci.ndm_refcnt = 0; - NLA_PUT(skb, NDA_CACHEINFO, sizeof(ci), &ci); - + if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci)) + goto nla_put_failure; return nlmsg_end(skb, nlh); nla_put_failure: @@ -535,44 +535,38 @@ errout: } /* Dump information about entries, in response to GETNEIGH */ -int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) +int br_fdb_dump(struct sk_buff *skb, + struct netlink_callback *cb, + struct net_device *dev, + int idx) { - struct net *net = sock_net(skb->sk); - struct net_device *dev; - int idx = 0; - - rcu_read_lock(); - for_each_netdev_rcu(net, dev) { - struct net_bridge *br = netdev_priv(dev); - int i; + struct net_bridge *br = netdev_priv(dev); + int i; - if (!(dev->priv_flags & IFF_EBRIDGE)) - continue; + if (!(dev->priv_flags & IFF_EBRIDGE)) + goto out; - for (i = 0; i < BR_HASH_SIZE; i++) { - struct hlist_node *h; - struct net_bridge_fdb_entry *f; - - hlist_for_each_entry_rcu(f, h, &br->hash[i], hlist) { - if (idx < cb->args[0]) - goto skip; + for (i = 0; i < BR_HASH_SIZE; i++) { + struct hlist_node *h; + struct net_bridge_fdb_entry *f; - if (fdb_fill_info(skb, br, f, - NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, - RTM_NEWNEIGH, - NLM_F_MULTI) < 0) - break; + hlist_for_each_entry_rcu(f, h, &br->hash[i], hlist) { + if (idx < cb->args[0]) + goto skip; + + if (fdb_fill_info(skb, br, f, + NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, + RTM_NEWNEIGH, + NLM_F_MULTI) < 0) + break; skip: - ++idx; - } + ++idx; } } - rcu_read_unlock(); - cb->args[0] = idx; - - return skb->len; +out: + return idx; } /* Update (create or replace) forwarding database entry */ @@ -614,43 +608,11 @@ static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr, } /* Add new permanent fdb entry with RTM_NEWNEIGH */ -int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) +int br_fdb_add(struct ndmsg *ndm, struct net_device *dev, + unsigned char *addr, u16 nlh_flags) { - struct net *net = sock_net(skb->sk); - struct ndmsg *ndm; - struct nlattr *tb[NDA_MAX+1]; - struct net_device *dev; struct net_bridge_port *p; - const __u8 *addr; - int err; - - ASSERT_RTNL(); - err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL); - if (err < 0) - return err; - - ndm = nlmsg_data(nlh); - if (ndm->ndm_ifindex == 0) { - pr_info("bridge: RTM_NEWNEIGH with invalid ifindex\n"); - return -EINVAL; - } - - dev = __dev_get_by_index(net, ndm->ndm_ifindex); - if (dev == NULL) { - pr_info("bridge: RTM_NEWNEIGH with unknown ifindex\n"); - return -ENODEV; - } - - if (!tb[NDA_LLADDR] || nla_len(tb[NDA_LLADDR]) != ETH_ALEN) { - pr_info("bridge: RTM_NEWNEIGH with invalid address\n"); - return -EINVAL; - } - - addr = nla_data(tb[NDA_LLADDR]); - if (!is_valid_ether_addr(addr)) { - pr_info("bridge: RTM_NEWNEIGH with invalid ether address\n"); - return -EINVAL; - } + int err = 0; if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE))) { pr_info("bridge: RTM_NEWNEIGH with invalid state %#x\n", ndm->ndm_state); @@ -670,14 +632,14 @@ int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) rcu_read_unlock(); } else { spin_lock_bh(&p->br->hash_lock); - err = fdb_add_entry(p, addr, ndm->ndm_state, nlh->nlmsg_flags); + err = fdb_add_entry(p, addr, ndm->ndm_state, nlh_flags); spin_unlock_bh(&p->br->hash_lock); } return err; } -static int fdb_delete_by_addr(struct net_bridge_port *p, const u8 *addr) +static int fdb_delete_by_addr(struct net_bridge_port *p, u8 *addr) { struct net_bridge *br = p->br; struct hlist_head *head = &br->hash[br_mac_hash(addr)]; @@ -692,40 +654,12 @@ static int fdb_delete_by_addr(struct net_bridge_port *p, const u8 *addr) } /* Remove neighbor entry with RTM_DELNEIGH */ -int br_fdb_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) +int br_fdb_delete(struct ndmsg *ndm, struct net_device *dev, + unsigned char *addr) { - struct net *net = sock_net(skb->sk); - struct ndmsg *ndm; struct net_bridge_port *p; - struct nlattr *llattr; - const __u8 *addr; - struct net_device *dev; int err; - ASSERT_RTNL(); - if (nlmsg_len(nlh) < sizeof(*ndm)) - return -EINVAL; - - ndm = nlmsg_data(nlh); - if (ndm->ndm_ifindex == 0) { - pr_info("bridge: RTM_DELNEIGH with invalid ifindex\n"); - return -EINVAL; - } - - dev = __dev_get_by_index(net, ndm->ndm_ifindex); - if (dev == NULL) { - pr_info("bridge: RTM_DELNEIGH with unknown ifindex\n"); - return -ENODEV; - } - - llattr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_LLADDR); - if (llattr == NULL || nla_len(llattr) != ETH_ALEN) { - pr_info("bridge: RTM_DELNEIGH with invalid address\n"); - return -EINVAL; - } - - addr = nla_data(llattr); - p = br_port_get_rtnl(dev); if (p == NULL) { pr_info("bridge: RTM_DELNEIGH %s not a bridge port\n", diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 61f6534..aab8470 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -34,7 +34,7 @@ static inline int should_deliver(const struct net_bridge_port *p, p->state == BR_STATE_FORWARDING); } -static inline unsigned packet_length(const struct sk_buff *skb) +static inline unsigned int packet_length(const struct sk_buff *skb) { return skb->len - (skb->protocol == htons(ETH_P_8021Q) ? VLAN_HLEN : 0); } diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 27ca25e..708e84f 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -36,6 +36,8 @@ #define mlock_dereference(X, br) \ rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock)) +static void br_multicast_start_querier(struct net_bridge *br); + #if IS_ENABLED(CONFIG_IPV6) static inline int ipv6_is_transient_multicast(const struct in6_addr *addr) { @@ -512,8 +514,8 @@ static struct net_bridge_mdb_entry *br_multicast_get_group( struct net_bridge_mdb_htable *mdb; struct net_bridge_mdb_entry *mp; struct hlist_node *p; - unsigned count = 0; - unsigned max; + unsigned int count = 0; + unsigned int max; int elasticity; int err; @@ -740,6 +742,21 @@ static void br_multicast_local_router_expired(unsigned long data) { } +static void br_multicast_querier_expired(unsigned long data) +{ + struct net_bridge_port *port = (void *)data; + struct net_bridge *br = port->br; + + spin_lock(&br->multicast_lock); + if (!netif_running(br->dev) || br->multicast_disabled) + goto out; + + br_multicast_start_querier(br); + +out: + spin_unlock(&br->multicast_lock); +} + static void __br_multicast_send_query(struct net_bridge *br, struct net_bridge_port *port, struct br_ip *ip) @@ -766,6 +783,7 @@ static void br_multicast_send_query(struct net_bridge *br, struct br_ip br_group; if (!netif_running(br->dev) || br->multicast_disabled || + !br->multicast_querier || timer_pending(&br->multicast_querier_timer)) return; @@ -1281,8 +1299,8 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, struct sk_buff *skb2 = skb; const struct iphdr *iph; struct igmphdr *ih; - unsigned len; - unsigned offset; + unsigned int len; + unsigned int offset; int err; /* We treat OOM as packet loss for now. */ @@ -1382,7 +1400,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, u8 icmp6_type; u8 nexthdr; __be16 frag_off; - unsigned len; + unsigned int len; int offset; int err; @@ -1548,6 +1566,7 @@ void br_multicast_init(struct net_bridge *br) br->hash_max = 512; br->multicast_router = 1; + br->multicast_querier = 0; br->multicast_last_member_count = 2; br->multicast_startup_query_count = 2; @@ -1562,7 +1581,7 @@ void br_multicast_init(struct net_bridge *br) setup_timer(&br->multicast_router_timer, br_multicast_local_router_expired, 0); setup_timer(&br->multicast_querier_timer, - br_multicast_local_router_expired, 0); + br_multicast_querier_expired, 0); setup_timer(&br->multicast_query_timer, br_multicast_query_expired, (unsigned long)br); } @@ -1689,9 +1708,23 @@ unlock: return err; } -int br_multicast_toggle(struct net_bridge *br, unsigned long val) +static void br_multicast_start_querier(struct net_bridge *br) { struct net_bridge_port *port; + + br_multicast_open(br); + + list_for_each_entry(port, &br->port_list, list) { + if (port->state == BR_STATE_DISABLED || + port->state == BR_STATE_BLOCKING) + continue; + + __br_multicast_enable_port(port); + } +} + +int br_multicast_toggle(struct net_bridge *br, unsigned long val) +{ int err = 0; struct net_bridge_mdb_htable *mdb; @@ -1721,14 +1754,7 @@ rollback: goto rollback; } - br_multicast_open(br); - list_for_each_entry(port, &br->port_list, list) { - if (port->state == BR_STATE_DISABLED || - port->state == BR_STATE_BLOCKING) - continue; - - __br_multicast_enable_port(port); - } + br_multicast_start_querier(br); unlock: spin_unlock_bh(&br->multicast_lock); @@ -1736,6 +1762,24 @@ unlock: return err; } +int br_multicast_set_querier(struct net_bridge *br, unsigned long val) +{ + val = !!val; + + spin_lock_bh(&br->multicast_lock); + if (br->multicast_querier == val) + goto unlock; + + br->multicast_querier = val; + if (val) + br_multicast_start_querier(br); + +unlock: + spin_unlock_bh(&br->multicast_lock); + + return 0; +} + int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val) { int err = -ENOENT; diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index a1daf82..2080485 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -60,20 +60,17 @@ static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *por hdr->ifi_flags = dev_get_flags(dev); hdr->ifi_change = 0; - NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); - NLA_PUT_U32(skb, IFLA_MASTER, br->dev->ifindex); - NLA_PUT_U32(skb, IFLA_MTU, dev->mtu); - NLA_PUT_U8(skb, IFLA_OPERSTATE, operstate); - - if (dev->addr_len) - NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); - - if (dev->ifindex != dev->iflink) - NLA_PUT_U32(skb, IFLA_LINK, dev->iflink); - - if (event == RTM_NEWLINK) - NLA_PUT_U8(skb, IFLA_PROTINFO, port->state); - + if (nla_put_string(skb, IFLA_IFNAME, dev->name) || + nla_put_u32(skb, IFLA_MASTER, br->dev->ifindex) || + nla_put_u32(skb, IFLA_MTU, dev->mtu) || + nla_put_u8(skb, IFLA_OPERSTATE, operstate) || + (dev->addr_len && + nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) || + (dev->ifindex != dev->iflink && + nla_put_u32(skb, IFLA_LINK, dev->iflink)) || + (event == RTM_NEWLINK && + nla_put_u8(skb, IFLA_PROTINFO, port->state))) + goto nla_put_failure; return nlmsg_end(skb, nlh); nla_put_failure: @@ -91,7 +88,7 @@ void br_ifinfo_notify(int event, struct net_bridge_port *port) int err = -ENOBUFS; br_debug(port->br, "port %u(%s) event %d\n", - (unsigned)port->port_no, port->dev->name, event); + (unsigned int)port->port_no, port->dev->name, event); skb = nlmsg_new(br_nlmsg_size(), GFP_ATOMIC); if (skb == NULL) @@ -235,18 +232,6 @@ int __init br_netlink_init(void) br_rtm_setlink, NULL, NULL); if (err) goto err3; - err = __rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, - br_fdb_add, NULL, NULL); - if (err) - goto err3; - err = __rtnl_register(PF_BRIDGE, RTM_DELNEIGH, - br_fdb_delete, NULL, NULL); - if (err) - goto err3; - err = __rtnl_register(PF_BRIDGE, RTM_GETNEIGH, - NULL, br_fdb_dump, NULL); - if (err) - goto err3; return 0; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index e1d8822..1a8ad4f 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -224,6 +224,7 @@ struct net_bridge unsigned char multicast_router; u8 multicast_disabled:1; + u8 multicast_querier:1; u32 hash_elasticity; u32 hash_max; @@ -359,9 +360,18 @@ extern int br_fdb_insert(struct net_bridge *br, extern void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, const unsigned char *addr); -extern int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb); -extern int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg); -extern int br_fdb_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg); + +extern int br_fdb_delete(struct ndmsg *ndm, + struct net_device *dev, + unsigned char *addr); +extern int br_fdb_add(struct ndmsg *nlh, + struct net_device *dev, + unsigned char *addr, + u16 nlh_flags); +extern int br_fdb_dump(struct sk_buff *skb, + struct netlink_callback *cb, + struct net_device *dev, + int idx); /* br_forward.c */ extern void br_deliver(const struct net_bridge_port *to, @@ -417,6 +427,7 @@ extern int br_multicast_set_router(struct net_bridge *br, unsigned long val); extern int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val); extern int br_multicast_toggle(struct net_bridge *br, unsigned long val); +extern int br_multicast_set_querier(struct net_bridge *br, unsigned long val); extern int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val); static inline bool br_multicast_is_router(struct net_bridge *br) diff --git a/net/bridge/br_private_stp.h b/net/bridge/br_private_stp.h index 05ed9bc..0c0fe36 100644 --- a/net/bridge/br_private_stp.h +++ b/net/bridge/br_private_stp.h @@ -29,10 +29,9 @@ #define BR_MIN_PATH_COST 1 #define BR_MAX_PATH_COST 65535 -struct br_config_bpdu -{ - unsigned topology_change:1; - unsigned topology_change_ack:1; +struct br_config_bpdu { + unsigned int topology_change:1; + unsigned int topology_change_ack:1; bridge_id root; int root_path_cost; bridge_id bridge_id; diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index 8c836d9..af9a120 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c @@ -32,7 +32,7 @@ static const char *const br_port_state_names[] = { void br_log_state(const struct net_bridge_port *p) { br_info(p->br, "port %u(%s) entered %s state\n", - (unsigned) p->port_no, p->dev->name, + (unsigned int) p->port_no, p->dev->name, br_port_state_names[p->state]); } @@ -478,7 +478,7 @@ void br_received_tcn_bpdu(struct net_bridge_port *p) { if (br_is_designated_port(p)) { br_info(p->br, "port %u(%s) received tcn bpdu\n", - (unsigned) p->port_no, p->dev->name); + (unsigned int) p->port_no, p->dev->name); br_topology_change_detection(p->br); br_topology_change_acknowledge(p); diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c index 58de2a0..a6747e6 100644 --- a/net/bridge/br_stp_timer.c +++ b/net/bridge/br_stp_timer.c @@ -56,7 +56,7 @@ static void br_message_age_timer_expired(unsigned long arg) return; br_info(br, "port %u(%s) neighbor %.2x%.2x.%pM lost\n", - (unsigned) p->port_no, p->dev->name, + (unsigned int) p->port_no, p->dev->name, id->prio[0], id->prio[1], &id->addr); /* @@ -84,7 +84,7 @@ static void br_forward_delay_timer_expired(unsigned long arg) struct net_bridge *br = p->br; br_debug(br, "port %u(%s) forward delay timer\n", - (unsigned) p->port_no, p->dev->name); + (unsigned int) p->port_no, p->dev->name); spin_lock(&br->lock); if (p->state == BR_STATE_LISTENING) { p->state = BR_STATE_LEARNING; @@ -131,7 +131,7 @@ static void br_hold_timer_expired(unsigned long arg) struct net_bridge_port *p = (struct net_bridge_port *) arg; br_debug(p->br, "port %u(%s) hold timer expired\n", - (unsigned) p->port_no, p->dev->name); + (unsigned int) p->port_no, p->dev->name); spin_lock(&p->br->lock); if (p->config_pending) diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index c236c0e..c5c0593 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -297,7 +297,7 @@ static ssize_t store_group_addr(struct device *d, const char *buf, size_t len) { struct net_bridge *br = to_bridge(d); - unsigned new_addr[6]; + unsigned int new_addr[6]; int i; if (!capable(CAP_NET_ADMIN)) @@ -379,6 +379,23 @@ static ssize_t store_multicast_snooping(struct device *d, static DEVICE_ATTR(multicast_snooping, S_IRUGO | S_IWUSR, show_multicast_snooping, store_multicast_snooping); +static ssize_t show_multicast_querier(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct net_bridge *br = to_bridge(d); + return sprintf(buf, "%d\n", br->multicast_querier); +} + +static ssize_t store_multicast_querier(struct device *d, + struct device_attribute *attr, + const char *buf, size_t len) +{ + return store_bridge_parm(d, buf, len, br_multicast_set_querier); +} +static DEVICE_ATTR(multicast_querier, S_IRUGO | S_IWUSR, + show_multicast_querier, store_multicast_querier); + static ssize_t show_hash_elasticity(struct device *d, struct device_attribute *attr, char *buf) { @@ -702,6 +719,7 @@ static struct attribute *bridge_attrs[] = { #ifdef CONFIG_BRIDGE_IGMP_SNOOPING &dev_attr_multicast_router.attr, &dev_attr_multicast_snooping.attr, + &dev_attr_multicast_querier.attr, &dev_attr_hash_elasticity.attr, &dev_attr_hash_max.attr, &dev_attr_multicast_last_member_count.attr, diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 5016fa5..0dccdb3 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -19,7 +19,7 @@ #include <linux/uaccess.h> #include <linux/debugfs.h> #include <linux/caif/caif_socket.h> -#include <linux/atomic.h> +#include <linux/pkt_sched.h> #include <net/sock.h> #include <net/tcp_states.h> #include <net/caif/caif_layer.h> @@ -130,7 +130,7 @@ static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= - (unsigned)sk->sk_rcvbuf && rx_flow_is_on(cf_sk)) { + (unsigned int)sk->sk_rcvbuf && rx_flow_is_on(cf_sk)) { if (net_ratelimit()) pr_debug("sending flow OFF (queue len = %d %d)\n", atomic_read(&cf_sk->sk.sk_rmem_alloc), @@ -505,6 +505,7 @@ static int transmit_skb(struct sk_buff *skb, struct caifsock *cf_sk, pkt = cfpkt_fromnative(CAIF_DIR_OUT, skb); memset(skb->cb, 0, sizeof(struct caif_payload_info)); + cfpkt_set_prio(pkt, cf_sk->sk.sk_priority); if (cf_sk->layer.dn == NULL) { kfree_skb(skb); @@ -1062,6 +1063,18 @@ static int caif_create(struct net *net, struct socket *sock, int protocol, /* Store the protocol */ sk->sk_protocol = (unsigned char) protocol; + /* Initialize default priority for well-known cases */ + switch (protocol) { + case CAIFPROTO_AT: + sk->sk_priority = TC_PRIO_CONTROL; + break; + case CAIFPROTO_RFM: + sk->sk_priority = TC_PRIO_INTERACTIVE_BULK; + break; + default: + sk->sk_priority = TC_PRIO_BESTEFFORT; + } + /* * Lock in order to try to stop someone from opening the socket * too early. @@ -1081,7 +1094,6 @@ static int caif_create(struct net *net, struct socket *sock, int protocol, set_rx_flow_on(cf_sk); /* Set default options on configuration */ - cf_sk->sk.sk_priority = CAIF_PRIO_NORMAL; cf_sk->conn_req.link_selector = CAIF_LINK_LOW_LATENCY; cf_sk->conn_req.protocol = protocol; release_sock(&cf_sk->sk); diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c index 5cf5222..047cd0e 100644 --- a/net/caif/cfctrl.c +++ b/net/caif/cfctrl.c @@ -9,6 +9,7 @@ #include <linux/stddef.h> #include <linux/spinlock.h> #include <linux/slab.h> +#include <linux/pkt_sched.h> #include <net/caif/caif_layer.h> #include <net/caif/cfpkt.h> #include <net/caif/cfctrl.h> @@ -189,6 +190,7 @@ void cfctrl_enum_req(struct cflayer *layer, u8 physlinkid) cfctrl->serv.dev_info.id = physlinkid; cfpkt_addbdy(pkt, CFCTRL_CMD_ENUM); cfpkt_addbdy(pkt, physlinkid); + cfpkt_set_prio(pkt, TC_PRIO_CONTROL); dn->transmit(dn, pkt); } @@ -281,6 +283,7 @@ int cfctrl_linkup_request(struct cflayer *layer, * might arrive with the newly allocated channel ID. */ cfpkt_info(pkt)->dev_info->id = param->phyid; + cfpkt_set_prio(pkt, TC_PRIO_CONTROL); ret = dn->transmit(dn, pkt); if (ret < 0) { @@ -314,6 +317,7 @@ int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid, cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_DESTROY); cfpkt_addbdy(pkt, channelid); init_info(cfpkt_info(pkt), cfctrl); + cfpkt_set_prio(pkt, TC_PRIO_CONTROL); ret = dn->transmit(dn, pkt); #ifndef CAIF_NO_LOOP diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c index e335ba8..863dedd 100644 --- a/net/caif/cfpkt_skbuff.c +++ b/net/caif/cfpkt_skbuff.c @@ -381,6 +381,7 @@ struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos) memcpy(skb2->data, split, len2nd); skb2->tail += len2nd; skb2->len += len2nd; + skb2->priority = skb->priority; return skb_to_pkt(skb2); } @@ -394,3 +395,9 @@ struct caif_payload_info *cfpkt_info(struct cfpkt *pkt) return (struct caif_payload_info *)&pkt_to_skb(pkt)->cb; } EXPORT_SYMBOL(cfpkt_info); + +void cfpkt_set_prio(struct cfpkt *pkt, int prio) +{ + pkt_to_skb(pkt)->priority = prio; +} +EXPORT_SYMBOL(cfpkt_set_prio); diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c index 4aa33d4..dd485f6 100644 --- a/net/caif/cfsrvl.c +++ b/net/caif/cfsrvl.c @@ -11,6 +11,7 @@ #include <linux/errno.h> #include <linux/slab.h> #include <linux/module.h> +#include <linux/pkt_sched.h> #include <net/caif/caif_layer.h> #include <net/caif/cfsrvl.h> #include <net/caif/cfpkt.h> @@ -120,6 +121,7 @@ static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl) info->channel_id = service->layer.id; info->hdr_len = 1; info->dev_info = &service->dev_info; + cfpkt_set_prio(pkt, TC_PRIO_CONTROL); return layr->dn->transmit(layr->dn, pkt); } case CAIF_MODEMCMD_FLOW_OFF_REQ: @@ -140,6 +142,7 @@ static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl) info->channel_id = service->layer.id; info->hdr_len = 1; info->dev_info = &service->dev_info; + cfpkt_set_prio(pkt, TC_PRIO_CONTROL); return layr->dn->transmit(layr->dn, pkt); } default: diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index d09340e..69771c0 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c @@ -424,14 +424,14 @@ static int ipcaif_fill_info(struct sk_buff *skb, const struct net_device *dev) struct chnl_net *priv; u8 loop; priv = netdev_priv(dev); - NLA_PUT_U32(skb, IFLA_CAIF_IPV4_CONNID, - priv->conn_req.sockaddr.u.dgm.connection_id); - NLA_PUT_U32(skb, IFLA_CAIF_IPV6_CONNID, - priv->conn_req.sockaddr.u.dgm.connection_id); + if (nla_put_u32(skb, IFLA_CAIF_IPV4_CONNID, + priv->conn_req.sockaddr.u.dgm.connection_id) || + nla_put_u32(skb, IFLA_CAIF_IPV6_CONNID, + priv->conn_req.sockaddr.u.dgm.connection_id)) + goto nla_put_failure; loop = priv->conn_req.protocol == CAIFPROTO_DATAGRAM_LOOP; - NLA_PUT_U8(skb, IFLA_CAIF_LOOPBACK, loop); - - + if (nla_put_u8(skb, IFLA_CAIF_LOOPBACK, loop)) + goto nla_put_failure; return 0; nla_put_failure: return -EMSGSIZE; diff --git a/net/ceph/auth_x.h b/net/ceph/auth_x.h index e02da7a..f459e93 100644 --- a/net/ceph/auth_x.h +++ b/net/ceph/auth_x.h @@ -13,7 +13,7 @@ */ struct ceph_x_ticket_handler { struct rb_node node; - unsigned service; + unsigned int service; struct ceph_crypto_key session_key; struct ceph_timespec validity; @@ -27,7 +27,7 @@ struct ceph_x_ticket_handler { struct ceph_x_authorizer { struct ceph_buffer *buf; - unsigned service; + unsigned int service; u64 nonce; char reply_buf[128]; /* big enough for encrypted blob */ }; @@ -38,7 +38,7 @@ struct ceph_x_info { bool starting; u64 server_challenge; - unsigned have_keys; + unsigned int have_keys; struct rb_root ticket_handlers; struct ceph_x_authorizer auth_authorizer; diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index cc91319..a776f75 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -441,8 +441,8 @@ EXPORT_SYMBOL(ceph_client_id); * create a fresh client instance */ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private, - unsigned supported_features, - unsigned required_features) + unsigned int supported_features, + unsigned int required_features) { struct ceph_client *client; struct ceph_entity_addr *myaddr = NULL; diff --git a/net/ceph/ceph_hash.c b/net/ceph/ceph_hash.c index 0a1b53b..67bb1f1 100644 --- a/net/ceph/ceph_hash.c +++ b/net/ceph/ceph_hash.c @@ -20,7 +20,7 @@ c = c - a; c = c - b; c = c ^ (b >> 15); \ } while (0) -unsigned ceph_str_hash_rjenkins(const char *str, unsigned length) +unsigned int ceph_str_hash_rjenkins(const char *str, unsigned int length) { const unsigned char *k = (const unsigned char *)str; __u32 a, b, c; /* the internal state */ @@ -81,7 +81,7 @@ unsigned ceph_str_hash_rjenkins(const char *str, unsigned length) /* * linux dcache hash */ -unsigned ceph_str_hash_linux(const char *str, unsigned length) +unsigned int ceph_str_hash_linux(const char *str, unsigned int length) { unsigned long hash = 0; unsigned char c; @@ -94,7 +94,7 @@ unsigned ceph_str_hash_linux(const char *str, unsigned length) } -unsigned ceph_str_hash(int type, const char *s, unsigned len) +unsigned int ceph_str_hash(int type, const char *s, unsigned int len) { switch (type) { case CEPH_STR_HASH_LINUX: diff --git a/net/ceph/crush/mapper.c b/net/ceph/crush/mapper.c index b79747c..854ac53 100644 --- a/net/ceph/crush/mapper.c +++ b/net/ceph/crush/mapper.c @@ -68,8 +68,8 @@ int crush_find_rule(struct crush_map *map, int ruleset, int type, int size) static int bucket_perm_choose(struct crush_bucket *bucket, int x, int r) { - unsigned pr = r % bucket->size; - unsigned i, s; + unsigned int pr = r % bucket->size; + unsigned int i, s; /* start a new permutation if @x has changed */ if (bucket->perm_x != x || bucket->perm_n == 0) { @@ -100,13 +100,13 @@ static int bucket_perm_choose(struct crush_bucket *bucket, for (i = 0; i < bucket->perm_n; i++) dprintk(" perm_choose have %d: %d\n", i, bucket->perm[i]); while (bucket->perm_n <= pr) { - unsigned p = bucket->perm_n; + unsigned int p = bucket->perm_n; /* no point in swapping the final entry */ if (p < bucket->size - 1) { i = crush_hash32_3(bucket->hash, x, bucket->id, p) % (bucket->size - p); if (i) { - unsigned t = bucket->perm[p + i]; + unsigned int t = bucket->perm[p + i]; bucket->perm[p + i] = bucket->perm[p]; bucket->perm[p] = t; } diff --git a/net/ceph/debugfs.c b/net/ceph/debugfs.c index 27d4ea31..54b531a 100644 --- a/net/ceph/debugfs.c +++ b/net/ceph/debugfs.c @@ -94,9 +94,9 @@ static int monc_show(struct seq_file *s, void *p) mutex_lock(&monc->mutex); if (monc->have_mdsmap) - seq_printf(s, "have mdsmap %u\n", (unsigned)monc->have_mdsmap); + seq_printf(s, "have mdsmap %u\n", (unsigned int)monc->have_mdsmap); if (monc->have_osdmap) - seq_printf(s, "have osdmap %u\n", (unsigned)monc->have_osdmap); + seq_printf(s, "have osdmap %u\n", (unsigned int)monc->have_osdmap); if (monc->want_next_osdmap) seq_printf(s, "want next osdmap\n"); @@ -146,7 +146,7 @@ static int osdc_show(struct seq_file *s, void *pp) if (req->r_reassert_version.epoch) seq_printf(s, "\t%u'%llu", - (unsigned)le32_to_cpu(req->r_reassert_version.epoch), + (unsigned int)le32_to_cpu(req->r_reassert_version.epoch), le64_to_cpu(req->r_reassert_version.version)); else seq_printf(s, "\t"); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index f0993af..36fa6bf 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -699,7 +699,7 @@ static int prepare_write_connect(struct ceph_messenger *msgr, struct ceph_connection *con, int include_banner) { - unsigned global_seq = get_global_seq(con->msgr, 0); + unsigned int global_seq = get_global_seq(con->msgr, 0); int proto; switch (con->peer_name.type) { @@ -816,7 +816,7 @@ static void iter_bio_next(struct bio **bio_iter, int *seg) static int write_partial_msg_pages(struct ceph_connection *con) { struct ceph_msg *msg = con->out_msg; - unsigned data_len = le32_to_cpu(msg->hdr.data_len); + unsigned int data_len = le32_to_cpu(msg->hdr.data_len); size_t len; bool do_datacrc = !con->msgr->nocrc; int ret; @@ -1554,7 +1554,7 @@ static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con, static int read_partial_message_pages(struct ceph_connection *con, struct page **pages, - unsigned data_len, bool do_datacrc) + unsigned int data_len, bool do_datacrc) { void *p; int ret; @@ -1587,7 +1587,7 @@ static int read_partial_message_pages(struct ceph_connection *con, #ifdef CONFIG_BLOCK static int read_partial_message_bio(struct ceph_connection *con, struct bio **bio_iter, int *bio_seg, - unsigned data_len, bool do_datacrc) + unsigned int data_len, bool do_datacrc) { struct bio_vec *bv = bio_iovec_idx(*bio_iter, *bio_seg); void *p; @@ -1629,7 +1629,7 @@ static int read_partial_message(struct ceph_connection *con) struct ceph_msg *m = con->in_msg; int ret; int to, left; - unsigned front_len, middle_len, data_len; + unsigned int front_len, middle_len, data_len; bool do_datacrc = !con->msgr->nocrc; int skip; u64 seq; @@ -2345,9 +2345,9 @@ void ceph_con_revoke_message(struct ceph_connection *con, struct ceph_msg *msg) { mutex_lock(&con->mutex); if (con->in_msg && con->in_msg == msg) { - unsigned front_len = le32_to_cpu(con->in_hdr.front_len); - unsigned middle_len = le32_to_cpu(con->in_hdr.middle_len); - unsigned data_len = le32_to_cpu(con->in_hdr.data_len); + unsigned int front_len = le32_to_cpu(con->in_hdr.front_len); + unsigned int middle_len = le32_to_cpu(con->in_hdr.middle_len); + unsigned int data_len = le32_to_cpu(con->in_hdr.data_len); /* skip rest of message */ dout("con_revoke_pages %p msg %p revoked\n", con, msg); diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 1845cde..10d6008 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -168,7 +168,7 @@ static bool __sub_expired(struct ceph_mon_client *monc) */ static void __schedule_delayed(struct ceph_mon_client *monc) { - unsigned delay; + unsigned int delay; if (monc->cur_mon < 0 || __sub_expired(monc)) delay = 10 * HZ; @@ -184,7 +184,7 @@ static void __schedule_delayed(struct ceph_mon_client *monc) static void __send_subscribe(struct ceph_mon_client *monc) { dout("__send_subscribe sub_sent=%u exp=%u want_osd=%d\n", - (unsigned)monc->sub_sent, __sub_expired(monc), + (unsigned int)monc->sub_sent, __sub_expired(monc), monc->want_next_osdmap); if ((__sub_expired(monc) && !monc->sub_sent) || monc->want_next_osdmap == 1) { @@ -201,7 +201,7 @@ static void __send_subscribe(struct ceph_mon_client *monc) if (monc->want_next_osdmap) { dout("__send_subscribe to 'osdmap' %u\n", - (unsigned)monc->have_osdmap); + (unsigned int)monc->have_osdmap); ceph_encode_string(&p, end, "osdmap", 6); i = p; i->have = cpu_to_le64(monc->have_osdmap); @@ -211,7 +211,7 @@ static void __send_subscribe(struct ceph_mon_client *monc) } if (monc->want_mdsmap) { dout("__send_subscribe to 'mdsmap' %u+\n", - (unsigned)monc->have_mdsmap); + (unsigned int)monc->have_mdsmap); ceph_encode_string(&p, end, "mdsmap", 6); i = p; i->have = cpu_to_le64(monc->have_mdsmap); @@ -236,7 +236,7 @@ static void __send_subscribe(struct ceph_mon_client *monc) static void handle_subscribe_ack(struct ceph_mon_client *monc, struct ceph_msg *msg) { - unsigned seconds; + unsigned int seconds; struct ceph_mon_subscribe_ack *h = msg->front.iov_base; if (msg->front.iov_len < sizeof(*h)) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 5e25405..1b0ef3c 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -1214,7 +1214,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, } if (!req->r_got_reply) { - unsigned bytes; + unsigned int bytes; req->r_result = le32_to_cpu(rhead->result); bytes = le32_to_cpu(msg->hdr.data_len); diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 29ad46e..56e561a 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -38,7 +38,7 @@ done: /* maps */ -static int calc_bits_of(unsigned t) +static int calc_bits_of(unsigned int t) { int b = 0; while (t) { @@ -154,7 +154,7 @@ static struct crush_map *crush_decode(void *pbyval, void *end) magic = ceph_decode_32(p); if (magic != CRUSH_MAGIC) { pr_err("crush_decode magic %x != current %x\n", - (unsigned)magic, (unsigned)CRUSH_MAGIC); + (unsigned int)magic, (unsigned int)CRUSH_MAGIC); goto bad; } c->max_buckets = ceph_decode_32(p); @@ -460,7 +460,7 @@ static void __remove_pg_pool(struct rb_root *root, struct ceph_pg_pool_info *pi) static int __decode_pool(void **p, void *end, struct ceph_pg_pool_info *pi) { - unsigned n, m; + unsigned int n, m; ceph_decode_copy(p, &pi->v, sizeof(pi->v)); calc_pg_masks(pi); @@ -970,7 +970,7 @@ void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, objsetno = stripeno / su_per_object; *ono = objsetno * sc + stripepos; - dout("objset %u * sc %u = ono %u\n", objsetno, sc, (unsigned)*ono); + dout("objset %u * sc %u = ono %u\n", objsetno, sc, (unsigned int)*ono); /* *oxoff = *off % layout->fl_stripe_unit; # offset in su */ t = off; @@ -998,12 +998,12 @@ int ceph_calc_object_layout(struct ceph_object_layout *ol, struct ceph_file_layout *fl, struct ceph_osdmap *osdmap) { - unsigned num, num_mask; + unsigned int num, num_mask; struct ceph_pg pgid; s32 preferred = (s32)le32_to_cpu(fl->fl_pg_preferred); int poolid = le32_to_cpu(fl->fl_pg_pool); struct ceph_pg_pool_info *pool; - unsigned ps; + unsigned int ps; BUG_ON(!osdmap); @@ -1045,7 +1045,7 @@ static int *calc_pg_raw(struct ceph_osdmap *osdmap, struct ceph_pg pgid, struct ceph_pg_mapping *pg; struct ceph_pg_pool_info *pool; int ruleno; - unsigned poolid, ps, pps, t; + unsigned int poolid, ps, pps, t; int preferred; poolid = le32_to_cpu(pgid.pool); diff --git a/net/compat.c b/net/compat.c index e055708..e240441 100644 --- a/net/compat.c +++ b/net/compat.c @@ -741,13 +741,13 @@ static unsigned char nas[21] = { }; #undef AL -asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags) +asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) { return sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); } asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg, - unsigned vlen, unsigned int flags) + unsigned int vlen, unsigned int flags) { return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, flags | MSG_CMSG_COMPAT); @@ -758,20 +758,20 @@ asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, uns return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); } -asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len, unsigned flags) +asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len, unsigned int flags) { return sys_recv(fd, buf, len, flags | MSG_CMSG_COMPAT); } asmlinkage long compat_sys_recvfrom(int fd, void __user *buf, size_t len, - unsigned flags, struct sockaddr __user *addr, + unsigned int flags, struct sockaddr __user *addr, int __user *addrlen) { return sys_recvfrom(fd, buf, len, flags | MSG_CMSG_COMPAT, addr, addrlen); } asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, - unsigned vlen, unsigned int flags, + unsigned int vlen, unsigned int flags, struct compat_timespec __user *timeout) { int datagrams; diff --git a/net/core/datagram.c b/net/core/datagram.c index e4fbfd6..ae6acf6 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -65,7 +65,7 @@ static inline int connection_based(struct sock *sk) return sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM; } -static int receiver_wake_function(wait_queue_t *wait, unsigned mode, int sync, +static int receiver_wake_function(wait_queue_t *wait, unsigned int mode, int sync, void *key) { unsigned long bits = (unsigned long)key; @@ -158,7 +158,7 @@ out_noerr: * quite explicitly by POSIX 1003.1g, don't change them without having * the standard around please. */ -struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags, +struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, int *peeked, int *off, int *err) { struct sk_buff *skb; @@ -216,7 +216,7 @@ no_packet: } EXPORT_SYMBOL(__skb_recv_datagram); -struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, +struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned int flags, int noblock, int *err) { int peeked, off = 0; diff --git a/net/core/dev.c b/net/core/dev.c index 9bb8f87..c938127 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -208,7 +208,8 @@ static inline void dev_base_seq_inc(struct net *net) static inline struct hlist_head *dev_name_hash(struct net *net, const char *name) { - unsigned hash = full_name_hash(name, strnlen(name, IFNAMSIZ)); + unsigned int hash = full_name_hash(name, strnlen(name, IFNAMSIZ)); + return &net->dev_name_head[hash_32(hash, NETDEV_HASHBITS)]; } @@ -4618,9 +4619,9 @@ void dev_set_rx_mode(struct net_device *dev) * * Get the combination of flag bits exported through APIs to userspace. */ -unsigned dev_get_flags(const struct net_device *dev) +unsigned int dev_get_flags(const struct net_device *dev) { - unsigned flags; + unsigned int flags; flags = (dev->flags & ~(IFF_PROMISC | IFF_ALLMULTI | diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index 626698f..c4cc2bc 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -21,12 +21,35 @@ * General list handling functions */ +static int __hw_addr_create_ex(struct netdev_hw_addr_list *list, + unsigned char *addr, int addr_len, + unsigned char addr_type, bool global) +{ + struct netdev_hw_addr *ha; + int alloc_size; + + alloc_size = sizeof(*ha); + if (alloc_size < L1_CACHE_BYTES) + alloc_size = L1_CACHE_BYTES; + ha = kmalloc(alloc_size, GFP_ATOMIC); + if (!ha) + return -ENOMEM; + memcpy(ha->addr, addr, addr_len); + ha->type = addr_type; + ha->refcount = 1; + ha->global_use = global; + ha->synced = false; + list_add_tail_rcu(&ha->list, &list->list); + list->count++; + + return 0; +} + static int __hw_addr_add_ex(struct netdev_hw_addr_list *list, unsigned char *addr, int addr_len, unsigned char addr_type, bool global) { struct netdev_hw_addr *ha; - int alloc_size; if (addr_len > MAX_ADDR_LEN) return -EINVAL; @@ -46,21 +69,7 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list, } } - - alloc_size = sizeof(*ha); - if (alloc_size < L1_CACHE_BYTES) - alloc_size = L1_CACHE_BYTES; - ha = kmalloc(alloc_size, GFP_ATOMIC); - if (!ha) - return -ENOMEM; - memcpy(ha->addr, addr, addr_len); - ha->type = addr_type; - ha->refcount = 1; - ha->global_use = global; - ha->synced = false; - list_add_tail_rcu(&ha->list, &list->list); - list->count++; - return 0; + return __hw_addr_create_ex(list, addr, addr_len, addr_type, global); } static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr, @@ -377,6 +386,34 @@ EXPORT_SYMBOL(dev_addr_del_multiple); */ /** + * dev_uc_add_excl - Add a global secondary unicast address + * @dev: device + * @addr: address to add + */ +int dev_uc_add_excl(struct net_device *dev, unsigned char *addr) +{ + struct netdev_hw_addr *ha; + int err; + + netif_addr_lock_bh(dev); + list_for_each_entry(ha, &dev->uc.list, list) { + if (!memcmp(ha->addr, addr, dev->addr_len) && + ha->type == NETDEV_HW_ADDR_T_UNICAST) { + err = -EEXIST; + goto out; + } + } + err = __hw_addr_create_ex(&dev->uc, addr, dev->addr_len, + NETDEV_HW_ADDR_T_UNICAST, true); + if (!err) + __dev_set_rx_mode(dev); +out: + netif_addr_unlock_bh(dev); + return err; +} +EXPORT_SYMBOL(dev_uc_add_excl); + +/** * dev_uc_add - Add a secondary unicast address * @dev: device * @addr: address to add @@ -501,6 +538,34 @@ EXPORT_SYMBOL(dev_uc_init); * Multicast list handling functions */ +/** + * dev_mc_add_excl - Add a global secondary multicast address + * @dev: device + * @addr: address to add + */ +int dev_mc_add_excl(struct net_device *dev, unsigned char *addr) +{ + struct netdev_hw_addr *ha; + int err; + + netif_addr_lock_bh(dev); + list_for_each_entry(ha, &dev->mc.list, list) { + if (!memcmp(ha->addr, addr, dev->addr_len) && + ha->type == NETDEV_HW_ADDR_T_MULTICAST) { + err = -EEXIST; + goto out; + } + } + err = __hw_addr_create_ex(&dev->mc, addr, dev->addr_len, + NETDEV_HW_ADDR_T_MULTICAST, true); + if (!err) + __dev_set_rx_mode(dev); +out: + netif_addr_unlock_bh(dev); + return err; +} +EXPORT_SYMBOL(dev_mc_add_excl); + static int __dev_mc_add(struct net_device *dev, unsigned char *addr, bool global) { diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 6d6d7d2..beacdd9 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -17,6 +17,8 @@ #include <linux/errno.h> #include <linux/ethtool.h> #include <linux/netdevice.h> +#include <linux/net_tstamp.h> +#include <linux/phy.h> #include <linux/bitops.h> #include <linux/uaccess.h> #include <linux/vmalloc.h> @@ -36,6 +38,17 @@ u32 ethtool_op_get_link(struct net_device *dev) } EXPORT_SYMBOL(ethtool_op_get_link); +int ethtool_op_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) +{ + info->so_timestamping = + SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE; + info->phc_index = -1; + return 0; +} +EXPORT_SYMBOL(ethtool_op_get_ts_info); + /* Handlers for each ethtool command */ #define ETHTOOL_DEV_FEATURE_WORDS ((NETDEV_FEATURE_COUNT + 31) / 32) @@ -1278,6 +1291,40 @@ out: return ret; } +static int ethtool_get_ts_info(struct net_device *dev, void __user *useraddr) +{ + int err = 0; + struct ethtool_ts_info info; + const struct ethtool_ops *ops = dev->ethtool_ops; + struct phy_device *phydev = dev->phydev; + + memset(&info, 0, sizeof(info)); + info.cmd = ETHTOOL_GET_TS_INFO; + + if (phydev && phydev->drv && phydev->drv->ts_info) { + + err = phydev->drv->ts_info(phydev, &info); + + } else if (dev->ethtool_ops && dev->ethtool_ops->get_ts_info) { + + err = ops->get_ts_info(dev, &info); + + } else { + info.so_timestamping = + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE; + info.phc_index = -1; + } + + if (err) + return err; + + if (copy_to_user(useraddr, &info, sizeof(info))) + err = -EFAULT; + + return err; +} + /* The main entry point in this file. Called from net/core/dev.c */ int dev_ethtool(struct net *net, struct ifreq *ifr) @@ -1295,11 +1342,13 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) return -EFAULT; if (!dev->ethtool_ops) { - /* ETHTOOL_GDRVINFO does not require any driver support. - * It is also unprivileged and does not change anything, - * so we can take a shortcut to it. */ + /* A few commands do not require any driver support, + * are unprivileged, and do not change anything, so we + * can take a shortcut to them. */ if (ethcmd == ETHTOOL_GDRVINFO) return ethtool_get_drvinfo(dev, useraddr); + else if (ethcmd == ETHTOOL_GET_TS_INFO) + return ethtool_get_ts_info(dev, useraddr); else return -EOPNOTSUPP; } @@ -1330,6 +1379,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) case ETHTOOL_GRXCLSRULE: case ETHTOOL_GRXCLSRLALL: case ETHTOOL_GFEATURES: + case ETHTOOL_GET_TS_INFO: break; default: if (!capable(CAP_NET_ADMIN)) @@ -1496,6 +1546,9 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) case ETHTOOL_GET_DUMP_DATA: rc = ethtool_get_dump_data(dev, useraddr); break; + case ETHTOOL_GET_TS_INFO: + rc = ethtool_get_ts_info(dev, useraddr); + break; default: rc = -EOPNOTSUPP; } diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index c02e63c..72cceb7 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -542,7 +542,8 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, frh = nlmsg_data(nlh); frh->family = ops->family; frh->table = rule->table; - NLA_PUT_U32(skb, FRA_TABLE, rule->table); + if (nla_put_u32(skb, FRA_TABLE, rule->table)) + goto nla_put_failure; frh->res1 = 0; frh->res2 = 0; frh->action = rule->action; @@ -553,31 +554,28 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, frh->flags |= FIB_RULE_UNRESOLVED; if (rule->iifname[0]) { - NLA_PUT_STRING(skb, FRA_IIFNAME, rule->iifname); - + if (nla_put_string(skb, FRA_IIFNAME, rule->iifname)) + goto nla_put_failure; if (rule->iifindex == -1) frh->flags |= FIB_RULE_IIF_DETACHED; } if (rule->oifname[0]) { - NLA_PUT_STRING(skb, FRA_OIFNAME, rule->oifname); - + if (nla_put_string(skb, FRA_OIFNAME, rule->oifname)) + goto nla_put_failure; if (rule->oifindex == -1) frh->flags |= FIB_RULE_OIF_DETACHED; } - if (rule->pref) - NLA_PUT_U32(skb, FRA_PRIORITY, rule->pref); - - if (rule->mark) - NLA_PUT_U32(skb, FRA_FWMARK, rule->mark); - - if (rule->mark_mask || rule->mark) - NLA_PUT_U32(skb, FRA_FWMASK, rule->mark_mask); - - if (rule->target) - NLA_PUT_U32(skb, FRA_GOTO, rule->target); - + if ((rule->pref && + nla_put_u32(skb, FRA_PRIORITY, rule->pref)) || + (rule->mark && + nla_put_u32(skb, FRA_FWMARK, rule->mark)) || + ((rule->mark_mask || rule->mark) && + nla_put_u32(skb, FRA_FWMASK, rule->mark_mask)) || + (rule->target && + nla_put_u32(skb, FRA_GOTO, rule->target))) + goto nla_put_failure; if (ops->fill(rule, skb, frh) < 0) goto nla_put_failure; diff --git a/net/core/filter.c b/net/core/filter.c index 6f755cc..47a5f05 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -317,6 +317,9 @@ load_b: case BPF_S_ANC_CPU: A = raw_smp_processor_id(); continue; + case BPF_S_ANC_ALU_XOR_X: + A ^= X; + continue; case BPF_S_ANC_NLATTR: { struct nlattr *nla; @@ -528,7 +531,7 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen) * Compare this with conditional jumps below, * where offsets are limited. --ANK (981016) */ - if (ftest->k >= (unsigned)(flen-pc-1)) + if (ftest->k >= (unsigned int)(flen-pc-1)) return -EINVAL; break; case BPF_S_JMP_JEQ_K: @@ -561,6 +564,7 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen) ANCILLARY(HATYPE); ANCILLARY(RXHASH); ANCILLARY(CPU); + ANCILLARY(ALU_XOR_X); } } ftest->code = code; @@ -589,6 +593,67 @@ void sk_filter_release_rcu(struct rcu_head *rcu) } EXPORT_SYMBOL(sk_filter_release_rcu); +static int __sk_prepare_filter(struct sk_filter *fp) +{ + int err; + + fp->bpf_func = sk_run_filter; + + err = sk_chk_filter(fp->insns, fp->len); + if (err) + return err; + + bpf_jit_compile(fp); + return 0; +} + +/** + * sk_unattached_filter_create - create an unattached filter + * @fprog: the filter program + * @sk: the socket to use + * + * Create a filter independent ofr any socket. We first run some + * sanity checks on it to make sure it does not explode on us later. + * If an error occurs or there is insufficient memory for the filter + * a negative errno code is returned. On success the return is zero. + */ +int sk_unattached_filter_create(struct sk_filter **pfp, + struct sock_fprog *fprog) +{ + struct sk_filter *fp; + unsigned int fsize = sizeof(struct sock_filter) * fprog->len; + int err; + + /* Make sure new filter is there and in the right amounts. */ + if (fprog->filter == NULL) + return -EINVAL; + + fp = kmalloc(fsize + sizeof(*fp), GFP_KERNEL); + if (!fp) + return -ENOMEM; + memcpy(fp->insns, fprog->filter, fsize); + + atomic_set(&fp->refcnt, 1); + fp->len = fprog->len; + + err = __sk_prepare_filter(fp); + if (err) + goto free_mem; + + *pfp = fp; + return 0; +free_mem: + kfree(fp); + return err; +} +EXPORT_SYMBOL_GPL(sk_unattached_filter_create); + +void sk_unattached_filter_destroy(struct sk_filter *fp) +{ + sk_filter_release(fp); +} +EXPORT_SYMBOL_GPL(sk_unattached_filter_destroy); + /** * sk_attach_filter - attach a socket filter * @fprog: the filter program @@ -619,16 +684,13 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) atomic_set(&fp->refcnt, 1); fp->len = fprog->len; - fp->bpf_func = sk_run_filter; - err = sk_chk_filter(fp->insns, fp->len); + err = __sk_prepare_filter(fp); if (err) { sk_filter_uncharge(sk, fp); return err; } - bpf_jit_compile(fp); - old_fp = rcu_dereference_protected(sk->sk_filter, sock_owned_by_user(sk)); rcu_assign_pointer(sk->sk_filter, fp); diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c index 0452eb2..ddedf21 100644 --- a/net/core/gen_stats.c +++ b/net/core/gen_stats.c @@ -27,7 +27,8 @@ static inline int gnet_stats_copy(struct gnet_dump *d, int type, void *buf, int size) { - NLA_PUT(d->skb, type, size, buf); + if (nla_put(d->skb, type, size, buf)) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/core/kmap_skb.h b/net/core/kmap_skb.h deleted file mode 100644 index 52d0a44..0000000 --- a/net/core/kmap_skb.h +++ /dev/null @@ -1,19 +0,0 @@ -#include <linux/highmem.h> - -static inline void *kmap_skb_frag(const skb_frag_t *frag) -{ -#ifdef CONFIG_HIGHMEM - BUG_ON(in_irq()); - - local_bh_disable(); -#endif - return kmap_atomic(skb_frag_page(frag)); -} - -static inline void kunmap_skb_frag(void *vaddr) -{ - kunmap_atomic(vaddr); -#ifdef CONFIG_HIGHMEM - local_bh_enable(); -#endif -} diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 0a68045..434eed8 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -890,7 +890,7 @@ static void neigh_timer_handler(unsigned long arg) { unsigned long now, next; struct neighbour *neigh = (struct neighbour *)arg; - unsigned state; + unsigned int state; int notify = 0; write_lock(&neigh->lock); @@ -1500,7 +1500,7 @@ static void neigh_parms_destroy(struct neigh_parms *parms) static struct lock_class_key neigh_table_proxy_queue_class; -void neigh_table_init_no_netlink(struct neigh_table *tbl) +static void neigh_table_init_no_netlink(struct neigh_table *tbl) { unsigned long now = jiffies; unsigned long phsize; @@ -1538,7 +1538,6 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl) tbl->last_flush = now; tbl->last_rand = now + tbl->parms.reachable_time * 20; } -EXPORT_SYMBOL(neigh_table_init_no_netlink); void neigh_table_init(struct neigh_table *tbl) { @@ -1768,29 +1767,29 @@ static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms) if (nest == NULL) return -ENOBUFS; - if (parms->dev) - NLA_PUT_U32(skb, NDTPA_IFINDEX, parms->dev->ifindex); - - NLA_PUT_U32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)); - NLA_PUT_U32(skb, NDTPA_QUEUE_LENBYTES, parms->queue_len_bytes); - /* approximative value for deprecated QUEUE_LEN (in packets) */ - NLA_PUT_U32(skb, NDTPA_QUEUE_LEN, - DIV_ROUND_UP(parms->queue_len_bytes, - SKB_TRUESIZE(ETH_FRAME_LEN))); - NLA_PUT_U32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen); - NLA_PUT_U32(skb, NDTPA_APP_PROBES, parms->app_probes); - NLA_PUT_U32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes); - NLA_PUT_U32(skb, NDTPA_MCAST_PROBES, parms->mcast_probes); - NLA_PUT_MSECS(skb, NDTPA_REACHABLE_TIME, parms->reachable_time); - NLA_PUT_MSECS(skb, NDTPA_BASE_REACHABLE_TIME, - parms->base_reachable_time); - NLA_PUT_MSECS(skb, NDTPA_GC_STALETIME, parms->gc_staletime); - NLA_PUT_MSECS(skb, NDTPA_DELAY_PROBE_TIME, parms->delay_probe_time); - NLA_PUT_MSECS(skb, NDTPA_RETRANS_TIME, parms->retrans_time); - NLA_PUT_MSECS(skb, NDTPA_ANYCAST_DELAY, parms->anycast_delay); - NLA_PUT_MSECS(skb, NDTPA_PROXY_DELAY, parms->proxy_delay); - NLA_PUT_MSECS(skb, NDTPA_LOCKTIME, parms->locktime); - + if ((parms->dev && + nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) || + nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) || + nla_put_u32(skb, NDTPA_QUEUE_LENBYTES, parms->queue_len_bytes) || + /* approximative value for deprecated QUEUE_LEN (in packets) */ + nla_put_u32(skb, NDTPA_QUEUE_LEN, + DIV_ROUND_UP(parms->queue_len_bytes, + SKB_TRUESIZE(ETH_FRAME_LEN))) || + nla_put_u32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen) || + nla_put_u32(skb, NDTPA_APP_PROBES, parms->app_probes) || + nla_put_u32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes) || + nla_put_u32(skb, NDTPA_MCAST_PROBES, parms->mcast_probes) || + nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time) || + nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME, + parms->base_reachable_time) || + nla_put_msecs(skb, NDTPA_GC_STALETIME, parms->gc_staletime) || + nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME, + parms->delay_probe_time) || + nla_put_msecs(skb, NDTPA_RETRANS_TIME, parms->retrans_time) || + nla_put_msecs(skb, NDTPA_ANYCAST_DELAY, parms->anycast_delay) || + nla_put_msecs(skb, NDTPA_PROXY_DELAY, parms->proxy_delay) || + nla_put_msecs(skb, NDTPA_LOCKTIME, parms->locktime)) + goto nla_put_failure; return nla_nest_end(skb, nest); nla_put_failure: @@ -1815,12 +1814,12 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, ndtmsg->ndtm_pad1 = 0; ndtmsg->ndtm_pad2 = 0; - NLA_PUT_STRING(skb, NDTA_NAME, tbl->id); - NLA_PUT_MSECS(skb, NDTA_GC_INTERVAL, tbl->gc_interval); - NLA_PUT_U32(skb, NDTA_THRESH1, tbl->gc_thresh1); - NLA_PUT_U32(skb, NDTA_THRESH2, tbl->gc_thresh2); - NLA_PUT_U32(skb, NDTA_THRESH3, tbl->gc_thresh3); - + if (nla_put_string(skb, NDTA_NAME, tbl->id) || + nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval) || + nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) || + nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) || + nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3)) + goto nla_put_failure; { unsigned long now = jiffies; unsigned int flush_delta = now - tbl->last_flush; @@ -1841,7 +1840,8 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1); rcu_read_unlock_bh(); - NLA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc); + if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc)) + goto nla_put_failure; } { @@ -1866,7 +1866,8 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, ndst.ndts_forced_gc_runs += st->forced_gc_runs; } - NLA_PUT(skb, NDTA_STATS, sizeof(ndst), &ndst); + if (nla_put(skb, NDTA_STATS, sizeof(ndst), &ndst)) + goto nla_put_failure; } BUG_ON(tbl->parms.dev); @@ -2137,7 +2138,8 @@ static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh, ndm->ndm_type = neigh->type; ndm->ndm_ifindex = neigh->dev->ifindex; - NLA_PUT(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key); + if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key)) + goto nla_put_failure; read_lock_bh(&neigh->lock); ndm->ndm_state = neigh->nud_state; @@ -2157,8 +2159,9 @@ static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh, ci.ndm_refcnt = atomic_read(&neigh->refcnt) - 1; read_unlock_bh(&neigh->lock); - NLA_PUT_U32(skb, NDA_PROBES, atomic_read(&neigh->probes)); - NLA_PUT(skb, NDA_CACHEINFO, sizeof(ci), &ci); + if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) || + nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci)) + goto nla_put_failure; return nlmsg_end(skb, nlh); @@ -2187,7 +2190,8 @@ static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn, ndm->ndm_ifindex = pn->dev->ifindex; ndm->ndm_state = NUD_NONE; - NLA_PUT(skb, NDA_DST, tbl->key_len, pn->key); + if (nla_put(skb, NDA_DST, tbl->key_len, pn->key)) + goto nla_put_failure; return nlmsg_end(skb, nlh); diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 4955862..fdf9e61 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -74,15 +74,14 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr, int (*set)(struct net_device *, unsigned long)) { struct net_device *net = to_net_dev(dev); - char *endp; unsigned long new; int ret = -EINVAL; if (!capable(CAP_NET_ADMIN)) return -EPERM; - new = simple_strtoul(buf, &endp, 0); - if (endp == buf) + ret = kstrtoul(buf, 0, &new); + if (ret) goto err; if (!rtnl_trylock()) @@ -232,7 +231,7 @@ NETDEVICE_SHOW(flags, fmt_hex); static int change_flags(struct net_device *net, unsigned long new_flags) { - return dev_change_flags(net, (unsigned) new_flags); + return dev_change_flags(net, (unsigned int) new_flags); } static ssize_t store_flags(struct device *dev, struct device_attribute *attr, @@ -582,7 +581,7 @@ static ssize_t store_rps_map(struct netdev_rx_queue *queue, return err; } - map = kzalloc(max_t(unsigned, + map = kzalloc(max_t(unsigned int, RPS_MAP_SIZE(cpumask_weight(mask)), L1_CACHE_BYTES), GFP_KERNEL); if (!map) { @@ -903,7 +902,7 @@ static ssize_t bql_set_hold_time(struct netdev_queue *queue, const char *buf, size_t len) { struct dql *dql = &queue->dql; - unsigned value; + unsigned int value; int err; err = kstrtouint(buf, 10, &value); @@ -1107,7 +1106,7 @@ static ssize_t store_xps_map(struct netdev_queue *queue, return err; } - new_dev_maps = kzalloc(max_t(unsigned, + new_dev_maps = kzalloc(max_t(unsigned int, XPS_DEV_MAPS_SIZE, L1_CACHE_BYTES), GFP_KERNEL); if (!new_dev_maps) { free_cpumask_var(mask); diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 4d8ce93..ffb5d38 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -320,7 +320,7 @@ struct pktgen_dev { (see RFC 3260, sec. 4) */ /* MPLS */ - unsigned nr_labels; /* Depth of stack, 0 = no MPLS */ + unsigned int nr_labels; /* Depth of stack, 0 = no MPLS */ __be32 labels[MAX_MPLS_LABELS]; /* VLAN/SVLAN (802.1Q/Q-in-Q) */ @@ -373,10 +373,10 @@ struct pktgen_dev { */ char odevname[32]; struct flow_state *flows; - unsigned cflows; /* Concurrent flows (config) */ - unsigned lflow; /* Flow length (config) */ - unsigned nflows; /* accumulated flows (stats) */ - unsigned curfl; /* current sequenced flow (state)*/ + unsigned int cflows; /* Concurrent flows (config) */ + unsigned int lflow; /* Flow length (config) */ + unsigned int nflows; /* accumulated flows (stats) */ + unsigned int curfl; /* current sequenced flow (state)*/ u16 queue_map_min; u16 queue_map_max; @@ -592,7 +592,7 @@ static int pktgen_if_show(struct seq_file *seq, void *v) pkt_dev->src_mac_count, pkt_dev->dst_mac_count); if (pkt_dev->nr_labels) { - unsigned i; + unsigned int i; seq_printf(seq, " mpls: "); for (i = 0; i < pkt_dev->nr_labels; i++) seq_printf(seq, "%08x%s", ntohl(pkt_dev->labels[i]), @@ -812,7 +812,7 @@ done_str: static ssize_t get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev) { - unsigned n = 0; + unsigned int n = 0; char c; ssize_t i = 0; int len; @@ -1510,7 +1510,7 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "mpls")) { - unsigned n, cnt; + unsigned int n, cnt; len = get_labels(&user_buffer[i], pkt_dev); if (len < 0) @@ -2324,7 +2324,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) } if (pkt_dev->flags & F_MPLS_RND) { - unsigned i; + unsigned int i; for (i = 0; i < pkt_dev->nr_labels; i++) if (pkt_dev->labels[i] & MPLS_STACK_BOTTOM) pkt_dev->labels[i] = MPLS_STACK_BOTTOM | @@ -2550,7 +2550,7 @@ err: static void mpls_push(__be32 *mpls, struct pktgen_dev *pkt_dev) { - unsigned i; + unsigned int i; for (i = 0; i < pkt_dev->nr_labels; i++) *mpls++ = pkt_dev->labels[i] & ~MPLS_STACK_BOTTOM; diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 90430b7..b442d35 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -35,7 +35,9 @@ #include <linux/security.h> #include <linux/mutex.h> #include <linux/if_addr.h> +#include <linux/if_bridge.h> #include <linux/pci.h> +#include <linux/etherdevice.h> #include <asm/uaccess.h> @@ -552,7 +554,7 @@ void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data } EXPORT_SYMBOL(__rta_fill); -int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group, int echo) +int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned int group, int echo) { struct sock *rtnl = net->rtnl; int err = 0; @@ -607,7 +609,8 @@ int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics) for (i = 0; i < RTAX_MAX; i++) { if (metrics[i]) { valid++; - NLA_PUT_U32(skb, i+1, metrics[i]); + if (nla_put_u32(skb, i+1, metrics[i])) + goto nla_put_failure; } } @@ -782,6 +785,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev, + nla_total_size(4) /* IFLA_MTU */ + nla_total_size(4) /* IFLA_LINK */ + nla_total_size(4) /* IFLA_MASTER */ + + nla_total_size(4) /* IFLA_PROMISCUITY */ + nla_total_size(1) /* IFLA_OPERSTATE */ + nla_total_size(1) /* IFLA_LINKMODE */ + nla_total_size(ext_filter_mask @@ -807,7 +811,8 @@ static int rtnl_vf_ports_fill(struct sk_buff *skb, struct net_device *dev) vf_port = nla_nest_start(skb, IFLA_VF_PORT); if (!vf_port) goto nla_put_failure; - NLA_PUT_U32(skb, IFLA_PORT_VF, vf); + if (nla_put_u32(skb, IFLA_PORT_VF, vf)) + goto nla_put_failure; err = dev->netdev_ops->ndo_get_vf_port(dev, vf, skb); if (err == -EMSGSIZE) goto nla_put_failure; @@ -891,25 +896,23 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, ifm->ifi_flags = dev_get_flags(dev); ifm->ifi_change = change; - NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); - NLA_PUT_U32(skb, IFLA_TXQLEN, dev->tx_queue_len); - NLA_PUT_U8(skb, IFLA_OPERSTATE, - netif_running(dev) ? dev->operstate : IF_OPER_DOWN); - NLA_PUT_U8(skb, IFLA_LINKMODE, dev->link_mode); - NLA_PUT_U32(skb, IFLA_MTU, dev->mtu); - NLA_PUT_U32(skb, IFLA_GROUP, dev->group); - - if (dev->ifindex != dev->iflink) - NLA_PUT_U32(skb, IFLA_LINK, dev->iflink); - - if (dev->master) - NLA_PUT_U32(skb, IFLA_MASTER, dev->master->ifindex); - - if (dev->qdisc) - NLA_PUT_STRING(skb, IFLA_QDISC, dev->qdisc->ops->id); - - if (dev->ifalias) - NLA_PUT_STRING(skb, IFLA_IFALIAS, dev->ifalias); + if (nla_put_string(skb, IFLA_IFNAME, dev->name) || + nla_put_u32(skb, IFLA_TXQLEN, dev->tx_queue_len) || + nla_put_u8(skb, IFLA_OPERSTATE, + netif_running(dev) ? dev->operstate : IF_OPER_DOWN) || + nla_put_u8(skb, IFLA_LINKMODE, dev->link_mode) || + nla_put_u32(skb, IFLA_MTU, dev->mtu) || + nla_put_u32(skb, IFLA_GROUP, dev->group) || + nla_put_u32(skb, IFLA_PROMISCUITY, dev->promiscuity) || + (dev->ifindex != dev->iflink && + nla_put_u32(skb, IFLA_LINK, dev->iflink)) || + (dev->master && + nla_put_u32(skb, IFLA_MASTER, dev->master->ifindex)) || + (dev->qdisc && + nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) || + (dev->ifalias && + nla_put_string(skb, IFLA_IFALIAS, dev->ifalias))) + goto nla_put_failure; if (1) { struct rtnl_link_ifmap map = { @@ -920,12 +923,14 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, .dma = dev->dma, .port = dev->if_port, }; - NLA_PUT(skb, IFLA_MAP, sizeof(map), &map); + if (nla_put(skb, IFLA_MAP, sizeof(map), &map)) + goto nla_put_failure; } if (dev->addr_len) { - NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); - NLA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast); + if (nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr) || + nla_put(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast)) + goto nla_put_failure; } attr = nla_reserve(skb, IFLA_STATS, @@ -942,8 +947,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, goto nla_put_failure; copy_rtnl_link_stats64(nla_data(attr), stats); - if (dev->dev.parent && (ext_filter_mask & RTEXT_FILTER_VF)) - NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent)); + if (dev->dev.parent && (ext_filter_mask & RTEXT_FILTER_VF) && + nla_put_u32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent))) + goto nla_put_failure; if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent && (ext_filter_mask & RTEXT_FILTER_VF)) { @@ -986,12 +992,13 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, nla_nest_cancel(skb, vfinfo); goto nla_put_failure; } - NLA_PUT(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac); - NLA_PUT(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan); - NLA_PUT(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate), - &vf_tx_rate); - NLA_PUT(skb, IFLA_VF_SPOOFCHK, sizeof(vf_spoofchk), - &vf_spoofchk); + if (nla_put(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac) || + nla_put(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan) || + nla_put(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate), + &vf_tx_rate) || + nla_put(skb, IFLA_VF_SPOOFCHK, sizeof(vf_spoofchk), + &vf_spoofchk)) + goto nla_put_failure; nla_nest_end(skb, vf); } nla_nest_end(skb, vfinfo); @@ -1113,6 +1120,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { [IFLA_PORT_SELF] = { .type = NLA_NESTED }, [IFLA_AF_SPEC] = { .type = NLA_NESTED }, [IFLA_EXT_MASK] = { .type = NLA_U32 }, + [IFLA_PROMISCUITY] = { .type = NLA_U32 }, }; EXPORT_SYMBOL(ifla_policy); @@ -1634,14 +1642,14 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net, int err; struct net_device *dev; unsigned int num_queues = 1; - unsigned int real_num_queues = 1; if (ops->get_tx_queues) { - err = ops->get_tx_queues(src_net, tb, &num_queues, - &real_num_queues); - if (err) + err = ops->get_tx_queues(src_net, tb); + if (err < 0) goto err; + num_queues = err; } + err = -ENOMEM; dev = alloc_netdev_mq(ops->priv_size, ifname, ops->setup, num_queues); if (!dev) @@ -1947,7 +1955,7 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) return skb->len; } -void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change) +void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change) { struct net *net = dev_net(dev); struct sk_buff *skb; @@ -1972,6 +1980,267 @@ errout: rtnl_set_sk_err(net, RTNLGRP_LINK, err); } +static int nlmsg_populate_fdb_fill(struct sk_buff *skb, + struct net_device *dev, + u8 *addr, u32 pid, u32 seq, + int type, unsigned int flags) +{ + struct nlmsghdr *nlh; + struct ndmsg *ndm; + + nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), NLM_F_MULTI); + if (!nlh) + return -EMSGSIZE; + + ndm = nlmsg_data(nlh); + ndm->ndm_family = AF_BRIDGE; + ndm->ndm_pad1 = 0; + ndm->ndm_pad2 = 0; + ndm->ndm_flags = flags; + ndm->ndm_type = 0; + ndm->ndm_ifindex = dev->ifindex; + ndm->ndm_state = NUD_PERMANENT; + + if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr)) + goto nla_put_failure; + + return nlmsg_end(skb, nlh); + +nla_put_failure: + nlmsg_cancel(skb, nlh); + return -EMSGSIZE; +} + +static inline size_t rtnl_fdb_nlmsg_size(void) +{ + return NLMSG_ALIGN(sizeof(struct ndmsg)) + nla_total_size(ETH_ALEN); +} + +static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, int type) +{ + struct net *net = dev_net(dev); + struct sk_buff *skb; + int err = -ENOBUFS; + + skb = nlmsg_new(rtnl_fdb_nlmsg_size(), GFP_ATOMIC); + if (!skb) + goto errout; + + err = nlmsg_populate_fdb_fill(skb, dev, addr, 0, 0, type, NTF_SELF); + if (err < 0) { + kfree_skb(skb); + goto errout; + } + + rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); + return; +errout: + rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); +} + +static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) +{ + struct net *net = sock_net(skb->sk); + struct net_device *master = NULL; + struct ndmsg *ndm; + struct nlattr *tb[NDA_MAX+1]; + struct net_device *dev; + u8 *addr; + int err; + + err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL); + if (err < 0) + return err; + + ndm = nlmsg_data(nlh); + if (ndm->ndm_ifindex == 0) { + pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid ifindex\n"); + return -EINVAL; + } + + dev = __dev_get_by_index(net, ndm->ndm_ifindex); + if (dev == NULL) { + pr_info("PF_BRIDGE: RTM_NEWNEIGH with unknown ifindex\n"); + return -ENODEV; + } + + if (!tb[NDA_LLADDR] || nla_len(tb[NDA_LLADDR]) != ETH_ALEN) { + pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid address\n"); + return -EINVAL; + } + + addr = nla_data(tb[NDA_LLADDR]); + if (!is_valid_ether_addr(addr)) { + pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid ether address\n"); + return -EINVAL; + } + + err = -EOPNOTSUPP; + + /* Support fdb on master device the net/bridge default case */ + if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) && + (dev->priv_flags & IFF_BRIDGE_PORT)) { + master = dev->master; + err = master->netdev_ops->ndo_fdb_add(ndm, dev, addr, + nlh->nlmsg_flags); + if (err) + goto out; + else + ndm->ndm_flags &= ~NTF_MASTER; + } + + /* Embedded bridge, macvlan, and any other device support */ + if ((ndm->ndm_flags & NTF_SELF) && dev->netdev_ops->ndo_fdb_add) { + err = dev->netdev_ops->ndo_fdb_add(ndm, dev, addr, + nlh->nlmsg_flags); + + if (!err) { + rtnl_fdb_notify(dev, addr, RTM_NEWNEIGH); + ndm->ndm_flags &= ~NTF_SELF; + } + } +out: + return err; +} + +static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) +{ + struct net *net = sock_net(skb->sk); + struct ndmsg *ndm; + struct nlattr *llattr; + struct net_device *dev; + int err = -EINVAL; + __u8 *addr; + + if (nlmsg_len(nlh) < sizeof(*ndm)) + return -EINVAL; + + ndm = nlmsg_data(nlh); + if (ndm->ndm_ifindex == 0) { + pr_info("PF_BRIDGE: RTM_DELNEIGH with invalid ifindex\n"); + return -EINVAL; + } + + dev = __dev_get_by_index(net, ndm->ndm_ifindex); + if (dev == NULL) { + pr_info("PF_BRIDGE: RTM_DELNEIGH with unknown ifindex\n"); + return -ENODEV; + } + + llattr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_LLADDR); + if (llattr == NULL || nla_len(llattr) != ETH_ALEN) { + pr_info("PF_BRIGDE: RTM_DELNEIGH with invalid address\n"); + return -EINVAL; + } + + addr = nla_data(llattr); + err = -EOPNOTSUPP; + + /* Support fdb on master device the net/bridge default case */ + if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) && + (dev->priv_flags & IFF_BRIDGE_PORT)) { + struct net_device *master = dev->master; + + if (master->netdev_ops->ndo_fdb_del) + err = master->netdev_ops->ndo_fdb_del(ndm, dev, addr); + + if (err) + goto out; + else + ndm->ndm_flags &= ~NTF_MASTER; + } + + /* Embedded bridge, macvlan, and any other device support */ + if ((ndm->ndm_flags & NTF_SELF) && dev->netdev_ops->ndo_fdb_del) { + err = dev->netdev_ops->ndo_fdb_del(ndm, dev, addr); + + if (!err) { + rtnl_fdb_notify(dev, addr, RTM_DELNEIGH); + ndm->ndm_flags &= ~NTF_SELF; + } + } +out: + return err; +} + +static int nlmsg_populate_fdb(struct sk_buff *skb, + struct netlink_callback *cb, + struct net_device *dev, + int *idx, + struct netdev_hw_addr_list *list) +{ + struct netdev_hw_addr *ha; + int err; + u32 pid, seq; + + pid = NETLINK_CB(cb->skb).pid; + seq = cb->nlh->nlmsg_seq; + + list_for_each_entry(ha, &list->list, list) { + if (*idx < cb->args[0]) + goto skip; + + err = nlmsg_populate_fdb_fill(skb, dev, ha->addr, + pid, seq, 0, NTF_SELF); + if (err < 0) + return err; +skip: + *idx += 1; + } + return 0; +} + +/** + * ndo_dflt_fdb_dump: default netdevice operation to dump an FDB table. + * @nlh: netlink message header + * @dev: netdevice + * + * Default netdevice operation to dump the existing unicast address list. + * Returns zero on success. + */ +int ndo_dflt_fdb_dump(struct sk_buff *skb, + struct netlink_callback *cb, + struct net_device *dev, + int idx) +{ + int err; + + netif_addr_lock_bh(dev); + err = nlmsg_populate_fdb(skb, cb, dev, &idx, &dev->uc); + if (err) + goto out; + nlmsg_populate_fdb(skb, cb, dev, &idx, &dev->mc); +out: + netif_addr_unlock_bh(dev); + return idx; +} +EXPORT_SYMBOL(ndo_dflt_fdb_dump); + +static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) +{ + int idx = 0; + struct net *net = sock_net(skb->sk); + struct net_device *dev; + + rcu_read_lock(); + for_each_netdev_rcu(net, dev) { + if (dev->priv_flags & IFF_BRIDGE_PORT) { + struct net_device *master = dev->master; + const struct net_device_ops *ops = master->netdev_ops; + + if (ops->ndo_fdb_dump) + idx = ops->ndo_fdb_dump(skb, cb, dev, idx); + } + + if (dev->netdev_ops->ndo_fdb_dump) + idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, idx); + } + rcu_read_unlock(); + + cb->args[0] = idx; + return skb->len; +} + /* Protected by RTNL sempahore. */ static struct rtattr **rta_buf; static int rtattr_max; @@ -2042,7 +2311,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) struct rtattr *attr = (void *)nlh + NLMSG_ALIGN(min_len); while (RTA_OK(attr, attrlen)) { - unsigned flavor = attr->rta_type; + unsigned int flavor = attr->rta_type; if (flavor) { if (flavor > rta_max[sz_idx]) return -EINVAL; @@ -2144,5 +2413,9 @@ void __init rtnetlink_init(void) rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all, NULL); rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, NULL); + + rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, rtnl_fdb_add, NULL, NULL); + rtnl_register(PF_BRIDGE, RTM_DELNEIGH, rtnl_fdb_del, NULL, NULL); + rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, rtnl_fdb_dump, NULL); } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index e598400..8f0d68d 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -67,8 +67,7 @@ #include <asm/uaccess.h> #include <trace/events/skb.h> - -#include "kmap_skb.h" +#include <linux/highmem.h> static struct kmem_cache *skbuff_head_cache __read_mostly; static struct kmem_cache *skbuff_fclone_cache __read_mostly; @@ -707,10 +706,10 @@ int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask) } return -ENOMEM; } - vaddr = kmap_skb_frag(&skb_shinfo(skb)->frags[i]); + vaddr = kmap_atomic(skb_frag_page(f)); memcpy(page_address(page), vaddr + f->page_offset, skb_frag_size(f)); - kunmap_skb_frag(vaddr); + kunmap_atomic(vaddr); page->private = (unsigned long)head; head = page; } @@ -1487,21 +1486,22 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { int end; + skb_frag_t *f = &skb_shinfo(skb)->frags[i]; WARN_ON(start > offset + len); - end = start + skb_frag_size(&skb_shinfo(skb)->frags[i]); + end = start + skb_frag_size(f); if ((copy = end - offset) > 0) { u8 *vaddr; if (copy > len) copy = len; - vaddr = kmap_skb_frag(&skb_shinfo(skb)->frags[i]); + vaddr = kmap_atomic(skb_frag_page(f)); memcpy(to, - vaddr + skb_shinfo(skb)->frags[i].page_offset+ - offset - start, copy); - kunmap_skb_frag(vaddr); + vaddr + f->page_offset + offset - start, + copy); + kunmap_atomic(vaddr); if ((len -= copy) == 0) return 0; @@ -1806,10 +1806,10 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) if (copy > len) copy = len; - vaddr = kmap_skb_frag(frag); + vaddr = kmap_atomic(skb_frag_page(frag)); memcpy(vaddr + frag->page_offset + offset - start, from, copy); - kunmap_skb_frag(vaddr); + kunmap_atomic(vaddr); if ((len -= copy) == 0) return 0; @@ -1869,21 +1869,21 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { int end; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; WARN_ON(start > offset + len); - end = start + skb_frag_size(&skb_shinfo(skb)->frags[i]); + end = start + skb_frag_size(frag); if ((copy = end - offset) > 0) { __wsum csum2; u8 *vaddr; - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; if (copy > len) copy = len; - vaddr = kmap_skb_frag(frag); + vaddr = kmap_atomic(skb_frag_page(frag)); csum2 = csum_partial(vaddr + frag->page_offset + offset - start, copy, 0); - kunmap_skb_frag(vaddr); + kunmap_atomic(vaddr); csum = csum_block_add(csum, csum2, pos); if (!(len -= copy)) return csum; @@ -1955,12 +1955,12 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, if (copy > len) copy = len; - vaddr = kmap_skb_frag(frag); + vaddr = kmap_atomic(skb_frag_page(frag)); csum2 = csum_partial_copy_nocheck(vaddr + frag->page_offset + offset - start, to, copy, 0); - kunmap_skb_frag(vaddr); + kunmap_atomic(vaddr); csum = csum_block_add(csum, csum2, pos); if (!(len -= copy)) return csum; @@ -2480,7 +2480,7 @@ next_skb: if (abs_offset < block_limit) { if (!st->frag_data) - st->frag_data = kmap_skb_frag(frag); + st->frag_data = kmap_atomic(skb_frag_page(frag)); *data = (u8 *) st->frag_data + frag->page_offset + (abs_offset - st->stepped_offset); @@ -2489,7 +2489,7 @@ next_skb: } if (st->frag_data) { - kunmap_skb_frag(st->frag_data); + kunmap_atomic(st->frag_data); st->frag_data = NULL; } @@ -2498,7 +2498,7 @@ next_skb: } if (st->frag_data) { - kunmap_skb_frag(st->frag_data); + kunmap_atomic(st->frag_data); st->frag_data = NULL; } @@ -2526,7 +2526,7 @@ EXPORT_SYMBOL(skb_seq_read); void skb_abort_seq_read(struct skb_seq_state *st) { if (st->frag_data) - kunmap_skb_frag(st->frag_data); + kunmap_atomic(st->frag_data); } EXPORT_SYMBOL(skb_abort_seq_read); @@ -3166,7 +3166,7 @@ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) int len = skb->len; if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= - (unsigned)sk->sk_rcvbuf) + (unsigned int)sk->sk_rcvbuf) return -ENOMEM; skb_orphan(skb); diff --git a/net/core/sock.c b/net/core/sock.c index b2e14c0..c7e60ea 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1534,7 +1534,7 @@ struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force, */ void *sock_kmalloc(struct sock *sk, int size, gfp_t priority) { - if ((unsigned)size <= sysctl_optmem_max && + if ((unsigned int)size <= sysctl_optmem_max && atomic_read(&sk->sk_omem_alloc) + size < sysctl_optmem_max) { void *mem; /* First do the add, to avoid the race if kmalloc diff --git a/net/core/utils.c b/net/core/utils.c index dc3c3fa..39895a6 100644 --- a/net/core/utils.c +++ b/net/core/utils.c @@ -58,14 +58,11 @@ __be32 in_aton(const char *str) int i; l = 0; - for (i = 0; i < 4; i++) - { + for (i = 0; i < 4; i++) { l <<= 8; - if (*str != '\0') - { + if (*str != '\0') { val = 0; - while (*str != '\0' && *str != '.' && *str != '\n') - { + while (*str != '\0' && *str != '.' && *str != '\n') { val *= 10; val += *str - '0'; str++; diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index d860530..8dfa1da 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c @@ -178,6 +178,7 @@ static const struct nla_policy dcbnl_ieee_policy[DCB_ATTR_IEEE_MAX + 1] = { [DCB_ATTR_IEEE_ETS] = {.len = sizeof(struct ieee_ets)}, [DCB_ATTR_IEEE_PFC] = {.len = sizeof(struct ieee_pfc)}, [DCB_ATTR_IEEE_APP_TABLE] = {.type = NLA_NESTED}, + [DCB_ATTR_IEEE_MAXRATE] = {.len = sizeof(struct ieee_maxrate)}, }; static const struct nla_policy dcbnl_ieee_app[DCB_ATTR_IEEE_APP_MAX + 1] = { @@ -1205,13 +1206,15 @@ static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb, if (!app) goto nla_put_failure; - if (app_info_type) - NLA_PUT(skb, app_info_type, sizeof(info), &info); - - for (i = 0; i < app_count; i++) - NLA_PUT(skb, app_entry_type, sizeof(struct dcb_app), - &table[i]); + if (app_info_type && + nla_put(skb, app_info_type, sizeof(info), &info)) + goto nla_put_failure; + for (i = 0; i < app_count; i++) { + if (nla_put(skb, app_entry_type, sizeof(struct dcb_app), + &table[i])) + goto nla_put_failure; + } nla_nest_end(skb, app); } err = 0; @@ -1230,8 +1233,8 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) int dcbx; int err = -EMSGSIZE; - NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name); - + if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name)) + goto nla_put_failure; ieee = nla_nest_start(skb, DCB_ATTR_IEEE); if (!ieee) goto nla_put_failure; @@ -1239,15 +1242,28 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) if (ops->ieee_getets) { struct ieee_ets ets; err = ops->ieee_getets(netdev, &ets); - if (!err) - NLA_PUT(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets); + if (!err && + nla_put(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets)) + goto nla_put_failure; + } + + if (ops->ieee_getmaxrate) { + struct ieee_maxrate maxrate; + err = ops->ieee_getmaxrate(netdev, &maxrate); + if (!err) { + err = nla_put(skb, DCB_ATTR_IEEE_MAXRATE, + sizeof(maxrate), &maxrate); + if (err) + goto nla_put_failure; + } } if (ops->ieee_getpfc) { struct ieee_pfc pfc; err = ops->ieee_getpfc(netdev, &pfc); - if (!err) - NLA_PUT(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc); + if (!err && + nla_put(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc)) + goto nla_put_failure; } app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE); @@ -1278,15 +1294,17 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) if (ops->ieee_peer_getets) { struct ieee_ets ets; err = ops->ieee_peer_getets(netdev, &ets); - if (!err) - NLA_PUT(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets); + if (!err && + nla_put(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets)) + goto nla_put_failure; } if (ops->ieee_peer_getpfc) { struct ieee_pfc pfc; err = ops->ieee_peer_getpfc(netdev, &pfc); - if (!err) - NLA_PUT(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc); + if (!err && + nla_put(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc)) + goto nla_put_failure; } if (ops->peer_getappinfo && ops->peer_getapptable) { @@ -1340,10 +1358,11 @@ static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev, ops->getpgtccfgtx(dev, i - DCB_PG_ATTR_TC_0, &prio, &pgid, &tc_pct, &up_map); - NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_PGID, pgid); - NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_UP_MAPPING, up_map); - NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_STRICT_PRIO, prio); - NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_BW_PCT, tc_pct); + if (nla_put_u8(skb, DCB_TC_ATTR_PARAM_PGID, pgid) || + nla_put_u8(skb, DCB_TC_ATTR_PARAM_UP_MAPPING, up_map) || + nla_put_u8(skb, DCB_TC_ATTR_PARAM_STRICT_PRIO, prio) || + nla_put_u8(skb, DCB_TC_ATTR_PARAM_BW_PCT, tc_pct)) + goto nla_put_failure; nla_nest_end(skb, tc_nest); } @@ -1356,7 +1375,8 @@ static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev, else ops->getpgbwgcfgtx(dev, i - DCB_PG_ATTR_BW_ID_0, &tc_pct); - NLA_PUT_U8(skb, i, tc_pct); + if (nla_put_u8(skb, i, tc_pct)) + goto nla_put_failure; } nla_nest_end(skb, pg); return 0; @@ -1373,8 +1393,8 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev) int dcbx, i, err = -EMSGSIZE; u8 value; - NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name); - + if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name)) + goto nla_put_failure; cee = nla_nest_start(skb, DCB_ATTR_CEE); if (!cee) goto nla_put_failure; @@ -1401,7 +1421,8 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev) for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) { ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, &value); - NLA_PUT_U8(skb, i, value); + if (nla_put_u8(skb, i, value)) + goto nla_put_failure; } nla_nest_end(skb, pfc_nest); } @@ -1454,8 +1475,9 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev) for (i = DCB_FEATCFG_ATTR_ALL + 1; i <= DCB_FEATCFG_ATTR_MAX; i++) - if (!ops->getfeatcfg(netdev, i, &value)) - NLA_PUT_U8(skb, i, value); + if (!ops->getfeatcfg(netdev, i, &value) && + nla_put_u8(skb, i, value)) + goto nla_put_failure; nla_nest_end(skb, feat); } @@ -1464,15 +1486,17 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev) if (ops->cee_peer_getpg) { struct cee_pg pg; err = ops->cee_peer_getpg(netdev, &pg); - if (!err) - NLA_PUT(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg); + if (!err && + nla_put(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg)) + goto nla_put_failure; } if (ops->cee_peer_getpfc) { struct cee_pfc pfc; err = ops->cee_peer_getpfc(netdev, &pfc); - if (!err) - NLA_PUT(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc); + if (!err && + nla_put(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc)) + goto nla_put_failure; } if (ops->peer_getappinfo && ops->peer_getapptable) { @@ -1589,6 +1613,14 @@ static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb, goto err; } + if (ieee[DCB_ATTR_IEEE_MAXRATE] && ops->ieee_setmaxrate) { + struct ieee_maxrate *maxrate = + nla_data(ieee[DCB_ATTR_IEEE_MAXRATE]); + err = ops->ieee_setmaxrate(netdev, maxrate); + if (err) + goto err; + } + if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) { struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]); err = ops->ieee_setpfc(netdev, pfc); diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 70bfaf2..8c67bed 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -100,7 +100,7 @@ static void ccid3_update_send_interval(struct ccid3_hc_tx_sock *hc) DCCP_BUG_ON(hc->tx_t_ipi == 0); ccid3_pr_debug("t_ipi=%u, s=%u, X=%u\n", hc->tx_t_ipi, - hc->tx_s, (unsigned)(hc->tx_x >> 6)); + hc->tx_s, (unsigned int)(hc->tx_x >> 6)); } static u32 ccid3_hc_tx_idle_rtt(struct ccid3_hc_tx_sock *hc, ktime_t now) @@ -153,9 +153,9 @@ static void ccid3_hc_tx_update_x(struct sock *sk, ktime_t *stamp) if (hc->tx_x != old_x) { ccid3_pr_debug("X_prev=%u, X_now=%u, X_calc=%u, " - "X_recv=%u\n", (unsigned)(old_x >> 6), - (unsigned)(hc->tx_x >> 6), hc->tx_x_calc, - (unsigned)(hc->tx_x_recv >> 6)); + "X_recv=%u\n", (unsigned int)(old_x >> 6), + (unsigned int)(hc->tx_x >> 6), hc->tx_x_calc, + (unsigned int)(hc->tx_x_recv >> 6)); ccid3_update_send_interval(hc); } @@ -425,8 +425,8 @@ done_computing_x: "p=%u, X_calc=%u, X_recv=%u, X=%u\n", dccp_role(sk), sk, hc->tx_rtt, r_sample, hc->tx_s, hc->tx_p, hc->tx_x_calc, - (unsigned)(hc->tx_x_recv >> 6), - (unsigned)(hc->tx_x >> 6)); + (unsigned int)(hc->tx_x_recv >> 6), + (unsigned int)(hc->tx_x >> 6)); /* unschedule no feedback timer */ sk_stop_timer(sk, &hc->tx_no_feedback_timer); diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 29d6bb6..9040be0 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -75,7 +75,7 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo); * state, about 60 seconds */ /* RFC 1122, 4.2.3.1 initial RTO value */ -#define DCCP_TIMEOUT_INIT ((unsigned)(3 * HZ)) +#define DCCP_TIMEOUT_INIT ((unsigned int)(3 * HZ)) /* * The maximum back-off value for retransmissions. This is needed for @@ -84,7 +84,7 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo); * - feature-negotiation retransmission (sec. 6.6.3), * - Acks in client-PARTOPEN state (sec. 8.1.5). */ -#define DCCP_RTO_MAX ((unsigned)(64 * HZ)) +#define DCCP_RTO_MAX ((unsigned int)(64 * HZ)) /* * RTT sampling: sanity bounds and fallback RTT value from RFC 4340, section 3.4 @@ -287,9 +287,9 @@ extern struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb, extern int dccp_child_process(struct sock *parent, struct sock *child, struct sk_buff *skb); extern int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, - struct dccp_hdr *dh, unsigned len); + struct dccp_hdr *dh, unsigned int len); extern int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, - const struct dccp_hdr *dh, const unsigned len); + const struct dccp_hdr *dh, const unsigned int len); extern int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized); extern void dccp_destroy_sock(struct sock *sk); diff --git a/net/dccp/input.c b/net/dccp/input.c index 51d5fe5..bc93a33 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -285,7 +285,7 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) } static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb, - const struct dccp_hdr *dh, const unsigned len) + const struct dccp_hdr *dh, const unsigned int len) { struct dccp_sock *dp = dccp_sk(sk); @@ -366,7 +366,7 @@ discard: } int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, - const struct dccp_hdr *dh, const unsigned len) + const struct dccp_hdr *dh, const unsigned int len) { if (dccp_check_seqno(sk, skb)) goto discard; @@ -388,7 +388,7 @@ EXPORT_SYMBOL_GPL(dccp_rcv_established); static int dccp_rcv_request_sent_state_process(struct sock *sk, struct sk_buff *skb, const struct dccp_hdr *dh, - const unsigned len) + const unsigned int len) { /* * Step 4: Prepare sequence numbers in REQUEST @@ -521,7 +521,7 @@ unable_to_proceed: static int dccp_rcv_respond_partopen_state_process(struct sock *sk, struct sk_buff *skb, const struct dccp_hdr *dh, - const unsigned len) + const unsigned int len) { struct dccp_sock *dp = dccp_sk(sk); u32 sample = dp->dccps_options_received.dccpor_timestamp_echo; @@ -572,7 +572,7 @@ static int dccp_rcv_respond_partopen_state_process(struct sock *sk, } int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, - struct dccp_hdr *dh, unsigned len) + struct dccp_hdr *dh, unsigned int len) { struct dccp_sock *dp = dccp_sk(sk); struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index caf6e17..07f5579 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -574,6 +574,11 @@ static void dccp_v4_reqsk_destructor(struct request_sock *req) kfree(inet_rsk(req)->opt); } +void dccp_syn_ack_timeout(struct sock *sk, struct request_sock *req) +{ +} +EXPORT_SYMBOL(dccp_syn_ack_timeout); + static struct request_sock_ops dccp_request_sock_ops __read_mostly = { .family = PF_INET, .obj_size = sizeof(struct dccp_request_sock), @@ -581,6 +586,7 @@ static struct request_sock_ops dccp_request_sock_ops __read_mostly = { .send_ack = dccp_reqsk_send_ack, .destructor = dccp_v4_reqsk_destructor, .send_reset = dccp_v4_ctl_send_reset, + .syn_ack_timeout = dccp_syn_ack_timeout, }; int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 4dc588f..e923ac9 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -343,6 +343,7 @@ static struct request_sock_ops dccp6_request_sock_ops = { .send_ack = dccp_reqsk_send_ack, .destructor = dccp_v6_reqsk_destructor, .send_reset = dccp_v6_ctl_send_reset, + .syn_ack_timeout = dccp_syn_ack_timeout, }; static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 4136987..2ba1a28 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -250,7 +250,7 @@ static void dn_unhash_sock_bh(struct sock *sk) static struct hlist_head *listen_hash(struct sockaddr_dn *addr) { int i; - unsigned hash = addr->sdn_objnum; + unsigned int hash = addr->sdn_objnum; if (hash == 0) { hash = addr->sdn_objnamel; @@ -1844,9 +1844,9 @@ static inline int dn_queue_too_long(struct dn_scp *scp, struct sk_buff_head *que * inclusion (or not) of the two 16 bit acknowledgement fields so it doesn't * make much practical difference. */ -unsigned dn_mss_from_pmtu(struct net_device *dev, int mtu) +unsigned int dn_mss_from_pmtu(struct net_device *dev, int mtu) { - unsigned mss = 230 - DN_MAX_NSP_DATA_HEADER; + unsigned int mss = 230 - DN_MAX_NSP_DATA_HEADER; if (dev) { struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr); mtu -= LL_RESERVED_SPACE(dev); diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index c00e307..a4aecb0 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -694,13 +694,13 @@ static int dn_nl_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa, ifm->ifa_scope = ifa->ifa_scope; ifm->ifa_index = ifa->ifa_dev->dev->ifindex; - if (ifa->ifa_address) - NLA_PUT_LE16(skb, IFA_ADDRESS, ifa->ifa_address); - if (ifa->ifa_local) - NLA_PUT_LE16(skb, IFA_LOCAL, ifa->ifa_local); - if (ifa->ifa_label[0]) - NLA_PUT_STRING(skb, IFA_LABEL, ifa->ifa_label); - + if ((ifa->ifa_address && + nla_put_le16(skb, IFA_ADDRESS, ifa->ifa_address)) || + (ifa->ifa_local && + nla_put_le16(skb, IFA_LOCAL, ifa->ifa_local)) || + (ifa->ifa_label[0] && + nla_put_string(skb, IFA_LABEL, ifa->ifa_label))) + goto nla_put_failure; return nlmsg_end(skb, nlh); nla_put_failure: diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c index 9e885f1..65a8cd7 100644 --- a/net/decnet/dn_fib.c +++ b/net/decnet/dn_fib.c @@ -302,11 +302,12 @@ struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, struct dn_kern_rta struct rtattr *attr = RTA_DATA(rta->rta_mx); while(RTA_OK(attr, attrlen)) { - unsigned flavour = attr->rta_type; + unsigned int flavour = attr->rta_type; + if (flavour) { if (flavour > RTAX_MAX) goto err_inval; - fi->fib_metrics[flavour-1] = *(unsigned*)RTA_DATA(attr); + fi->fib_metrics[flavour-1] = *(unsigned int *)RTA_DATA(attr); } attr = RTA_NEXT(attr, attrlen); } diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c index f6544b2..58084f3 100644 --- a/net/decnet/dn_nsp_in.c +++ b/net/decnet/dn_nsp_in.c @@ -588,7 +588,7 @@ static __inline__ int dn_queue_skb(struct sock *sk, struct sk_buff *skb, int sig number of warnings when compiling with -W --ANK */ if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= - (unsigned)sk->sk_rcvbuf) { + (unsigned int)sk->sk_rcvbuf) { err = -ENOMEM; goto out; } diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c index e446e85..b952f88 100644 --- a/net/decnet/dn_nsp_out.c +++ b/net/decnet/dn_nsp_out.c @@ -209,7 +209,7 @@ static void dn_nsp_rtt(struct sock *sk, long rtt) * * Returns: The number of times the packet has been sent previously */ -static inline unsigned dn_nsp_clone_and_send(struct sk_buff *skb, +static inline unsigned int dn_nsp_clone_and_send(struct sk_buff *skb, gfp_t gfp) { struct dn_skb_cb *cb = DN_SKB_CB(skb); @@ -240,7 +240,7 @@ void dn_nsp_output(struct sock *sk) { struct dn_scp *scp = DN_SK(sk); struct sk_buff *skb; - unsigned reduce_win = 0; + unsigned int reduce_win = 0; /* * First we check for otherdata/linkservice messages diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 80a3de4..7e1f878 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -122,7 +122,7 @@ static int dn_route_input(struct sk_buff *); static void dn_run_flush(unsigned long dummy); static struct dn_rt_hash_bucket *dn_rt_hash_table; -static unsigned dn_rt_hash_mask; +static unsigned int dn_rt_hash_mask; static struct timer_list dn_route_timer; static DEFINE_TIMER(dn_rt_flush_timer, dn_run_flush, 0, 0); @@ -149,13 +149,13 @@ static void dn_dst_destroy(struct dst_entry *dst) dst_destroy_metrics_generic(dst); } -static __inline__ unsigned dn_hash(__le16 src, __le16 dst) +static __inline__ unsigned int dn_hash(__le16 src, __le16 dst) { __u16 tmp = (__u16 __force)(src ^ dst); tmp ^= (tmp >> 3); tmp ^= (tmp >> 5); tmp ^= (tmp >> 10); - return dn_rt_hash_mask & (unsigned)tmp; + return dn_rt_hash_mask & (unsigned int)tmp; } static inline void dnrt_free(struct dn_route *rt) @@ -297,7 +297,7 @@ static inline int compare_keys(struct flowidn *fl1, struct flowidn *fl2) (fl1->flowidn_iif ^ fl2->flowidn_iif)) == 0; } -static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route **rp) +static int dn_insert_route(struct dn_route *rt, unsigned int hash, struct dn_route **rp) { struct dn_route *rth; struct dn_route __rcu **rthp; @@ -934,8 +934,8 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowidn *o struct dn_route *rt = NULL; struct net_device *dev_out = NULL, *dev; struct neighbour *neigh = NULL; - unsigned hash; - unsigned flags = 0; + unsigned int hash; + unsigned int flags = 0; struct dn_fib_res res = { .fi = NULL, .type = RTN_UNICAST }; int err; int free_res = 0; @@ -1209,7 +1209,7 @@ e_neighbour: */ static int __dn_route_output_key(struct dst_entry **pprt, const struct flowidn *flp, int flags) { - unsigned hash = dn_hash(flp->saddr, flp->daddr); + unsigned int hash = dn_hash(flp->saddr, flp->daddr); struct dn_route *rt = NULL; if (!(flags & MSG_TRYHARD)) { @@ -1275,7 +1275,7 @@ static int dn_route_input_slow(struct sk_buff *skb) struct net_device *out_dev = NULL; struct dn_dev *dn_db; struct neighbour *neigh = NULL; - unsigned hash; + unsigned int hash; int flags = 0; __le16 gateway = 0; __le16 local_src = 0; @@ -1490,7 +1490,7 @@ static int dn_route_input(struct sk_buff *skb) { struct dn_route *rt; struct dn_skb_cb *cb = DN_SKB_CB(skb); - unsigned hash = dn_hash(cb->src, cb->dst); + unsigned int hash = dn_hash(cb->src, cb->dst); if (skb_dst(skb)) return 0; diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index f65c9dd..e65f2c8 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c @@ -177,11 +177,11 @@ static int dn_fib_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, return 1; } -unsigned dnet_addr_type(__le16 addr) +unsigned int dnet_addr_type(__le16 addr) { struct flowidn fld = { .daddr = addr }; struct dn_fib_res res; - unsigned ret = RTN_UNICAST; + unsigned int ret = RTN_UNICAST; struct dn_fib_table *tb = dn_fib_get_table(RT_TABLE_LOCAL, 0); res.r = NULL; @@ -204,11 +204,11 @@ static int dn_fib_rule_fill(struct fib_rule *rule, struct sk_buff *skb, frh->src_len = r->src_len; frh->tos = 0; - if (r->dst_len) - NLA_PUT_LE16(skb, FRA_DST, r->dst); - if (r->src_len) - NLA_PUT_LE16(skb, FRA_SRC, r->src); - + if ((r->dst_len && + nla_put_le16(skb, FRA_DST, r->dst)) || + (r->src_len && + nla_put_le16(skb, FRA_SRC, r->src))) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c index c73bba3..6f70ea9 100644 --- a/net/dns_resolver/dns_key.c +++ b/net/dns_resolver/dns_key.c @@ -38,7 +38,7 @@ MODULE_DESCRIPTION("DNS Resolver"); MODULE_AUTHOR("Wang Lei"); MODULE_LICENSE("GPL"); -unsigned dns_resolver_debug; +unsigned int dns_resolver_debug; module_param_named(debug, dns_resolver_debug, uint, S_IWUSR | S_IRUGO); MODULE_PARM_DESC(debug, "DNS Resolver debugging mask"); diff --git a/net/dns_resolver/internal.h b/net/dns_resolver/internal.h index 189ca9e..17c7886 100644 --- a/net/dns_resolver/internal.h +++ b/net/dns_resolver/internal.h @@ -31,7 +31,7 @@ extern const struct cred *dns_resolver_cache; /* * debug tracing */ -extern unsigned dns_resolver_debug; +extern unsigned int dns_resolver_debug; #define kdebug(FMT, ...) \ do { \ diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index bf10a31..5889a6c 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -77,7 +77,7 @@ __setup("ether=", netdev_boot_setup); */ int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, - const void *daddr, const void *saddr, unsigned len) + const void *daddr, const void *saddr, unsigned int len) { struct ethhdr *eth = (struct ethhdr *)skb_push(skb, ETH_HLEN); diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c index 3685158..58c8895 100644 --- a/net/ieee802154/6lowpan.c +++ b/net/ieee802154/6lowpan.c @@ -371,7 +371,7 @@ err: static int lowpan_header_create(struct sk_buff *skb, struct net_device *dev, unsigned short type, const void *_daddr, - const void *_saddr, unsigned len) + const void *_saddr, unsigned int len) { u8 tmp, iphc0, iphc1, *hc06_ptr; struct ipv6hdr *hdr; diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c index 1b09eaa..6fbb2ad 100644 --- a/net/ieee802154/dgram.c +++ b/net/ieee802154/dgram.c @@ -44,8 +44,8 @@ struct dgram_sock { struct ieee802154_addr src_addr; struct ieee802154_addr dst_addr; - unsigned bound:1; - unsigned want_ack:1; + unsigned int bound:1; + unsigned int want_ack:1; }; static inline struct dgram_sock *dgram_sk(const struct sock *sk) @@ -206,7 +206,7 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t size) { struct net_device *dev; - unsigned mtu; + unsigned int mtu; struct sk_buff *skb; struct dgram_sock *ro = dgram_sk(sk); int hlen, tlen; diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c index adaf462..ca92587 100644 --- a/net/ieee802154/nl-mac.c +++ b/net/ieee802154/nl-mac.c @@ -63,15 +63,14 @@ int ieee802154_nl_assoc_indic(struct net_device *dev, if (!msg) return -ENOBUFS; - NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); - NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); - NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, - dev->dev_addr); - - NLA_PUT(msg, IEEE802154_ATTR_SRC_HW_ADDR, IEEE802154_ADDR_LEN, - addr->hwaddr); - - NLA_PUT_U8(msg, IEEE802154_ATTR_CAPABILITY, cap); + if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || + nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || + nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, + dev->dev_addr) || + nla_put(msg, IEEE802154_ATTR_SRC_HW_ADDR, IEEE802154_ADDR_LEN, + addr->hwaddr) || + nla_put_u8(msg, IEEE802154_ATTR_CAPABILITY, cap)) + goto nla_put_failure; return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id); @@ -92,14 +91,13 @@ int ieee802154_nl_assoc_confirm(struct net_device *dev, u16 short_addr, if (!msg) return -ENOBUFS; - NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); - NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); - NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, - dev->dev_addr); - - NLA_PUT_U16(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr); - NLA_PUT_U8(msg, IEEE802154_ATTR_STATUS, status); - + if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || + nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || + nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, + dev->dev_addr) || + nla_put_u16(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) || + nla_put_u8(msg, IEEE802154_ATTR_STATUS, status)) + goto nla_put_failure; return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id); nla_put_failure: @@ -119,20 +117,22 @@ int ieee802154_nl_disassoc_indic(struct net_device *dev, if (!msg) return -ENOBUFS; - NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); - NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); - NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, - dev->dev_addr); - - if (addr->addr_type == IEEE802154_ADDR_LONG) - NLA_PUT(msg, IEEE802154_ATTR_SRC_HW_ADDR, IEEE802154_ADDR_LEN, - addr->hwaddr); - else - NLA_PUT_U16(msg, IEEE802154_ATTR_SRC_SHORT_ADDR, - addr->short_addr); - - NLA_PUT_U8(msg, IEEE802154_ATTR_REASON, reason); - + if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || + nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || + nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, + dev->dev_addr)) + goto nla_put_failure; + if (addr->addr_type == IEEE802154_ADDR_LONG) { + if (nla_put(msg, IEEE802154_ATTR_SRC_HW_ADDR, IEEE802154_ADDR_LEN, + addr->hwaddr)) + goto nla_put_failure; + } else { + if (nla_put_u16(msg, IEEE802154_ATTR_SRC_SHORT_ADDR, + addr->short_addr)) + goto nla_put_failure; + } + if (nla_put_u8(msg, IEEE802154_ATTR_REASON, reason)) + goto nla_put_failure; return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id); nla_put_failure: @@ -151,13 +151,12 @@ int ieee802154_nl_disassoc_confirm(struct net_device *dev, u8 status) if (!msg) return -ENOBUFS; - NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); - NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); - NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, - dev->dev_addr); - - NLA_PUT_U8(msg, IEEE802154_ATTR_STATUS, status); - + if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || + nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || + nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, + dev->dev_addr) || + nla_put_u8(msg, IEEE802154_ATTR_STATUS, status)) + goto nla_put_failure; return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id); nla_put_failure: @@ -177,13 +176,13 @@ int ieee802154_nl_beacon_indic(struct net_device *dev, if (!msg) return -ENOBUFS; - NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); - NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); - NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, - dev->dev_addr); - NLA_PUT_U16(msg, IEEE802154_ATTR_COORD_SHORT_ADDR, coord_addr); - NLA_PUT_U16(msg, IEEE802154_ATTR_COORD_PAN_ID, panid); - + if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || + nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || + nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, + dev->dev_addr) || + nla_put_u16(msg, IEEE802154_ATTR_COORD_SHORT_ADDR, coord_addr) || + nla_put_u16(msg, IEEE802154_ATTR_COORD_PAN_ID, panid)) + goto nla_put_failure; return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id); nla_put_failure: @@ -204,19 +203,17 @@ int ieee802154_nl_scan_confirm(struct net_device *dev, if (!msg) return -ENOBUFS; - NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); - NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); - NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, - dev->dev_addr); - - NLA_PUT_U8(msg, IEEE802154_ATTR_STATUS, status); - NLA_PUT_U8(msg, IEEE802154_ATTR_SCAN_TYPE, scan_type); - NLA_PUT_U32(msg, IEEE802154_ATTR_CHANNELS, unscanned); - NLA_PUT_U8(msg, IEEE802154_ATTR_PAGE, page); - - if (edl) - NLA_PUT(msg, IEEE802154_ATTR_ED_LIST, 27, edl); - + if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || + nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || + nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, + dev->dev_addr) || + nla_put_u8(msg, IEEE802154_ATTR_STATUS, status) || + nla_put_u8(msg, IEEE802154_ATTR_SCAN_TYPE, scan_type) || + nla_put_u32(msg, IEEE802154_ATTR_CHANNELS, unscanned) || + nla_put_u8(msg, IEEE802154_ATTR_PAGE, page) || + (edl && + nla_put(msg, IEEE802154_ATTR_ED_LIST, 27, edl))) + goto nla_put_failure; return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id); nla_put_failure: @@ -235,13 +232,12 @@ int ieee802154_nl_start_confirm(struct net_device *dev, u8 status) if (!msg) return -ENOBUFS; - NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); - NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); - NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, - dev->dev_addr); - - NLA_PUT_U8(msg, IEEE802154_ATTR_STATUS, status); - + if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || + nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || + nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, + dev->dev_addr) || + nla_put_u8(msg, IEEE802154_ATTR_STATUS, status)) + goto nla_put_failure; return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id); nla_put_failure: @@ -266,16 +262,16 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 pid, phy = ieee802154_mlme_ops(dev)->get_phy(dev); BUG_ON(!phy); - NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); - NLA_PUT_STRING(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)); - NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); - - NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, - dev->dev_addr); - NLA_PUT_U16(msg, IEEE802154_ATTR_SHORT_ADDR, - ieee802154_mlme_ops(dev)->get_short_addr(dev)); - NLA_PUT_U16(msg, IEEE802154_ATTR_PAN_ID, - ieee802154_mlme_ops(dev)->get_pan_id(dev)); + if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || + nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) || + nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || + nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, + dev->dev_addr) || + nla_put_u16(msg, IEEE802154_ATTR_SHORT_ADDR, + ieee802154_mlme_ops(dev)->get_short_addr(dev)) || + nla_put_u16(msg, IEEE802154_ATTR_PAN_ID, + ieee802154_mlme_ops(dev)->get_pan_id(dev))) + goto nla_put_failure; wpan_phy_put(phy); return genlmsg_end(msg, hdr); diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c index c64a38d..3bdc430 100644 --- a/net/ieee802154/nl-phy.c +++ b/net/ieee802154/nl-phy.c @@ -53,18 +53,18 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 pid, goto out; mutex_lock(&phy->pib_lock); - NLA_PUT_STRING(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)); - - NLA_PUT_U8(msg, IEEE802154_ATTR_PAGE, phy->current_page); - NLA_PUT_U8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel); + if (nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) || + nla_put_u8(msg, IEEE802154_ATTR_PAGE, phy->current_page) || + nla_put_u8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel)) + goto nla_put_failure; for (i = 0; i < 32; i++) { if (phy->channels_supported[i]) buf[pages++] = phy->channels_supported[i] | (i << 27); } - if (pages) - NLA_PUT(msg, IEEE802154_ATTR_CHANNEL_PAGE_LIST, - pages * sizeof(uint32_t), buf); - + if (pages && + nla_put(msg, IEEE802154_ATTR_CHANNEL_PAGE_LIST, + pages * sizeof(uint32_t), buf)) + goto nla_put_failure; mutex_unlock(&phy->pib_lock); kfree(buf); return genlmsg_end(msg, hdr); @@ -245,9 +245,9 @@ static int ieee802154_add_iface(struct sk_buff *skb, goto dev_unregister; } - NLA_PUT_STRING(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)); - NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); - + if (nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) || + nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name)) + goto nla_put_failure; dev_put(dev); wpan_phy_put(phy); @@ -333,10 +333,9 @@ static int ieee802154_del_iface(struct sk_buff *skb, rtnl_unlock(); - - NLA_PUT_STRING(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)); - NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, name); - + if (nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) || + nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, name)) + goto nla_put_failure; wpan_phy_put(phy); return ieee802154_nl_reply(msg, info); diff --git a/net/ieee802154/raw.c b/net/ieee802154/raw.c index f96bae8..50e8239 100644 --- a/net/ieee802154/raw.c +++ b/net/ieee802154/raw.c @@ -106,7 +106,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t size) { struct net_device *dev; - unsigned mtu; + unsigned int mtu; struct sk_buff *skb; int hlen, tlen; int err; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 10e3751..3744c1c 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -541,7 +541,7 @@ out: } EXPORT_SYMBOL(inet_bind); -int inet_dgram_connect(struct socket *sock, struct sockaddr * uaddr, +int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) { struct sock *sk = sock->sk; diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index fd508b5..3a28075 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -77,7 +77,7 @@ static inline struct scatterlist *ah_req_sg(struct crypto_ahash *ahash, static int ip_clear_mutable_options(const struct iphdr *iph, __be32 *daddr) { - unsigned char * optptr = (unsigned char*)(iph+1); + unsigned char *optptr = (unsigned char *)(iph+1); int l = iph->ihl*4 - sizeof(struct iphdr); int optlen; diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 18d9b81..373b56b 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1059,7 +1059,7 @@ static int arp_req_set(struct net *net, struct arpreq *r, neigh = __neigh_lookup_errno(&arp_tbl, &ip, dev); err = PTR_ERR(neigh); if (!IS_ERR(neigh)) { - unsigned state = NUD_STALE; + unsigned int state = NUD_STALE; if (r->arp_flags & ATF_PERM) state = NUD_PERMANENT; err = neigh_update(neigh, (r->arp_flags & ATF_COM) ? @@ -1071,7 +1071,7 @@ static int arp_req_set(struct net *net, struct arpreq *r, return err; } -static unsigned arp_state_to_flags(struct neighbour *neigh) +static unsigned int arp_state_to_flags(struct neighbour *neigh) { if (neigh->nud_state&NUD_PERMANENT) return ATF_PERM | ATF_COM; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 6e447ff..8a01bfb 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1125,7 +1125,7 @@ skip: } } -static inline bool inetdev_valid_mtu(unsigned mtu) +static inline bool inetdev_valid_mtu(unsigned int mtu) { return mtu >= 68; } @@ -1266,17 +1266,15 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa, ifm->ifa_scope = ifa->ifa_scope; ifm->ifa_index = ifa->ifa_dev->dev->ifindex; - if (ifa->ifa_address) - NLA_PUT_BE32(skb, IFA_ADDRESS, ifa->ifa_address); - - if (ifa->ifa_local) - NLA_PUT_BE32(skb, IFA_LOCAL, ifa->ifa_local); - - if (ifa->ifa_broadcast) - NLA_PUT_BE32(skb, IFA_BROADCAST, ifa->ifa_broadcast); - - if (ifa->ifa_label[0]) - NLA_PUT_STRING(skb, IFA_LABEL, ifa->ifa_label); + if ((ifa->ifa_address && + nla_put_be32(skb, IFA_ADDRESS, ifa->ifa_address)) || + (ifa->ifa_local && + nla_put_be32(skb, IFA_LOCAL, ifa->ifa_local)) || + (ifa->ifa_broadcast && + nla_put_be32(skb, IFA_BROADCAST, ifa->ifa_broadcast)) || + (ifa->ifa_label[0] && + nla_put_string(skb, IFA_LABEL, ifa->ifa_label))) + goto nla_put_failure; return nlmsg_end(skb, nlh); diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index cbe3a68..3854411 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -136,13 +136,13 @@ static void fib_flush(struct net *net) * Find address type as if only "dev" was present in the system. If * on_dev is NULL then all interfaces are taken into consideration. */ -static inline unsigned __inet_dev_addr_type(struct net *net, - const struct net_device *dev, - __be32 addr) +static inline unsigned int __inet_dev_addr_type(struct net *net, + const struct net_device *dev, + __be32 addr) { struct flowi4 fl4 = { .daddr = addr }; struct fib_result res; - unsigned ret = RTN_BROADCAST; + unsigned int ret = RTN_BROADCAST; struct fib_table *local_table; if (ipv4_is_zeronet(addr) || ipv4_is_lbcast(addr)) @@ -740,7 +740,7 @@ void fib_del_ifaddr(struct in_ifaddr *ifa, struct in_ifaddr *iprim) #define BRD_OK 2 #define BRD0_OK 4 #define BRD1_OK 8 - unsigned ok = 0; + unsigned int ok = 0; int subnet = 0; /* Primary network */ int gone = 1; /* Address is missing */ int same_prefsrc = 0; /* Another primary with same IP */ diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index 799fc79..2d043f7 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -221,15 +221,15 @@ static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb, frh->src_len = rule4->src_len; frh->tos = rule4->tos; - if (rule4->dst_len) - NLA_PUT_BE32(skb, FRA_DST, rule4->dst); - - if (rule4->src_len) - NLA_PUT_BE32(skb, FRA_SRC, rule4->src); - + if ((rule4->dst_len && + nla_put_be32(skb, FRA_DST, rule4->dst)) || + (rule4->src_len && + nla_put_be32(skb, FRA_SRC, rule4->src))) + goto nla_put_failure; #ifdef CONFIG_IP_ROUTE_CLASSID - if (rule4->tclassid) - NLA_PUT_U32(skb, FRA_FLOW, rule4->tclassid); + if (rule4->tclassid && + nla_put_u32(skb, FRA_FLOW, rule4->tclassid)) + goto nla_put_failure; #endif return 0; diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 5063fa3..a8bdf740 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -931,33 +931,36 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, rtm->rtm_table = tb_id; else rtm->rtm_table = RT_TABLE_COMPAT; - NLA_PUT_U32(skb, RTA_TABLE, tb_id); + if (nla_put_u32(skb, RTA_TABLE, tb_id)) + goto nla_put_failure; rtm->rtm_type = type; rtm->rtm_flags = fi->fib_flags; rtm->rtm_scope = fi->fib_scope; rtm->rtm_protocol = fi->fib_protocol; - if (rtm->rtm_dst_len) - NLA_PUT_BE32(skb, RTA_DST, dst); - - if (fi->fib_priority) - NLA_PUT_U32(skb, RTA_PRIORITY, fi->fib_priority); - + if (rtm->rtm_dst_len && + nla_put_be32(skb, RTA_DST, dst)) + goto nla_put_failure; + if (fi->fib_priority && + nla_put_u32(skb, RTA_PRIORITY, fi->fib_priority)) + goto nla_put_failure; if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0) goto nla_put_failure; - if (fi->fib_prefsrc) - NLA_PUT_BE32(skb, RTA_PREFSRC, fi->fib_prefsrc); - + if (fi->fib_prefsrc && + nla_put_be32(skb, RTA_PREFSRC, fi->fib_prefsrc)) + goto nla_put_failure; if (fi->fib_nhs == 1) { - if (fi->fib_nh->nh_gw) - NLA_PUT_BE32(skb, RTA_GATEWAY, fi->fib_nh->nh_gw); - - if (fi->fib_nh->nh_oif) - NLA_PUT_U32(skb, RTA_OIF, fi->fib_nh->nh_oif); + if (fi->fib_nh->nh_gw && + nla_put_be32(skb, RTA_GATEWAY, fi->fib_nh->nh_gw)) + goto nla_put_failure; + if (fi->fib_nh->nh_oif && + nla_put_u32(skb, RTA_OIF, fi->fib_nh->nh_oif)) + goto nla_put_failure; #ifdef CONFIG_IP_ROUTE_CLASSID - if (fi->fib_nh[0].nh_tclassid) - NLA_PUT_U32(skb, RTA_FLOW, fi->fib_nh[0].nh_tclassid); + if (fi->fib_nh[0].nh_tclassid && + nla_put_u32(skb, RTA_FLOW, fi->fib_nh[0].nh_tclassid)) + goto nla_put_failure; #endif } #ifdef CONFIG_IP_ROUTE_MULTIPATH @@ -978,11 +981,13 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, rtnh->rtnh_hops = nh->nh_weight - 1; rtnh->rtnh_ifindex = nh->nh_oif; - if (nh->nh_gw) - NLA_PUT_BE32(skb, RTA_GATEWAY, nh->nh_gw); + if (nh->nh_gw && + nla_put_be32(skb, RTA_GATEWAY, nh->nh_gw)) + goto nla_put_failure; #ifdef CONFIG_IP_ROUTE_CLASSID - if (nh->nh_tclassid) - NLA_PUT_U32(skb, RTA_FLOW, nh->nh_tclassid); + if (nh->nh_tclassid && + nla_put_u32(skb, RTA_FLOW, nh->nh_tclassid)) + goto nla_put_failure; #endif /* length of rtnetlink header + attributes */ rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *) rtnh; diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 5dfecfd..6699f23 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -344,10 +344,10 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) pip->protocol = IPPROTO_IGMP; pip->tot_len = 0; /* filled in later */ ip_select_ident(pip, &rt->dst, NULL); - ((u8*)&pip[1])[0] = IPOPT_RA; - ((u8*)&pip[1])[1] = 4; - ((u8*)&pip[1])[2] = 0; - ((u8*)&pip[1])[3] = 0; + ((u8 *)&pip[1])[0] = IPOPT_RA; + ((u8 *)&pip[1])[1] = 4; + ((u8 *)&pip[1])[2] = 0; + ((u8 *)&pip[1])[3] = 0; skb->transport_header = skb->network_header + sizeof(struct iphdr) + 4; skb_put(skb, sizeof(*pig)); @@ -688,10 +688,10 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, iph->saddr = fl4.saddr; iph->protocol = IPPROTO_IGMP; ip_select_ident(iph, &rt->dst, NULL); - ((u8*)&iph[1])[0] = IPOPT_RA; - ((u8*)&iph[1])[1] = 4; - ((u8*)&iph[1])[2] = 0; - ((u8*)&iph[1])[3] = 0; + ((u8 *)&iph[1])[0] = IPOPT_RA; + ((u8 *)&iph[1])[1] = 4; + ((u8 *)&iph[1])[2] = 0; + ((u8 *)&iph[1])[3] = 0; ih = (struct igmphdr *)skb_put(skb, sizeof(struct igmphdr)); ih->type = type; @@ -774,7 +774,7 @@ static int igmp_xmarksources(struct ip_mc_list *pmc, int nsrcs, __be32 *srcs) if (psf->sf_count[MCAST_INCLUDE] || pmc->sfcount[MCAST_EXCLUDE] != psf->sf_count[MCAST_EXCLUDE]) - continue; + break; if (srcs[i] == psf->sf_inaddr) { scount++; break; diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 19d66ce..7d972f6 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -42,7 +42,8 @@ EXPORT_SYMBOL(sysctl_local_reserved_ports); void inet_get_local_port_range(int *low, int *high) { - unsigned seq; + unsigned int seq; + do { seq = read_seqbegin(&sysctl_local_ports.lock); @@ -53,7 +54,7 @@ void inet_get_local_port_range(int *low, int *high) EXPORT_SYMBOL(inet_get_local_port_range); int inet_csk_bind_conflict(const struct sock *sk, - const struct inet_bind_bucket *tb) + const struct inet_bind_bucket *tb, bool relax) { struct sock *sk2; struct hlist_node *node; @@ -79,6 +80,14 @@ int inet_csk_bind_conflict(const struct sock *sk, sk2_rcv_saddr == sk_rcv_saddr(sk)) break; } + if (!relax && reuse && sk2->sk_reuse && + sk2->sk_state != TCP_LISTEN) { + const __be32 sk2_rcv_saddr = sk_rcv_saddr(sk2); + + if (!sk2_rcv_saddr || !sk_rcv_saddr(sk) || + sk2_rcv_saddr == sk_rcv_saddr(sk)) + break; + } } } return node != NULL; @@ -122,12 +131,13 @@ again: (tb->num_owners < smallest_size || smallest_size == -1)) { smallest_size = tb->num_owners; smallest_rover = rover; - if (atomic_read(&hashinfo->bsockets) > (high - low) + 1) { + if (atomic_read(&hashinfo->bsockets) > (high - low) + 1 && + !inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, false)) { snum = smallest_rover; goto tb_found; } } - if (!inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) { + if (!inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, false)) { snum = rover; goto tb_found; } @@ -178,12 +188,13 @@ tb_found: goto success; } else { ret = 1; - if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) { + if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, true)) { if (sk->sk_reuse && sk->sk_state != TCP_LISTEN && smallest_size != -1 && --attempts >= 0) { spin_unlock(&head->lock); goto again; } + goto fail_unlock; } } @@ -514,7 +525,7 @@ void inet_csk_reqsk_queue_prune(struct sock *parent, /* Normally all the openreqs are young and become mature * (i.e. converted to established socket) for first timeout. - * If synack was not acknowledged for 3 seconds, it means + * If synack was not acknowledged for 1 second, it means * one of the following things: synack was lost, ack was lost, * rtt is high or nobody planned to ack (i.e. synflood). * When server is a bit loaded, queue is populated with old @@ -555,8 +566,7 @@ void inet_csk_reqsk_queue_prune(struct sock *parent, syn_ack_recalc(req, thresh, max_retries, queue->rskq_defer_accept, &expire, &resend); - if (req->rsk_ops->syn_ack_timeout) - req->rsk_ops->syn_ack_timeout(parent, req); + req->rsk_ops->syn_ack_timeout(parent, req); if (!expire && (!resend || !req->rsk_ops->rtx_syn_ack(parent, req, NULL) || diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 984ec65..7880af9 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -217,7 +217,7 @@ begin: } EXPORT_SYMBOL_GPL(__inet_lookup_listener); -struct sock * __inet_lookup_established(struct net *net, +struct sock *__inet_lookup_established(struct net *net, struct inet_hashinfo *hashinfo, const __be32 saddr, const __be16 sport, const __be32 daddr, const u16 hnum, diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index 89168c6..543ef62 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -263,7 +263,7 @@ rescan: void inet_twdr_hangman(unsigned long data) { struct inet_timewait_death_row *twdr; - int unsigned need_timer; + unsigned int need_timer; twdr = (struct inet_timewait_death_row *)data; spin_lock(&twdr->death_lock); diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 29a07b6..e5c44fc 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -41,7 +41,7 @@ static int ip_forward_finish(struct sk_buff *skb) { - struct ip_options * opt = &(IPCB(skb)->opt); + struct ip_options *opt = &(IPCB(skb)->opt); IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS); @@ -55,7 +55,7 @@ int ip_forward(struct sk_buff *skb) { struct iphdr *iph; /* Our header */ struct rtable *rt; /* Route we use */ - struct ip_options * opt = &(IPCB(skb)->opt); + struct ip_options *opt = &(IPCB(skb)->opt); if (skb_warn_if_lro(skb)) goto drop; diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index b57532d..f49047b 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -169,37 +169,56 @@ struct ipgre_net { /* often modified stats are per cpu, other are shared (netdev->stats) */ struct pcpu_tstats { - unsigned long rx_packets; - unsigned long rx_bytes; - unsigned long tx_packets; - unsigned long tx_bytes; -} __attribute__((aligned(4*sizeof(unsigned long)))); + u64 rx_packets; + u64 rx_bytes; + u64 tx_packets; + u64 tx_bytes; + struct u64_stats_sync syncp; +}; -static struct net_device_stats *ipgre_get_stats(struct net_device *dev) +static struct rtnl_link_stats64 *ipgre_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *tot) { - struct pcpu_tstats sum = { 0 }; int i; for_each_possible_cpu(i) { const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i); - - sum.rx_packets += tstats->rx_packets; - sum.rx_bytes += tstats->rx_bytes; - sum.tx_packets += tstats->tx_packets; - sum.tx_bytes += tstats->tx_bytes; + u64 rx_packets, rx_bytes, tx_packets, tx_bytes; + unsigned int start; + + do { + start = u64_stats_fetch_begin_bh(&tstats->syncp); + rx_packets = tstats->rx_packets; + tx_packets = tstats->tx_packets; + rx_bytes = tstats->rx_bytes; + tx_bytes = tstats->tx_bytes; + } while (u64_stats_fetch_retry_bh(&tstats->syncp, start)); + + tot->rx_packets += rx_packets; + tot->tx_packets += tx_packets; + tot->rx_bytes += rx_bytes; + tot->tx_bytes += tx_bytes; } - dev->stats.rx_packets = sum.rx_packets; - dev->stats.rx_bytes = sum.rx_bytes; - dev->stats.tx_packets = sum.tx_packets; - dev->stats.tx_bytes = sum.tx_bytes; - return &dev->stats; + + tot->multicast = dev->stats.multicast; + tot->rx_crc_errors = dev->stats.rx_crc_errors; + tot->rx_fifo_errors = dev->stats.rx_fifo_errors; + tot->rx_length_errors = dev->stats.rx_length_errors; + tot->rx_errors = dev->stats.rx_errors; + tot->tx_fifo_errors = dev->stats.tx_fifo_errors; + tot->tx_carrier_errors = dev->stats.tx_carrier_errors; + tot->tx_dropped = dev->stats.tx_dropped; + tot->tx_aborted_errors = dev->stats.tx_aborted_errors; + tot->tx_errors = dev->stats.tx_errors; + + return tot; } /* Given src, dst and key, find appropriate for input tunnel. */ -static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev, - __be32 remote, __be32 local, - __be32 key, __be16 gre_proto) +static struct ip_tunnel *ipgre_tunnel_lookup(struct net_device *dev, + __be32 remote, __be32 local, + __be32 key, __be16 gre_proto) { struct net *net = dev_net(dev); int link = dev->ifindex; @@ -464,7 +483,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info) */ const struct iphdr *iph = (const struct iphdr *)skb->data; - __be16 *p = (__be16*)(skb->data+(iph->ihl<<2)); + __be16 *p = (__be16 *)(skb->data+(iph->ihl<<2)); int grehlen = (iph->ihl<<2) + 4; const int type = icmp_hdr(skb)->type; const int code = icmp_hdr(skb)->code; @@ -574,7 +593,7 @@ static int ipgre_rcv(struct sk_buff *skb) iph = ip_hdr(skb); h = skb->data; - flags = *(__be16*)h; + flags = *(__be16 *)h; if (flags&(GRE_CSUM|GRE_KEY|GRE_ROUTING|GRE_SEQ|GRE_VERSION)) { /* - Version must be 0. @@ -598,11 +617,11 @@ static int ipgre_rcv(struct sk_buff *skb) offset += 4; } if (flags&GRE_KEY) { - key = *(__be32*)(h + offset); + key = *(__be32 *)(h + offset); offset += 4; } if (flags&GRE_SEQ) { - seqno = ntohl(*(__be32*)(h + offset)); + seqno = ntohl(*(__be32 *)(h + offset)); offset += 4; } } @@ -672,8 +691,10 @@ static int ipgre_rcv(struct sk_buff *skb) } tstats = this_cpu_ptr(tunnel->dev->tstats); + u64_stats_update_begin(&tstats->syncp); tstats->rx_packets++; tstats->rx_bytes += skb->len; + u64_stats_update_end(&tstats->syncp); __skb_tunnel_rx(skb, tunnel->dev); @@ -900,7 +921,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev htons(ETH_P_TEB) : skb->protocol; if (tunnel->parms.o_flags&(GRE_KEY|GRE_CSUM|GRE_SEQ)) { - __be32 *ptr = (__be32*)(((u8*)iph) + tunnel->hlen - 4); + __be32 *ptr = (__be32 *)(((u8 *)iph) + tunnel->hlen - 4); if (tunnel->parms.o_flags&GRE_SEQ) { ++tunnel->o_seqno; @@ -913,7 +934,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev } if (tunnel->parms.o_flags&GRE_CSUM) { *ptr = 0; - *(__sum16*)ptr = ip_compute_csum((void*)(iph+1), skb->len - sizeof(struct iphdr)); + *(__sum16 *)ptr = ip_compute_csum((void *)(iph+1), skb->len - sizeof(struct iphdr)); } } @@ -1169,7 +1190,7 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev, { struct ip_tunnel *t = netdev_priv(dev); struct iphdr *iph = (struct iphdr *)skb_push(skb, t->hlen); - __be16 *p = (__be16*)(iph+1); + __be16 *p = (__be16 *)(iph+1); memcpy(iph, &t->parms.iph, sizeof(struct iphdr)); p[0] = t->parms.o_flags; @@ -1253,7 +1274,7 @@ static const struct net_device_ops ipgre_netdev_ops = { .ndo_start_xmit = ipgre_tunnel_xmit, .ndo_do_ioctl = ipgre_tunnel_ioctl, .ndo_change_mtu = ipgre_tunnel_change_mtu, - .ndo_get_stats = ipgre_get_stats, + .ndo_get_stats64 = ipgre_get_stats64, }; static void ipgre_dev_free(struct net_device *dev) @@ -1507,7 +1528,7 @@ static const struct net_device_ops ipgre_tap_netdev_ops = { .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = ipgre_tunnel_change_mtu, - .ndo_get_stats = ipgre_get_stats, + .ndo_get_stats64 = ipgre_get_stats64, }; static void ipgre_tap_setup(struct net_device *dev) @@ -1654,17 +1675,18 @@ static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) struct ip_tunnel *t = netdev_priv(dev); struct ip_tunnel_parm *p = &t->parms; - NLA_PUT_U32(skb, IFLA_GRE_LINK, p->link); - NLA_PUT_BE16(skb, IFLA_GRE_IFLAGS, p->i_flags); - NLA_PUT_BE16(skb, IFLA_GRE_OFLAGS, p->o_flags); - NLA_PUT_BE32(skb, IFLA_GRE_IKEY, p->i_key); - NLA_PUT_BE32(skb, IFLA_GRE_OKEY, p->o_key); - NLA_PUT_BE32(skb, IFLA_GRE_LOCAL, p->iph.saddr); - NLA_PUT_BE32(skb, IFLA_GRE_REMOTE, p->iph.daddr); - NLA_PUT_U8(skb, IFLA_GRE_TTL, p->iph.ttl); - NLA_PUT_U8(skb, IFLA_GRE_TOS, p->iph.tos); - NLA_PUT_U8(skb, IFLA_GRE_PMTUDISC, !!(p->iph.frag_off & htons(IP_DF))); - + if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || + nla_put_be16(skb, IFLA_GRE_IFLAGS, p->i_flags) || + nla_put_be16(skb, IFLA_GRE_OFLAGS, p->o_flags) || + nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || + nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || + nla_put_be32(skb, IFLA_GRE_LOCAL, p->iph.saddr) || + nla_put_be32(skb, IFLA_GRE_REMOTE, p->iph.daddr) || + nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) || + nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) || + nla_put_u8(skb, IFLA_GRE_PMTUDISC, + !!(p->iph.frag_off & htons(IP_DF)))) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index a0d0d9d..95722ed 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -210,10 +210,10 @@ int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb) * Simple and stupid 8), but the most efficient way. */ -void ip_options_fragment(struct sk_buff * skb) +void ip_options_fragment(struct sk_buff *skb) { unsigned char *optptr = skb_network_header(skb) + sizeof(struct iphdr); - struct ip_options * opt = &(IPCB(skb)->opt); + struct ip_options *opt = &(IPCB(skb)->opt); int l = opt->optlen; int optlen; @@ -248,13 +248,13 @@ void ip_options_fragment(struct sk_buff * skb) */ int ip_options_compile(struct net *net, - struct ip_options * opt, struct sk_buff * skb) + struct ip_options *opt, struct sk_buff *skb) { int l; - unsigned char * iph; - unsigned char * optptr; + unsigned char *iph; + unsigned char *optptr; int optlen; - unsigned char * pp_ptr = NULL; + unsigned char *pp_ptr = NULL; struct rtable *rt = NULL; if (skb != NULL) { @@ -413,7 +413,7 @@ int ip_options_compile(struct net *net, opt->is_changed = 1; } } else { - unsigned overflow = optptr[3]>>4; + unsigned int overflow = optptr[3]>>4; if (overflow == 15) { pp_ptr = optptr + 3; goto error; @@ -473,20 +473,20 @@ EXPORT_SYMBOL(ip_options_compile); * Undo all the changes done by ip_options_compile(). */ -void ip_options_undo(struct ip_options * opt) +void ip_options_undo(struct ip_options *opt) { if (opt->srr) { - unsigned char * optptr = opt->__data+opt->srr-sizeof(struct iphdr); + unsigned char *optptr = opt->__data+opt->srr-sizeof(struct iphdr); memmove(optptr+7, optptr+3, optptr[1]-7); memcpy(optptr+3, &opt->faddr, 4); } if (opt->rr_needaddr) { - unsigned char * optptr = opt->__data+opt->rr-sizeof(struct iphdr); + unsigned char *optptr = opt->__data+opt->rr-sizeof(struct iphdr); optptr[2] -= 4; memset(&optptr[optptr[2]-1], 0, 4); } if (opt->ts) { - unsigned char * optptr = opt->__data+opt->ts-sizeof(struct iphdr); + unsigned char *optptr = opt->__data+opt->ts-sizeof(struct iphdr); if (opt->ts_needtime) { optptr[2] -= 4; memset(&optptr[optptr[2]-1], 0, 4); @@ -549,8 +549,8 @@ int ip_options_get(struct net *net, struct ip_options_rcu **optp, void ip_forward_options(struct sk_buff *skb) { - struct ip_options * opt = &(IPCB(skb)->opt); - unsigned char * optptr; + struct ip_options *opt = &(IPCB(skb)->opt); + unsigned char *optptr; struct rtable *rt = skb_rtable(skb); unsigned char *raw = skb_network_header(skb); diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 2fd0fba..51c6c67 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -90,7 +90,7 @@ static void ip_cmsg_recv_opts(struct msghdr *msg, struct sk_buff *skb) static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb) { unsigned char optbuf[sizeof(struct ip_options) + 40]; - struct ip_options * opt = (struct ip_options *)optbuf; + struct ip_options *opt = (struct ip_options *)optbuf; if (IPCB(skb)->opt.optlen == 0) return; @@ -147,7 +147,7 @@ static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb) void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) { struct inet_sock *inet = inet_sk(skb->sk); - unsigned flags = inet->cmsg_flags; + unsigned int flags = inet->cmsg_flags; /* Ordered by supposed usage frequency */ if (flags & 1) @@ -1094,7 +1094,7 @@ EXPORT_SYMBOL(compat_ip_setsockopt); */ static int do_ip_getsockopt(struct sock *sk, int level, int optname, - char __user *optval, int __user *optlen, unsigned flags) + char __user *optval, int __user *optlen, unsigned int flags) { struct inet_sock *inet = inet_sk(sk); int val; diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 92ac7e7..f267280 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -1198,7 +1198,7 @@ static int __init ic_dynamic(void) d = ic_first_dev; retries = CONF_SEND_RETRIES; get_random_bytes(&timeout, sizeof(timeout)); - timeout = CONF_BASE_TIMEOUT + (timeout % (unsigned) CONF_TIMEOUT_RANDOM); + timeout = CONF_BASE_TIMEOUT + (timeout % (unsigned int) CONF_TIMEOUT_RANDOM); for (;;) { /* Track the device we are configuring */ ic_dev_xid = d->xid; diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index ae1413e..2d0f99b 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -144,33 +144,48 @@ static void ipip_dev_free(struct net_device *dev); /* often modified stats are per cpu, other are shared (netdev->stats) */ struct pcpu_tstats { - unsigned long rx_packets; - unsigned long rx_bytes; - unsigned long tx_packets; - unsigned long tx_bytes; -} __attribute__((aligned(4*sizeof(unsigned long)))); + u64 rx_packets; + u64 rx_bytes; + u64 tx_packets; + u64 tx_bytes; + struct u64_stats_sync syncp; +}; -static struct net_device_stats *ipip_get_stats(struct net_device *dev) +static struct rtnl_link_stats64 *ipip_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *tot) { - struct pcpu_tstats sum = { 0 }; int i; for_each_possible_cpu(i) { const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i); - - sum.rx_packets += tstats->rx_packets; - sum.rx_bytes += tstats->rx_bytes; - sum.tx_packets += tstats->tx_packets; - sum.tx_bytes += tstats->tx_bytes; + u64 rx_packets, rx_bytes, tx_packets, tx_bytes; + unsigned int start; + + do { + start = u64_stats_fetch_begin_bh(&tstats->syncp); + rx_packets = tstats->rx_packets; + tx_packets = tstats->tx_packets; + rx_bytes = tstats->rx_bytes; + tx_bytes = tstats->tx_bytes; + } while (u64_stats_fetch_retry_bh(&tstats->syncp, start)); + + tot->rx_packets += rx_packets; + tot->tx_packets += tx_packets; + tot->rx_bytes += rx_bytes; + tot->tx_bytes += tx_bytes; } - dev->stats.rx_packets = sum.rx_packets; - dev->stats.rx_bytes = sum.rx_bytes; - dev->stats.tx_packets = sum.tx_packets; - dev->stats.tx_bytes = sum.tx_bytes; - return &dev->stats; + + tot->tx_fifo_errors = dev->stats.tx_fifo_errors; + tot->tx_carrier_errors = dev->stats.tx_carrier_errors; + tot->tx_dropped = dev->stats.tx_dropped; + tot->tx_aborted_errors = dev->stats.tx_aborted_errors; + tot->tx_errors = dev->stats.tx_errors; + tot->collisions = dev->stats.collisions; + + return tot; } -static struct ip_tunnel * ipip_tunnel_lookup(struct net *net, +static struct ip_tunnel *ipip_tunnel_lookup(struct net *net, __be32 remote, __be32 local) { unsigned int h0 = HASH(remote); @@ -245,7 +260,7 @@ static void ipip_tunnel_link(struct ipip_net *ipn, struct ip_tunnel *t) rcu_assign_pointer(*tp, t); } -static struct ip_tunnel * ipip_tunnel_locate(struct net *net, +static struct ip_tunnel *ipip_tunnel_locate(struct net *net, struct ip_tunnel_parm *parms, int create) { __be32 remote = parms->iph.daddr; @@ -404,8 +419,10 @@ static int ipip_rcv(struct sk_buff *skb) skb->pkt_type = PACKET_HOST; tstats = this_cpu_ptr(tunnel->dev->tstats); + u64_stats_update_begin(&tstats->syncp); tstats->rx_packets++; tstats->rx_bytes += skb->len; + u64_stats_update_end(&tstats->syncp); __skb_tunnel_rx(skb, tunnel->dev); @@ -730,7 +747,7 @@ static const struct net_device_ops ipip_netdev_ops = { .ndo_start_xmit = ipip_tunnel_xmit, .ndo_do_ioctl = ipip_tunnel_ioctl, .ndo_change_mtu = ipip_tunnel_change_mtu, - .ndo_get_stats = ipip_get_stats, + .ndo_get_stats64 = ipip_get_stats64, }; static void ipip_dev_free(struct net_device *dev) diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 960fbfc3..5bef604 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -2119,15 +2119,16 @@ static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, rtm->rtm_src_len = 32; rtm->rtm_tos = 0; rtm->rtm_table = mrt->id; - NLA_PUT_U32(skb, RTA_TABLE, mrt->id); + if (nla_put_u32(skb, RTA_TABLE, mrt->id)) + goto nla_put_failure; rtm->rtm_type = RTN_MULTICAST; rtm->rtm_scope = RT_SCOPE_UNIVERSE; rtm->rtm_protocol = RTPROT_UNSPEC; rtm->rtm_flags = 0; - NLA_PUT_BE32(skb, RTA_SRC, c->mfc_origin); - NLA_PUT_BE32(skb, RTA_DST, c->mfc_mcastgrp); - + if (nla_put_be32(skb, RTA_SRC, c->mfc_origin) || + nla_put_be32(skb, RTA_DST, c->mfc_mcastgrp)) + goto nla_put_failure; if (__ipmr_fill_mroute(mrt, skb, c, rtm) < 0) goto nla_put_failure; diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index 4f47e06..3cd8c58 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -12,7 +12,7 @@ #include <net/netfilter/nf_queue.h> /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */ -int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) +int ip_route_me_harder(struct sk_buff *skb, unsigned int addr_type) { struct net *net = dev_net(skb_dst(skb)->dev); const struct iphdr *iph = ip_hdr(skb); diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index fd7a3f6..a393527 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -303,7 +303,7 @@ unsigned int arpt_do_table(struct sk_buff *skb, if (v < 0) { /* Pop from stack? */ if (v != XT_RETURN) { - verdict = (unsigned)(-v) - 1; + verdict = (unsigned int)(-v) - 1; break; } e = back; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 24e556e..585b80f 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -377,7 +377,7 @@ ipt_do_table(struct sk_buff *skb, if (v < 0) { /* Pop from stack? */ if (v != XT_RETURN) { - verdict = (unsigned)(-v) - 1; + verdict = (unsigned int)(-v) - 1; break; } if (*stackptr <= origptr) { diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index cf73cc7..345c7dc 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -311,8 +311,9 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len) static int ipv4_tuple_to_nlattr(struct sk_buff *skb, const struct nf_conntrack_tuple *tuple) { - NLA_PUT_BE32(skb, CTA_IP_V4_SRC, tuple->src.u3.ip); - NLA_PUT_BE32(skb, CTA_IP_V4_DST, tuple->dst.u3.ip); + if (nla_put_be32(skb, CTA_IP_V4_SRC, tuple->src.u3.ip) || + nla_put_be32(skb, CTA_IP_V4_DST, tuple->dst.u3.ip)) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 7cbe9cb..0847e37 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -228,10 +228,10 @@ icmp_error(struct net *net, struct nf_conn *tmpl, static int icmp_tuple_to_nlattr(struct sk_buff *skb, const struct nf_conntrack_tuple *t) { - NLA_PUT_BE16(skb, CTA_PROTO_ICMP_ID, t->src.u.icmp.id); - NLA_PUT_U8(skb, CTA_PROTO_ICMP_TYPE, t->dst.u.icmp.type); - NLA_PUT_U8(skb, CTA_PROTO_ICMP_CODE, t->dst.u.icmp.code); - + if (nla_put_be16(skb, CTA_PROTO_ICMP_ID, t->src.u.icmp.id) || + nla_put_u8(skb, CTA_PROTO_ICMP_TYPE, t->dst.u.icmp.type) || + nla_put_u8(skb, CTA_PROTO_ICMP_CODE, t->dst.u.icmp.code)) + goto nla_put_failure; return 0; nla_put_failure: @@ -293,8 +293,8 @@ icmp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data) { const unsigned int *timeout = data; - NLA_PUT_BE32(skb, CTA_TIMEOUT_ICMP_TIMEOUT, htonl(*timeout / HZ)); - + if (nla_put_be32(skb, CTA_TIMEOUT_ICMP_TIMEOUT, htonl(*timeout / HZ))) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index 57932c4..ea4a2381 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c @@ -283,7 +283,7 @@ static unsigned int ip_nat_sip_expect(struct sk_buff *skb, unsigned int dataoff, __be32 newip; u_int16_t port; char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; - unsigned buflen; + unsigned int buflen; /* Connection will come from reply */ if (ct->tuplehash[dir].tuple.src.u3.ip == ct->tuplehash[!dir].tuple.dst.u3.ip) diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 50009c7..6e930c7 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -51,15 +51,16 @@ static struct ping_table ping_table; static u16 ping_port_rover; -static inline int ping_hashfn(struct net *net, unsigned num, unsigned mask) +static inline int ping_hashfn(struct net *net, unsigned int num, unsigned int mask) { int res = (num + net_hash_mix(net)) & mask; + pr_debug("hash(%d) = %d\n", num, res); return res; } static inline struct hlist_nulls_head *ping_hashslot(struct ping_table *table, - struct net *net, unsigned num) + struct net *net, unsigned int num) { return &table->hash[ping_hashfn(net, num, PING_HTABLE_MASK)]; } @@ -188,7 +189,8 @@ static void inet_get_ping_group_range_net(struct net *net, gid_t *low, gid_t *high) { gid_t *data = net->ipv4.sysctl_ping_group_range; - unsigned seq; + unsigned int seq; + do { seq = read_seqbegin(&sysctl_local_ports.lock); @@ -410,7 +412,7 @@ struct pingfakehdr { __wsum wcheck; }; -static int ping_getfrag(void *from, char * to, +static int ping_getfrag(void *from, char *to, int offset, int fraglen, int odd, struct sk_buff *skb) { struct pingfakehdr *pfh = (struct pingfakehdr *)from; diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index bbd604c..4032b81 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -288,7 +288,7 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info) read_unlock(&raw_v4_hashinfo.lock); } -static int raw_rcv_skb(struct sock * sk, struct sk_buff * skb) +static int raw_rcv_skb(struct sock *sk, struct sk_buff *skb) { /* Charge it to the socket. */ diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 167ea10..ac4d6b3 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -229,7 +229,7 @@ const __u8 ip_tos2prio[16] = { TC_PRIO_INTERACTIVE_BULK, ECN_OR_COST(INTERACTIVE_BULK) }; - +EXPORT_SYMBOL(ip_tos2prio); /* * Route cache. @@ -296,7 +296,7 @@ static inline void rt_hash_lock_init(void) #endif static struct rt_hash_bucket *rt_hash_table __read_mostly; -static unsigned rt_hash_mask __read_mostly; +static unsigned int rt_hash_mask __read_mostly; static unsigned int rt_hash_log __read_mostly; static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat); @@ -1143,7 +1143,7 @@ static int rt_bind_neighbour(struct rtable *rt) return 0; } -static struct rtable *rt_intern_hash(unsigned hash, struct rtable *rt, +static struct rtable *rt_intern_hash(unsigned int hash, struct rtable *rt, struct sk_buff *skb, int ifindex) { struct rtable *rth, *cand; @@ -1384,7 +1384,7 @@ void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more) } EXPORT_SYMBOL(__ip_select_ident); -static void rt_del(unsigned hash, struct rtable *rt) +static void rt_del(unsigned int hash, struct rtable *rt) { struct rtable __rcu **rthp; struct rtable *aux; @@ -1538,7 +1538,7 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) ip_rt_put(rt); ret = NULL; } else if (rt->rt_flags & RTCF_REDIRECTED) { - unsigned hash = rt_hash(rt->rt_key_dst, rt->rt_key_src, + unsigned int hash = rt_hash(rt->rt_key_dst, rt->rt_key_src, rt->rt_oif, rt_genid(dev_net(dst->dev))); rt_del(hash, rt); @@ -2215,9 +2215,9 @@ static int ip_mkroute_input(struct sk_buff *skb, struct in_device *in_dev, __be32 daddr, __be32 saddr, u32 tos) { - struct rtable* rth = NULL; + struct rtable *rth = NULL; int err; - unsigned hash; + unsigned int hash; #ifdef CONFIG_IP_ROUTE_MULTIPATH if (res->fi && res->fi->fib_nhs > 1) @@ -2255,13 +2255,13 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, struct fib_result res; struct in_device *in_dev = __in_dev_get_rcu(dev); struct flowi4 fl4; - unsigned flags = 0; + unsigned int flags = 0; u32 itag = 0; - struct rtable * rth; - unsigned hash; + struct rtable *rth; + unsigned int hash; __be32 spec_dst; int err = -EINVAL; - struct net * net = dev_net(dev); + struct net *net = dev_net(dev); /* IP on this device is disabled. */ @@ -2433,8 +2433,8 @@ martian_source_keep_err: int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr, u8 tos, struct net_device *dev, bool noref) { - struct rtable * rth; - unsigned hash; + struct rtable *rth; + unsigned int hash; int iif = dev->ifindex; struct net *net; int res; @@ -2972,7 +2972,8 @@ static int rt_fill_info(struct net *net, r->rtm_src_len = 0; r->rtm_tos = rt->rt_key_tos; r->rtm_table = RT_TABLE_MAIN; - NLA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN); + if (nla_put_u32(skb, RTA_TABLE, RT_TABLE_MAIN)) + goto nla_put_failure; r->rtm_type = rt->rt_type; r->rtm_scope = RT_SCOPE_UNIVERSE; r->rtm_protocol = RTPROT_UNSPEC; @@ -2980,31 +2981,38 @@ static int rt_fill_info(struct net *net, if (rt->rt_flags & RTCF_NOTIFY) r->rtm_flags |= RTM_F_NOTIFY; - NLA_PUT_BE32(skb, RTA_DST, rt->rt_dst); - + if (nla_put_be32(skb, RTA_DST, rt->rt_dst)) + goto nla_put_failure; if (rt->rt_key_src) { r->rtm_src_len = 32; - NLA_PUT_BE32(skb, RTA_SRC, rt->rt_key_src); + if (nla_put_be32(skb, RTA_SRC, rt->rt_key_src)) + goto nla_put_failure; } - if (rt->dst.dev) - NLA_PUT_U32(skb, RTA_OIF, rt->dst.dev->ifindex); + if (rt->dst.dev && + nla_put_u32(skb, RTA_OIF, rt->dst.dev->ifindex)) + goto nla_put_failure; #ifdef CONFIG_IP_ROUTE_CLASSID - if (rt->dst.tclassid) - NLA_PUT_U32(skb, RTA_FLOW, rt->dst.tclassid); + if (rt->dst.tclassid && + nla_put_u32(skb, RTA_FLOW, rt->dst.tclassid)) + goto nla_put_failure; #endif - if (rt_is_input_route(rt)) - NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_spec_dst); - else if (rt->rt_src != rt->rt_key_src) - NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_src); - - if (rt->rt_dst != rt->rt_gateway) - NLA_PUT_BE32(skb, RTA_GATEWAY, rt->rt_gateway); + if (rt_is_input_route(rt)) { + if (nla_put_be32(skb, RTA_PREFSRC, rt->rt_spec_dst)) + goto nla_put_failure; + } else if (rt->rt_src != rt->rt_key_src) { + if (nla_put_be32(skb, RTA_PREFSRC, rt->rt_src)) + goto nla_put_failure; + } + if (rt->rt_dst != rt->rt_gateway && + nla_put_be32(skb, RTA_GATEWAY, rt->rt_gateway)) + goto nla_put_failure; if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) goto nla_put_failure; - if (rt->rt_mark) - NLA_PUT_BE32(skb, RTA_MARK, rt->rt_mark); + if (rt->rt_mark && + nla_put_be32(skb, RTA_MARK, rt->rt_mark)) + goto nla_put_failure; error = rt->dst.error; if (peer) { @@ -3045,7 +3053,8 @@ static int rt_fill_info(struct net *net, } } else #endif - NLA_PUT_U32(skb, RTA_IIF, rt->rt_iif); + if (nla_put_u32(skb, RTA_IIF, rt->rt_iif)) + goto nla_put_failure; } if (rtnl_put_cacheinfo(skb, &rt->dst, id, ts, tsage, @@ -3059,7 +3068,7 @@ nla_put_failure: return -EMSGSIZE; } -static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) +static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg) { struct net *net = sock_net(in_skb->sk); struct rtmsg *rtm; diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 7a7724d..34a6286 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -78,7 +78,7 @@ static int ipv4_local_port_range(ctl_table *table, int write, static void inet_get_ping_group_range_table(struct ctl_table *table, gid_t *low, gid_t *high) { gid_t *data = table->data; - unsigned seq; + unsigned int seq; do { seq = read_seqbegin(&sysctl_local_ports.lock); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 8bb6ade..c53e8a8 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2675,7 +2675,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, { struct sk_buff *segs = ERR_PTR(-EINVAL); struct tcphdr *th; - unsigned thlen; + unsigned int thlen; unsigned int seq; __be32 delta; unsigned int oldlen; @@ -3033,9 +3033,9 @@ int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp, struct scatterlist sg; const struct tcphdr *tp = tcp_hdr(skb); struct hash_desc *desc = &hp->md5_desc; - unsigned i; - const unsigned head_data_len = skb_headlen(skb) > header_len ? - skb_headlen(skb) - header_len : 0; + unsigned int i; + const unsigned int head_data_len = skb_headlen(skb) > header_len ? + skb_headlen(skb) - header_len : 0; const struct skb_shared_info *shi = skb_shinfo(skb); struct sk_buff *frag_iter; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 9944c1d..99448f0 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -175,7 +175,7 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb) static void tcp_incr_quickack(struct sock *sk) { struct inet_connection_sock *icsk = inet_csk(sk); - unsigned quickacks = tcp_sk(sk)->rcv_wnd / (2 * icsk->icsk_ack.rcv_mss); + unsigned int quickacks = tcp_sk(sk)->rcv_wnd / (2 * icsk->icsk_ack.rcv_mss); if (quickacks == 0) quickacks = 2; @@ -936,7 +936,7 @@ static void tcp_init_metrics(struct sock *sk) tcp_set_rto(sk); reset: if (tp->srtt == 0) { - /* RFC2988bis: We've failed to get a valid RTT sample from + /* RFC6298: 5.7 We've failed to get a valid RTT sample from * 3WHS. This is most likely due to retransmission, * including spurious one. Reset the RTO back to 3secs * from the more aggressive 1sec to avoid more spurious @@ -946,7 +946,7 @@ reset: inet_csk(sk)->icsk_rto = TCP_TIMEOUT_FALLBACK; } /* Cut cwnd down to 1 per RFC5681 if SYN or SYN-ACK has been - * retransmitted. In light of RFC2988bis' more aggressive 1sec + * retransmitted. In light of RFC6298 more aggressive 1sec * initRTO, we only reset cwnd when more than 1 SYN/SYN-ACK * retransmission has occurred. */ @@ -5734,8 +5734,6 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, */ inet_csk_schedule_ack(sk); icsk->icsk_ack.lrcvtime = tcp_time_stamp; - icsk->icsk_ack.ato = TCP_ATO_MIN; - tcp_incr_quickack(sk); tcp_enter_quickack_mode(sk); inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, TCP_DELACK_MAX, TCP_RTO_MAX); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 376b2cf..de8790c 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -563,13 +563,13 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, /* Compute TCP options for SYN packets. This is not the final * network wire format yet. */ -static unsigned tcp_syn_options(struct sock *sk, struct sk_buff *skb, +static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb, struct tcp_out_options *opts, struct tcp_md5sig_key **md5) { struct tcp_sock *tp = tcp_sk(sk); struct tcp_cookie_values *cvp = tp->cookie_values; - unsigned remaining = MAX_TCP_OPTION_SPACE; + unsigned int remaining = MAX_TCP_OPTION_SPACE; u8 cookie_size = (!tp->rx_opt.cookie_out_never && cvp != NULL) ? tcp_cookie_size_check(cvp->cookie_desired) : 0; @@ -663,15 +663,15 @@ static unsigned tcp_syn_options(struct sock *sk, struct sk_buff *skb, } /* Set up TCP options for SYN-ACKs. */ -static unsigned tcp_synack_options(struct sock *sk, +static unsigned int tcp_synack_options(struct sock *sk, struct request_sock *req, - unsigned mss, struct sk_buff *skb, + unsigned int mss, struct sk_buff *skb, struct tcp_out_options *opts, struct tcp_md5sig_key **md5, struct tcp_extend_values *xvp) { struct inet_request_sock *ireq = inet_rsk(req); - unsigned remaining = MAX_TCP_OPTION_SPACE; + unsigned int remaining = MAX_TCP_OPTION_SPACE; u8 cookie_plus = (xvp != NULL && !xvp->cookie_out_never) ? xvp->cookie_plus : 0; @@ -742,13 +742,13 @@ static unsigned tcp_synack_options(struct sock *sk, /* Compute TCP options for ESTABLISHED sockets. This is not the * final wire format yet. */ -static unsigned tcp_established_options(struct sock *sk, struct sk_buff *skb, +static unsigned int tcp_established_options(struct sock *sk, struct sk_buff *skb, struct tcp_out_options *opts, struct tcp_md5sig_key **md5) { struct tcp_skb_cb *tcb = skb ? TCP_SKB_CB(skb) : NULL; struct tcp_sock *tp = tcp_sk(sk); - unsigned size = 0; + unsigned int size = 0; unsigned int eff_sacks; #ifdef CONFIG_TCP_MD5SIG @@ -770,9 +770,9 @@ static unsigned tcp_established_options(struct sock *sk, struct sk_buff *skb, eff_sacks = tp->rx_opt.num_sacks + tp->rx_opt.dsack; if (unlikely(eff_sacks)) { - const unsigned remaining = MAX_TCP_OPTION_SPACE - size; + const unsigned int remaining = MAX_TCP_OPTION_SPACE - size; opts->num_sack_blocks = - min_t(unsigned, eff_sacks, + min_t(unsigned int, eff_sacks, (remaining - TCPOLEN_SACK_BASE_ALIGNED) / TCPOLEN_SACK_PERBLOCK); size += TCPOLEN_SACK_BASE_ALIGNED + @@ -801,7 +801,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, struct tcp_sock *tp; struct tcp_skb_cb *tcb; struct tcp_out_options opts; - unsigned tcp_options_size, tcp_header_size; + unsigned int tcp_options_size, tcp_header_size; struct tcp_md5sig_key *md5; struct tcphdr *th; int err; @@ -1258,7 +1258,7 @@ unsigned int tcp_current_mss(struct sock *sk) const struct tcp_sock *tp = tcp_sk(sk); const struct dst_entry *dst = __sk_dst_get(sk); u32 mss_now; - unsigned header_len; + unsigned int header_len; struct tcp_out_options opts; struct tcp_md5sig_key *md5; @@ -1389,7 +1389,7 @@ static inline int tcp_minshall_check(const struct tcp_sock *tp) */ static inline int tcp_nagle_check(const struct tcp_sock *tp, const struct sk_buff *skb, - unsigned mss_now, int nonagle) + unsigned int mss_now, int nonagle) { return skb->len < mss_now && ((nonagle & TCP_NAGLE_CORK) || diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c index a981cdc..4526fe6 100644 --- a/net/ipv4/tcp_probe.c +++ b/net/ipv4/tcp_probe.c @@ -91,7 +91,7 @@ static inline int tcp_probe_avail(void) * Note: arguments must match tcp_rcv_established()! */ static int jtcp_rcv_established(struct sock *sk, struct sk_buff *skb, - struct tcphdr *th, unsigned len) + struct tcphdr *th, unsigned int len) { const struct tcp_sock *tp = tcp_sk(sk); const struct inet_sock *inet = inet_sk(sk); @@ -138,7 +138,7 @@ static struct jprobe tcp_jprobe = { .entry = jtcp_rcv_established, }; -static int tcpprobe_open(struct inode * inode, struct file * file) +static int tcpprobe_open(struct inode *inode, struct file *file) { /* Reset (empty) log */ spin_lock_bh(&tcp_probe.lock); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index fe14105..3430e8f 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -107,6 +107,7 @@ #include <net/checksum.h> #include <net/xfrm.h> #include <trace/events/udp.h> +#include <linux/static_key.h> #include "udp_impl.h" struct udp_table udp_table __read_mostly; @@ -206,7 +207,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, if (!snum) { int low, high, remaining; - unsigned rand; + unsigned int rand; unsigned short first, last; DECLARE_BITMAP(bitmap, PORTS_PER_CHAIN); @@ -846,7 +847,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, * Get and verify the address. */ if (msg->msg_name) { - struct sockaddr_in * usin = (struct sockaddr_in *)msg->msg_name; + struct sockaddr_in *usin = (struct sockaddr_in *)msg->msg_name; if (msg->msg_namelen < sizeof(*usin)) return -EINVAL; if (usin->sin_family != AF_INET) { @@ -1379,6 +1380,14 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) } +static struct static_key udp_encap_needed __read_mostly; +void udp_encap_enable(void) +{ + if (!static_key_enabled(&udp_encap_needed)) + static_key_slow_inc(&udp_encap_needed); +} +EXPORT_SYMBOL(udp_encap_enable); + /* returns: * -1: error * 0: success @@ -1400,7 +1409,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) goto drop; nf_reset(skb); - if (up->encap_type) { + if (static_key_false(&udp_encap_needed) && up->encap_type) { int (*encap_rcv)(struct sock *sk, struct sk_buff *skb); /* @@ -1760,6 +1769,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, /* FALLTHROUGH */ case UDP_ENCAP_L2TPINUDP: up->encap_type = val; + udp_encap_enable(); break; default: err = -ENOPROTOOPT; diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h index aaad650..5a681e2 100644 --- a/net/ipv4/udp_impl.h +++ b/net/ipv4/udp_impl.h @@ -25,7 +25,7 @@ extern int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len, int noblock, int flags, int *addr_len); extern int udp_sendpage(struct sock *sk, struct page *page, int offset, size_t size, int flags); -extern int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb); +extern int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); extern void udp_destroy_sock(struct sock *sk); #ifdef CONFIG_PROC_FS diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index a0b4c5d..8ef24e1 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -152,7 +152,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) case IPPROTO_AH: if (pskb_may_pull(skb, xprth + 8 - skb->data)) { - __be32 *ah_hdr = (__be32*)xprth; + __be32 *ah_hdr = (__be32 *)xprth; fl4->fl4_ipsec_spi = ah_hdr[1]; } diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 7d5cb97..4a83983 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -149,7 +149,7 @@ static void addrconf_type_change(struct net_device *dev, unsigned long event); static int addrconf_ifdown(struct net_device *dev, int how); -static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); +static void addrconf_dad_start(struct inet6_ifaddr *ifp); static void addrconf_dad_timer(unsigned long data); static void addrconf_dad_completed(struct inet6_ifaddr *ifp); static void addrconf_dad_run(struct inet6_dev *idev); @@ -336,10 +336,9 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) snmp6_free_dev(idev); kfree_rcu(idev, rcu); } - EXPORT_SYMBOL(in6_dev_finish_destroy); -static struct inet6_dev * ipv6_add_dev(struct net_device *dev) +static struct inet6_dev *ipv6_add_dev(struct net_device *dev) { struct inet6_dev *ndev; @@ -441,7 +440,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) return ndev; } -static struct inet6_dev * ipv6_find_idev(struct net_device *dev) +static struct inet6_dev *ipv6_find_idev(struct net_device *dev) { struct inet6_dev *idev; @@ -929,7 +928,7 @@ retry: ift->tstamp = tmp_tstamp; spin_unlock_bh(&ift->lock); - addrconf_dad_start(ift, 0); + addrconf_dad_start(ift); in6_ifa_put(ift); in6_dev_put(idev); out: @@ -1332,7 +1331,6 @@ int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev) rcu_read_unlock(); return onlink; } - EXPORT_SYMBOL(ipv6_chk_prefix); struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *addr, @@ -1522,7 +1520,7 @@ static int addrconf_ifid_arcnet(u8 *eui, struct net_device *dev) if (dev->addr_len != ARCNET_ALEN) return -1; memset(eui, 0, 7); - eui[7] = *(u8*)dev->dev_addr; + eui[7] = *(u8 *)dev->dev_addr; return 0; } @@ -1667,7 +1665,8 @@ out: in6_dev_put(idev); } -static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr) { +static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr) +{ int ret = 0; if (tmpaddr && memcmp(idev->rndid, &tmpaddr->s6_addr[8], 8) == 0) @@ -1908,7 +1907,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao) /* Try to figure out our local address for this prefix */ if (pinfo->autoconf && in6_dev->cnf.autoconf) { - struct inet6_ifaddr * ifp; + struct inet6_ifaddr *ifp; struct in6_addr addr; int create = 0, update_lft = 0; @@ -1957,7 +1956,7 @@ ok: update_lft = create = 1; ifp->cstamp = jiffies; - addrconf_dad_start(ifp, RTF_ADDRCONF|RTF_PREFIX_RT); + addrconf_dad_start(ifp); } if (ifp) { @@ -2236,7 +2235,7 @@ static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *p * that the Optimistic flag should not be set for * manually configured addresses */ - addrconf_dad_start(ifp, 0); + addrconf_dad_start(ifp); in6_ifa_put(ifp); addrconf_verify(0); return 0; @@ -2362,9 +2361,9 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) } for_each_netdev(net, dev) { - struct in_device * in_dev = __in_dev_get_rtnl(dev); + struct in_device *in_dev = __in_dev_get_rtnl(dev); if (in_dev && (dev->flags & IFF_UP)) { - struct in_ifaddr * ifa; + struct in_ifaddr *ifa; int flag = scope; @@ -2410,7 +2409,7 @@ static void init_loopback(struct net_device *dev) static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr) { - struct inet6_ifaddr * ifp; + struct inet6_ifaddr *ifp; u32 addr_flags = IFA_F_PERMANENT; #ifdef CONFIG_IPV6_OPTIMISTIC_DAD @@ -2423,7 +2422,7 @@ static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr ifp = ipv6_add_addr(idev, addr, 64, IFA_LINK, addr_flags); if (!IS_ERR(ifp)) { addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0); - addrconf_dad_start(ifp, 0); + addrconf_dad_start(ifp); in6_ifa_put(ifp); } } @@ -2431,7 +2430,7 @@ static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr static void addrconf_dev_config(struct net_device *dev) { struct in6_addr addr; - struct inet6_dev * idev; + struct inet6_dev *idev; ASSERT_RTNL(); @@ -2567,7 +2566,7 @@ static void addrconf_ip6_tnl_config(struct net_device *dev) } static int addrconf_notify(struct notifier_block *this, unsigned long event, - void * data) + void *data) { struct net_device *dev = (struct net_device *) data; struct inet6_dev *idev = __in6_dev_get(dev); @@ -2918,7 +2917,7 @@ static void addrconf_dad_kick(struct inet6_ifaddr *ifp) addrconf_mod_timer(ifp, AC_DAD, rand_num); } -static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) +static void addrconf_dad_start(struct inet6_ifaddr *ifp) { struct inet6_dev *idev = ifp->idev; struct net_device *dev = idev->dev; @@ -3791,7 +3790,7 @@ static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb) return inet6_dump_addr(skb, cb, type); } -static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, +static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg) { struct net *net = sock_net(in_skb->sk); @@ -3986,14 +3985,14 @@ static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev) struct nlattr *nla; struct ifla_cacheinfo ci; - NLA_PUT_U32(skb, IFLA_INET6_FLAGS, idev->if_flags); - + if (nla_put_u32(skb, IFLA_INET6_FLAGS, idev->if_flags)) + goto nla_put_failure; ci.max_reasm_len = IPV6_MAXPLEN; ci.tstamp = cstamp_delta(idev->tstamp); ci.reachable_time = jiffies_to_msecs(idev->nd_parms->reachable_time); ci.retrans_time = jiffies_to_msecs(idev->nd_parms->retrans_time); - NLA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci); - + if (nla_put(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci)) + goto nla_put_failure; nla = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32)); if (nla == NULL) goto nla_put_failure; @@ -4058,15 +4057,13 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, hdr->ifi_flags = dev_get_flags(dev); hdr->ifi_change = 0; - NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); - - if (dev->addr_len) - NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); - - NLA_PUT_U32(skb, IFLA_MTU, dev->mtu); - if (dev->ifindex != dev->iflink) - NLA_PUT_U32(skb, IFLA_LINK, dev->iflink); - + if (nla_put_string(skb, IFLA_IFNAME, dev->name) || + (dev->addr_len && + nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) || + nla_put_u32(skb, IFLA_MTU, dev->mtu) || + (dev->ifindex != dev->iflink && + nla_put_u32(skb, IFLA_LINK, dev->iflink))) + goto nla_put_failure; protoinfo = nla_nest_start(skb, IFLA_PROTINFO); if (protoinfo == NULL) goto nla_put_failure; @@ -4179,12 +4176,12 @@ static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev, if (pinfo->autoconf) pmsg->prefix_flags |= IF_PREFIX_AUTOCONF; - NLA_PUT(skb, PREFIX_ADDRESS, sizeof(pinfo->prefix), &pinfo->prefix); - + if (nla_put(skb, PREFIX_ADDRESS, sizeof(pinfo->prefix), &pinfo->prefix)) + goto nla_put_failure; ci.preferred_time = ntohl(pinfo->prefered); ci.valid_time = ntohl(pinfo->valid); - NLA_PUT(skb, PREFIX_CACHEINFO, sizeof(ci), &ci); - + if (nla_put(skb, PREFIX_CACHEINFO, sizeof(ci), &ci)) + goto nla_put_failure; return nlmsg_end(skb, nlh); nla_put_failure: diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c index 399287e..d051e5f 100644 --- a/net/ipv6/addrconf_core.c +++ b/net/ipv6/addrconf_core.c @@ -8,9 +8,9 @@ #define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) -static inline unsigned ipv6_addr_scope2type(unsigned scope) +static inline unsigned int ipv6_addr_scope2type(unsigned int scope) { - switch(scope) { + switch (scope) { case IPV6_ADDR_SCOPE_NODELOCAL: return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) | IPV6_ADDR_LOOPBACK); diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 76832c8..7fba35a 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -98,7 +98,7 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) sin.sin_port = usin->sin6_port; err = ip4_datagram_connect(sk, - (struct sockaddr*) &sin, + (struct sockaddr *) &sin, sizeof(sin)); ipv4_connected: @@ -515,10 +515,10 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) u8 nexthdr = ipv6_hdr(skb)->nexthdr; while (off <= opt->lastopt) { - unsigned len; + unsigned int len; u8 *ptr = nh + off; - switch(nexthdr) { + switch (nexthdr) { case IPPROTO_DSTOPTS: nexthdr = ptr[0]; len = (ptr[1] + 1) << 3; @@ -827,9 +827,8 @@ int datagram_send_ctl(struct net *net, struct sock *sk, int tc; err = -EINVAL; - if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) { + if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) goto exit_f; - } tc = *(int *)CMSG_DATA(cmsg); if (tc < -1 || tc > 0xff) @@ -846,9 +845,8 @@ int datagram_send_ctl(struct net *net, struct sock *sk, int df; err = -EINVAL; - if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) { + if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) goto exit_f; - } df = *(int *)CMSG_DATA(cmsg); if (df < 0 || df > 1) diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 3d641b6..aa0a51e 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -153,6 +153,7 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb) while (len > 0) { int optlen = nh[off + 1] + 2; + int i; switch (nh[off]) { case IPV6_TLV_PAD0: @@ -160,6 +161,21 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb) break; case IPV6_TLV_PADN: + /* RFC 2460 states that the purpose of PadN is + * to align the containing header to multiples + * of 8. 7 is therefore the highest valid value. + * See also RFC 4942, Section 2.1.9.5. + */ + if (optlen > 7) + goto bad; + /* RFC 4942 recommends receiving hosts to + * actively check PadN payload to contain + * only zeroes. + */ + for (i = 2; i < optlen; i++) { + if (nh[off + i] != 0) + goto bad; + } break; default: /* Other TLV code so scan list */ @@ -722,7 +738,6 @@ void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, if (opt->hopopt) ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt); } - EXPORT_SYMBOL(ipv6_push_nfrag_opts); void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto) @@ -738,20 +753,19 @@ ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt) opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC); if (opt2) { - long dif = (char*)opt2 - (char*)opt; + long dif = (char *)opt2 - (char *)opt; memcpy(opt2, opt, opt->tot_len); if (opt2->hopopt) - *((char**)&opt2->hopopt) += dif; + *((char **)&opt2->hopopt) += dif; if (opt2->dst0opt) - *((char**)&opt2->dst0opt) += dif; + *((char **)&opt2->dst0opt) += dif; if (opt2->dst1opt) - *((char**)&opt2->dst1opt) += dif; + *((char **)&opt2->dst1opt) += dif; if (opt2->srcrt) - *((char**)&opt2->srcrt) += dif; + *((char **)&opt2->srcrt) += dif; } return opt2; } - EXPORT_SYMBOL_GPL(ipv6_dup_options); static int ipv6_renew_option(void *ohdr, @@ -892,5 +906,4 @@ struct in6_addr *fl6_update_dst(struct flowi6 *fl6, fl6->daddr = *((struct rt0_hdr *)opt->srcrt)->addr; return orig; } - EXPORT_SYMBOL_GPL(fl6_update_dst); diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c index 72957f4..7b1a884 100644 --- a/net/ipv6/exthdrs_core.c +++ b/net/ipv6/exthdrs_core.c @@ -21,6 +21,7 @@ int ipv6_ext_hdr(u8 nexthdr) (nexthdr == NEXTHDR_NONE) || (nexthdr == NEXTHDR_DEST); } +EXPORT_SYMBOL(ipv6_ext_hdr); /* * Skip any extension headers. This is used by the ICMP module. @@ -109,6 +110,4 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, *nexthdrp = nexthdr; return start; } - -EXPORT_SYMBOL(ipv6_ext_hdr); EXPORT_SYMBOL(ipv6_skip_exthdr); diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index b6c5731..0ff1cfd 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c @@ -22,8 +22,7 @@ #include <net/ip6_route.h> #include <net/netlink.h> -struct fib6_rule -{ +struct fib6_rule { struct fib_rule common; struct rt6key src; struct rt6key dst; @@ -215,14 +214,13 @@ static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb, frh->src_len = rule6->src.plen; frh->tos = rule6->tclass; - if (rule6->dst.plen) - NLA_PUT(skb, FRA_DST, sizeof(struct in6_addr), - &rule6->dst.addr); - - if (rule6->src.plen) - NLA_PUT(skb, FRA_SRC, sizeof(struct in6_addr), - &rule6->src.addr); - + if ((rule6->dst.plen && + nla_put(skb, FRA_DST, sizeof(struct in6_addr), + &rule6->dst.addr)) || + (rule6->src.plen && + nla_put(skb, FRA_SRC, sizeof(struct in6_addr), + &rule6->src.addr))) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 27ac95a..cc079d8 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -498,7 +498,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) err = ip6_append_data(sk, icmpv6_getfrag, &msg, len + sizeof(struct icmp6hdr), sizeof(struct icmp6hdr), hlimit, - np->tclass, NULL, &fl6, (struct rt6_info*)dst, + np->tclass, NULL, &fl6, (struct rt6_info *)dst, MSG_DONTWAIT, np->dontfrag); if (err) { ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); @@ -579,7 +579,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl6, - (struct rt6_info*)dst, MSG_DONTWAIT, + (struct rt6_info *)dst, MSG_DONTWAIT, np->dontfrag); if (err) { @@ -950,7 +950,6 @@ int icmpv6_err_convert(u8 type, u8 code, int *err) return fatal; } - EXPORT_SYMBOL(icmpv6_err_convert); #ifdef CONFIG_SYSCTL diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 02dd203..e6cee52 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c @@ -28,7 +28,7 @@ #include <net/inet6_connection_sock.h> int inet6_csk_bind_conflict(const struct sock *sk, - const struct inet_bind_bucket *tb) + const struct inet_bind_bucket *tb, bool relax) { const struct sock *sk2; const struct hlist_node *node; diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index b7867a1..1dd6329 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -705,9 +705,9 @@ static int ip6fl_seq_show(struct seq_file *seq, void *v) struct ip6_flowlabel *fl = v; seq_printf(seq, "%05X %-1d %-6d %-6d %-6ld %-8ld %pi6 %-4d\n", - (unsigned)ntohl(fl->label), + (unsigned int)ntohl(fl->label), fl->share, - (unsigned)fl->owner, + (int)fl->owner, atomic_read(&fl->users), fl->linger/HZ, (long)(fl->expires - jiffies)/HZ, diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index aa21da6..e25b0fd 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -198,7 +198,7 @@ ip6_tnl_bucket(struct ip6_tnl_net *ip6n, const struct ip6_tnl_parm *p) { const struct in6_addr *remote = &p->raddr; const struct in6_addr *local = &p->laddr; - unsigned h = 0; + unsigned int h = 0; int prio = 0; if (!ipv6_addr_any(remote) || !ipv6_addr_any(local)) { diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 8110362..efc0098 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -2215,14 +2215,15 @@ static int ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, rtm->rtm_src_len = 128; rtm->rtm_tos = 0; rtm->rtm_table = mrt->id; - NLA_PUT_U32(skb, RTA_TABLE, mrt->id); + if (nla_put_u32(skb, RTA_TABLE, mrt->id)) + goto nla_put_failure; rtm->rtm_scope = RT_SCOPE_UNIVERSE; rtm->rtm_protocol = RTPROT_UNSPEC; rtm->rtm_flags = 0; - NLA_PUT(skb, RTA_SRC, 16, &c->mf6c_origin); - NLA_PUT(skb, RTA_DST, 16, &c->mf6c_mcastgrp); - + if (nla_put(skb, RTA_SRC, 16, &c->mf6c_origin) || + nla_put(skb, RTA_DST, 16, &c->mf6c_mcastgrp)) + goto nla_put_failure; if (__ip6mr_fill_mroute(mrt, skb, c, rtm) < 0) goto nla_put_failure; diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 63dd1f8..ba6d13d 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -678,7 +678,6 @@ done: } case MCAST_MSFILTER: { - extern int sysctl_mld_max_msf; struct group_filter *gsf; if (optlen < GROUP_FILTER_SIZE(0)) @@ -943,7 +942,7 @@ static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt, } static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, - char __user *optval, int __user *optlen, unsigned flags) + char __user *optval, int __user *optlen, unsigned int flags) { struct ipv6_pinfo *np = inet6_sk(sk); int len; diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index b2869ca..7dfb89f 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1061,7 +1061,7 @@ static int mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs, if (psf->sf_count[MCAST_INCLUDE] || pmc->mca_sfcount[MCAST_EXCLUDE] != psf->sf_count[MCAST_EXCLUDE]) - continue; + break; if (ipv6_addr_equal(&srcs[i], &psf->sf_addr)) { scount++; break; diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 176b469..35615c6 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -15,6 +15,7 @@ /* * Changes: * + * Alexey I. Froloff : RFC6106 (DNSSL) support * Pierre Ynard : export userland ND options * through netlink (RDNSS support) * Lars Fenneberg : fixed MTU setting on receipt @@ -228,7 +229,8 @@ static struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur, static inline int ndisc_is_useropt(struct nd_opt_hdr *opt) { - return opt->nd_opt_type == ND_OPT_RDNSS; + return opt->nd_opt_type == ND_OPT_RDNSS || + opt->nd_opt_type == ND_OPT_DNSSL; } static struct nd_opt_hdr *ndisc_next_useropt(struct nd_opt_hdr *cur, @@ -1099,8 +1101,9 @@ static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt) memcpy(ndmsg + 1, opt, opt->nd_opt_len << 3); - NLA_PUT(skb, NDUSEROPT_SRCADDR, sizeof(struct in6_addr), - &ipv6_hdr(ra)->saddr); + if (nla_put(skb, NDUSEROPT_SRCADDR, sizeof(struct in6_addr), + &ipv6_hdr(ra)->saddr)) + goto nla_put_failure; nlmsg_end(skb, nlh); rtnl_notify(skb, net, 0, RTNLGRP_ND_USEROPT, NULL, GFP_ATOMIC); diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 9d4e155..d4e350f 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -396,7 +396,7 @@ ip6t_do_table(struct sk_buff *skb, if (v < 0) { /* Pop from stack? */ if (v != XT_RETURN) { - verdict = (unsigned)(-v) - 1; + verdict = (unsigned int)(-v) - 1; break; } if (*stackptr <= origptr) diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 4111050..fe925e4 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -278,10 +278,11 @@ static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = { static int ipv6_tuple_to_nlattr(struct sk_buff *skb, const struct nf_conntrack_tuple *tuple) { - NLA_PUT(skb, CTA_IP_V6_SRC, sizeof(u_int32_t) * 4, - &tuple->src.u3.ip6); - NLA_PUT(skb, CTA_IP_V6_DST, sizeof(u_int32_t) * 4, - &tuple->dst.u3.ip6); + if (nla_put(skb, CTA_IP_V6_SRC, sizeof(u_int32_t) * 4, + &tuple->src.u3.ip6) || + nla_put(skb, CTA_IP_V6_DST, sizeof(u_int32_t) * 4, + &tuple->dst.u3.ip6)) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 92cc9f2..3e81904 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -234,10 +234,10 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl, static int icmpv6_tuple_to_nlattr(struct sk_buff *skb, const struct nf_conntrack_tuple *t) { - NLA_PUT_BE16(skb, CTA_PROTO_ICMPV6_ID, t->src.u.icmp.id); - NLA_PUT_U8(skb, CTA_PROTO_ICMPV6_TYPE, t->dst.u.icmp.type); - NLA_PUT_U8(skb, CTA_PROTO_ICMPV6_CODE, t->dst.u.icmp.code); - + if (nla_put_be16(skb, CTA_PROTO_ICMPV6_ID, t->src.u.icmp.id) || + nla_put_u8(skb, CTA_PROTO_ICMPV6_TYPE, t->dst.u.icmp.type) || + nla_put_u8(skb, CTA_PROTO_ICMPV6_CODE, t->dst.u.icmp.code)) + goto nla_put_failure; return 0; nla_put_failure: @@ -300,8 +300,8 @@ icmpv6_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data) { const unsigned int *timeout = data; - NLA_PUT_BE32(skb, CTA_TIMEOUT_ICMPV6_TIMEOUT, htonl(*timeout / HZ)); - + if (nla_put_be32(skb, CTA_TIMEOUT_ICMPV6_TIMEOUT, htonl(*timeout / HZ))) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/ipv6/route.c b/net/ipv6/route.c index bc4888d..0aefc36 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -82,7 +82,7 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu); static struct rt6_info *rt6_add_route_info(struct net *net, const struct in6_addr *prefix, int prefixlen, const struct in6_addr *gwaddr, int ifindex, - unsigned pref); + unsigned int pref); static struct rt6_info *rt6_get_route_info(struct net *net, const struct in6_addr *prefix, int prefixlen, const struct in6_addr *gwaddr, int ifindex); @@ -1887,7 +1887,7 @@ out: static struct rt6_info *rt6_add_route_info(struct net *net, const struct in6_addr *prefix, int prefixlen, const struct in6_addr *gwaddr, int ifindex, - unsigned pref) + unsigned int pref) { struct fib6_config cfg = { .fc_table = RT6_TABLE_INFO, @@ -2217,10 +2217,9 @@ void rt6_ifdown(struct net *net, struct net_device *dev) icmp6_clean_all(fib6_ifdown, &adn); } -struct rt6_mtu_change_arg -{ +struct rt6_mtu_change_arg { struct net_device *dev; - unsigned mtu; + unsigned int mtu; }; static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) @@ -2262,7 +2261,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) return 0; } -void rt6_mtu_change(struct net_device *dev, unsigned mtu) +void rt6_mtu_change(struct net_device *dev, unsigned int mtu) { struct rt6_mtu_change_arg arg = { .dev = dev, @@ -2430,7 +2429,8 @@ static int rt6_fill_node(struct net *net, else table = RT6_TABLE_UNSPEC; rtm->rtm_table = table; - NLA_PUT_U32(skb, RTA_TABLE, table); + if (nla_put_u32(skb, RTA_TABLE, table)) + goto nla_put_failure; if (rt->rt6i_flags & RTF_REJECT) rtm->rtm_type = RTN_UNREACHABLE; else if (rt->rt6i_flags & RTF_LOCAL) @@ -2453,16 +2453,20 @@ static int rt6_fill_node(struct net *net, rtm->rtm_flags |= RTM_F_CLONED; if (dst) { - NLA_PUT(skb, RTA_DST, 16, dst); + if (nla_put(skb, RTA_DST, 16, dst)) + goto nla_put_failure; rtm->rtm_dst_len = 128; } else if (rtm->rtm_dst_len) - NLA_PUT(skb, RTA_DST, 16, &rt->rt6i_dst.addr); + if (nla_put(skb, RTA_DST, 16, &rt->rt6i_dst.addr)) + goto nla_put_failure; #ifdef CONFIG_IPV6_SUBTREES if (src) { - NLA_PUT(skb, RTA_SRC, 16, src); + if (nla_put(skb, RTA_SRC, 16, src)) + goto nla_put_failure; rtm->rtm_src_len = 128; - } else if (rtm->rtm_src_len) - NLA_PUT(skb, RTA_SRC, 16, &rt->rt6i_src.addr); + } else if (rtm->rtm_src_len && + nla_put(skb, RTA_SRC, 16, &rt->rt6i_src.addr)) + goto nla_put_failure; #endif if (iif) { #ifdef CONFIG_IPV6_MROUTE @@ -2480,17 +2484,20 @@ static int rt6_fill_node(struct net *net, } } else #endif - NLA_PUT_U32(skb, RTA_IIF, iif); + if (nla_put_u32(skb, RTA_IIF, iif)) + goto nla_put_failure; } else if (dst) { struct in6_addr saddr_buf; - if (ip6_route_get_saddr(net, rt, dst, 0, &saddr_buf) == 0) - NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); + if (ip6_route_get_saddr(net, rt, dst, 0, &saddr_buf) == 0 && + nla_put(skb, RTA_PREFSRC, 16, &saddr_buf)) + goto nla_put_failure; } if (rt->rt6i_prefsrc.plen) { struct in6_addr saddr_buf; saddr_buf = rt->rt6i_prefsrc.addr; - NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); + if (nla_put(skb, RTA_PREFSRC, 16, &saddr_buf)) + goto nla_put_failure; } if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) @@ -2506,11 +2513,11 @@ static int rt6_fill_node(struct net *net, } rcu_read_unlock(); - if (rt->dst.dev) - NLA_PUT_U32(skb, RTA_OIF, rt->dst.dev->ifindex); - - NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); - + if (rt->dst.dev && + nla_put_u32(skb, RTA_OIF, rt->dst.dev->ifindex)) + goto nla_put_failure; + if (nla_put_u32(skb, RTA_PRIORITY, rt->rt6i_metric)) + goto nla_put_failure; if (!(rt->rt6i_flags & RTF_EXPIRES)) expires = 0; else if (rt->dst.expires - jiffies < INT_MAX) @@ -2615,6 +2622,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb) { + dst_release(&rt->dst); err = -ENOBUFS; goto errout; } diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index c4ffd17..e5fef943 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -87,35 +87,51 @@ struct sit_net { /* often modified stats are per cpu, other are shared (netdev->stats) */ struct pcpu_tstats { - unsigned long rx_packets; - unsigned long rx_bytes; - unsigned long tx_packets; - unsigned long tx_bytes; -} __attribute__((aligned(4*sizeof(unsigned long)))); + u64 rx_packets; + u64 rx_bytes; + u64 tx_packets; + u64 tx_bytes; + struct u64_stats_sync syncp; +}; -static struct net_device_stats *ipip6_get_stats(struct net_device *dev) +static struct rtnl_link_stats64 *ipip6_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *tot) { - struct pcpu_tstats sum = { 0 }; int i; for_each_possible_cpu(i) { const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i); - - sum.rx_packets += tstats->rx_packets; - sum.rx_bytes += tstats->rx_bytes; - sum.tx_packets += tstats->tx_packets; - sum.tx_bytes += tstats->tx_bytes; + u64 rx_packets, rx_bytes, tx_packets, tx_bytes; + unsigned int start; + + do { + start = u64_stats_fetch_begin_bh(&tstats->syncp); + rx_packets = tstats->rx_packets; + tx_packets = tstats->tx_packets; + rx_bytes = tstats->rx_bytes; + tx_bytes = tstats->tx_bytes; + } while (u64_stats_fetch_retry_bh(&tstats->syncp, start)); + + tot->rx_packets += rx_packets; + tot->tx_packets += tx_packets; + tot->rx_bytes += rx_bytes; + tot->tx_bytes += tx_bytes; } - dev->stats.rx_packets = sum.rx_packets; - dev->stats.rx_bytes = sum.rx_bytes; - dev->stats.tx_packets = sum.tx_packets; - dev->stats.tx_bytes = sum.tx_bytes; - return &dev->stats; + + tot->rx_errors = dev->stats.rx_errors; + tot->tx_fifo_errors = dev->stats.tx_fifo_errors; + tot->tx_carrier_errors = dev->stats.tx_carrier_errors; + tot->tx_dropped = dev->stats.tx_dropped; + tot->tx_aborted_errors = dev->stats.tx_aborted_errors; + tot->tx_errors = dev->stats.tx_errors; + + return tot; } + /* * Must be invoked with rcu_read_lock */ -static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net, +static struct ip_tunnel *ipip6_tunnel_lookup(struct net *net, struct net_device *dev, __be32 remote, __be32 local) { unsigned int h0 = HASH(remote); @@ -691,7 +707,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, goto tx_error; } - addr6 = (const struct in6_addr*)&neigh->primary_key; + addr6 = (const struct in6_addr *)&neigh->primary_key; addr_type = ipv6_addr_type(addr6); if ((addr_type & IPV6_ADDR_UNICAST) && @@ -721,7 +737,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, goto tx_error; } - addr6 = (const struct in6_addr*)&neigh->primary_key; + addr6 = (const struct in6_addr *)&neigh->primary_key; addr_type = ipv6_addr_type(addr6); if (addr_type == IPV6_ADDR_ANY) { @@ -1126,7 +1142,7 @@ static const struct net_device_ops ipip6_netdev_ops = { .ndo_start_xmit = ipip6_tunnel_xmit, .ndo_do_ioctl = ipip6_tunnel_ioctl, .ndo_change_mtu = ipip6_tunnel_change_mtu, - .ndo_get_stats = ipip6_get_stats, + .ndo_get_stats64= ipip6_get_stats64, }; static void ipip6_dev_free(struct net_device *dev) diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 4fe1db12..ee5a706 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -68,9 +68,9 @@ static DEFINE_SPINLOCK(xfrm6_tunnel_spi_lock); static struct kmem_cache *xfrm6_tunnel_spi_kmem __read_mostly; -static inline unsigned xfrm6_tunnel_spi_hash_byaddr(const xfrm_address_t *addr) +static inline unsigned int xfrm6_tunnel_spi_hash_byaddr(const xfrm_address_t *addr) { - unsigned h; + unsigned int h; h = (__force u32)(addr->a6[0] ^ addr->a6[1] ^ addr->a6[2] ^ addr->a6[3]); h ^= h >> 16; @@ -80,7 +80,7 @@ static inline unsigned xfrm6_tunnel_spi_hash_byaddr(const xfrm_address_t *addr) return h; } -static inline unsigned xfrm6_tunnel_spi_hash_byspi(u32 spi) +static inline unsigned int xfrm6_tunnel_spi_hash_byspi(u32 spi) { return spi % XFRM6_TUNNEL_SPI_BYSPI_HSIZE; } diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c index 77c5e64..d0667d6 100644 --- a/net/irda/ircomm/ircomm_tty_ioctl.c +++ b/net/irda/ircomm/ircomm_tty_ioctl.c @@ -54,7 +54,7 @@ */ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self) { - unsigned cflag, cval; + unsigned int cflag, cval; int baud; IRDA_DEBUG(2, "%s()\n", __func__ ); diff --git a/net/key/af_key.c b/net/key/af_key.c index 7e5d927..34e4185 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1714,7 +1714,7 @@ static int key_notify_sa_flush(const struct km_event *c) static int pfkey_flush(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs) { struct net *net = sock_net(sk); - unsigned proto; + unsigned int proto; struct km_event c; struct xfrm_audit audit_info; int err, err2; @@ -3547,7 +3547,7 @@ static int pfkey_sendmsg(struct kiocb *kiocb, goto out; err = -EMSGSIZE; - if ((unsigned)len > sk->sk_sndbuf - 32) + if ((unsigned int)len > sk->sk_sndbuf - 32) goto out; err = -ENOBUFS; diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 89ff8c6..f6732b6 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -1424,6 +1424,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */ udp_sk(sk)->encap_type = UDP_ENCAP_L2TPINUDP; udp_sk(sk)->encap_rcv = l2tp_udp_encap_recv; + udp_encap_enable(); } sk->sk_user_data = tunnel; diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index a16a48e..09e4a38 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h @@ -54,15 +54,15 @@ struct l2tp_tunnel; */ struct l2tp_session_cfg { enum l2tp_pwtype pw_type; - unsigned data_seq:2; /* data sequencing level + unsigned int data_seq:2; /* data sequencing level * 0 => none, 1 => IP only, * 2 => all */ - unsigned recv_seq:1; /* expect receive packets with + unsigned int recv_seq:1; /* expect receive packets with * sequence numbers? */ - unsigned send_seq:1; /* send packets with sequence + unsigned int send_seq:1; /* send packets with sequence * numbers? */ - unsigned lns_mode:1; /* behave as LNS? LAC enables + unsigned int lns_mode:1; /* behave as LNS? LAC enables * sequence numbers under * control of LNS. */ int debug; /* bitmask of debug message @@ -107,15 +107,15 @@ struct l2tp_session { char name[32]; /* for logging */ char ifname[IFNAMSIZ]; - unsigned data_seq:2; /* data sequencing level + unsigned int data_seq:2; /* data sequencing level * 0 => none, 1 => IP only, * 2 => all */ - unsigned recv_seq:1; /* expect receive packets with + unsigned int recv_seq:1; /* expect receive packets with * sequence numbers? */ - unsigned send_seq:1; /* send packets with sequence + unsigned int send_seq:1; /* send packets with sequence * numbers? */ - unsigned lns_mode:1; /* behave as LNS? LAC enables + unsigned int lns_mode:1; /* behave as LNS? LAC enables * sequence numbers under * control of LNS. */ int debug; /* bitmask of debug message diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c index 93a41a0..bc8c334 100644 --- a/net/l2tp/l2tp_netlink.c +++ b/net/l2tp/l2tp_netlink.c @@ -231,24 +231,28 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 pid, u32 seq, int flags, if (IS_ERR(hdr)) return PTR_ERR(hdr); - NLA_PUT_U8(skb, L2TP_ATTR_PROTO_VERSION, tunnel->version); - NLA_PUT_U32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id); - NLA_PUT_U32(skb, L2TP_ATTR_PEER_CONN_ID, tunnel->peer_tunnel_id); - NLA_PUT_U32(skb, L2TP_ATTR_DEBUG, tunnel->debug); - NLA_PUT_U16(skb, L2TP_ATTR_ENCAP_TYPE, tunnel->encap); + if (nla_put_u8(skb, L2TP_ATTR_PROTO_VERSION, tunnel->version) || + nla_put_u32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id) || + nla_put_u32(skb, L2TP_ATTR_PEER_CONN_ID, tunnel->peer_tunnel_id) || + nla_put_u32(skb, L2TP_ATTR_DEBUG, tunnel->debug) || + nla_put_u16(skb, L2TP_ATTR_ENCAP_TYPE, tunnel->encap)) + goto nla_put_failure; nest = nla_nest_start(skb, L2TP_ATTR_STATS); if (nest == NULL) goto nla_put_failure; - NLA_PUT_U64(skb, L2TP_ATTR_TX_PACKETS, tunnel->stats.tx_packets); - NLA_PUT_U64(skb, L2TP_ATTR_TX_BYTES, tunnel->stats.tx_bytes); - NLA_PUT_U64(skb, L2TP_ATTR_TX_ERRORS, tunnel->stats.tx_errors); - NLA_PUT_U64(skb, L2TP_ATTR_RX_PACKETS, tunnel->stats.rx_packets); - NLA_PUT_U64(skb, L2TP_ATTR_RX_BYTES, tunnel->stats.rx_bytes); - NLA_PUT_U64(skb, L2TP_ATTR_RX_SEQ_DISCARDS, tunnel->stats.rx_seq_discards); - NLA_PUT_U64(skb, L2TP_ATTR_RX_OOS_PACKETS, tunnel->stats.rx_oos_packets); - NLA_PUT_U64(skb, L2TP_ATTR_RX_ERRORS, tunnel->stats.rx_errors); + if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS, tunnel->stats.tx_packets) || + nla_put_u64(skb, L2TP_ATTR_TX_BYTES, tunnel->stats.tx_bytes) || + nla_put_u64(skb, L2TP_ATTR_TX_ERRORS, tunnel->stats.tx_errors) || + nla_put_u64(skb, L2TP_ATTR_RX_PACKETS, tunnel->stats.rx_packets) || + nla_put_u64(skb, L2TP_ATTR_RX_BYTES, tunnel->stats.rx_bytes) || + nla_put_u64(skb, L2TP_ATTR_RX_SEQ_DISCARDS, + tunnel->stats.rx_seq_discards) || + nla_put_u64(skb, L2TP_ATTR_RX_OOS_PACKETS, + tunnel->stats.rx_oos_packets) || + nla_put_u64(skb, L2TP_ATTR_RX_ERRORS, tunnel->stats.rx_errors)) + goto nla_put_failure; nla_nest_end(skb, nest); sk = tunnel->sock; @@ -259,13 +263,16 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 pid, u32 seq, int flags, switch (tunnel->encap) { case L2TP_ENCAPTYPE_UDP: - NLA_PUT_U16(skb, L2TP_ATTR_UDP_SPORT, ntohs(inet->inet_sport)); - NLA_PUT_U16(skb, L2TP_ATTR_UDP_DPORT, ntohs(inet->inet_dport)); - NLA_PUT_U8(skb, L2TP_ATTR_UDP_CSUM, (sk->sk_no_check != UDP_CSUM_NOXMIT)); + if (nla_put_u16(skb, L2TP_ATTR_UDP_SPORT, ntohs(inet->inet_sport)) || + nla_put_u16(skb, L2TP_ATTR_UDP_DPORT, ntohs(inet->inet_dport)) || + nla_put_u8(skb, L2TP_ATTR_UDP_CSUM, + (sk->sk_no_check != UDP_CSUM_NOXMIT))) + goto nla_put_failure; /* NOBREAK */ case L2TP_ENCAPTYPE_IP: - NLA_PUT_BE32(skb, L2TP_ATTR_IP_SADDR, inet->inet_saddr); - NLA_PUT_BE32(skb, L2TP_ATTR_IP_DADDR, inet->inet_daddr); + if (nla_put_be32(skb, L2TP_ATTR_IP_SADDR, inet->inet_saddr) || + nla_put_be32(skb, L2TP_ATTR_IP_DADDR, inet->inet_daddr)) + goto nla_put_failure; break; } @@ -563,43 +570,50 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 pid, u32 seq, int flags if (IS_ERR(hdr)) return PTR_ERR(hdr); - NLA_PUT_U32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id); - NLA_PUT_U32(skb, L2TP_ATTR_SESSION_ID, session->session_id); - NLA_PUT_U32(skb, L2TP_ATTR_PEER_CONN_ID, tunnel->peer_tunnel_id); - NLA_PUT_U32(skb, L2TP_ATTR_PEER_SESSION_ID, session->peer_session_id); - NLA_PUT_U32(skb, L2TP_ATTR_DEBUG, session->debug); - NLA_PUT_U16(skb, L2TP_ATTR_PW_TYPE, session->pwtype); - NLA_PUT_U16(skb, L2TP_ATTR_MTU, session->mtu); - if (session->mru) - NLA_PUT_U16(skb, L2TP_ATTR_MRU, session->mru); - - if (session->ifname && session->ifname[0]) - NLA_PUT_STRING(skb, L2TP_ATTR_IFNAME, session->ifname); - if (session->cookie_len) - NLA_PUT(skb, L2TP_ATTR_COOKIE, session->cookie_len, &session->cookie[0]); - if (session->peer_cookie_len) - NLA_PUT(skb, L2TP_ATTR_PEER_COOKIE, session->peer_cookie_len, &session->peer_cookie[0]); - NLA_PUT_U8(skb, L2TP_ATTR_RECV_SEQ, session->recv_seq); - NLA_PUT_U8(skb, L2TP_ATTR_SEND_SEQ, session->send_seq); - NLA_PUT_U8(skb, L2TP_ATTR_LNS_MODE, session->lns_mode); + if (nla_put_u32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id) || + nla_put_u32(skb, L2TP_ATTR_SESSION_ID, session->session_id) || + nla_put_u32(skb, L2TP_ATTR_PEER_CONN_ID, tunnel->peer_tunnel_id) || + nla_put_u32(skb, L2TP_ATTR_PEER_SESSION_ID, + session->peer_session_id) || + nla_put_u32(skb, L2TP_ATTR_DEBUG, session->debug) || + nla_put_u16(skb, L2TP_ATTR_PW_TYPE, session->pwtype) || + nla_put_u16(skb, L2TP_ATTR_MTU, session->mtu) || + (session->mru && + nla_put_u16(skb, L2TP_ATTR_MRU, session->mru))) + goto nla_put_failure; + + if ((session->ifname && session->ifname[0] && + nla_put_string(skb, L2TP_ATTR_IFNAME, session->ifname)) || + (session->cookie_len && + nla_put(skb, L2TP_ATTR_COOKIE, session->cookie_len, + &session->cookie[0])) || + (session->peer_cookie_len && + nla_put(skb, L2TP_ATTR_PEER_COOKIE, session->peer_cookie_len, + &session->peer_cookie[0])) || + nla_put_u8(skb, L2TP_ATTR_RECV_SEQ, session->recv_seq) || + nla_put_u8(skb, L2TP_ATTR_SEND_SEQ, session->send_seq) || + nla_put_u8(skb, L2TP_ATTR_LNS_MODE, session->lns_mode) || #ifdef CONFIG_XFRM - if ((sk) && (sk->sk_policy[0] || sk->sk_policy[1])) - NLA_PUT_U8(skb, L2TP_ATTR_USING_IPSEC, 1); + (((sk) && (sk->sk_policy[0] || sk->sk_policy[1])) && + nla_put_u8(skb, L2TP_ATTR_USING_IPSEC, 1)) || #endif - if (session->reorder_timeout) - NLA_PUT_MSECS(skb, L2TP_ATTR_RECV_TIMEOUT, session->reorder_timeout); - + (session->reorder_timeout && + nla_put_msecs(skb, L2TP_ATTR_RECV_TIMEOUT, session->reorder_timeout))) + goto nla_put_failure; nest = nla_nest_start(skb, L2TP_ATTR_STATS); if (nest == NULL) goto nla_put_failure; - NLA_PUT_U64(skb, L2TP_ATTR_TX_PACKETS, session->stats.tx_packets); - NLA_PUT_U64(skb, L2TP_ATTR_TX_BYTES, session->stats.tx_bytes); - NLA_PUT_U64(skb, L2TP_ATTR_TX_ERRORS, session->stats.tx_errors); - NLA_PUT_U64(skb, L2TP_ATTR_RX_PACKETS, session->stats.rx_packets); - NLA_PUT_U64(skb, L2TP_ATTR_RX_BYTES, session->stats.rx_bytes); - NLA_PUT_U64(skb, L2TP_ATTR_RX_SEQ_DISCARDS, session->stats.rx_seq_discards); - NLA_PUT_U64(skb, L2TP_ATTR_RX_OOS_PACKETS, session->stats.rx_oos_packets); - NLA_PUT_U64(skb, L2TP_ATTR_RX_ERRORS, session->stats.rx_errors); + if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS, session->stats.tx_packets) || + nla_put_u64(skb, L2TP_ATTR_TX_BYTES, session->stats.tx_bytes) || + nla_put_u64(skb, L2TP_ATTR_TX_ERRORS, session->stats.tx_errors) || + nla_put_u64(skb, L2TP_ATTR_RX_PACKETS, session->stats.rx_packets) || + nla_put_u64(skb, L2TP_ATTR_RX_BYTES, session->stats.rx_bytes) || + nla_put_u64(skb, L2TP_ATTR_RX_SEQ_DISCARDS, + session->stats.rx_seq_discards) || + nla_put_u64(skb, L2TP_ATTR_RX_OOS_PACKETS, + session->stats.rx_oos_packets) || + nla_put_u64(skb, L2TP_ATTR_RX_ERRORS, session->stats.rx_errors)) + goto nla_put_failure; nla_nest_end(skb, nest); return genlmsg_end(skb, hdr); diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index b9bef2c..17bc85d 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -518,7 +518,7 @@ static int llc_ui_listen(struct socket *sock, int backlog) if (sock_flag(sk, SOCK_ZAPPED)) goto out; rc = 0; - if (!(unsigned)backlog) /* BSDism */ + if (!(unsigned int)backlog) /* BSDism */ backlog = 1; sk->sk_max_ack_backlog = backlog; if (sk->sk_state != TCP_LISTEN) { diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 96ddb72..8d249d7 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -225,6 +225,17 @@ config MAC80211_VERBOSE_MHWMP_DEBUG Do not select this option. +config MAC80211_VERBOSE_MESH_SYNC_DEBUG + bool "Verbose mesh mesh synchronization debugging" + depends on MAC80211_DEBUG_MENU + depends on MAC80211_MESH + ---help--- + Selecting this option causes mac80211 to print out very verbose mesh + synchronization debugging messages (when mac80211 is taking part in a + mesh network). + + Do not select this option. + config MAC80211_VERBOSE_TDLS_DEBUG bool "Verbose TDLS debugging" depends on MAC80211_DEBUG_MENU diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 1be7a45..3e9d931 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile @@ -38,7 +38,8 @@ mac80211-$(CONFIG_MAC80211_MESH) += \ mesh.o \ mesh_pathtbl.o \ mesh_plink.o \ - mesh_hwmp.o + mesh_hwmp.o \ + mesh_sync.o mac80211-$(CONFIG_PM) += pm.o diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 64d3ce5..a070d4f 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -142,6 +142,18 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) u8 *timer_to_id = ptid - *ptid; struct sta_info *sta = container_of(timer_to_id, struct sta_info, timer_to_tid[0]); + struct tid_ampdu_rx *tid_rx; + unsigned long timeout; + + tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[*ptid]); + if (!tid_rx) + return; + + timeout = tid_rx->last_rx + TU_TO_JIFFIES(tid_rx->timeout); + if (time_is_after_jiffies(timeout)) { + mod_timer(&tid_rx->session_timer, timeout); + return; + } #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); @@ -291,7 +303,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, /* rx timer */ tid_agg_rx->session_timer.function = sta_rx_agg_session_timer_expired; tid_agg_rx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; - init_timer(&tid_agg_rx->session_timer); + init_timer_deferrable(&tid_agg_rx->session_timer); /* rx reorder timer */ tid_agg_rx->reorder_timer.function = sta_rx_agg_reorder_timer_expired; @@ -335,8 +347,10 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, /* activate it for RX */ rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx); - if (timeout) + if (timeout) { mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout)); + tid_agg_rx->last_rx = jiffies; + } end: mutex_unlock(&sta->ampdu_mlme.mtx); diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 76be6174..5b7053c 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -286,25 +286,25 @@ static inline int ieee80211_ac_from_tid(int tid) * a global "agg_queue_stop" refcount. */ static void __acquires(agg_queue) -ieee80211_stop_queue_agg(struct ieee80211_local *local, int tid) +ieee80211_stop_queue_agg(struct ieee80211_sub_if_data *sdata, int tid) { - int queue = ieee80211_ac_from_tid(tid); + int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)]; - if (atomic_inc_return(&local->agg_queue_stop[queue]) == 1) + if (atomic_inc_return(&sdata->local->agg_queue_stop[queue]) == 1) ieee80211_stop_queue_by_reason( - &local->hw, queue, + &sdata->local->hw, queue, IEEE80211_QUEUE_STOP_REASON_AGGREGATION); __acquire(agg_queue); } static void __releases(agg_queue) -ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid) +ieee80211_wake_queue_agg(struct ieee80211_sub_if_data *sdata, int tid) { - int queue = ieee80211_ac_from_tid(tid); + int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)]; - if (atomic_dec_return(&local->agg_queue_stop[queue]) == 0) + if (atomic_dec_return(&sdata->local->agg_queue_stop[queue]) == 0) ieee80211_wake_queue_by_reason( - &local->hw, queue, + &sdata->local->hw, queue, IEEE80211_QUEUE_STOP_REASON_AGGREGATION); __release(agg_queue); } @@ -314,13 +314,14 @@ ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid) * requires a call to ieee80211_agg_splice_finish later */ static void __acquires(agg_queue) -ieee80211_agg_splice_packets(struct ieee80211_local *local, +ieee80211_agg_splice_packets(struct ieee80211_sub_if_data *sdata, struct tid_ampdu_tx *tid_tx, u16 tid) { - int queue = ieee80211_ac_from_tid(tid); + struct ieee80211_local *local = sdata->local; + int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)]; unsigned long flags; - ieee80211_stop_queue_agg(local, tid); + ieee80211_stop_queue_agg(sdata, tid); if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates" " from the pending queue\n", tid)) @@ -336,9 +337,9 @@ ieee80211_agg_splice_packets(struct ieee80211_local *local, } static void __releases(agg_queue) -ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) +ieee80211_agg_splice_finish(struct ieee80211_sub_if_data *sdata, u16 tid) { - ieee80211_wake_queue_agg(local, tid); + ieee80211_wake_queue_agg(sdata, tid); } void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) @@ -376,9 +377,9 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) " tid %d\n", tid); #endif spin_lock_bh(&sta->lock); - ieee80211_agg_splice_packets(local, tid_tx, tid); + ieee80211_agg_splice_packets(sdata, tid_tx, tid); ieee80211_assign_tid_tx(sta, tid, NULL); - ieee80211_agg_splice_finish(local, tid); + ieee80211_agg_splice_finish(sdata, tid); spin_unlock_bh(&sta->lock); kfree_rcu(tid_tx, rcu_head); @@ -417,6 +418,18 @@ static void sta_tx_agg_session_timer_expired(unsigned long data) u8 *timer_to_id = ptid - *ptid; struct sta_info *sta = container_of(timer_to_id, struct sta_info, timer_to_tid[0]); + struct tid_ampdu_tx *tid_tx; + unsigned long timeout; + + tid_tx = rcu_dereference_protected_tid_tx(sta, *ptid); + if (!tid_tx) + return; + + timeout = tid_tx->last_tx + TU_TO_JIFFIES(tid_tx->timeout); + if (time_is_after_jiffies(timeout)) { + mod_timer(&tid_tx->session_timer, timeout); + return; + } #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "tx session timer expired on tid %d\n", (u16)*ptid); @@ -542,7 +555,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, /* tx timer */ tid_tx->session_timer.function = sta_tx_agg_session_timer_expired; tid_tx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; - init_timer(&tid_tx->session_timer); + init_timer_deferrable(&tid_tx->session_timer); /* assign a dialog token */ sta->ampdu_mlme.dialog_token_allocator++; @@ -586,14 +599,14 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, */ spin_lock_bh(&sta->lock); - ieee80211_agg_splice_packets(local, tid_tx, tid); + ieee80211_agg_splice_packets(sta->sdata, tid_tx, tid); /* * Now mark as operational. This will be visible * in the TX path, and lets it go lock-free in * the common case. */ set_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); - ieee80211_agg_splice_finish(local, tid); + ieee80211_agg_splice_finish(sta->sdata, tid); spin_unlock_bh(&sta->lock); } @@ -778,12 +791,12 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) * more. */ - ieee80211_agg_splice_packets(local, tid_tx, tid); + ieee80211_agg_splice_packets(sta->sdata, tid_tx, tid); /* future packets must not find the tid_tx struct any more */ ieee80211_assign_tid_tx(sta, tid, NULL); - ieee80211_agg_splice_finish(local, tid); + ieee80211_agg_splice_finish(sta->sdata, tid); kfree_rcu(tid_tx, rcu_head); @@ -884,9 +897,11 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, sta->ampdu_mlme.addba_req_num[tid] = 0; - if (tid_tx->timeout) + if (tid_tx->timeout) { mod_timer(&tid_tx->session_timer, TU_TO_EXP_TIME(tid_tx->timeout)); + tid_tx->last_tx = jiffies; + } } else { ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR, diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 677d659..3557354 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -412,6 +412,10 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) sinfo->llid = le16_to_cpu(sta->llid); sinfo->plid = le16_to_cpu(sta->plid); sinfo->plink_state = sta->plink_state; + if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { + sinfo->filled |= STATION_INFO_T_OFFSET; + sinfo->t_offset = sta->t_offset; + } #endif } @@ -640,6 +644,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, ieee80211_bss_info_change_notify(sdata, changed); + netif_carrier_on(dev); + list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) + netif_carrier_on(vlan->dev); + return 0; } @@ -665,7 +673,7 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata, *vlan; struct beacon_data *old; sdata = IEEE80211_DEV_TO_SUB_IF(dev); @@ -674,6 +682,10 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) if (!old) return -ENOENT; + list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) + netif_carrier_off(vlan->dev); + netif_carrier_off(dev); + RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); kfree_rcu(old, rcu_head); @@ -1235,6 +1247,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, /* now copy the rest of the setup parameters */ ifmsh->mesh_id_len = setup->mesh_id_len; memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); + ifmsh->mesh_sp_id = setup->sync_method; ifmsh->mesh_pp_id = setup->path_sel_proto; ifmsh->mesh_pm_id = setup->path_metric; ifmsh->security = IEEE80211_MESH_SEC_NONE; @@ -1279,6 +1292,9 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, conf->dot11MeshTTL = nconf->element_ttl; if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) conf->auto_open_plinks = nconf->auto_open_plinks; + if (_chg_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask)) + conf->dot11MeshNbrOffsetMaxNeighbor = + nconf->dot11MeshNbrOffsetMaxNeighbor; if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask)) conf->dot11MeshHWMPmaxPREQretries = nconf->dot11MeshHWMPmaxPREQretries; @@ -1437,6 +1453,9 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, if (!local->ops->conf_tx) return -EOPNOTSUPP; + if (local->hw.queues < IEEE80211_NUM_ACS) + return -EOPNOTSUPP; + memset(&p, 0, sizeof(p)); p.aifs = params->aifs; p.cw_max = params->cwmax; @@ -1449,14 +1468,11 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, */ p.uapsd = false; - if (params->queue >= local->hw.queues) - return -EINVAL; - - sdata->tx_conf[params->queue] = p; - if (drv_conf_tx(local, sdata, params->queue, &p)) { + sdata->tx_conf[params->ac] = p; + if (drv_conf_tx(local, sdata, params->ac, &p)) { wiphy_debug(local->hw.wiphy, - "failed to set TX queue parameters for queue %d\n", - params->queue); + "failed to set TX queue parameters for AC %d\n", + params->ac); return -EINVAL; } @@ -2090,6 +2106,10 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, IEEE80211_SKB_CB(skb)->flags = flags; + if (flags & IEEE80211_TX_CTL_TX_OFFCHAN) + IEEE80211_SKB_CB(skb)->hw_queue = + local->hw.offchannel_tx_hw_queue; + skb->dev = sdata->dev; *cookie = (unsigned long) skb; @@ -2131,6 +2151,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, /* modify cookie to prevent API mismatches */ *cookie ^= 2; IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN; + IEEE80211_SKB_CB(skb)->hw_queue = + local->hw.offchannel_tx_hw_queue; local->hw_roc_skb = skb; local->hw_roc_skb_for_status = skb; mutex_unlock(&local->mtx); @@ -2350,8 +2372,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, tf->u.setup_req.capability = cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); - ieee80211_add_srates_ie(&sdata->vif, skb); - ieee80211_add_ext_srates_ie(&sdata->vif, skb); + ieee80211_add_srates_ie(&sdata->vif, skb, false); + ieee80211_add_ext_srates_ie(&sdata->vif, skb, false); ieee80211_tdls_add_ext_capab(skb); break; case WLAN_TDLS_SETUP_RESPONSE: @@ -2364,8 +2386,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, tf->u.setup_resp.capability = cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); - ieee80211_add_srates_ie(&sdata->vif, skb); - ieee80211_add_ext_srates_ie(&sdata->vif, skb); + ieee80211_add_srates_ie(&sdata->vif, skb, false); + ieee80211_add_ext_srates_ie(&sdata->vif, skb, false); ieee80211_tdls_add_ext_capab(skb); break; case WLAN_TDLS_SETUP_CONFIRM: @@ -2425,8 +2447,8 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, mgmt->u.action.u.tdls_discover_resp.capability = cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); - ieee80211_add_srates_ie(&sdata->vif, skb); - ieee80211_add_ext_srates_ie(&sdata->vif, skb); + ieee80211_add_srates_ie(&sdata->vif, skb, false); + ieee80211_add_ext_srates_ie(&sdata->vif, skb, false); ieee80211_tdls_add_ext_capab(skb); break; default: @@ -2673,6 +2695,13 @@ ieee80211_wiphy_get_channel(struct wiphy *wiphy) return local->oper_channel; } +#ifdef CONFIG_PM +static void ieee80211_set_wakeup(struct wiphy *wiphy, bool enabled) +{ + drv_set_wakeup(wiphy_priv(wiphy), enabled); +} +#endif + struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, .del_virtual_intf = ieee80211_del_iface, @@ -2741,4 +2770,7 @@ struct cfg80211_ops mac80211_config_ops = { .probe_client = ieee80211_probe_client, .get_channel = ieee80211_wiphy_get_channel, .set_noack_map = ieee80211_set_noack_map, +#ifdef CONFIG_PM + .set_wakeup = ieee80211_set_wakeup, +#endif }; diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index e00ce8c..c76cf72 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -135,29 +135,3 @@ bool ieee80211_set_channel_type(struct ieee80211_local *local, return result; } - -/* - * ieee80211_get_tx_channel_type returns the channel type we should - * use for packet transmission, given the channel capability and - * whatever regulatory flags we have been given. - */ -enum nl80211_channel_type ieee80211_get_tx_channel_type( - struct ieee80211_local *local, - enum nl80211_channel_type channel_type) -{ - switch (channel_type) { - case NL80211_CHAN_HT40PLUS: - if (local->hw.conf.channel->flags & - IEEE80211_CHAN_NO_HT40PLUS) - return NL80211_CHAN_HT20; - break; - case NL80211_CHAN_HT40MINUS: - if (local->hw.conf.channel->flags & - IEEE80211_CHAN_NO_HT40MINUS) - return NL80211_CHAN_HT20; - break; - default: - break; - } - return channel_type; -} diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 30f99c3..e7af5227 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -424,6 +424,7 @@ static ssize_t ieee80211_if_parse_tsf( struct ieee80211_local *local = sdata->local; unsigned long long tsf; int ret; + int tsf_is_delta = 0; if (strncmp(buf, "reset", 5) == 0) { if (local->ops->reset_tsf) { @@ -431,9 +432,20 @@ static ssize_t ieee80211_if_parse_tsf( wiphy_info(local->hw.wiphy, "debugfs reset TSF\n"); } } else { + if (buflen > 10 && buf[1] == '=') { + if (buf[0] == '+') + tsf_is_delta = 1; + else if (buf[0] == '-') + tsf_is_delta = -1; + else + return -EINVAL; + buf += 2; + } ret = kstrtoull(buf, 10, &tsf); if (ret < 0) return -EINVAL; + if (tsf_is_delta) + tsf = drv_get_tsf(local, sdata) + tsf_is_delta * tsf; if (local->ops->set_tsf) { drv_set_tsf(local, sdata, tsf); wiphy_info(local->hw.wiphy, @@ -499,26 +511,23 @@ IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC); IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC); #endif - -#define DEBUGFS_ADD(name) \ - debugfs_create_file(#name, 0400, sdata->debugfs.dir, \ - sdata, &name##_ops); - #define DEBUGFS_ADD_MODE(name, mode) \ debugfs_create_file(#name, mode, sdata->debugfs.dir, \ sdata, &name##_ops); -static void add_sta_files(struct ieee80211_sub_if_data *sdata) +#define DEBUGFS_ADD(name) DEBUGFS_ADD_MODE(name, 0400) + +static void add_common_files(struct ieee80211_sub_if_data *sdata) { DEBUGFS_ADD(drop_unencrypted); - DEBUGFS_ADD(flags); - DEBUGFS_ADD(state); - DEBUGFS_ADD(channel_type); DEBUGFS_ADD(rc_rateidx_mask_2ghz); DEBUGFS_ADD(rc_rateidx_mask_5ghz); DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); +} +static void add_sta_files(struct ieee80211_sub_if_data *sdata) +{ DEBUGFS_ADD(bssid); DEBUGFS_ADD(aid); DEBUGFS_ADD(last_beacon); @@ -531,15 +540,6 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) static void add_ap_files(struct ieee80211_sub_if_data *sdata) { - DEBUGFS_ADD(drop_unencrypted); - DEBUGFS_ADD(flags); - DEBUGFS_ADD(state); - DEBUGFS_ADD(channel_type); - DEBUGFS_ADD(rc_rateidx_mask_2ghz); - DEBUGFS_ADD(rc_rateidx_mask_5ghz); - DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); - DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); - DEBUGFS_ADD(num_sta_authorized); DEBUGFS_ADD(num_sta_ps); DEBUGFS_ADD(dtim_count); @@ -549,48 +549,14 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) static void add_ibss_files(struct ieee80211_sub_if_data *sdata) { - DEBUGFS_ADD(channel_type); - DEBUGFS_ADD(rc_rateidx_mask_2ghz); - DEBUGFS_ADD(rc_rateidx_mask_5ghz); - DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); - DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); - DEBUGFS_ADD_MODE(tsf, 0600); } static void add_wds_files(struct ieee80211_sub_if_data *sdata) { - DEBUGFS_ADD(drop_unencrypted); - DEBUGFS_ADD(flags); - DEBUGFS_ADD(state); - DEBUGFS_ADD(channel_type); - DEBUGFS_ADD(rc_rateidx_mask_2ghz); - DEBUGFS_ADD(rc_rateidx_mask_5ghz); - DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); - DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); - DEBUGFS_ADD(peer); } -static void add_vlan_files(struct ieee80211_sub_if_data *sdata) -{ - DEBUGFS_ADD(drop_unencrypted); - DEBUGFS_ADD(flags); - DEBUGFS_ADD(state); - DEBUGFS_ADD(channel_type); - DEBUGFS_ADD(rc_rateidx_mask_2ghz); - DEBUGFS_ADD(rc_rateidx_mask_5ghz); - DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); - DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); -} - -static void add_monitor_files(struct ieee80211_sub_if_data *sdata) -{ - DEBUGFS_ADD(flags); - DEBUGFS_ADD(state); - DEBUGFS_ADD(channel_type); -} - #ifdef CONFIG_MAC80211_MESH static void add_mesh_files(struct ieee80211_sub_if_data *sdata) @@ -651,6 +617,13 @@ static void add_files(struct ieee80211_sub_if_data *sdata) if (!sdata->debugfs.dir) return; + DEBUGFS_ADD(flags); + DEBUGFS_ADD(state); + DEBUGFS_ADD(channel_type); + + if (sdata->vif.type != NL80211_IFTYPE_MONITOR) + add_common_files(sdata); + switch (sdata->vif.type) { case NL80211_IFTYPE_MESH_POINT: #ifdef CONFIG_MAC80211_MESH @@ -671,12 +644,6 @@ static void add_files(struct ieee80211_sub_if_data *sdata) case NL80211_IFTYPE_WDS: add_wds_files(sdata); break; - case NL80211_IFTYPE_MONITOR: - add_monitor_files(sdata); - break; - case NL80211_IFTYPE_AP_VLAN: - add_vlan_files(sdata); - break; default: break; } diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 832b2da..5ccec2c 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -63,7 +63,7 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" int res = scnprintf(buf, sizeof(buf), - "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", TEST(AUTH), TEST(ASSOC), TEST(PS_STA), TEST(PS_DRIVER), TEST(AUTHORIZED), TEST(SHORT_PREAMBLE), @@ -71,7 +71,8 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT), - TEST(INSERTED), TEST(RATE_CONTROL)); + TEST(INSERTED), TEST(RATE_CONTROL), + TEST(TOFFSET_KNOWN)); #undef TEST return simple_read_from_buffer(userbuf, count, ppos, buf, res); } diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index af4691f..4a0e559 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -7,7 +7,9 @@ static inline void check_sdata_in_driver(struct ieee80211_sub_if_data *sdata) { - WARN_ON(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER)); + WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER), + "%s: Failed check-sdata-in-driver check, flags: 0x%x\n", + sdata->dev->name, sdata->flags); } static inline struct ieee80211_sub_if_data * @@ -89,6 +91,19 @@ static inline int drv_resume(struct ieee80211_local *local) trace_drv_return_int(local, ret); return ret; } + +static inline void drv_set_wakeup(struct ieee80211_local *local, + bool enabled) +{ + might_sleep(); + + if (!local->ops->set_wakeup) + return; + + trace_drv_set_wakeup(local, enabled); + local->ops->set_wakeup(&local->hw, enabled); + trace_drv_return_void(local); +} #endif static inline int drv_add_interface(struct ieee80211_local *local, @@ -99,7 +114,8 @@ static inline int drv_add_interface(struct ieee80211_local *local, might_sleep(); if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN || - sdata->vif.type == NL80211_IFTYPE_MONITOR)) + (sdata->vif.type == NL80211_IFTYPE_MONITOR && + !(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)))) return -EINVAL; trace_drv_add_interface(local, sdata); @@ -474,8 +490,23 @@ int drv_sta_state(struct ieee80211_local *local, return ret; } +static inline void drv_sta_rc_update(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta *sta, u32 changed) +{ + sdata = get_bss_sdata(sdata); + check_sdata_in_driver(sdata); + + trace_drv_sta_rc_update(local, sdata, sta, changed); + if (local->ops->sta_rc_update) + local->ops->sta_rc_update(&local->hw, &sdata->vif, + sta, changed); + + trace_drv_return_void(local); +} + static inline int drv_conf_tx(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, u16 queue, + struct ieee80211_sub_if_data *sdata, u16 ac, const struct ieee80211_tx_queue_params *params) { int ret = -EOPNOTSUPP; @@ -484,10 +515,10 @@ static inline int drv_conf_tx(struct ieee80211_local *local, check_sdata_in_driver(sdata); - trace_drv_conf_tx(local, sdata, queue, params); + trace_drv_conf_tx(local, sdata, ac, params); if (local->ops->conf_tx) ret = local->ops->conf_tx(&local->hw, &sdata->vif, - queue, params); + ac, params); trace_drv_return_int(local, ret); return ret; } diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 21d6f52..7c0754b 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -171,6 +171,20 @@ DEFINE_EVENT(local_only_evt, drv_resume, TP_ARGS(local) ); +TRACE_EVENT(drv_set_wakeup, + TP_PROTO(struct ieee80211_local *local, bool enabled), + TP_ARGS(local, enabled), + TP_STRUCT__entry( + LOCAL_ENTRY + __field(bool, enabled) + ), + TP_fast_assign( + LOCAL_ASSIGN; + __entry->enabled = enabled; + ), + TP_printk(LOCAL_PR_FMT " enabled:%d", LOCAL_PR_ARG, __entry->enabled) +); + DEFINE_EVENT(local_only_evt, drv_stop, TP_PROTO(struct ieee80211_local *local), TP_ARGS(local) @@ -624,6 +638,34 @@ TRACE_EVENT(drv_sta_state, ) ); +TRACE_EVENT(drv_sta_rc_update, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta *sta, + u32 changed), + + TP_ARGS(local, sdata, sta, changed), + + TP_STRUCT__entry( + LOCAL_ENTRY + VIF_ENTRY + STA_ENTRY + __field(u32, changed) + ), + + TP_fast_assign( + LOCAL_ASSIGN; + VIF_ASSIGN; + STA_ASSIGN; + __entry->changed = changed; + ), + + TP_printk( + LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " changed: 0x%x", + LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->changed + ) +); + TRACE_EVENT(drv_sta_add, TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, @@ -677,15 +719,14 @@ TRACE_EVENT(drv_sta_remove, TRACE_EVENT(drv_conf_tx, TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, - u16 queue, - const struct ieee80211_tx_queue_params *params), + u16 ac, const struct ieee80211_tx_queue_params *params), - TP_ARGS(local, sdata, queue, params), + TP_ARGS(local, sdata, ac, params), TP_STRUCT__entry( LOCAL_ENTRY VIF_ENTRY - __field(u16, queue) + __field(u16, ac) __field(u16, txop) __field(u16, cw_min) __field(u16, cw_max) @@ -696,7 +737,7 @@ TRACE_EVENT(drv_conf_tx, TP_fast_assign( LOCAL_ASSIGN; VIF_ASSIGN; - __entry->queue = queue; + __entry->ac = ac; __entry->txop = params->txop; __entry->cw_max = params->cw_max; __entry->cw_min = params->cw_min; @@ -705,8 +746,8 @@ TRACE_EVENT(drv_conf_tx, ), TP_printk( - LOCAL_PR_FMT VIF_PR_FMT " queue:%d", - LOCAL_PR_ARG, VIF_PR_ARG, __entry->queue + LOCAL_PR_FMT VIF_PR_FMT " AC:%d", + LOCAL_PR_ARG, VIF_PR_ARG, __entry->ac ) ); diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index f25fff7..9b60336 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -19,15 +19,6 @@ #include "ieee80211_i.h" #include "rate.h" -bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata) -{ - const __le16 flg = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40); - if ((sdata->u.mgd.ht_capa_mask.cap_info & flg) && - !(sdata->u.mgd.ht_capa.cap_info & flg)) - return true; - return false; -} - static void __check_htcap_disable(struct ieee80211_sub_if_data *sdata, struct ieee80211_sta_ht_cap *ht_cap, u16 flag) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 33fd8d9..49a2079 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -160,16 +160,14 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, if (channel_type && sband->ht_cap.ht_supported) { pos = skb_put(skb, 4 + sizeof(struct ieee80211_ht_cap) + - sizeof(struct ieee80211_ht_info)); + sizeof(struct ieee80211_ht_operation)); pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, sband->ht_cap.cap); - pos = ieee80211_ie_build_ht_info(pos, - &sband->ht_cap, - chan, - channel_type); + pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap, + chan, channel_type); } - if (local->hw.queues >= 4) { + if (local->hw.queues >= IEEE80211_NUM_ACS) { pos = skb_put(skb, 9); *pos++ = WLAN_EID_VENDOR_SPECIFIC; *pos++ = 7; /* len */ @@ -410,7 +408,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, if (elems->supp_rates) { supp_rates = ieee80211_sta_get_rates(local, elems, - band); + band, NULL); if (sta) { u32 prev_rates; @@ -441,13 +439,13 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, if (sta && elems->wmm_info) set_sta_flag(sta, WLAN_STA_WME); - if (sta && elems->ht_info_elem && elems->ht_cap_elem && + if (sta && elems->ht_operation && elems->ht_cap_elem && sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) { /* we both use HT */ struct ieee80211_sta_ht_cap sta_ht_cap_new; enum nl80211_channel_type channel_type = - ieee80211_ht_info_to_channel_type( - elems->ht_info_elem); + ieee80211_ht_oper_to_channel_type( + elems->ht_operation); ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, elems->ht_cap_elem, @@ -560,7 +558,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, sdata->name, mgmt->bssid); #endif ieee80211_sta_join_ibss(sdata, bss); - supp_rates = ieee80211_sta_get_rates(local, elems, band); + supp_rates = ieee80211_sta_get_rates(local, elems, band, NULL); ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates, true); rcu_read_unlock(); @@ -1063,7 +1061,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, 4 /* IBSS params */ + 2 + (IEEE80211_MAX_SUPP_RATES - 8) + 2 + sizeof(struct ieee80211_ht_cap) + - 2 + sizeof(struct ieee80211_ht_info) + + 2 + sizeof(struct ieee80211_ht_operation) + params->ie_len); if (!skb) return -ENOMEM; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index d9798a3..4be11ea 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -52,7 +52,8 @@ struct ieee80211_local; * increased memory use (about 2 kB of RAM per entry). */ #define IEEE80211_FRAGMENT_MAX 4 -#define TU_TO_EXP_TIME(x) (jiffies + usecs_to_jiffies((x) * 1024)) +#define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024)) +#define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x)) #define IEEE80211_DEFAULT_UAPSD_QUEUES \ (IEEE80211_WMM_IE_STA_QOSINFO_AC_BK | \ @@ -378,6 +379,7 @@ enum ieee80211_sta_flags { IEEE80211_STA_UAPSD_ENABLED = BIT(7), IEEE80211_STA_NULLFUNC_ACKED = BIT(8), IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), + IEEE80211_STA_DISABLE_40MHZ = BIT(10), }; struct ieee80211_mgd_auth_data { @@ -397,7 +399,7 @@ struct ieee80211_mgd_auth_data { struct ieee80211_mgd_assoc_data { struct cfg80211_bss *bss; const u8 *supp_rates; - const u8 *ht_information_ie; + const u8 *ht_operation_ie; unsigned long timeout; int tries; @@ -552,6 +554,24 @@ struct ieee80211_if_ibss { } state; }; +/** + * struct ieee80211_mesh_sync_ops - Extensible synchronization framework interface + * + * these declarations define the interface, which enables + * vendor-specific mesh synchronization + * + */ +struct ieee802_11_elems; +struct ieee80211_mesh_sync_ops { + void (*rx_bcn_presp)(struct ieee80211_sub_if_data *sdata, + u16 stype, + struct ieee80211_mgmt *mgmt, + struct ieee802_11_elems *elems, + struct ieee80211_rx_status *rx_status); + void (*adjust_tbtt)(struct ieee80211_sub_if_data *sdata); + /* add other framework functions here */ +}; + struct ieee80211_if_mesh { struct timer_list housekeeping_timer; struct timer_list mesh_path_timer; @@ -600,6 +620,11 @@ struct ieee80211_if_mesh { IEEE80211_MESH_SEC_AUTHED = 0x1, IEEE80211_MESH_SEC_SECURED = 0x2, } security; + /* Extensible Synchronization Framework */ + struct ieee80211_mesh_sync_ops *sync_ops; + s64 sync_offset_clockdrift_max; + spinlock_t sync_offset_lock; + bool adjusting_tbtt; }; #ifdef CONFIG_MAC80211_MESH @@ -666,12 +691,6 @@ struct ieee80211_sub_if_data { char name[IFNAMSIZ]; - /* - * keep track of whether the HT opmode (stored in - * vif.bss_info.ht_operation_mode) is valid. - */ - bool ht_opmode_valid; - /* to detect idle changes */ bool old_idle; @@ -691,7 +710,7 @@ struct ieee80211_sub_if_data { __be16 control_port_protocol; bool control_port_no_encrypt; - struct ieee80211_tx_queue_params tx_conf[IEEE80211_MAX_QUEUES]; + struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS]; struct work_struct work; struct sk_buff_head skb_queue; @@ -761,7 +780,6 @@ enum queue_stop_reason { IEEE80211_QUEUE_STOP_REASON_AGGREGATION, IEEE80211_QUEUE_STOP_REASON_SUSPEND, IEEE80211_QUEUE_STOP_REASON_SKB_ADD, - IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE, }; #ifdef CONFIG_MAC80211_LEDS @@ -1082,6 +1100,9 @@ struct ieee80211_local { struct net_device napi_dev; struct napi_struct napi; + + /* virtual monitor interface */ + struct ieee80211_sub_if_data __rcu *monitor_sdata; }; static inline struct ieee80211_sub_if_data * @@ -1117,7 +1138,7 @@ struct ieee802_11_elems { u8 *wmm_info; u8 *wmm_param; struct ieee80211_ht_cap *ht_cap_elem; - struct ieee80211_ht_info *ht_info_elem; + struct ieee80211_ht_operation *ht_operation; struct ieee80211_meshconf_ie *mesh_config; u8 *mesh_id; u8 *peering; @@ -1299,7 +1320,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); /* HT */ -bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata); void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, struct ieee80211_sta_ht_cap *ht_cap); void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, @@ -1429,13 +1449,17 @@ void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, enum queue_stop_reason reason); void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, enum queue_stop_reason reason); +void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue); void ieee80211_add_pending_skb(struct ieee80211_local *local, struct sk_buff *skb); -void ieee80211_add_pending_skbs(struct ieee80211_local *local, - struct sk_buff_head *skbs); void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, struct sk_buff_head *skbs, void (*fn)(void *data), void *data); +static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local, + struct sk_buff_head *skbs) +{ + ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); +} void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, u16 transaction, u16 auth_alg, @@ -1460,7 +1484,7 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, const u8 *supp_rates); u32 ieee80211_sta_get_rates(struct ieee80211_local *local, struct ieee802_11_elems *elems, - enum ieee80211_band band); + enum ieee80211_band band, u32 *basic_rates); int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, enum ieee80211_smps_mode smps_mode); void ieee80211_recalc_smps(struct ieee80211_local *local); @@ -1470,10 +1494,9 @@ size_t ieee80211_ie_split(const u8 *ies, size_t ielen, size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset); u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, u16 cap); -u8 *ieee80211_ie_build_ht_info(u8 *pos, - struct ieee80211_sta_ht_cap *ht_cap, - struct ieee80211_channel *channel, - enum nl80211_channel_type channel_type); +u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, + struct ieee80211_channel *channel, + enum nl80211_channel_type channel_type); /* internal work items */ void ieee80211_work_init(struct ieee80211_local *local); @@ -1501,10 +1524,7 @@ bool ieee80211_set_channel_type(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, enum nl80211_channel_type chantype); enum nl80211_channel_type -ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info); -enum nl80211_channel_type ieee80211_get_tx_channel_type( - struct ieee80211_local *local, - enum nl80211_channel_type channel_type); +ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper); #ifdef CONFIG_MAC80211_NOINLINE #define debug_noinline noinline diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 401c01f..6e85fae 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -149,6 +149,34 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata, return 0; } +static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata) +{ + int n_queues = sdata->local->hw.queues; + int i; + + for (i = 0; i < IEEE80211_NUM_ACS; i++) { + if (WARN_ON_ONCE(sdata->vif.hw_queue[i] == + IEEE80211_INVAL_HW_QUEUE)) + return -EINVAL; + if (WARN_ON_ONCE(sdata->vif.hw_queue[i] >= + n_queues)) + return -EINVAL; + } + + if (sdata->vif.type != NL80211_IFTYPE_AP) { + sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; + return 0; + } + + if (WARN_ON_ONCE(sdata->vif.cab_queue == IEEE80211_INVAL_HW_QUEUE)) + return -EINVAL; + + if (WARN_ON_ONCE(sdata->vif.cab_queue >= n_queues)) + return -EINVAL; + + return 0; +} + void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, const int offset) { @@ -169,6 +197,81 @@ void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, #undef ADJUST } +static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + int i; + + for (i = 0; i < IEEE80211_NUM_ACS; i++) { + if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) + sdata->vif.hw_queue[i] = IEEE80211_INVAL_HW_QUEUE; + else + sdata->vif.hw_queue[i] = i; + } + sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; +} + +static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) +{ + struct ieee80211_sub_if_data *sdata; + int ret; + + if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) + return 0; + + if (local->monitor_sdata) + return 0; + + sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); + if (!sdata) + return -ENOMEM; + + /* set up data */ + sdata->local = local; + sdata->vif.type = NL80211_IFTYPE_MONITOR; + snprintf(sdata->name, IFNAMSIZ, "%s-monitor", + wiphy_name(local->hw.wiphy)); + + ieee80211_set_default_queues(sdata); + + ret = drv_add_interface(local, sdata); + if (WARN_ON(ret)) { + /* ok .. stupid driver, it asked for this! */ + kfree(sdata); + return ret; + } + + ret = ieee80211_check_queues(sdata); + if (ret) { + kfree(sdata); + return ret; + } + + rcu_assign_pointer(local->monitor_sdata, sdata); + + return 0; +} + +static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) +{ + struct ieee80211_sub_if_data *sdata; + + if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) + return; + + sdata = rtnl_dereference(local->monitor_sdata); + + if (!sdata) + return; + + rcu_assign_pointer(local->monitor_sdata, NULL); + synchronize_net(); + + drv_remove_interface(local, sdata); + + kfree(sdata); +} + /* * NOTE: Be very careful when changing this function, it must NOT return * an error on interface type changes that have been pre-checked, so most @@ -246,15 +349,18 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN); if (!is_valid_ether_addr(dev->dev_addr)) { - if (!local->open_count) - drv_stop(local); - return -EADDRNOTAVAIL; + res = -EADDRNOTAVAIL; + goto err_stop; } } switch (sdata->vif.type) { case NL80211_IFTYPE_AP_VLAN: - /* no need to tell driver */ + /* no need to tell driver, but set carrier */ + if (rtnl_dereference(sdata->bss->beacon)) + netif_carrier_on(dev); + else + netif_carrier_off(dev); break; case NL80211_IFTYPE_MONITOR: if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { @@ -262,6 +368,12 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) break; } + if (local->monitors == 0 && local->open_count == 0) { + res = ieee80211_add_virtual_monitor(local); + if (res) + goto err_stop; + } + /* must be before the call to ieee80211_configure_filter */ local->monitors++; if (local->monitors == 1) { @@ -276,9 +388,14 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) break; default: if (coming_up) { + ieee80211_del_virtual_monitor(local); + res = drv_add_interface(local, sdata); if (res) goto err_stop; + res = ieee80211_check_queues(sdata); + if (res) + goto err_del_interface; } if (sdata->vif.type == NL80211_IFTYPE_AP) { @@ -294,7 +411,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) ieee80211_bss_info_change_notify(sdata, changed); if (sdata->vif.type == NL80211_IFTYPE_STATION || - sdata->vif.type == NL80211_IFTYPE_ADHOC) + sdata->vif.type == NL80211_IFTYPE_ADHOC || + sdata->vif.type == NL80211_IFTYPE_AP) netif_carrier_off(dev); else netif_carrier_on(dev); @@ -366,6 +484,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) sdata->bss = NULL; if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) list_del(&sdata->u.vlan.list); + /* might already be clear but that doesn't matter */ clear_bit(SDATA_STATE_RUNNING, &sdata->state); return res; } @@ -506,6 +625,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, if (local->monitors == 0) { local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; + ieee80211_del_virtual_monitor(local); } ieee80211_adjust_monitor_flags(sdata, -1); @@ -579,6 +699,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, } } spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); + + if (local->monitors == local->open_count && local->monitors > 0) + ieee80211_add_virtual_monitor(local); } static int ieee80211_stop(struct net_device *dev) @@ -676,7 +799,7 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev, struct ieee80211_hdr *hdr; struct ieee80211_radiotap_header *rtap = (void *)skb->data; - if (local->hw.queues < 4) + if (local->hw.queues < IEEE80211_NUM_ACS) return 0; if (skb->len < 4 || @@ -970,6 +1093,13 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, if (ret) type = sdata->vif.type; + /* + * Ignore return value here, there's not much we can do since + * the driver changed the interface type internally already. + * The warnings will hopefully make driver authors fix it :-) + */ + ieee80211_check_queues(sdata); + ieee80211_setup_sdata(sdata, type); err = ieee80211_do_open(sdata->dev, false); @@ -1133,11 +1263,15 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, struct net_device *ndev; struct ieee80211_sub_if_data *sdata = NULL; int ret, i; + int txqs = 1; ASSERT_RTNL(); + if (local->hw.queues >= IEEE80211_NUM_ACS) + txqs = IEEE80211_NUM_ACS; + ndev = alloc_netdev_mqs(sizeof(*sdata) + local->hw.vif_data_size, - name, ieee80211_if_setup, local->hw.queues, 1); + name, ieee80211_if_setup, txqs, 1); if (!ndev) return -ENOMEM; dev_net_set(ndev, wiphy_net(local->hw.wiphy)); @@ -1192,6 +1326,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, sizeof(sdata->rc_rateidx_mcs_mask[i])); } + ieee80211_set_default_queues(sdata); + /* setup type-dependent data */ ieee80211_setup_sdata(sdata, type); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 1633648..ac79d5e 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -557,8 +557,10 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, WIPHY_FLAG_4ADDR_AP | WIPHY_FLAG_4ADDR_STATION | WIPHY_FLAG_REPORTS_OBSS | - WIPHY_FLAG_OFFCHAN_TX | - WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; + WIPHY_FLAG_OFFCHAN_TX; + + if (ops->remain_on_channel) + wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; wiphy->features = NL80211_FEATURE_SK_TX_STATUS | NL80211_FEATURE_HT_IBSS; @@ -589,6 +591,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, local->hw.max_report_rates = 0; local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; local->hw.max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; + local->hw.offchannel_tx_hw_queue = IEEE80211_INVAL_HW_QUEUE; local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; local->user_power_level = -1; @@ -685,6 +688,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) WLAN_CIPHER_SUITE_AES_CMAC }; + if (hw->flags & IEEE80211_HW_QUEUE_CONTROL && + (local->hw.offchannel_tx_hw_queue == IEEE80211_INVAL_HW_QUEUE || + local->hw.offchannel_tx_hw_queue >= local->hw.queues)) + return -EINVAL; + if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns) #ifdef CONFIG_PM && (!local->ops->suspend || !local->ops->resume) diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index e5fbb7c..133c1185 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -13,9 +13,6 @@ #include "ieee80211_i.h" #include "mesh.h" -#define MESHCONF_CAPAB_ACCEPT_PLINKS 0x01 -#define MESHCONF_CAPAB_FORWARDING 0x08 - #define TMR_RUNNING_HK 0 #define TMR_RUNNING_MP 1 #define TMR_RUNNING_MPR 2 @@ -69,11 +66,13 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data) * * @ie: information elements of a management frame from the mesh peer * @sdata: local mesh subif + * @basic_rates: BSSBasicRateSet of the peer candidate * * This function checks if the mesh configuration of a mesh point matches the * local mesh configuration, i.e. if both nodes belong to the same mesh network. */ -bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata) +bool mesh_matches_local(struct ieee802_11_elems *ie, + struct ieee80211_sub_if_data *sdata, u32 basic_rates) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_local *local = sdata->local; @@ -97,10 +96,13 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))) goto mismatch; + if (sdata->vif.bss_conf.basic_rates != basic_rates) + goto mismatch; + /* disallow peering with mismatched channel types for now */ - if (ie->ht_info_elem && + if (ie->ht_operation && (local->_oper_channel_type != - ieee80211_ht_info_to_channel_type(ie->ht_info_elem))) + ieee80211_ht_oper_to_channel_type(ie->ht_operation))) goto mismatch; return true; @@ -251,8 +253,10 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) /* Mesh capability */ ifmsh->accepting_plinks = mesh_plink_availables(sdata); *pos = MESHCONF_CAPAB_FORWARDING; - *pos++ |= ifmsh->accepting_plinks ? + *pos |= ifmsh->accepting_plinks ? MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; + *pos++ |= ifmsh->adjusting_tbtt ? + MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; *pos++ = 0x00; return 0; @@ -371,7 +375,7 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb, return 0; } -int mesh_add_ht_info_ie(struct sk_buff *skb, +int mesh_add_ht_oper_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; @@ -385,11 +389,11 @@ int mesh_add_ht_info_ie(struct sk_buff *skb, if (!ht_cap->ht_supported || channel_type == NL80211_CHAN_NO_HT) return 0; - if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_info)) + if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_operation)) return -ENOMEM; - pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_info)); - ieee80211_ie_build_ht_info(pos, ht_cap, channel, channel_type); + pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation)); + ieee80211_ie_build_ht_oper(pos, ht_cap, channel, channel_type); return 0; } @@ -573,14 +577,21 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) ieee80211_configure_filter(local); ifmsh->mesh_cc_id = 0; /* Disabled */ - ifmsh->mesh_sp_id = 0; /* Neighbor Offset */ ifmsh->mesh_auth_id = 0; /* Disabled */ + /* register sync ops from extensible synchronization framework */ + ifmsh->sync_ops = ieee80211_mesh_sync_ops_get(ifmsh->mesh_sp_id); + ifmsh->adjusting_tbtt = false; + ifmsh->sync_offset_clockdrift_max = 0; set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); ieee80211_mesh_root_setup(ifmsh); ieee80211_queue_work(&local->hw, &sdata->work); sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; + sdata->vif.bss_conf.basic_rates = + ieee80211_mandatory_rates(sdata->local, + sdata->local->hw.conf.channel->band); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED | + BSS_CHANGED_BASIC_RATES | BSS_CHANGED_BEACON_INT); } @@ -616,9 +627,10 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, struct ieee80211_rx_status *rx_status) { struct ieee80211_local *local = sdata->local; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee802_11_elems elems; struct ieee80211_channel *channel; - u32 supp_rates = 0; + u32 supp_rates = 0, basic_rates = 0; size_t baselen; int freq; enum ieee80211_band band = rx_status->band; @@ -649,11 +661,16 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) return; + supp_rates = ieee80211_sta_get_rates(local, &elems, + band, &basic_rates); + if (elems.mesh_id && elems.mesh_config && - mesh_matches_local(&elems, sdata)) { - supp_rates = ieee80211_sta_get_rates(local, &elems, band); + mesh_matches_local(&elems, sdata, basic_rates)) mesh_neighbour_update(mgmt->sa, supp_rates, sdata, &elems); - } + + if (ifmsh->sync_ops) + ifmsh->sync_ops->rx_bcn_presp(sdata, + stype, mgmt, &elems, rx_status); } static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, @@ -721,6 +738,9 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) if (test_and_clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags)) ieee80211_mesh_rootpath(sdata); + + if (test_and_clear_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags)) + mesh_sync_adjust_tbtt(sdata); } void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) @@ -761,4 +781,5 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) (unsigned long) sdata); INIT_LIST_HEAD(&ifmsh->preq_queue.list); spin_lock_init(&ifmsh->mesh_preq_queue_lock); + spin_lock_init(&ifmsh->sync_offset_lock); } diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 8d53b71..4ad7389 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -19,6 +19,20 @@ /* Data structures */ /** + * enum mesh_config_capab_flags - mesh config IE capability flags + * + * @MESHCONF_CAPAB_ACCEPT_PLINKS: STA is willing to establish + * additional mesh peerings with other mesh STAs + * @MESHCONF_CAPAB_FORWARDING: the STA forwards MSDUs + * @MESHCONF_CAPAB_TBTT_ADJUSTING: TBTT adjustment procedure is ongoing + */ +enum mesh_config_capab_flags { + MESHCONF_CAPAB_ACCEPT_PLINKS = BIT(0), + MESHCONF_CAPAB_FORWARDING = BIT(3), + MESHCONF_CAPAB_TBTT_ADJUSTING = BIT(5), +}; + +/** * enum mesh_path_flags - mac80211 mesh path flags * * @@ -56,12 +70,15 @@ enum mesh_path_flags { * @MESH_WORK_GROW_MPP_TABLE: the mesh portals table is full and needs to * grow * @MESH_WORK_ROOT: the mesh root station needs to send a frame + * @MESH_WORK_DRIFT_ADJUST: time to compensate for clock drift relative to other + * mesh nodes */ enum mesh_deferred_task_flags { MESH_WORK_HOUSEKEEPING, MESH_WORK_GROW_MPATH_TABLE, MESH_WORK_GROW_MPP_TABLE, MESH_WORK_ROOT, + MESH_WORK_DRIFT_ADJUST, }; /** @@ -86,6 +103,7 @@ enum mesh_deferred_task_flags { * mpath itself. No need to take this lock when adding or removing * an mpath to a hash bucket on a path table. * @rann_snd_addr: the RANN sender address + * @rann_metric: the aggregated path metric towards the root node * @is_root: the destination station of this path is a root node * @is_gate: the destination station of this path is a mesh gate * @@ -112,6 +130,7 @@ struct mesh_path { enum mesh_path_flags flags; spinlock_t state_lock; u8 rann_snd_addr[ETH_ALEN]; + u32 rann_metric; bool is_root; bool is_gate; }; @@ -204,7 +223,7 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, struct ieee80211_sub_if_data *sdata); bool mesh_matches_local(struct ieee802_11_elems *ie, - struct ieee80211_sub_if_data *sdata); + struct ieee80211_sub_if_data *sdata, u32 basic_rates); void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); @@ -220,7 +239,7 @@ int mesh_add_ds_params_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); int mesh_add_ht_cap_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); -int mesh_add_ht_info_ie(struct sk_buff *skb, +int mesh_add_ht_oper_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); @@ -232,6 +251,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh); +struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method); /* Mesh paths */ int mesh_nexthop_lookup(struct sk_buff *skb, @@ -325,6 +345,7 @@ void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata); void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata); void mesh_plink_quiesce(struct sta_info *sta); void mesh_plink_restart(struct sta_info *sta); +void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata); #else #define mesh_allocated 0 static inline void diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 1c6f3d0..a80da37 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -86,8 +86,8 @@ static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae) #define PERR_IE_TARGET_RCODE(x) u16_field_get(x, 13, 0) #define MSEC_TO_TU(x) (x*1000/1024) -#define SN_GT(x, y) ((long) (y) - (long) (x) < 0) -#define SN_LT(x, y) ((long) (x) - (long) (y) < 0) +#define SN_GT(x, y) ((s32)(y - x) < 0) +#define SN_LT(x, y) ((s32)(x - y) < 0) #define net_traversal_jiffies(s) \ msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime) @@ -732,11 +732,12 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, struct ieee80211_rann_ie *rann) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + struct ieee80211_local *local = sdata->local; + struct sta_info *sta; struct mesh_path *mpath; u8 ttl, flags, hopcount; u8 *orig_addr; - u32 orig_sn, metric; - u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval; + u32 orig_sn, metric, metric_txsta, interval; bool root_is_gate; ttl = rann->rann_ttl; @@ -748,10 +749,11 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, flags = rann->rann_flags; root_is_gate = !!(flags & RANN_FLAG_IS_GATE); orig_addr = rann->rann_addr; - orig_sn = rann->rann_seq; + orig_sn = le32_to_cpu(rann->rann_seq); + interval = le32_to_cpu(rann->rann_interval); hopcount = rann->rann_hopcount; hopcount++; - metric = rann->rann_metric; + metric = le32_to_cpu(rann->rann_metric); /* Ignore our own RANNs */ if (compare_ether_addr(orig_addr, sdata->vif.addr) == 0) @@ -761,6 +763,14 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, orig_addr, mgmt->sa, root_is_gate); rcu_read_lock(); + sta = sta_info_get(sdata, mgmt->sa); + if (!sta) { + rcu_read_unlock(); + return; + } + + metric_txsta = airtime_link_metric_get(local, sta); + mpath = mesh_path_lookup(orig_addr, sdata); if (!mpath) { mesh_path_add(orig_addr, sdata); @@ -780,14 +790,16 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); } - if (mpath->sn < orig_sn && ifmsh->mshcfg.dot11MeshForwarding) { + if ((SN_LT(mpath->sn, orig_sn) || (mpath->sn == orig_sn && + metric < mpath->rann_metric)) && ifmsh->mshcfg.dot11MeshForwarding) { mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, cpu_to_le32(orig_sn), 0, NULL, 0, broadcast_addr, hopcount, ttl, cpu_to_le32(interval), - cpu_to_le32(metric + mpath->metric), + cpu_to_le32(metric + metric_txsta), 0, sdata); mpath->sn = orig_sn; + mpath->rann_metric = metric + metric_txsta; } /* Using individually addressed PREQ for root node */ diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 4e53c4c..9c836e7 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -187,7 +187,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, 2 + sdata->u.mesh.mesh_id_len + 2 + sizeof(struct ieee80211_meshconf_ie) + 2 + sizeof(struct ieee80211_ht_cap) + - 2 + sizeof(struct ieee80211_ht_info) + + 2 + sizeof(struct ieee80211_ht_operation) + 2 + 8 + /* peering IE */ sdata->u.mesh.ie_len); if (!skb) @@ -212,8 +212,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, pos = skb_put(skb, 2); memcpy(pos + 2, &plid, 2); } - if (ieee80211_add_srates_ie(&sdata->vif, skb) || - ieee80211_add_ext_srates_ie(&sdata->vif, skb) || + if (ieee80211_add_srates_ie(&sdata->vif, skb, true) || + ieee80211_add_ext_srates_ie(&sdata->vif, skb, true) || mesh_add_rsn_ie(skb, sdata) || mesh_add_meshid_ie(skb, sdata) || mesh_add_meshconf_ie(skb, sdata)) @@ -263,7 +263,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, if (action != WLAN_SP_MESH_PEERING_CLOSE) { if (mesh_add_ht_cap_ie(skb, sdata) || - mesh_add_ht_info_ie(skb, sdata)) + mesh_add_ht_oper_ie(skb, sdata)) return -1; } @@ -465,6 +465,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m bool deactivated, matches_local = true; u8 ie_len; u8 *baseaddr; + u32 rates, basic_rates = 0; __le16 plid, llid, reason; #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG static const char *mplstates[] = { @@ -559,8 +560,11 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m /* Now we will figure out the appropriate event... */ event = PLINK_UNDEFINED; + rates = ieee80211_sta_get_rates(local, &elems, + rx_status->band, &basic_rates); + if (ftype != WLAN_SP_MESH_PEERING_CLOSE && - (!mesh_matches_local(&elems, sdata))) { + (!mesh_matches_local(&elems, sdata, basic_rates))) { matches_local = false; switch (ftype) { case WLAN_SP_MESH_PEERING_OPEN: @@ -583,7 +587,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m return; } else if (!sta) { /* ftype == WLAN_SP_MESH_PEERING_OPEN */ - u32 rates; rcu_read_unlock(); @@ -591,8 +594,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m mpl_dbg("Mesh plink error: no more free plinks\n"); return; } - - rates = ieee80211_sta_get_rates(local, &elems, rx_status->band); sta = mesh_plink_alloc(sdata, mgmt->sa, rates, &elems); if (!sta) { mpl_dbg("Mesh plink error: plink table full\n"); diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c new file mode 100644 index 0000000..f78b013 --- /dev/null +++ b/net/mac80211/mesh_sync.c @@ -0,0 +1,296 @@ +/* + * Copyright 2011-2012, Pavel Zubarev <pavel.zubarev@gmail.com> + * Copyright 2011-2012, Marco Porsch <marco.porsch@s2005.tu-chemnitz.de> + * Copyright 2011-2012, cozybit Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include "ieee80211_i.h" +#include "mesh.h" +#include "driver-ops.h" + +#ifdef CONFIG_MAC80211_VERBOSE_MESH_SYNC_DEBUG +#define msync_dbg(fmt, args...) \ + printk(KERN_DEBUG "Mesh sync (%s): " fmt "\n", sdata->name, ##args) +#else +#define msync_dbg(fmt, args...) do { (void)(0); } while (0) +#endif + +/* This is not in the standard. It represents a tolerable tbtt drift below + * which we do no TSF adjustment. + */ +#define TBTT_MINIMUM_ADJUSTMENT 10 + +struct sync_method { + u8 method; + struct ieee80211_mesh_sync_ops ops; +}; + +/** + * mesh_peer_tbtt_adjusting - check if an mp is currently adjusting its TBTT + * + * @ie: information elements of a management frame from the mesh peer + */ +static bool mesh_peer_tbtt_adjusting(struct ieee802_11_elems *ie) +{ + return (ie->mesh_config->meshconf_cap & + MESHCONF_CAPAB_TBTT_ADJUSTING) != 0; +} + +void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + /* sdata->vif.bss_conf.beacon_int in 1024us units, 0.04% */ + u64 beacon_int_fraction = sdata->vif.bss_conf.beacon_int * 1024 / 2500; + u64 tsf; + u64 tsfdelta; + + spin_lock_bh(&ifmsh->sync_offset_lock); + + if (ifmsh->sync_offset_clockdrift_max < beacon_int_fraction) { + msync_dbg("TBTT : max clockdrift=%lld; adjusting", + (long long) ifmsh->sync_offset_clockdrift_max); + tsfdelta = -ifmsh->sync_offset_clockdrift_max; + ifmsh->sync_offset_clockdrift_max = 0; + } else { + msync_dbg("TBTT : max clockdrift=%lld; adjusting by %llu", + (long long) ifmsh->sync_offset_clockdrift_max, + (unsigned long long) beacon_int_fraction); + tsfdelta = -beacon_int_fraction; + ifmsh->sync_offset_clockdrift_max -= beacon_int_fraction; + } + + tsf = drv_get_tsf(local, sdata); + if (tsf != -1ULL) + drv_set_tsf(local, sdata, tsf + tsfdelta); + spin_unlock_bh(&ifmsh->sync_offset_lock); +} + +static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, + u16 stype, + struct ieee80211_mgmt *mgmt, + struct ieee802_11_elems *elems, + struct ieee80211_rx_status *rx_status) +{ + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + struct ieee80211_local *local = sdata->local; + struct sta_info *sta; + u64 t_t, t_r; + + WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET); + + /* standard mentions only beacons */ + if (stype != IEEE80211_STYPE_BEACON) + return; + + /* The current tsf is a first approximation for the timestamp + * for the received beacon. Further down we try to get a + * better value from the rx_status->mactime field if + * available. Also we have to call drv_get_tsf() before + * entering the rcu-read section.*/ + t_r = drv_get_tsf(local, sdata); + + rcu_read_lock(); + sta = sta_info_get(sdata, mgmt->sa); + if (!sta) + goto no_sync; + + /* check offset sync conditions (13.13.2.2.1) + * + * TODO also sync to + * dot11MeshNbrOffsetMaxNeighbor non-peer non-MBSS neighbors + */ + + if (elems->mesh_config && mesh_peer_tbtt_adjusting(elems)) { + clear_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN); + msync_dbg("STA %pM : is adjusting TBTT", sta->sta.addr); + goto no_sync; + } + + if (rx_status->flag & RX_FLAG_MACTIME_MPDU && rx_status->mactime) { + /* + * The mactime is defined as the time the first data symbol + * of the frame hits the PHY, and the timestamp of the beacon + * is defined as "the time that the data symbol containing the + * first bit of the timestamp is transmitted to the PHY plus + * the transmitting STA's delays through its local PHY from the + * MAC-PHY interface to its interface with the WM" (802.11 + * 11.1.2) + * + * T_r, in 13.13.2.2.2, is just defined as "the frame reception + * time" but we unless we interpret that time to be the same + * time of the beacon timestamp, the offset calculation will be + * off. Below we adjust t_r to be "the time at which the first + * symbol of the timestamp element in the beacon is received". + * This correction depends on the rate. + * + * Based on similar code in ibss.c + */ + int rate; + + if (rx_status->flag & RX_FLAG_HT) { + /* TODO: + * In principle there could be HT-beacons (Dual Beacon + * HT Operation options), but for now ignore them and + * just use the primary (i.e. non-HT) beacons for + * synchronization. + * */ + goto no_sync; + } else + rate = local->hw.wiphy->bands[rx_status->band]-> + bitrates[rx_status->rate_idx].bitrate; + + /* 24 bytes of header * 8 bits/byte * + * 10*(100 Kbps)/Mbps / rate (100 Kbps)*/ + t_r = rx_status->mactime + (24 * 8 * 10 / rate); + } + + /* Timing offset calculation (see 13.13.2.2.2) */ + t_t = le64_to_cpu(mgmt->u.beacon.timestamp); + sta->t_offset = t_t - t_r; + + if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { + s64 t_clockdrift = sta->t_offset_setpoint + - sta->t_offset; + + msync_dbg("STA %pM : sta->t_offset=%lld," + " sta->t_offset_setpoint=%lld," + " t_clockdrift=%lld", + sta->sta.addr, + (long long) sta->t_offset, + (long long) + sta->t_offset_setpoint, + (long long) t_clockdrift); + rcu_read_unlock(); + + spin_lock_bh(&ifmsh->sync_offset_lock); + if (t_clockdrift > + ifmsh->sync_offset_clockdrift_max) + ifmsh->sync_offset_clockdrift_max + = t_clockdrift; + spin_unlock_bh(&ifmsh->sync_offset_lock); + + } else { + sta->t_offset_setpoint = sta->t_offset; + set_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN); + msync_dbg("STA %pM : offset was invalid, " + " sta->t_offset=%lld", + sta->sta.addr, + (long long) sta->t_offset); + rcu_read_unlock(); + } + return; + +no_sync: + rcu_read_unlock(); +} + +static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + + WARN_ON(ifmsh->mesh_sp_id + != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET); + BUG_ON(!rcu_read_lock_held()); + + spin_lock_bh(&ifmsh->sync_offset_lock); + + if (ifmsh->sync_offset_clockdrift_max > + TBTT_MINIMUM_ADJUSTMENT) { + /* Since ajusting the tsf here would + * require a possibly blocking call + * to the driver tsf setter, we punt + * the tsf adjustment to the mesh tasklet + */ + msync_dbg("TBTT : kicking off TBTT " + "adjustment with " + "clockdrift_max=%lld", + ifmsh->sync_offset_clockdrift_max); + set_bit(MESH_WORK_DRIFT_ADJUST, + &ifmsh->wrkq_flags); + } else { + msync_dbg("TBTT : max clockdrift=%lld; " + "too small to adjust", + (long long) + ifmsh->sync_offset_clockdrift_max); + ifmsh->sync_offset_clockdrift_max = 0; + } + spin_unlock_bh(&ifmsh->sync_offset_lock); +} + +static const u8 *mesh_get_vendor_oui(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + u8 offset; + + if (!ifmsh->ie || !ifmsh->ie_len) + return NULL; + + offset = ieee80211_ie_split_vendor(ifmsh->ie, + ifmsh->ie_len, 0); + + if (!offset) + return NULL; + + return ifmsh->ie + offset + 2; +} + +static void mesh_sync_vendor_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, + u16 stype, + struct ieee80211_mgmt *mgmt, + struct ieee802_11_elems *elems, + struct ieee80211_rx_status *rx_status) +{ + const u8 *oui; + + WARN_ON(sdata->u.mesh.mesh_sp_id != IEEE80211_SYNC_METHOD_VENDOR); + msync_dbg("called mesh_sync_vendor_rx_bcn_presp"); + oui = mesh_get_vendor_oui(sdata); + /* here you would implement the vendor offset tracking for this oui */ +} + +static void mesh_sync_vendor_adjust_tbtt(struct ieee80211_sub_if_data *sdata) +{ + const u8 *oui; + + WARN_ON(sdata->u.mesh.mesh_sp_id != IEEE80211_SYNC_METHOD_VENDOR); + msync_dbg("called mesh_sync_vendor_adjust_tbtt"); + oui = mesh_get_vendor_oui(sdata); + /* here you would implement the vendor tsf adjustment for this oui */ +} + +/* global variable */ +static struct sync_method sync_methods[] = { + { + .method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET, + .ops = { + .rx_bcn_presp = &mesh_sync_offset_rx_bcn_presp, + .adjust_tbtt = &mesh_sync_offset_adjust_tbtt, + } + }, + { + .method = IEEE80211_SYNC_METHOD_VENDOR, + .ops = { + .rx_bcn_presp = &mesh_sync_vendor_rx_bcn_presp, + .adjust_tbtt = &mesh_sync_vendor_adjust_tbtt, + } + }, +}; + +struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method) +{ + struct ieee80211_mesh_sync_ops *ops = NULL; + u8 i; + + for (i = 0 ; i < ARRAY_SIZE(sync_methods); ++i) { + if (sync_methods[i].method == method) { + ops = &sync_methods[i].ops; + break; + } + } + return ops; +} diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f76da5b..bbf1100 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -171,122 +171,64 @@ static int ecw2cw(int ecw) return (1 << ecw) - 1; } -/* - * ieee80211_enable_ht should be called only after the operating band - * has been determined as ht configuration depends on the hw's - * HT abilities for a specific band. - */ -static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, - struct ieee80211_ht_info *hti, - const u8 *bssid, u16 ap_ht_cap_flags, - bool beacon_htcap_ie) +static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata, + struct ieee80211_ht_operation *ht_oper, + const u8 *bssid, bool reconfig) { struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; struct sta_info *sta; u32 changed = 0; - int hti_cfreq; u16 ht_opmode; - bool enable_ht = true; - enum nl80211_channel_type prev_chantype; - enum nl80211_channel_type rx_channel_type = NL80211_CHAN_NO_HT; - enum nl80211_channel_type tx_channel_type; + bool disable_40 = false; sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - prev_chantype = sdata->vif.bss_conf.channel_type; - - hti_cfreq = ieee80211_channel_to_frequency(hti->control_chan, - sband->band); - /* check that channel matches the right operating channel */ - if (local->hw.conf.channel->center_freq != hti_cfreq) { - /* Some APs mess this up, evidently. - * Netgear WNDR3700 sometimes reports 4 higher than - * the actual channel, for instance. - */ - printk(KERN_DEBUG - "%s: Wrong control channel in association" - " response: configured center-freq: %d" - " hti-cfreq: %d hti->control_chan: %d" - " band: %d. Disabling HT.\n", - sdata->name, - local->hw.conf.channel->center_freq, - hti_cfreq, hti->control_chan, - sband->band); - enable_ht = false; - } - - if (enable_ht) { - rx_channel_type = NL80211_CHAN_HT20; - - if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && - !ieee80111_cfg_override_disables_ht40(sdata) && - (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && - (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { - switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - rx_channel_type = NL80211_CHAN_HT40PLUS; - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - rx_channel_type = NL80211_CHAN_HT40MINUS; - break; - } - } + switch (sdata->vif.bss_conf.channel_type) { + case NL80211_CHAN_HT40PLUS: + if (local->hw.conf.channel->flags & IEEE80211_CHAN_NO_HT40PLUS) + disable_40 = true; + break; + case NL80211_CHAN_HT40MINUS: + if (local->hw.conf.channel->flags & IEEE80211_CHAN_NO_HT40MINUS) + disable_40 = true; + break; + default: + break; } - tx_channel_type = ieee80211_get_tx_channel_type(local, rx_channel_type); - - if (local->tmp_channel) - local->tmp_channel_type = rx_channel_type; + /* This can change during the lifetime of the BSS */ + if (!(ht_oper->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) + disable_40 = true; - if (!ieee80211_set_channel_type(local, sdata, rx_channel_type)) { - /* can only fail due to HT40+/- mismatch */ - rx_channel_type = NL80211_CHAN_HT20; - WARN_ON(!ieee80211_set_channel_type(local, sdata, - rx_channel_type)); - } - - if (beacon_htcap_ie && (prev_chantype != rx_channel_type)) { - /* - * Whenever the AP announces the HT mode change that can be - * 40MHz intolerant or etc., it would be safer to stop tx - * queues before doing hw config to avoid buffer overflow. - */ - ieee80211_stop_queues_by_reason(&sdata->local->hw, - IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); + mutex_lock(&local->sta_mtx); + sta = sta_info_get(sdata, bssid); - /* flush out all packets */ - synchronize_net(); + WARN_ON_ONCE(!sta); - drv_flush(local, false); - } + if (sta && !sta->supports_40mhz) + disable_40 = true; - /* channel_type change automatically detected */ - ieee80211_hw_config(local, 0); + if (sta && (!reconfig || + (disable_40 != !!(sta->sta.ht_cap.cap & + IEEE80211_HT_CAP_SUP_WIDTH_20_40)))) { - if (prev_chantype != tx_channel_type) { - rcu_read_lock(); - sta = sta_info_get(sdata, bssid); - if (sta) - rate_control_rate_update(local, sband, sta, - IEEE80211_RC_HT_CHANGED, - tx_channel_type); - rcu_read_unlock(); + if (disable_40) + sta->sta.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + else + sta->sta.ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; - if (beacon_htcap_ie) - ieee80211_wake_queues_by_reason(&sdata->local->hw, - IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); + rate_control_rate_update(local, sband, sta, + IEEE80211_RC_BW_CHANGED); } + mutex_unlock(&local->sta_mtx); - ht_opmode = le16_to_cpu(hti->operation_mode); + ht_opmode = le16_to_cpu(ht_oper->operation_mode); /* if bss configuration changed store the new one */ - if (sdata->ht_opmode_valid != enable_ht || - sdata->vif.bss_conf.ht_operation_mode != ht_opmode || - prev_chantype != rx_channel_type) { + if (!reconfig || (sdata->vif.bss_conf.ht_operation_mode != ht_opmode)) { changed |= BSS_CHANGED_HT; sdata->vif.bss_conf.ht_operation_mode = ht_opmode; - sdata->ht_opmode_valid = enable_ht; } return changed; @@ -316,12 +258,12 @@ static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len, } static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, - struct sk_buff *skb, const u8 *ht_info_ie, + struct sk_buff *skb, const u8 *ht_oper_ie, struct ieee80211_supported_band *sband, struct ieee80211_channel *channel, enum ieee80211_smps_mode smps) { - struct ieee80211_ht_info *ht_info; + struct ieee80211_ht_operation *ht_oper; u8 *pos; u32 flags = channel->flags; u16 cap; @@ -329,21 +271,21 @@ static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap)); - if (!ht_info_ie) + if (!ht_oper_ie) return; - if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info)) + if (ht_oper_ie[1] < sizeof(struct ieee80211_ht_operation)) return; memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); ieee80211_apply_htcap_overrides(sdata, &ht_cap); - ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2); + ht_oper = (struct ieee80211_ht_operation *)(ht_oper_ie + 2); /* determine capability flags */ cap = ht_cap.cap; - switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { + switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: if (flags & IEEE80211_CHAN_NO_HT40PLUS) { cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; @@ -358,6 +300,16 @@ static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, break; } + /* + * If 40 MHz was disabled associate as though we weren't + * capable of 40 MHz -- some broken APs will never fall + * back to trying to transmit in 20 MHz. + */ + if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_40MHZ) { + cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + cap &= ~IEEE80211_HT_CAP_SGI_40; + } + /* set SM PS mode properly */ cap &= ~IEEE80211_HT_CAP_SM_PS; switch (smps) { @@ -557,7 +509,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) } if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) - ieee80211_add_ht_ie(sdata, skb, assoc_data->ht_information_ie, + ieee80211_add_ht_ie(sdata, skb, assoc_data->ht_operation_ie, sband, local->oper_channel, ifmgd->ap_smps); /* if present, add any custom non-vendor IEs that go after HT */ @@ -1182,7 +1134,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, if (!local->ops->conf_tx) return; - if (local->hw.queues < 4) + if (local->hw.queues < IEEE80211_NUM_ACS) return; if (!wmm_param) @@ -1435,7 +1387,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, sdata->vif.bss_conf.assoc = false; /* on the next assoc, re-program HT parameters */ - sdata->ht_opmode_valid = false; memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); @@ -1567,14 +1518,23 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) ifmgd->nullfunc_failed = false; ieee80211_send_nullfunc(sdata->local, sdata, 0); } else { + int ssid_len; + ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); - ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0, - (u32) -1, true, false); + if (WARN_ON_ONCE(ssid == NULL)) + ssid_len = 0; + else + ssid_len = ssid[1]; + + ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, + 0, (u32) -1, true, false); } ifmgd->probe_send_count++; ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); run_again(ifmgd, ifmgd->probe_timeout); + if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) + drv_flush(sdata->local, false); } static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, @@ -1643,6 +1603,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct sk_buff *skb; const u8 *ssid; + int ssid_len; if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) return NULL; @@ -1653,8 +1614,13 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, return NULL; ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); + if (WARN_ON_ONCE(ssid == NULL)) + ssid_len = 0; + else + ssid_len = ssid[1]; + skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid, - (u32) -1, ssid + 2, ssid[1], + (u32) -1, ssid + 2, ssid_len, NULL, 0, true); return skb; @@ -2000,7 +1966,6 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; u32 changed = 0; int err; - u16 ap_ht_cap_flags; /* AssocResp and ReassocResp have identical structure */ @@ -2051,7 +2016,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, elems.ht_cap_elem, &sta->sta.ht_cap); - ap_ht_cap_flags = sta->sta.ht_cap.cap; + sta->supports_40mhz = + sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; rate_control_rate_init(sta); @@ -2092,11 +2058,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, ieee80211_set_wmm_default(sdata, false); changed |= BSS_CHANGED_QOS; - if (elems.ht_info_elem && elems.wmm_param && + if (elems.ht_operation && elems.wmm_param && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) - changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, - cbss->bssid, ap_ht_cap_flags, - false); + changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, + cbss->bssid, false); /* set AID and assoc capability, * ieee80211_set_associated() will tell the driver */ @@ -2319,7 +2284,7 @@ static const u64 care_about_ies = (1ULL << WLAN_EID_CHANNEL_SWITCH) | (1ULL << WLAN_EID_PWR_CONSTRAINT) | (1ULL << WLAN_EID_HT_CAPABILITY) | - (1ULL << WLAN_EID_HT_INFORMATION); + (1ULL << WLAN_EID_HT_OPERATION); static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, @@ -2468,11 +2433,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) { if (directed_tim) { if (local->hw.conf.dynamic_ps_timeout > 0) { - local->hw.conf.flags &= ~IEEE80211_CONF_PS; - ieee80211_hw_config(local, - IEEE80211_CONF_CHANGE_PS); + if (local->hw.conf.flags & IEEE80211_CONF_PS) { + local->hw.conf.flags &= ~IEEE80211_CONF_PS; + ieee80211_hw_config(local, + IEEE80211_CONF_CHANGE_PS); + } ieee80211_send_nullfunc(local, sdata, 0); - } else { + } else if (!local->pspolling && sdata->u.mgd.powersave) { local->pspolling = true; /* @@ -2504,31 +2471,14 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, erp_valid, erp_value); - if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param && + if (elems.ht_cap_elem && elems.ht_operation && elems.wmm_param && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) { - struct sta_info *sta; struct ieee80211_supported_band *sband; - u16 ap_ht_cap_flags; - - rcu_read_lock(); - - sta = sta_info_get(sdata, bssid); - if (WARN_ON(!sta)) { - rcu_read_unlock(); - return; - } sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, - elems.ht_cap_elem, &sta->sta.ht_cap); - - ap_ht_cap_flags = sta->sta.ht_cap.cap; - - rcu_read_unlock(); - - changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, - bssid, ap_ht_cap_flags, true); + changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, + bssid, true); } /* Note: country IE parsing is done for us by cfg80211 */ @@ -3060,6 +3010,11 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, struct sta_info *sta; bool have_sta = false; int err; + int ht_cfreq; + enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; + const u8 *ht_oper_ie; + const struct ieee80211_ht_operation *ht_oper = NULL; + struct ieee80211_supported_band *sband; if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data)) return -EINVAL; @@ -3081,17 +3036,76 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, mutex_unlock(&local->mtx); /* switch to the right channel */ + sband = local->hw.wiphy->bands[cbss->channel->band]; + + ifmgd->flags &= ~IEEE80211_STA_DISABLE_40MHZ; + + if (sband->ht_cap.ht_supported) { + ht_oper_ie = cfg80211_find_ie(WLAN_EID_HT_OPERATION, + cbss->information_elements, + cbss->len_information_elements); + if (ht_oper_ie && ht_oper_ie[1] >= sizeof(*ht_oper)) + ht_oper = (void *)(ht_oper_ie + 2); + } + + if (ht_oper) { + ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan, + cbss->channel->band); + /* check that channel matches the right operating channel */ + if (cbss->channel->center_freq != ht_cfreq) { + /* + * It's possible that some APs are confused here; + * Netgear WNDR3700 sometimes reports 4 higher than + * the actual channel in association responses, but + * since we look at probe response/beacon data here + * it should be OK. + */ + printk(KERN_DEBUG + "%s: Wrong control channel: center-freq: %d" + " ht-cfreq: %d ht->primary_chan: %d" + " band: %d. Disabling HT.\n", + sdata->name, cbss->channel->center_freq, + ht_cfreq, ht_oper->primary_chan, + cbss->channel->band); + ht_oper = NULL; + } + } + + if (ht_oper) { + channel_type = NL80211_CHAN_HT20; + + if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { + switch (ht_oper->ht_param & + IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + channel_type = NL80211_CHAN_HT40PLUS; + break; + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: + channel_type = NL80211_CHAN_HT40MINUS; + break; + } + } + } + + if (!ieee80211_set_channel_type(local, sdata, channel_type)) { + /* can only fail due to HT40+/- mismatch */ + channel_type = NL80211_CHAN_HT20; + printk(KERN_DEBUG + "%s: disabling 40 MHz due to multi-vif mismatch\n", + sdata->name); + ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; + WARN_ON(!ieee80211_set_channel_type(local, sdata, + channel_type)); + } + local->oper_channel = cbss->channel; - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); + ieee80211_hw_config(local, 0); if (!have_sta) { - struct ieee80211_supported_band *sband; u32 rates = 0, basic_rates = 0; bool have_higher_than_11mbit; int min_rate = INT_MAX, min_rate_index = -1; - sband = sdata->local->hw.wiphy->bands[cbss->channel->band]; - ieee80211_get_rates(sband, bss->supp_rates, bss->supp_rates_len, &rates, &basic_rates, @@ -3311,7 +3325,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, /* Also disable HT if we don't support it or the AP doesn't use WMM */ sband = local->hw.wiphy->bands[req->bss->channel->band]; if (!sband->ht_cap.ht_supported || - local->hw.queues < 4 || !bss->wmm_used) + local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) ifmgd->flags |= IEEE80211_STA_DISABLE_11N; memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); @@ -3334,11 +3348,12 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, ifmgd->ap_smps = ifmgd->req_smps; assoc_data->capability = req->bss->capability; - assoc_data->wmm = bss->wmm_used && (local->hw.queues >= 4); + assoc_data->wmm = bss->wmm_used && + (local->hw.queues >= IEEE80211_NUM_ACS); assoc_data->supp_rates = bss->supp_rates; assoc_data->supp_rates_len = bss->supp_rates_len; - assoc_data->ht_information_ie = - ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_INFORMATION); + assoc_data->ht_operation_ie = + ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION); if (bss->wmm_used && bss->uapsd_supported && (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index ef8eba1..af1c4e2 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -127,6 +127,10 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) drv_remove_interface(local, sdata); } + sdata = rtnl_dereference(local->monitor_sdata); + if (sdata) + drv_remove_interface(local, sdata); + /* stop hardware - this must stop RX */ if (local->open_count) ieee80211_stop_device(local); diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index fbb1efd..6e4fd32 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -17,6 +17,7 @@ #include <net/mac80211.h> #include "ieee80211_i.h" #include "sta_info.h" +#include "driver-ops.h" struct rate_control_ref { struct ieee80211_local *local; @@ -63,8 +64,7 @@ static inline void rate_control_rate_init(struct sta_info *sta) static inline void rate_control_rate_update(struct ieee80211_local *local, struct ieee80211_supported_band *sband, - struct sta_info *sta, u32 changed, - enum nl80211_channel_type oper_chan_type) + struct sta_info *sta, u32 changed) { struct rate_control_ref *ref = local->rate_ctrl; struct ieee80211_sta *ista = &sta->sta; @@ -72,7 +72,8 @@ static inline void rate_control_rate_update(struct ieee80211_local *local, if (ref && ref->ops->rate_update) ref->ops->rate_update(ref->priv, sband, ista, - priv_sta, changed, oper_chan_type); + priv_sta, changed); + drv_sta_rc_update(local, sta->sdata, &sta->sta, changed); } static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 16e0b27..3b3dcae 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -686,8 +686,7 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, static void minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - enum nl80211_channel_type oper_chan_type) + struct ieee80211_sta *sta, void *priv_sta) { struct minstrel_priv *mp = priv; struct minstrel_ht_sta_priv *msp = priv_sta; @@ -735,10 +734,6 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, if (sta_cap & IEEE80211_HT_CAP_LDPC_CODING) mi->tx_flags |= IEEE80211_TX_CTL_LDPC; - if (oper_chan_type != NL80211_CHAN_HT40MINUS && - oper_chan_type != NL80211_CHAN_HT40PLUS) - sta_cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - smps = (sta_cap & IEEE80211_HT_CAP_SM_PS) >> IEEE80211_HT_CAP_SM_PS_SHIFT; @@ -788,17 +783,15 @@ static void minstrel_ht_rate_init(void *priv, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta) { - struct minstrel_priv *mp = priv; - - minstrel_ht_update_caps(priv, sband, sta, priv_sta, mp->hw->conf.channel_type); + minstrel_ht_update_caps(priv, sband, sta, priv_sta); } static void minstrel_ht_rate_update(void *priv, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta, - u32 changed, enum nl80211_channel_type oper_chan_type) + u32 changed) { - minstrel_ht_update_caps(priv, sband, sta, priv_sta, oper_chan_type); + minstrel_ht_update_caps(priv, sband, sta, priv_sta); } static void * diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index bcfe8c7..54a0491 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -793,8 +793,7 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx) /* reset session timer */ if (tid_agg_rx->timeout) - mod_timer(&tid_agg_rx->session_timer, - TU_TO_EXP_TIME(tid_agg_rx->timeout)); + tid_agg_rx->last_rx = jiffies; /* if this mpdu is fragmented - terminate rx aggregation session */ sc = le16_to_cpu(hdr->seq_ctrl); @@ -2269,11 +2268,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) sband = rx->local->hw.wiphy->bands[status->band]; - rate_control_rate_update( - local, sband, rx->sta, - IEEE80211_RC_SMPS_CHANGED, - ieee80211_get_tx_channel_type( - local, local->_oper_channel_type)); + rate_control_rate_update(local, sband, rx->sta, + IEEE80211_RC_SMPS_CHANGED); goto handled; } default: diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 38137cb..7fd7ac4 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -1195,13 +1195,15 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta, ieee80211_is_qos_nullfunc(hdr->frame_control)) qoshdr = ieee80211_get_qos_ctl(hdr); - /* set EOSP for the frame */ - if (reason == IEEE80211_FRAME_RELEASE_UAPSD && - qoshdr && skb_queue_empty(&frames)) - *qoshdr |= IEEE80211_QOS_CTL_EOSP; - - info->flags |= IEEE80211_TX_STATUS_EOSP | - IEEE80211_TX_CTL_REQ_TX_STATUS; + /* end service period after last frame */ + if (skb_queue_empty(&frames)) { + if (reason == IEEE80211_FRAME_RELEASE_UAPSD && + qoshdr) + *qoshdr |= IEEE80211_QOS_CTL_EOSP; + + info->flags |= IEEE80211_TX_STATUS_EOSP | + IEEE80211_TX_CTL_REQ_TX_STATUS; + } if (qoshdr) tids |= BIT(*qoshdr & IEEE80211_QOS_CTL_TID_MASK); diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index ab05768..f75f5d9 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -55,6 +55,7 @@ * @WLAN_STA_4ADDR_EVENT: 4-addr event was already sent for this frame. * @WLAN_STA_INSERTED: This station is inserted into the hash table. * @WLAN_STA_RATE_CONTROL: rate control was initialized for this station. + * @WLAN_STA_TOFFSET_KNOWN: toffset calculated for this station is valid. */ enum ieee80211_sta_info_flags { WLAN_STA_AUTH, @@ -76,6 +77,7 @@ enum ieee80211_sta_info_flags { WLAN_STA_4ADDR_EVENT, WLAN_STA_INSERTED, WLAN_STA_RATE_CONTROL, + WLAN_STA_TOFFSET_KNOWN, }; #define STA_TID_NUM 16 @@ -101,6 +103,7 @@ enum ieee80211_sta_info_flags { * @dialog_token: dialog token for aggregation session * @timeout: session timeout value to be filled in ADDBA requests * @state: session state (see above) + * @last_tx: jiffies of last tx activity * @stop_initiator: initiator of a session stop * @tx_stop: TX DelBA frame when stopping * @buf_size: reorder buffer size at receiver @@ -122,6 +125,7 @@ struct tid_ampdu_tx { struct timer_list addba_resp_timer; struct sk_buff_head pending; unsigned long state; + unsigned long last_tx; u16 timeout; u8 dialog_token; u8 stop_initiator; @@ -139,6 +143,7 @@ struct tid_ampdu_tx { * @reorder_time: jiffies when skb was added * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) * @reorder_timer: releases expired frames from the reorder buffer. + * @last_rx: jiffies of last rx activity * @head_seq_num: head sequence number in reordering buffer. * @stored_mpdu_num: number of MPDUs in reordering buffer * @ssn: Starting Sequence Number expected to be aggregated. @@ -163,6 +168,7 @@ struct tid_ampdu_rx { unsigned long *reorder_time; struct timer_list session_timer; struct timer_list reorder_timer; + unsigned long last_rx; u16 head_seq_num; u16 stored_mpdu_num; u16 ssn; @@ -264,6 +270,7 @@ struct sta_ampdu_mlme { * @plink_timeout: timeout of peer link * @plink_timer: peer link watch timer * @plink_timer_was_running: used by suspend/resume to restore timers + * @t_offset: timing offset relative to this host * @debugfs: debug filesystem info * @dead: set to true when sta is unlinked * @uploaded: set to true when sta is uploaded to the driver @@ -353,6 +360,8 @@ struct sta_info { enum nl80211_plink_state plink_state; u32 plink_timeout; struct timer_list plink_timer; + s64 t_offset; + s64 t_offset_setpoint; #endif #ifdef CONFIG_MAC80211_DEBUGFS @@ -365,6 +374,8 @@ struct sta_info { unsigned int lost_packets; unsigned int beacon_loss_count; + bool supports_40mhz; + /* keep last! */ struct ieee80211_sta sta; }; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 782a601..4f6aac1 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -230,9 +230,9 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) * changed via debugfs, user needs to reassociate manually to have * everything in sync. */ - if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) - && (ifmgd->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) - && skb_get_queue_mapping(tx->skb) == 0) + if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) && + (ifmgd->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) && + skb_get_queue_mapping(tx->skb) == IEEE80211_AC_VO) return TX_CONTINUE; if (local->hw.conf.flags & IEEE80211_CONF_PS) { @@ -400,6 +400,8 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) return TX_CONTINUE; info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM; + if (tx->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) + info->hw_queue = tx->sdata->vif.cab_queue; /* device releases frame after DTIM beacon */ if (!(tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING)) @@ -1118,8 +1120,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, /* reset session timer */ if (reset_agg_timer && tid_tx->timeout) - mod_timer(&tid_tx->session_timer, - TU_TO_EXP_TIME(tid_tx->timeout)); + tid_tx->last_tx = jiffies; return queued; } @@ -1215,11 +1216,19 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, bool txpending) { struct sk_buff *skb, *tmp; - struct ieee80211_tx_info *info; unsigned long flags; skb_queue_walk_safe(skbs, skb, tmp) { - int q = skb_get_queue_mapping(skb); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + int q = info->hw_queue; + +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + if (WARN_ON_ONCE(q >= local->hw.queues)) { + __skb_unlink(skb, skbs); + dev_kfree_skb(skb); + continue; + } +#endif spin_lock_irqsave(&local->queue_stop_reason_lock, flags); if (local->queue_stop_reasons[q] || @@ -1241,7 +1250,6 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, } spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); - info = IEEE80211_SKB_CB(skb); info->control.vif = vif; info->control.sta = sta; @@ -1284,8 +1292,16 @@ static bool __ieee80211_tx(struct ieee80211_local *local, switch (sdata->vif.type) { case NL80211_IFTYPE_MONITOR: - sdata = NULL; - vif = NULL; + sdata = rcu_dereference(local->monitor_sdata); + if (sdata) { + vif = &sdata->vif; + info->hw_queue = + vif->hw_queue[skb_get_queue_mapping(skb)]; + } else if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) { + dev_kfree_skb(skb); + return true; + } else + vif = NULL; break; case NL80211_IFTYPE_AP_VLAN: sdata = container_of(sdata->bss, @@ -1400,6 +1416,12 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, tx.channel = local->hw.conf.channel; info->band = tx.channel->band; + /* set up hw_queue value early */ + if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) || + !(local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)) + info->hw_queue = + sdata->vif.hw_queue[skb_get_queue_mapping(skb)]; + if (!invoke_tx_handlers(&tx)) result = __ieee80211_tx(local, &tx.skbs, led_len, tx.sta, txpending); @@ -1468,12 +1490,12 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) if (ieee80211_vif_is_mesh(&sdata->vif) && ieee80211_is_data(hdr->frame_control) && - !is_multicast_ether_addr(hdr->addr1)) - if (mesh_nexthop_resolve(skb, sdata)) { - /* skb queued: don't free */ - rcu_read_unlock(); - return; - } + !is_multicast_ether_addr(hdr->addr1) && + mesh_nexthop_resolve(skb, sdata)) { + /* skb queued: don't free */ + rcu_read_unlock(); + return; + } ieee80211_set_qos_hdr(sdata, skb); ieee80211_tx(sdata, skb, false); @@ -1929,7 +1951,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, wme_sta = true; /* receiver and we are QoS enabled, use a QoS type frame */ - if (wme_sta && local->hw.queues >= 4) { + if (wme_sta && local->hw.queues >= IEEE80211_NUM_ACS) { fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); hdrlen += 2; } @@ -2170,7 +2192,6 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, void ieee80211_tx_pending(unsigned long data) { struct ieee80211_local *local = (struct ieee80211_local *)data; - struct ieee80211_sub_if_data *sdata; unsigned long flags; int i; bool txok; @@ -2207,8 +2228,7 @@ void ieee80211_tx_pending(unsigned long data) } if (skb_queue_empty(&local->pending[i])) - list_for_each_entry_rcu(sdata, &local->interfaces, list) - netif_wake_subqueue(sdata->dev, i); + ieee80211_propagate_queue_wake(local, i); } spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); @@ -2374,6 +2394,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, IEEE80211_STYPE_BEACON); } else if (ieee80211_vif_is_mesh(&sdata->vif)) { struct ieee80211_mgmt *mgmt; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; u8 *pos; int hdr_len = offsetof(struct ieee80211_mgmt, u.beacon) + sizeof(mgmt->u.beacon); @@ -2383,6 +2404,10 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, goto out; #endif + if (ifmsh->sync_ops) + ifmsh->sync_ops->adjust_tbtt( + sdata); + skb = dev_alloc_skb(local->tx_headroom + hdr_len + 2 + /* NULL SSID */ @@ -2390,7 +2415,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, 2 + 3 + /* DS params */ 2 + (IEEE80211_MAX_SUPP_RATES - 8) + 2 + sizeof(struct ieee80211_ht_cap) + - 2 + sizeof(struct ieee80211_ht_info) + + 2 + sizeof(struct ieee80211_ht_operation) + 2 + sdata->u.mesh.mesh_id_len + 2 + sizeof(struct ieee80211_meshconf_ie) + sdata->u.mesh.ie_len); @@ -2414,12 +2439,12 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, *pos++ = WLAN_EID_SSID; *pos++ = 0x0; - if (ieee80211_add_srates_ie(&sdata->vif, skb) || + if (ieee80211_add_srates_ie(&sdata->vif, skb, true) || mesh_add_ds_params_ie(skb, sdata) || - ieee80211_add_ext_srates_ie(&sdata->vif, skb) || + ieee80211_add_ext_srates_ie(&sdata->vif, skb, true) || mesh_add_rsn_ie(skb, sdata) || mesh_add_ht_cap_ie(skb, sdata) || - mesh_add_ht_info_ie(skb, sdata) || + mesh_add_ht_oper_ie(skb, sdata) || mesh_add_meshid_ie(skb, sdata) || mesh_add_meshconf_ie(skb, sdata) || mesh_add_vendor_ies(skb, sdata)) { @@ -2603,7 +2628,7 @@ struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, pos = skb_put(skb, ie_ssid_len); *pos++ = WLAN_EID_SSID; *pos++ = ssid_len; - if (ssid) + if (ssid_len) memcpy(pos, ssid, ssid_len); pos += ssid_len; @@ -2710,11 +2735,13 @@ EXPORT_SYMBOL(ieee80211_get_buffered_bc); void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int tid) { + int ac = ieee802_1d_to_ac[tid]; + skb_set_mac_header(skb, 0); skb_set_network_header(skb, 0); skb_set_transport_header(skb, 0); - skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]); + skb_set_queue_mapping(skb, ac); skb->priority = tid; /* diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 32f7a3b..e67fe5c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -265,17 +265,45 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, } EXPORT_SYMBOL(ieee80211_ctstoself_duration); +void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue) +{ + struct ieee80211_sub_if_data *sdata; + + list_for_each_entry_rcu(sdata, &local->interfaces, list) { + int ac; + + if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) + continue; + + if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE && + local->queue_stop_reasons[sdata->vif.cab_queue] != 0) + continue; + + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { + int ac_queue = sdata->vif.hw_queue[ac]; + + if (ac_queue == queue || + (sdata->vif.cab_queue == queue && + local->queue_stop_reasons[ac_queue] == 0 && + skb_queue_empty(&local->pending[ac_queue]))) + netif_wake_subqueue(sdata->dev, ac); + } + } +} + static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, enum queue_stop_reason reason) { struct ieee80211_local *local = hw_to_local(hw); - struct ieee80211_sub_if_data *sdata; trace_wake_queue(local, queue, reason); if (WARN_ON(queue >= hw->queues)) return; + if (!test_bit(reason, &local->queue_stop_reasons[queue])) + return; + __clear_bit(reason, &local->queue_stop_reasons[queue]); if (local->queue_stop_reasons[queue] != 0) @@ -284,11 +312,7 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, if (skb_queue_empty(&local->pending[queue])) { rcu_read_lock(); - list_for_each_entry_rcu(sdata, &local->interfaces, list) { - if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) - continue; - netif_wake_subqueue(sdata->dev, queue); - } + ieee80211_propagate_queue_wake(local, queue); rcu_read_unlock(); } else tasklet_schedule(&local->tx_pending_tasklet); @@ -323,11 +347,21 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, if (WARN_ON(queue >= hw->queues)) return; + if (test_bit(reason, &local->queue_stop_reasons[queue])) + return; + __set_bit(reason, &local->queue_stop_reasons[queue]); rcu_read_lock(); - list_for_each_entry_rcu(sdata, &local->interfaces, list) - netif_stop_subqueue(sdata->dev, queue); + list_for_each_entry_rcu(sdata, &local->interfaces, list) { + int ac; + + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { + if (sdata->vif.hw_queue[ac] == queue || + sdata->vif.cab_queue == queue) + netif_stop_subqueue(sdata->dev, ac); + } + } rcu_read_unlock(); } @@ -354,8 +388,8 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, { struct ieee80211_hw *hw = &local->hw; unsigned long flags; - int queue = skb_get_queue_mapping(skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + int queue = info->hw_queue; if (WARN_ON(!info->control.vif)) { kfree_skb(skb); @@ -379,10 +413,6 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, int queue, i; spin_lock_irqsave(&local->queue_stop_reason_lock, flags); - for (i = 0; i < hw->queues; i++) - __ieee80211_stop_queue(hw, i, - IEEE80211_QUEUE_STOP_REASON_SKB_ADD); - while ((skb = skb_dequeue(skbs))) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -391,7 +421,11 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, continue; } - queue = skb_get_queue_mapping(skb); + queue = info->hw_queue; + + __ieee80211_stop_queue(hw, queue, + IEEE80211_QUEUE_STOP_REASON_SKB_ADD); + __skb_queue_tail(&local->pending[queue], skb); } @@ -404,12 +438,6 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); } -void ieee80211_add_pending_skbs(struct ieee80211_local *local, - struct sk_buff_head *skbs) -{ - ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); -} - void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, enum queue_stop_reason reason) { @@ -684,9 +712,9 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, else elem_parse_failed = true; break; - case WLAN_EID_HT_INFORMATION: - if (elen >= sizeof(struct ieee80211_ht_info)) - elems->ht_info_elem = (void *)pos; + case WLAN_EID_HT_OPERATION: + if (elen >= sizeof(struct ieee80211_ht_operation)) + elems->ht_operation = (void *)pos; else elem_parse_failed = true; break; @@ -775,19 +803,22 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; struct ieee80211_tx_queue_params qparam; - int queue; + int ac; bool use_11b; int aCWmin, aCWmax; if (!local->ops->conf_tx) return; + if (local->hw.queues < IEEE80211_NUM_ACS) + return; + memset(&qparam, 0, sizeof(qparam)); use_11b = (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) && !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); - for (queue = 0; queue < local->hw.queues; queue++) { + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { /* Set defaults according to 802.11-2007 Table 7-37 */ aCWmax = 1023; if (use_11b) @@ -795,21 +826,21 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, else aCWmin = 15; - switch (queue) { - case 3: /* AC_BK */ + switch (ac) { + case IEEE80211_AC_BK: qparam.cw_max = aCWmax; qparam.cw_min = aCWmin; qparam.txop = 0; qparam.aifs = 7; break; default: /* never happens but let's not leave undefined */ - case 2: /* AC_BE */ + case IEEE80211_AC_BE: qparam.cw_max = aCWmax; qparam.cw_min = aCWmin; qparam.txop = 0; qparam.aifs = 3; break; - case 1: /* AC_VI */ + case IEEE80211_AC_VI: qparam.cw_max = aCWmin; qparam.cw_min = (aCWmin + 1) / 2 - 1; if (use_11b) @@ -818,7 +849,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, qparam.txop = 3008/32; qparam.aifs = 2; break; - case 0: /* AC_VO */ + case IEEE80211_AC_VO: qparam.cw_max = (aCWmin + 1) / 2 - 1; qparam.cw_min = (aCWmin + 1) / 4 - 1; if (use_11b) @@ -831,8 +862,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, qparam.uapsd = false; - sdata->tx_conf[queue] = qparam; - drv_conf_tx(local, sdata, queue, &qparam); + sdata->tx_conf[ac] = qparam; + drv_conf_tx(local, sdata, ac, &qparam); } /* after reinitialize QoS TX queues setting to default, @@ -1106,7 +1137,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, u32 ieee80211_sta_get_rates(struct ieee80211_local *local, struct ieee802_11_elems *elems, - enum ieee80211_band band) + enum ieee80211_band band, u32 *basic_rates) { struct ieee80211_supported_band *sband; struct ieee80211_rate *bitrates; @@ -1127,15 +1158,25 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local, elems->ext_supp_rates_len; i++) { u8 rate = 0; int own_rate; + bool is_basic; if (i < elems->supp_rates_len) rate = elems->supp_rates[i]; else if (elems->ext_supp_rates) rate = elems->ext_supp_rates [i - elems->supp_rates_len]; own_rate = 5 * (rate & 0x7f); - for (j = 0; j < num_rates; j++) - if (bitrates[j].bitrate == own_rate) + is_basic = !!(rate & 0x80); + + if (is_basic && (rate & 0x7f) == BSS_MEMBERSHIP_SELECTOR_HT_PHY) + continue; + + for (j = 0; j < num_rates; j++) { + if (bitrates[j].bitrate == own_rate) { supp_rates |= BIT(j); + if (basic_rates && is_basic) + *basic_rates |= BIT(j); + } + } } return supp_rates; } @@ -1210,6 +1251,16 @@ int ieee80211_reconfig(struct ieee80211_local *local) IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); /* add interfaces */ + sdata = rtnl_dereference(local->monitor_sdata); + if (sdata) { + res = drv_add_interface(local, sdata); + if (WARN_ON(res)) { + rcu_assign_pointer(local->monitor_sdata, NULL); + synchronize_net(); + kfree(sdata); + } + } + list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && sdata->vif.type != NL80211_IFTYPE_MONITOR && @@ -1232,14 +1283,17 @@ int ieee80211_reconfig(struct ieee80211_local *local) mutex_unlock(&local->sta_mtx); /* reconfigure tx conf */ - list_for_each_entry(sdata, &local->interfaces, list) { - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN || - sdata->vif.type == NL80211_IFTYPE_MONITOR || - !ieee80211_sdata_running(sdata)) - continue; + if (hw->queues >= IEEE80211_NUM_ACS) { + list_for_each_entry(sdata, &local->interfaces, list) { + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN || + sdata->vif.type == NL80211_IFTYPE_MONITOR || + !ieee80211_sdata_running(sdata)) + continue; - for (i = 0; i < hw->queues; i++) - drv_conf_tx(local, sdata, i, &sdata->tx_conf[i]); + for (i = 0; i < IEEE80211_NUM_ACS; i++) + drv_conf_tx(local, sdata, i, + &sdata->tx_conf[i]); + } } /* reconfigure hardware */ @@ -1611,57 +1665,56 @@ u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, return pos; } -u8 *ieee80211_ie_build_ht_info(u8 *pos, - struct ieee80211_sta_ht_cap *ht_cap, +u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, struct ieee80211_channel *channel, enum nl80211_channel_type channel_type) { - struct ieee80211_ht_info *ht_info; + struct ieee80211_ht_operation *ht_oper; /* Build HT Information */ - *pos++ = WLAN_EID_HT_INFORMATION; - *pos++ = sizeof(struct ieee80211_ht_info); - ht_info = (struct ieee80211_ht_info *)pos; - ht_info->control_chan = + *pos++ = WLAN_EID_HT_OPERATION; + *pos++ = sizeof(struct ieee80211_ht_operation); + ht_oper = (struct ieee80211_ht_operation *)pos; + ht_oper->primary_chan = ieee80211_frequency_to_channel(channel->center_freq); switch (channel_type) { case NL80211_CHAN_HT40MINUS: - ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; + ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; break; case NL80211_CHAN_HT40PLUS: - ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; + ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; break; case NL80211_CHAN_HT20: default: - ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; + ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; break; } if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) - ht_info->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; + ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; /* * Note: According to 802.11n-2009 9.13.3.1, HT Protection field and * RIFS Mode are reserved in IBSS mode, therefore keep them at 0 */ - ht_info->operation_mode = 0x0000; - ht_info->stbc_param = 0x0000; + ht_oper->operation_mode = 0x0000; + ht_oper->stbc_param = 0x0000; /* It seems that Basic MCS set and Supported MCS set are identical for the first 10 bytes */ - memset(&ht_info->basic_set, 0, 16); - memcpy(&ht_info->basic_set, &ht_cap->mcs, 10); + memset(&ht_oper->basic_set, 0, 16); + memcpy(&ht_oper->basic_set, &ht_cap->mcs, 10); - return pos + sizeof(struct ieee80211_ht_info); + return pos + sizeof(struct ieee80211_ht_operation); } enum nl80211_channel_type -ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info) +ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper) { enum nl80211_channel_type channel_type; - if (!ht_info) + if (!ht_oper) return NL80211_CHAN_NO_HT; - switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { + switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { case IEEE80211_HT_PARAM_CHA_SEC_NONE: channel_type = NL80211_CHAN_HT20; break; @@ -1678,13 +1731,15 @@ ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info) return channel_type; } -int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb) +int ieee80211_add_srates_ie(struct ieee80211_vif *vif, + struct sk_buff *skb, bool need_basic) { struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; int rate; u8 i, rates, *pos; + u32 basic_rates = vif->bss_conf.basic_rates; sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; rates = sband->n_bitrates; @@ -1698,20 +1753,25 @@ int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb) *pos++ = WLAN_EID_SUPP_RATES; *pos++ = rates; for (i = 0; i < rates; i++) { + u8 basic = 0; + if (need_basic && basic_rates & BIT(i)) + basic = 0x80; rate = sband->bitrates[i].bitrate; - *pos++ = (u8) (rate / 5); + *pos++ = basic | (u8) (rate / 5); } return 0; } -int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb) +int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, + struct sk_buff *skb, bool need_basic) { struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; int rate; u8 i, exrates, *pos; + u32 basic_rates = vif->bss_conf.basic_rates; sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; exrates = sband->n_bitrates; @@ -1728,8 +1788,11 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb) *pos++ = WLAN_EID_EXT_SUPP_RATES; *pos++ = exrates; for (i = 8; i < sband->n_bitrates; i++) { + u8 basic = 0; + if (need_basic && basic_rates & BIT(i)) + basic = 0x80; rate = sband->bitrates[i].bitrate; - *pos++ = (u8) (rate / 5); + *pos++ = basic | (u8) (rate / 5); } } return 0; diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 89511be..c3d643a 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -52,6 +52,26 @@ static int wme_downgrade_ac(struct sk_buff *skb) } } +static u16 ieee80211_downgrade_queue(struct ieee80211_local *local, + struct sk_buff *skb) +{ + /* in case we are a client verify acm is not set for this ac */ + while (unlikely(local->wmm_acm & BIT(skb->priority))) { + if (wme_downgrade_ac(skb)) { + /* + * This should not really happen. The AP has marked all + * lower ACs to require admission control which is not + * a reasonable configuration. Allow the frame to be + * transmitted using AC_BK as a workaround. + */ + break; + } + } + + /* look up which queue to use for frames with this 1d tag */ + return ieee802_1d_to_ac[skb->priority]; +} + /* Indicate which queue to use for this fully formed 802.11 frame */ u16 ieee80211_select_queue_80211(struct ieee80211_local *local, struct sk_buff *skb, @@ -59,7 +79,7 @@ u16 ieee80211_select_queue_80211(struct ieee80211_local *local, { u8 *p; - if (local->hw.queues < 4) + if (local->hw.queues < IEEE80211_NUM_ACS) return 0; if (!ieee80211_is_data(hdr->frame_control)) { @@ -86,9 +106,9 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, const u8 *ra = NULL; bool qos = false; - if (local->hw.queues < 4 || skb->len < 6) { + if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) { skb->priority = 0; /* required for correct WPA/11i MIC */ - return min_t(u16, local->hw.queues - 1, IEEE80211_AC_BE); + return 0; } rcu_read_lock(); @@ -139,26 +159,6 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, return ieee80211_downgrade_queue(local, skb); } -u16 ieee80211_downgrade_queue(struct ieee80211_local *local, - struct sk_buff *skb) -{ - /* in case we are a client verify acm is not set for this ac */ - while (unlikely(local->wmm_acm & BIT(skb->priority))) { - if (wme_downgrade_ac(skb)) { - /* - * This should not really happen. The AP has marked all - * lower ACs to require admission control which is not - * a reasonable configuration. Allow the frame to be - * transmitted using AC_BK as a workaround. - */ - break; - } - } - - /* look up which queue to use for frames with this 1d tag */ - return ieee802_1d_to_ac[skb->priority]; -} - void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h index 94edceb..ca80818 100644 --- a/net/mac80211/wme.h +++ b/net/mac80211/wme.h @@ -22,8 +22,5 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); -u16 ieee80211_downgrade_queue(struct ieee80211_local *local, - struct sk_buff *skb); - #endif /* _WME_H */ diff --git a/net/netfilter/ipset/ip_set_bitmap_ip.c b/net/netfilter/ipset/ip_set_bitmap_ip.c index a72a4df..7e1b061 100644 --- a/net/netfilter/ipset/ip_set_bitmap_ip.c +++ b/net/netfilter/ipset/ip_set_bitmap_ip.c @@ -109,8 +109,9 @@ bitmap_ip_list(const struct ip_set *set, } else goto nla_put_failure; } - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, - htonl(map->first_ip + id * map->hosts)); + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, + htonl(map->first_ip + id * map->hosts))) + goto nla_put_failure; ipset_nest_end(skb, nested); } ipset_nest_end(skb, atd); @@ -194,10 +195,11 @@ bitmap_ip_tlist(const struct ip_set *set, } else goto nla_put_failure; } - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, - htonl(map->first_ip + id * map->hosts)); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(members[id]))); + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, + htonl(map->first_ip + id * map->hosts)) || + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, + htonl(ip_set_timeout_get(members[id])))) + goto nla_put_failure; ipset_nest_end(skb, nested); } ipset_nest_end(skb, adt); @@ -334,15 +336,16 @@ bitmap_ip_head(struct ip_set *set, struct sk_buff *skb) nested = ipset_nest_start(skb, IPSET_ATTR_DATA); if (!nested) goto nla_put_failure; - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip)); - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)); - if (map->netmask != 32) - NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask); - NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)); - NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, - htonl(sizeof(*map) + map->memsize)); - if (with_timeout(map->timeout)) - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)); + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, htonl(map->first_ip)) || + nla_put_ipaddr4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)) || + (map->netmask != 32 && + nla_put_u8(skb, IPSET_ATTR_NETMASK, map->netmask)) || + nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) || + nla_put_net32(skb, IPSET_ATTR_MEMSIZE, + htonl(sizeof(*map) + map->memsize)) || + (with_timeout(map->timeout) && + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)))) + goto nla_put_failure; ipset_nest_end(skb, nested); return 0; diff --git a/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/net/netfilter/ipset/ip_set_bitmap_ipmac.c index 81324c1..0bb16c46 100644 --- a/net/netfilter/ipset/ip_set_bitmap_ipmac.c +++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c @@ -186,11 +186,12 @@ bitmap_ipmac_list(const struct ip_set *set, } else goto nla_put_failure; } - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, - htonl(map->first_ip + id)); - if (elem->match == MAC_FILLED) - NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN, - elem->ether); + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, + htonl(map->first_ip + id)) || + (elem->match == MAC_FILLED && + nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN, + elem->ether))) + goto nla_put_failure; ipset_nest_end(skb, nested); } ipset_nest_end(skb, atd); @@ -314,14 +315,16 @@ bitmap_ipmac_tlist(const struct ip_set *set, } else goto nla_put_failure; } - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, - htonl(map->first_ip + id)); - if (elem->match == MAC_FILLED) - NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN, - elem->ether); + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, + htonl(map->first_ip + id)) || + (elem->match == MAC_FILLED && + nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN, + elem->ether))) + goto nla_put_failure; timeout = elem->match == MAC_UNSET ? elem->timeout : ip_set_timeout_get(elem->timeout); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(timeout)); + if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(timeout))) + goto nla_put_failure; ipset_nest_end(skb, nested); } ipset_nest_end(skb, atd); @@ -438,14 +441,16 @@ bitmap_ipmac_head(struct ip_set *set, struct sk_buff *skb) nested = ipset_nest_start(skb, IPSET_ATTR_DATA); if (!nested) goto nla_put_failure; - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip)); - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)); - NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)); - NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, - htonl(sizeof(*map) - + (map->last_ip - map->first_ip + 1) * map->dsize)); - if (with_timeout(map->timeout)) - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)); + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, htonl(map->first_ip)) || + nla_put_ipaddr4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)) || + nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) || + nla_put_net32(skb, IPSET_ATTR_MEMSIZE, + htonl(sizeof(*map) + + ((map->last_ip - map->first_ip + 1) * + map->dsize))) || + (with_timeout(map->timeout) && + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)))) + goto nla_put_failure; ipset_nest_end(skb, nested); return 0; diff --git a/net/netfilter/ipset/ip_set_bitmap_port.c b/net/netfilter/ipset/ip_set_bitmap_port.c index 382ec28..b9f1fce 100644 --- a/net/netfilter/ipset/ip_set_bitmap_port.c +++ b/net/netfilter/ipset/ip_set_bitmap_port.c @@ -96,8 +96,9 @@ bitmap_port_list(const struct ip_set *set, } else goto nla_put_failure; } - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, - htons(map->first_port + id)); + if (nla_put_net16(skb, IPSET_ATTR_PORT, + htons(map->first_port + id))) + goto nla_put_failure; ipset_nest_end(skb, nested); } ipset_nest_end(skb, atd); @@ -183,10 +184,11 @@ bitmap_port_tlist(const struct ip_set *set, } else goto nla_put_failure; } - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, - htons(map->first_port + id)); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(members[id]))); + if (nla_put_net16(skb, IPSET_ATTR_PORT, + htons(map->first_port + id)) || + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, + htonl(ip_set_timeout_get(members[id])))) + goto nla_put_failure; ipset_nest_end(skb, nested); } ipset_nest_end(skb, adt); @@ -320,13 +322,14 @@ bitmap_port_head(struct ip_set *set, struct sk_buff *skb) nested = ipset_nest_start(skb, IPSET_ATTR_DATA); if (!nested) goto nla_put_failure; - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, htons(map->first_port)); - NLA_PUT_NET16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port)); - NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)); - NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, - htonl(sizeof(*map) + map->memsize)); - if (with_timeout(map->timeout)) - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)); + if (nla_put_net16(skb, IPSET_ATTR_PORT, htons(map->first_port)) || + nla_put_net16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port)) || + nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) || + nla_put_net32(skb, IPSET_ATTR_MEMSIZE, + htonl(sizeof(*map) + map->memsize)) || + (with_timeout(map->timeout) && + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)))) + goto nla_put_failure; ipset_nest_end(skb, nested); return 0; diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index e6c1c96..819c342 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c @@ -1092,19 +1092,21 @@ dump_last: ret = -EMSGSIZE; goto release_refcount; } - NLA_PUT_U8(skb, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL); - NLA_PUT_STRING(skb, IPSET_ATTR_SETNAME, set->name); + if (nla_put_u8(skb, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL) || + nla_put_string(skb, IPSET_ATTR_SETNAME, set->name)) + goto nla_put_failure; if (dump_flags & IPSET_FLAG_LIST_SETNAME) goto next_set; switch (cb->args[2]) { case 0: /* Core header data */ - NLA_PUT_STRING(skb, IPSET_ATTR_TYPENAME, - set->type->name); - NLA_PUT_U8(skb, IPSET_ATTR_FAMILY, - set->family); - NLA_PUT_U8(skb, IPSET_ATTR_REVISION, - set->revision); + if (nla_put_string(skb, IPSET_ATTR_TYPENAME, + set->type->name) || + nla_put_u8(skb, IPSET_ATTR_FAMILY, + set->family) || + nla_put_u8(skb, IPSET_ATTR_REVISION, + set->revision)) + goto nla_put_failure; ret = set->variant->head(set, skb); if (ret < 0) goto release_refcount; @@ -1410,11 +1412,12 @@ ip_set_header(struct sock *ctnl, struct sk_buff *skb, IPSET_CMD_HEADER); if (!nlh2) goto nlmsg_failure; - NLA_PUT_U8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL); - NLA_PUT_STRING(skb2, IPSET_ATTR_SETNAME, set->name); - NLA_PUT_STRING(skb2, IPSET_ATTR_TYPENAME, set->type->name); - NLA_PUT_U8(skb2, IPSET_ATTR_FAMILY, set->family); - NLA_PUT_U8(skb2, IPSET_ATTR_REVISION, set->revision); + if (nla_put_u8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL) || + nla_put_string(skb2, IPSET_ATTR_SETNAME, set->name) || + nla_put_string(skb2, IPSET_ATTR_TYPENAME, set->type->name) || + nla_put_u8(skb2, IPSET_ATTR_FAMILY, set->family) || + nla_put_u8(skb2, IPSET_ATTR_REVISION, set->revision)) + goto nla_put_failure; nlmsg_end(skb2, nlh2); ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); @@ -1469,11 +1472,12 @@ ip_set_type(struct sock *ctnl, struct sk_buff *skb, IPSET_CMD_TYPE); if (!nlh2) goto nlmsg_failure; - NLA_PUT_U8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL); - NLA_PUT_STRING(skb2, IPSET_ATTR_TYPENAME, typename); - NLA_PUT_U8(skb2, IPSET_ATTR_FAMILY, family); - NLA_PUT_U8(skb2, IPSET_ATTR_REVISION, max); - NLA_PUT_U8(skb2, IPSET_ATTR_REVISION_MIN, min); + if (nla_put_u8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL) || + nla_put_string(skb2, IPSET_ATTR_TYPENAME, typename) || + nla_put_u8(skb2, IPSET_ATTR_FAMILY, family) || + nla_put_u8(skb2, IPSET_ATTR_REVISION, max) || + nla_put_u8(skb2, IPSET_ATTR_REVISION_MIN, min)) + goto nla_put_failure; nlmsg_end(skb2, nlh2); pr_debug("Send TYPE, nlmsg_len: %u\n", nlh2->nlmsg_len); @@ -1517,7 +1521,8 @@ ip_set_protocol(struct sock *ctnl, struct sk_buff *skb, IPSET_CMD_PROTOCOL); if (!nlh2) goto nlmsg_failure; - NLA_PUT_U8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL); + if (nla_put_u8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL)) + goto nla_put_failure; nlmsg_end(skb2, nlh2); ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); @@ -1613,7 +1618,7 @@ static struct nfnetlink_subsystem ip_set_netlink_subsys __read_mostly = { static int ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len) { - unsigned *op; + unsigned int *op; void *data; int copylen = *len, ret = 0; @@ -1621,7 +1626,7 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len) return -EPERM; if (optval != SO_IP_SET) return -EBADF; - if (*len < sizeof(unsigned)) + if (*len < sizeof(unsigned int)) return -EINVAL; data = vmalloc(*len); @@ -1631,7 +1636,7 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len) ret = -EFAULT; goto done; } - op = (unsigned *) data; + op = (unsigned int *) data; if (*op < IP_SET_OP_VERSION) { /* Check the version at the beginning of operations */ diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c index 5139dea..507fe93 100644 --- a/net/netfilter/ipset/ip_set_hash_ip.c +++ b/net/netfilter/ipset/ip_set_hash_ip.c @@ -81,7 +81,8 @@ hash_ip4_data_zero_out(struct hash_ip4_elem *elem) static inline bool hash_ip4_data_list(struct sk_buff *skb, const struct hash_ip4_elem *data) { - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip)) + goto nla_put_failure; return 0; nla_put_failure: @@ -94,9 +95,10 @@ hash_ip4_data_tlist(struct sk_buff *skb, const struct hash_ip4_elem *data) const struct hash_ip4_telem *tdata = (const struct hash_ip4_telem *)data; - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(tdata->timeout))); + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, tdata->ip) || + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, + htonl(ip_set_timeout_get(tdata->timeout)))) + goto nla_put_failure; return 0; @@ -262,7 +264,8 @@ ip6_netmask(union nf_inet_addr *ip, u8 prefix) static bool hash_ip6_data_list(struct sk_buff *skb, const struct hash_ip6_elem *data) { - NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); + if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6)) + goto nla_put_failure; return 0; nla_put_failure: @@ -275,9 +278,10 @@ hash_ip6_data_tlist(struct sk_buff *skb, const struct hash_ip6_elem *data) const struct hash_ip6_telem *e = (const struct hash_ip6_telem *)data; - NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(e->timeout))); + if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6) || + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, + htonl(ip_set_timeout_get(e->timeout)))) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c index 9c27e24..68f284c 100644 --- a/net/netfilter/ipset/ip_set_hash_ipport.c +++ b/net/netfilter/ipset/ip_set_hash_ipport.c @@ -93,9 +93,10 @@ static bool hash_ipport4_data_list(struct sk_buff *skb, const struct hash_ipport4_elem *data) { - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) || + nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || + nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto)) + goto nla_put_failure; return 0; nla_put_failure: @@ -109,12 +110,12 @@ hash_ipport4_data_tlist(struct sk_buff *skb, const struct hash_ipport4_telem *tdata = (const struct hash_ipport4_telem *)data; - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip); - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port); - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(tdata->timeout))); - + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, tdata->ip) || + nla_put_net16(skb, IPSET_ATTR_PORT, tdata->port) || + nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) || + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, + htonl(ip_set_timeout_get(tdata->timeout)))) + goto nla_put_failure; return 0; nla_put_failure: @@ -308,9 +309,10 @@ static bool hash_ipport6_data_list(struct sk_buff *skb, const struct hash_ipport6_elem *data) { - NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); + if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) || + nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || + nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto)) + goto nla_put_failure; return 0; nla_put_failure: @@ -324,11 +326,12 @@ hash_ipport6_data_tlist(struct sk_buff *skb, const struct hash_ipport6_telem *e = (const struct hash_ipport6_telem *)data; - NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip); - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(e->timeout))); + if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6) || + nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || + nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) || + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, + htonl(ip_set_timeout_get(e->timeout)))) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c index 9134057..1eec4b9 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportip.c +++ b/net/netfilter/ipset/ip_set_hash_ipportip.c @@ -94,10 +94,11 @@ static bool hash_ipportip4_data_list(struct sk_buff *skb, const struct hash_ipportip4_elem *data) { - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, data->ip2); - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) || + nla_put_ipaddr4(skb, IPSET_ATTR_IP2, data->ip2) || + nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || + nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto)) + goto nla_put_failure; return 0; nla_put_failure: @@ -111,13 +112,13 @@ hash_ipportip4_data_tlist(struct sk_buff *skb, const struct hash_ipportip4_telem *tdata = (const struct hash_ipportip4_telem *)data; - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip); - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, tdata->ip2); - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port); - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(tdata->timeout))); - + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, tdata->ip) || + nla_put_ipaddr4(skb, IPSET_ATTR_IP2, tdata->ip2) || + nla_put_net16(skb, IPSET_ATTR_PORT, tdata->port) || + nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) || + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, + htonl(ip_set_timeout_get(tdata->timeout)))) + goto nla_put_failure; return 0; nla_put_failure: @@ -319,10 +320,11 @@ static bool hash_ipportip6_data_list(struct sk_buff *skb, const struct hash_ipportip6_elem *data) { - NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); - NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2); - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); + if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) || + nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip2.in6) || + nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || + nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto)) + goto nla_put_failure; return 0; nla_put_failure: @@ -336,12 +338,13 @@ hash_ipportip6_data_tlist(struct sk_buff *skb, const struct hash_ipportip6_telem *e = (const struct hash_ipportip6_telem *)data; - NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip); - NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2); - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(e->timeout))); + if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6) || + nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip2.in6) || + nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || + nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) || + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, + htonl(ip_set_timeout_get(e->timeout)))) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c index 5d05e69..62d66ec 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportnet.c +++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c @@ -124,13 +124,14 @@ hash_ipportnet4_data_list(struct sk_buff *skb, { u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, data->ip2); - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); - NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr + 1); - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); - if (flags) - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) || + nla_put_ipaddr4(skb, IPSET_ATTR_IP2, data->ip2) || + nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || + nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr + 1) || + nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) || + (flags && + nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) + goto nla_put_failure; return 0; nla_put_failure: @@ -145,16 +146,16 @@ hash_ipportnet4_data_tlist(struct sk_buff *skb, (const struct hash_ipportnet4_telem *)data; u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip); - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, tdata->ip2); - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port); - NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr + 1); - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(tdata->timeout))); - if (flags) - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); - + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, tdata->ip) || + nla_put_ipaddr4(skb, IPSET_ATTR_IP2, tdata->ip2) || + nla_put_net16(skb, IPSET_ATTR_PORT, tdata->port) || + nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr + 1) || + nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) || + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, + htonl(ip_set_timeout_get(tdata->timeout))) || + (flags && + nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) + goto nla_put_failure; return 0; nla_put_failure: @@ -436,13 +437,14 @@ hash_ipportnet6_data_list(struct sk_buff *skb, { u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; - NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); - NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2); - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); - NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr + 1); - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); - if (flags) - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); + if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) || + nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip2.in6) || + nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || + nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr + 1) || + nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) || + (flags && + nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) + goto nla_put_failure; return 0; nla_put_failure: @@ -457,15 +459,16 @@ hash_ipportnet6_data_tlist(struct sk_buff *skb, (const struct hash_ipportnet6_telem *)data; u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; - NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip); - NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2); - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); - NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr + 1); - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(e->timeout))); - if (flags) - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); + if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6) || + nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip2.in6) || + nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || + nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr + 1) || + nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) || + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, + htonl(ip_set_timeout_get(e->timeout))) || + (flags && + nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c index 7c3d945..6607a81 100644 --- a/net/netfilter/ipset/ip_set_hash_net.c +++ b/net/netfilter/ipset/ip_set_hash_net.c @@ -111,10 +111,11 @@ hash_net4_data_list(struct sk_buff *skb, const struct hash_net4_elem *data) { u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); - NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); - if (flags) - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) || + nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) || + (flags && + nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) + goto nla_put_failure; return 0; nla_put_failure: @@ -128,13 +129,13 @@ hash_net4_data_tlist(struct sk_buff *skb, const struct hash_net4_elem *data) (const struct hash_net4_telem *)data; u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip); - NLA_PUT_U8(skb, IPSET_ATTR_CIDR, tdata->cidr); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(tdata->timeout))); - if (flags) - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); - + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, tdata->ip) || + nla_put_u8(skb, IPSET_ATTR_CIDR, tdata->cidr) || + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, + htonl(ip_set_timeout_get(tdata->timeout))) || + (flags && + nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) + goto nla_put_failure; return 0; nla_put_failure: @@ -339,10 +340,11 @@ hash_net6_data_list(struct sk_buff *skb, const struct hash_net6_elem *data) { u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; - NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); - NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); - if (flags) - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); + if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) || + nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) || + (flags && + nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) + goto nla_put_failure; return 0; nla_put_failure: @@ -356,12 +358,13 @@ hash_net6_data_tlist(struct sk_buff *skb, const struct hash_net6_elem *data) (const struct hash_net6_telem *)data; u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; - NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip); - NLA_PUT_U8(skb, IPSET_ATTR_CIDR, e->cidr); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(e->timeout))); - if (flags) - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); + if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6) || + nla_put_u8(skb, IPSET_ATTR_CIDR, e->cidr) || + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, + htonl(ip_set_timeout_get(e->timeout))) || + (flags && + nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c index f24037f..6093f3d 100644 --- a/net/netfilter/ipset/ip_set_hash_netiface.c +++ b/net/netfilter/ipset/ip_set_hash_netiface.c @@ -252,11 +252,12 @@ hash_netiface4_data_list(struct sk_buff *skb, if (data->nomatch) flags |= IPSET_FLAG_NOMATCH; - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); - NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); - NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface); - if (flags) - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) || + nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) || + nla_put_string(skb, IPSET_ATTR_IFACE, data->iface) || + (flags && + nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) + goto nla_put_failure; return 0; nla_put_failure: @@ -273,13 +274,14 @@ hash_netiface4_data_tlist(struct sk_buff *skb, if (data->nomatch) flags |= IPSET_FLAG_NOMATCH; - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); - NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); - NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface); - if (flags) - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(tdata->timeout))); + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) || + nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) || + nla_put_string(skb, IPSET_ATTR_IFACE, data->iface) || + (flags && + nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))) || + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, + htonl(ip_set_timeout_get(tdata->timeout)))) + goto nla_put_failure; return 0; @@ -555,11 +557,12 @@ hash_netiface6_data_list(struct sk_buff *skb, if (data->nomatch) flags |= IPSET_FLAG_NOMATCH; - NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); - NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); - NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface); - if (flags) - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); + if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) || + nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) || + nla_put_string(skb, IPSET_ATTR_IFACE, data->iface) || + (flags && + nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) + goto nla_put_failure; return 0; nla_put_failure: @@ -576,13 +579,14 @@ hash_netiface6_data_tlist(struct sk_buff *skb, if (data->nomatch) flags |= IPSET_FLAG_NOMATCH; - NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip); - NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); - NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface); - if (flags) - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(e->timeout))); + if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6) || + nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) || + nla_put_string(skb, IPSET_ATTR_IFACE, data->iface) || + (flags && + nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))) || + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, + htonl(ip_set_timeout_get(e->timeout)))) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c index ce2e771..ae3c644 100644 --- a/net/netfilter/ipset/ip_set_hash_netport.c +++ b/net/netfilter/ipset/ip_set_hash_netport.c @@ -124,12 +124,13 @@ hash_netport4_data_list(struct sk_buff *skb, { u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); - NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr + 1); - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); - if (flags) - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) || + nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || + nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr + 1) || + nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) || + (flags && + nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) + goto nla_put_failure; return 0; nla_put_failure: @@ -144,15 +145,15 @@ hash_netport4_data_tlist(struct sk_buff *skb, (const struct hash_netport4_telem *)data; u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip); - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port); - NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr + 1); - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(tdata->timeout))); - if (flags) - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); - + if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, tdata->ip) || + nla_put_net16(skb, IPSET_ATTR_PORT, tdata->port) || + nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr + 1) || + nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) || + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, + htonl(ip_set_timeout_get(tdata->timeout))) || + (flags && + nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) + goto nla_put_failure; return 0; nla_put_failure: @@ -402,12 +403,13 @@ hash_netport6_data_list(struct sk_buff *skb, { u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; - NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); - NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr + 1); - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); - if (flags) - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); + if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) || + nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || + nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr + 1) || + nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) || + (flags && + nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) + goto nla_put_failure; return 0; nla_put_failure: @@ -422,14 +424,15 @@ hash_netport6_data_tlist(struct sk_buff *skb, (const struct hash_netport6_telem *)data; u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; - NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip); - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); - NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr + 1); - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(e->timeout))); - if (flags) - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); + if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6) || + nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || + nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr + 1) || + nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) || + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, + htonl(ip_set_timeout_get(e->timeout))) || + (flags && + nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c index 7e095f9..6cb1225 100644 --- a/net/netfilter/ipset/ip_set_list_set.c +++ b/net/netfilter/ipset/ip_set_list_set.c @@ -402,12 +402,13 @@ list_set_head(struct ip_set *set, struct sk_buff *skb) nested = ipset_nest_start(skb, IPSET_ATTR_DATA); if (!nested) goto nla_put_failure; - NLA_PUT_NET32(skb, IPSET_ATTR_SIZE, htonl(map->size)); - if (with_timeout(map->timeout)) - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)); - NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)); - NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, - htonl(sizeof(*map) + map->size * map->dsize)); + if (nla_put_net32(skb, IPSET_ATTR_SIZE, htonl(map->size)) || + (with_timeout(map->timeout) && + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout))) || + nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) || + nla_put_net32(skb, IPSET_ATTR_MEMSIZE, + htonl(sizeof(*map) + map->size * map->dsize))) + goto nla_put_failure; ipset_nest_end(skb, nested); return 0; @@ -442,13 +443,15 @@ list_set_list(const struct ip_set *set, } else goto nla_put_failure; } - NLA_PUT_STRING(skb, IPSET_ATTR_NAME, - ip_set_name_byindex(e->id)); + if (nla_put_string(skb, IPSET_ATTR_NAME, + ip_set_name_byindex(e->id))) + goto nla_put_failure; if (with_timeout(map->timeout)) { const struct set_telem *te = (const struct set_telem *) e; - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(te->timeout))); + __be32 to = htonl(ip_set_timeout_get(te->timeout)); + if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT, to)) + goto nla_put_failure; } ipset_nest_end(skb, nested); } diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c index 5285617..64f9e8f 100644 --- a/net/netfilter/ipvs/ip_vs_app.c +++ b/net/netfilter/ipvs/ip_vs_app.c @@ -313,7 +313,7 @@ vs_fix_ack_seq(const struct ip_vs_seq *vseq, struct tcphdr *th) * Assumes already checked proto==IPPROTO_TCP and diff!=0. */ static inline void vs_seq_update(struct ip_vs_conn *cp, struct ip_vs_seq *vseq, - unsigned flag, __u32 seq, int diff) + unsigned int flag, __u32 seq, int diff) { /* spinlock is to keep updating cp->flags atomic */ spin_lock(&cp->lock); diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index 29fa5ba..4a09b78 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -86,42 +86,42 @@ struct ip_vs_aligned_lock static struct ip_vs_aligned_lock __ip_vs_conntbl_lock_array[CT_LOCKARRAY_SIZE] __cacheline_aligned; -static inline void ct_read_lock(unsigned key) +static inline void ct_read_lock(unsigned int key) { read_lock(&__ip_vs_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l); } -static inline void ct_read_unlock(unsigned key) +static inline void ct_read_unlock(unsigned int key) { read_unlock(&__ip_vs_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l); } -static inline void ct_write_lock(unsigned key) +static inline void ct_write_lock(unsigned int key) { write_lock(&__ip_vs_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l); } -static inline void ct_write_unlock(unsigned key) +static inline void ct_write_unlock(unsigned int key) { write_unlock(&__ip_vs_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l); } -static inline void ct_read_lock_bh(unsigned key) +static inline void ct_read_lock_bh(unsigned int key) { read_lock_bh(&__ip_vs_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l); } -static inline void ct_read_unlock_bh(unsigned key) +static inline void ct_read_unlock_bh(unsigned int key) { read_unlock_bh(&__ip_vs_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l); } -static inline void ct_write_lock_bh(unsigned key) +static inline void ct_write_lock_bh(unsigned int key) { write_lock_bh(&__ip_vs_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l); } -static inline void ct_write_unlock_bh(unsigned key) +static inline void ct_write_unlock_bh(unsigned int key) { write_unlock_bh(&__ip_vs_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l); } @@ -130,7 +130,7 @@ static inline void ct_write_unlock_bh(unsigned key) /* * Returns hash value for IPVS connection entry */ -static unsigned int ip_vs_conn_hashkey(struct net *net, int af, unsigned proto, +static unsigned int ip_vs_conn_hashkey(struct net *net, int af, unsigned int proto, const union nf_inet_addr *addr, __be16 port) { @@ -188,7 +188,7 @@ static unsigned int ip_vs_conn_hashkey_conn(const struct ip_vs_conn *cp) */ static inline int ip_vs_conn_hash(struct ip_vs_conn *cp) { - unsigned hash; + unsigned int hash; int ret; if (cp->flags & IP_VS_CONN_F_ONE_PACKET) @@ -224,7 +224,7 @@ static inline int ip_vs_conn_hash(struct ip_vs_conn *cp) */ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp) { - unsigned hash; + unsigned int hash; int ret; /* unhash it and decrease its reference counter */ @@ -257,7 +257,7 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp) static inline struct ip_vs_conn * __ip_vs_conn_in_get(const struct ip_vs_conn_param *p) { - unsigned hash; + unsigned int hash; struct ip_vs_conn *cp; struct hlist_node *n; @@ -344,7 +344,7 @@ EXPORT_SYMBOL_GPL(ip_vs_conn_in_get_proto); /* Get reference to connection template */ struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p) { - unsigned hash; + unsigned int hash; struct ip_vs_conn *cp; struct hlist_node *n; @@ -394,7 +394,7 @@ struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p) * p->vaddr, p->vport: pkt dest address (foreign host) */ struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p) { - unsigned hash; + unsigned int hash; struct ip_vs_conn *cp, *ret=NULL; struct hlist_node *n; @@ -824,7 +824,7 @@ void ip_vs_conn_expire_now(struct ip_vs_conn *cp) */ struct ip_vs_conn * ip_vs_conn_new(const struct ip_vs_conn_param *p, - const union nf_inet_addr *daddr, __be16 dport, unsigned flags, + const union nf_inet_addr *daddr, __be16 dport, unsigned int flags, struct ip_vs_dest *dest, __u32 fwmark) { struct ip_vs_conn *cp; @@ -1057,7 +1057,7 @@ static const struct file_operations ip_vs_conn_fops = { .release = seq_release_net, }; -static const char *ip_vs_origin_name(unsigned flags) +static const char *ip_vs_origin_name(unsigned int flags) { if (flags & IP_VS_CONN_F_SYNC) return "SYNC"; @@ -1169,7 +1169,7 @@ void ip_vs_random_dropentry(struct net *net) * Randomly scan 1/32 of the whole table every second */ for (idx = 0; idx < (ip_vs_conn_tab_size>>5); idx++) { - unsigned hash = net_random() & ip_vs_conn_tab_mask; + unsigned int hash = net_random() & ip_vs_conn_tab_mask; struct hlist_node *n; /* diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 2555816..b5a5c73 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -80,7 +80,7 @@ static atomic_t ipvs_netns_cnt = ATOMIC_INIT(0); #define icmp_id(icmph) (((icmph)->un).echo.id) #define icmpv6_id(icmph) (icmph->icmp6_dataun.u_echo.identifier) -const char *ip_vs_proto_name(unsigned proto) +const char *ip_vs_proto_name(unsigned int proto) { static char buf[20]; diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index b3afe18..b8d0df7 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -265,11 +265,11 @@ static struct list_head ip_vs_svc_fwm_table[IP_VS_SVC_TAB_SIZE]; /* * Returns hash value for virtual service */ -static inline unsigned -ip_vs_svc_hashkey(struct net *net, int af, unsigned proto, +static inline unsigned int +ip_vs_svc_hashkey(struct net *net, int af, unsigned int proto, const union nf_inet_addr *addr, __be16 port) { - register unsigned porth = ntohs(port); + register unsigned int porth = ntohs(port); __be32 addr_fold = addr->ip; #ifdef CONFIG_IP_VS_IPV6 @@ -286,7 +286,7 @@ ip_vs_svc_hashkey(struct net *net, int af, unsigned proto, /* * Returns hash value of fwmark for virtual service lookup */ -static inline unsigned ip_vs_svc_fwm_hashkey(struct net *net, __u32 fwmark) +static inline unsigned int ip_vs_svc_fwm_hashkey(struct net *net, __u32 fwmark) { return (((size_t)net>>8) ^ fwmark) & IP_VS_SVC_TAB_MASK; } @@ -298,7 +298,7 @@ static inline unsigned ip_vs_svc_fwm_hashkey(struct net *net, __u32 fwmark) */ static int ip_vs_svc_hash(struct ip_vs_service *svc) { - unsigned hash; + unsigned int hash; if (svc->flags & IP_VS_SVC_F_HASHED) { pr_err("%s(): request for already hashed, called from %pF\n", @@ -361,7 +361,7 @@ static inline struct ip_vs_service * __ip_vs_service_find(struct net *net, int af, __u16 protocol, const union nf_inet_addr *vaddr, __be16 vport) { - unsigned hash; + unsigned int hash; struct ip_vs_service *svc; /* Check for "full" addressed entries */ @@ -388,7 +388,7 @@ __ip_vs_service_find(struct net *net, int af, __u16 protocol, static inline struct ip_vs_service * __ip_vs_svc_fwm_find(struct net *net, int af, __u32 fwmark) { - unsigned hash; + unsigned int hash; struct ip_vs_service *svc; /* Check for fwmark addressed entries */ @@ -489,11 +489,11 @@ __ip_vs_unbind_svc(struct ip_vs_dest *dest) /* * Returns hash value for real service */ -static inline unsigned ip_vs_rs_hashkey(int af, +static inline unsigned int ip_vs_rs_hashkey(int af, const union nf_inet_addr *addr, __be16 port) { - register unsigned porth = ntohs(port); + register unsigned int porth = ntohs(port); __be32 addr_fold = addr->ip; #ifdef CONFIG_IP_VS_IPV6 @@ -512,7 +512,7 @@ static inline unsigned ip_vs_rs_hashkey(int af, */ static int ip_vs_rs_hash(struct netns_ipvs *ipvs, struct ip_vs_dest *dest) { - unsigned hash; + unsigned int hash; if (!list_empty(&dest->d_list)) { return 0; @@ -555,7 +555,7 @@ ip_vs_lookup_real_service(struct net *net, int af, __u16 protocol, __be16 dport) { struct netns_ipvs *ipvs = net_ipvs(net); - unsigned hash; + unsigned int hash; struct ip_vs_dest *dest; /* @@ -842,7 +842,7 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest, struct ip_vs_dest **dest_p) { struct ip_vs_dest *dest; - unsigned atype; + unsigned int atype; EnterFunction(2); @@ -1867,7 +1867,7 @@ struct ip_vs_iter { * Write the contents of the VS rule table to a PROCfs file. * (It is kept just for backward compatibility) */ -static inline const char *ip_vs_fwd_name(unsigned flags) +static inline const char *ip_vs_fwd_name(unsigned int flags) { switch (flags & IP_VS_CONN_F_FWD_MASK) { case IP_VS_CONN_F_LOCALNODE: @@ -2816,17 +2816,17 @@ static int ip_vs_genl_fill_stats(struct sk_buff *skb, int container_type, ip_vs_copy_stats(&ustats, stats); - NLA_PUT_U32(skb, IPVS_STATS_ATTR_CONNS, ustats.conns); - NLA_PUT_U32(skb, IPVS_STATS_ATTR_INPKTS, ustats.inpkts); - NLA_PUT_U32(skb, IPVS_STATS_ATTR_OUTPKTS, ustats.outpkts); - NLA_PUT_U64(skb, IPVS_STATS_ATTR_INBYTES, ustats.inbytes); - NLA_PUT_U64(skb, IPVS_STATS_ATTR_OUTBYTES, ustats.outbytes); - NLA_PUT_U32(skb, IPVS_STATS_ATTR_CPS, ustats.cps); - NLA_PUT_U32(skb, IPVS_STATS_ATTR_INPPS, ustats.inpps); - NLA_PUT_U32(skb, IPVS_STATS_ATTR_OUTPPS, ustats.outpps); - NLA_PUT_U32(skb, IPVS_STATS_ATTR_INBPS, ustats.inbps); - NLA_PUT_U32(skb, IPVS_STATS_ATTR_OUTBPS, ustats.outbps); - + if (nla_put_u32(skb, IPVS_STATS_ATTR_CONNS, ustats.conns) || + nla_put_u32(skb, IPVS_STATS_ATTR_INPKTS, ustats.inpkts) || + nla_put_u32(skb, IPVS_STATS_ATTR_OUTPKTS, ustats.outpkts) || + nla_put_u64(skb, IPVS_STATS_ATTR_INBYTES, ustats.inbytes) || + nla_put_u64(skb, IPVS_STATS_ATTR_OUTBYTES, ustats.outbytes) || + nla_put_u32(skb, IPVS_STATS_ATTR_CPS, ustats.cps) || + nla_put_u32(skb, IPVS_STATS_ATTR_INPPS, ustats.inpps) || + nla_put_u32(skb, IPVS_STATS_ATTR_OUTPPS, ustats.outpps) || + nla_put_u32(skb, IPVS_STATS_ATTR_INBPS, ustats.inbps) || + nla_put_u32(skb, IPVS_STATS_ATTR_OUTBPS, ustats.outbps)) + goto nla_put_failure; nla_nest_end(skb, nl_stats); return 0; @@ -2847,23 +2847,25 @@ static int ip_vs_genl_fill_service(struct sk_buff *skb, if (!nl_service) return -EMSGSIZE; - NLA_PUT_U16(skb, IPVS_SVC_ATTR_AF, svc->af); - + if (nla_put_u16(skb, IPVS_SVC_ATTR_AF, svc->af)) + goto nla_put_failure; if (svc->fwmark) { - NLA_PUT_U32(skb, IPVS_SVC_ATTR_FWMARK, svc->fwmark); + if (nla_put_u32(skb, IPVS_SVC_ATTR_FWMARK, svc->fwmark)) + goto nla_put_failure; } else { - NLA_PUT_U16(skb, IPVS_SVC_ATTR_PROTOCOL, svc->protocol); - NLA_PUT(skb, IPVS_SVC_ATTR_ADDR, sizeof(svc->addr), &svc->addr); - NLA_PUT_U16(skb, IPVS_SVC_ATTR_PORT, svc->port); + if (nla_put_u16(skb, IPVS_SVC_ATTR_PROTOCOL, svc->protocol) || + nla_put(skb, IPVS_SVC_ATTR_ADDR, sizeof(svc->addr), &svc->addr) || + nla_put_u16(skb, IPVS_SVC_ATTR_PORT, svc->port)) + goto nla_put_failure; } - NLA_PUT_STRING(skb, IPVS_SVC_ATTR_SCHED_NAME, svc->scheduler->name); - if (svc->pe) - NLA_PUT_STRING(skb, IPVS_SVC_ATTR_PE_NAME, svc->pe->name); - NLA_PUT(skb, IPVS_SVC_ATTR_FLAGS, sizeof(flags), &flags); - NLA_PUT_U32(skb, IPVS_SVC_ATTR_TIMEOUT, svc->timeout / HZ); - NLA_PUT_U32(skb, IPVS_SVC_ATTR_NETMASK, svc->netmask); - + if (nla_put_string(skb, IPVS_SVC_ATTR_SCHED_NAME, svc->scheduler->name) || + (svc->pe && + nla_put_string(skb, IPVS_SVC_ATTR_PE_NAME, svc->pe->name)) || + nla_put(skb, IPVS_SVC_ATTR_FLAGS, sizeof(flags), &flags) || + nla_put_u32(skb, IPVS_SVC_ATTR_TIMEOUT, svc->timeout / HZ) || + nla_put_u32(skb, IPVS_SVC_ATTR_NETMASK, svc->netmask)) + goto nla_put_failure; if (ip_vs_genl_fill_stats(skb, IPVS_SVC_ATTR_STATS, &svc->stats)) goto nla_put_failure; @@ -3038,21 +3040,22 @@ static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest) if (!nl_dest) return -EMSGSIZE; - NLA_PUT(skb, IPVS_DEST_ATTR_ADDR, sizeof(dest->addr), &dest->addr); - NLA_PUT_U16(skb, IPVS_DEST_ATTR_PORT, dest->port); - - NLA_PUT_U32(skb, IPVS_DEST_ATTR_FWD_METHOD, - atomic_read(&dest->conn_flags) & IP_VS_CONN_F_FWD_MASK); - NLA_PUT_U32(skb, IPVS_DEST_ATTR_WEIGHT, atomic_read(&dest->weight)); - NLA_PUT_U32(skb, IPVS_DEST_ATTR_U_THRESH, dest->u_threshold); - NLA_PUT_U32(skb, IPVS_DEST_ATTR_L_THRESH, dest->l_threshold); - NLA_PUT_U32(skb, IPVS_DEST_ATTR_ACTIVE_CONNS, - atomic_read(&dest->activeconns)); - NLA_PUT_U32(skb, IPVS_DEST_ATTR_INACT_CONNS, - atomic_read(&dest->inactconns)); - NLA_PUT_U32(skb, IPVS_DEST_ATTR_PERSIST_CONNS, - atomic_read(&dest->persistconns)); - + if (nla_put(skb, IPVS_DEST_ATTR_ADDR, sizeof(dest->addr), &dest->addr) || + nla_put_u16(skb, IPVS_DEST_ATTR_PORT, dest->port) || + nla_put_u32(skb, IPVS_DEST_ATTR_FWD_METHOD, + (atomic_read(&dest->conn_flags) & + IP_VS_CONN_F_FWD_MASK)) || + nla_put_u32(skb, IPVS_DEST_ATTR_WEIGHT, + atomic_read(&dest->weight)) || + nla_put_u32(skb, IPVS_DEST_ATTR_U_THRESH, dest->u_threshold) || + nla_put_u32(skb, IPVS_DEST_ATTR_L_THRESH, dest->l_threshold) || + nla_put_u32(skb, IPVS_DEST_ATTR_ACTIVE_CONNS, + atomic_read(&dest->activeconns)) || + nla_put_u32(skb, IPVS_DEST_ATTR_INACT_CONNS, + atomic_read(&dest->inactconns)) || + nla_put_u32(skb, IPVS_DEST_ATTR_PERSIST_CONNS, + atomic_read(&dest->persistconns))) + goto nla_put_failure; if (ip_vs_genl_fill_stats(skb, IPVS_DEST_ATTR_STATS, &dest->stats)) goto nla_put_failure; @@ -3181,10 +3184,10 @@ static int ip_vs_genl_fill_daemon(struct sk_buff *skb, __be32 state, if (!nl_daemon) return -EMSGSIZE; - NLA_PUT_U32(skb, IPVS_DAEMON_ATTR_STATE, state); - NLA_PUT_STRING(skb, IPVS_DAEMON_ATTR_MCAST_IFN, mcast_ifn); - NLA_PUT_U32(skb, IPVS_DAEMON_ATTR_SYNC_ID, syncid); - + if (nla_put_u32(skb, IPVS_DAEMON_ATTR_STATE, state) || + nla_put_string(skb, IPVS_DAEMON_ATTR_MCAST_IFN, mcast_ifn) || + nla_put_u32(skb, IPVS_DAEMON_ATTR_SYNC_ID, syncid)) + goto nla_put_failure; nla_nest_end(skb, nl_daemon); return 0; @@ -3473,21 +3476,26 @@ static int ip_vs_genl_get_cmd(struct sk_buff *skb, struct genl_info *info) __ip_vs_get_timeouts(net, &t); #ifdef CONFIG_IP_VS_PROTO_TCP - NLA_PUT_U32(msg, IPVS_CMD_ATTR_TIMEOUT_TCP, t.tcp_timeout); - NLA_PUT_U32(msg, IPVS_CMD_ATTR_TIMEOUT_TCP_FIN, - t.tcp_fin_timeout); + if (nla_put_u32(msg, IPVS_CMD_ATTR_TIMEOUT_TCP, + t.tcp_timeout) || + nla_put_u32(msg, IPVS_CMD_ATTR_TIMEOUT_TCP_FIN, + t.tcp_fin_timeout)) + goto nla_put_failure; #endif #ifdef CONFIG_IP_VS_PROTO_UDP - NLA_PUT_U32(msg, IPVS_CMD_ATTR_TIMEOUT_UDP, t.udp_timeout); + if (nla_put_u32(msg, IPVS_CMD_ATTR_TIMEOUT_UDP, t.udp_timeout)) + goto nla_put_failure; #endif break; } case IPVS_CMD_GET_INFO: - NLA_PUT_U32(msg, IPVS_INFO_ATTR_VERSION, IP_VS_VERSION_CODE); - NLA_PUT_U32(msg, IPVS_INFO_ATTR_CONN_TAB_SIZE, - ip_vs_conn_tab_size); + if (nla_put_u32(msg, IPVS_INFO_ATTR_VERSION, + IP_VS_VERSION_CODE) || + nla_put_u32(msg, IPVS_INFO_ATTR_CONN_TAB_SIZE, + ip_vs_conn_tab_size)) + goto nla_put_failure; break; } diff --git a/net/netfilter/ipvs/ip_vs_dh.c b/net/netfilter/ipvs/ip_vs_dh.c index 1c269e5..1a53a7a 100644 --- a/net/netfilter/ipvs/ip_vs_dh.c +++ b/net/netfilter/ipvs/ip_vs_dh.c @@ -68,7 +68,7 @@ struct ip_vs_dh_bucket { /* * Returns hash value for IPVS DH entry */ -static inline unsigned ip_vs_dh_hashkey(int af, const union nf_inet_addr *addr) +static inline unsigned int ip_vs_dh_hashkey(int af, const union nf_inet_addr *addr) { __be32 addr_fold = addr->ip; diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c index 538d74e..debb8c7 100644 --- a/net/netfilter/ipvs/ip_vs_ftp.c +++ b/net/netfilter/ipvs/ip_vs_ftp.c @@ -177,7 +177,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, __be16 port; struct ip_vs_conn *n_cp; char buf[24]; /* xxx.xxx.xxx.xxx,ppp,ppp\000 */ - unsigned buf_len; + unsigned int buf_len; int ret = 0; enum ip_conntrack_info ctinfo; struct nf_conn *ct; diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c index 0f16283..27c24f1 100644 --- a/net/netfilter/ipvs/ip_vs_lblc.c +++ b/net/netfilter/ipvs/ip_vs_lblc.c @@ -142,7 +142,7 @@ static inline void ip_vs_lblc_free(struct ip_vs_lblc_entry *en) /* * Returns hash value for IPVS LBLC entry */ -static inline unsigned +static inline unsigned int ip_vs_lblc_hashkey(int af, const union nf_inet_addr *addr) { __be32 addr_fold = addr->ip; @@ -163,7 +163,7 @@ ip_vs_lblc_hashkey(int af, const union nf_inet_addr *addr) static void ip_vs_lblc_hash(struct ip_vs_lblc_table *tbl, struct ip_vs_lblc_entry *en) { - unsigned hash = ip_vs_lblc_hashkey(en->af, &en->addr); + unsigned int hash = ip_vs_lblc_hashkey(en->af, &en->addr); list_add(&en->list, &tbl->bucket[hash]); atomic_inc(&tbl->entries); @@ -178,7 +178,7 @@ static inline struct ip_vs_lblc_entry * ip_vs_lblc_get(int af, struct ip_vs_lblc_table *tbl, const union nf_inet_addr *addr) { - unsigned hash = ip_vs_lblc_hashkey(af, addr); + unsigned int hash = ip_vs_lblc_hashkey(af, addr); struct ip_vs_lblc_entry *en; list_for_each_entry(en, &tbl->bucket[hash], list) diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c index eec797f..7498756 100644 --- a/net/netfilter/ipvs/ip_vs_lblcr.c +++ b/net/netfilter/ipvs/ip_vs_lblcr.c @@ -311,7 +311,7 @@ static inline void ip_vs_lblcr_free(struct ip_vs_lblcr_entry *en) /* * Returns hash value for IPVS LBLCR entry */ -static inline unsigned +static inline unsigned int ip_vs_lblcr_hashkey(int af, const union nf_inet_addr *addr) { __be32 addr_fold = addr->ip; @@ -332,7 +332,7 @@ ip_vs_lblcr_hashkey(int af, const union nf_inet_addr *addr) static void ip_vs_lblcr_hash(struct ip_vs_lblcr_table *tbl, struct ip_vs_lblcr_entry *en) { - unsigned hash = ip_vs_lblcr_hashkey(en->af, &en->addr); + unsigned int hash = ip_vs_lblcr_hashkey(en->af, &en->addr); list_add(&en->list, &tbl->bucket[hash]); atomic_inc(&tbl->entries); @@ -347,7 +347,7 @@ static inline struct ip_vs_lblcr_entry * ip_vs_lblcr_get(int af, struct ip_vs_lblcr_table *tbl, const union nf_inet_addr *addr) { - unsigned hash = ip_vs_lblcr_hashkey(af, addr); + unsigned int hash = ip_vs_lblcr_hashkey(af, addr); struct ip_vs_lblcr_entry *en; list_for_each_entry(en, &tbl->bucket[hash], list) diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c index f843a88..6eda11d 100644 --- a/net/netfilter/ipvs/ip_vs_proto.c +++ b/net/netfilter/ipvs/ip_vs_proto.c @@ -48,7 +48,7 @@ static struct ip_vs_protocol *ip_vs_proto_table[IP_VS_PROTO_TAB_SIZE]; */ static int __used __init register_ip_vs_protocol(struct ip_vs_protocol *pp) { - unsigned hash = IP_VS_PROTO_HASH(pp->protocol); + unsigned int hash = IP_VS_PROTO_HASH(pp->protocol); pp->next = ip_vs_proto_table[hash]; ip_vs_proto_table[hash] = pp; @@ -69,7 +69,7 @@ static int register_ip_vs_proto_netns(struct net *net, struct ip_vs_protocol *pp) { struct netns_ipvs *ipvs = net_ipvs(net); - unsigned hash = IP_VS_PROTO_HASH(pp->protocol); + unsigned int hash = IP_VS_PROTO_HASH(pp->protocol); struct ip_vs_proto_data *pd = kzalloc(sizeof(struct ip_vs_proto_data), GFP_ATOMIC); @@ -94,7 +94,7 @@ register_ip_vs_proto_netns(struct net *net, struct ip_vs_protocol *pp) static int unregister_ip_vs_protocol(struct ip_vs_protocol *pp) { struct ip_vs_protocol **pp_p; - unsigned hash = IP_VS_PROTO_HASH(pp->protocol); + unsigned int hash = IP_VS_PROTO_HASH(pp->protocol); pp_p = &ip_vs_proto_table[hash]; for (; *pp_p; pp_p = &(*pp_p)->next) { @@ -117,7 +117,7 @@ unregister_ip_vs_proto_netns(struct net *net, struct ip_vs_proto_data *pd) { struct netns_ipvs *ipvs = net_ipvs(net); struct ip_vs_proto_data **pd_p; - unsigned hash = IP_VS_PROTO_HASH(pd->pp->protocol); + unsigned int hash = IP_VS_PROTO_HASH(pd->pp->protocol); pd_p = &ipvs->proto_data_table[hash]; for (; *pd_p; pd_p = &(*pd_p)->next) { @@ -139,7 +139,7 @@ unregister_ip_vs_proto_netns(struct net *net, struct ip_vs_proto_data *pd) struct ip_vs_protocol * ip_vs_proto_get(unsigned short proto) { struct ip_vs_protocol *pp; - unsigned hash = IP_VS_PROTO_HASH(proto); + unsigned int hash = IP_VS_PROTO_HASH(proto); for (pp = ip_vs_proto_table[hash]; pp; pp = pp->next) { if (pp->protocol == proto) @@ -157,7 +157,7 @@ struct ip_vs_proto_data * __ipvs_proto_data_get(struct netns_ipvs *ipvs, unsigned short proto) { struct ip_vs_proto_data *pd; - unsigned hash = IP_VS_PROTO_HASH(proto); + unsigned int hash = IP_VS_PROTO_HASH(proto); for (pd = ipvs->proto_data_table[hash]; pd; pd = pd->next) { if (pd->pp->protocol == proto) diff --git a/net/netfilter/ipvs/ip_vs_sh.c b/net/netfilter/ipvs/ip_vs_sh.c index 069e8d4..91e97ee 100644 --- a/net/netfilter/ipvs/ip_vs_sh.c +++ b/net/netfilter/ipvs/ip_vs_sh.c @@ -70,7 +70,7 @@ struct ip_vs_sh_bucket { /* * Returns hash value for IPVS SH entry */ -static inline unsigned ip_vs_sh_hashkey(int af, const union nf_inet_addr *addr) +static inline unsigned int ip_vs_sh_hashkey(int af, const union nf_inet_addr *addr) { __be32 addr_fold = addr->ip; diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index 8a0d6d6..f4e0b6c 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c @@ -839,7 +839,7 @@ static void ip_vs_process_message_v0(struct net *net, const char *buffer, p = (char *)buffer + sizeof(struct ip_vs_sync_mesg_v0); for (i=0; i<m->nr_conns; i++) { - unsigned flags, state; + unsigned int flags, state; if (p + SIMPLE_CONN_SIZE > buffer+buflen) { IP_VS_ERR_RL("BACKUP v0, bogus conn\n"); @@ -1109,7 +1109,7 @@ static void ip_vs_process_message(struct net *net, __u8 *buffer, for (i=0; i<nr_conns; i++) { union ip_vs_sync_conn *s; - unsigned size; + unsigned int size; int retc; p = msg_end; diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 729f157..cf0747c 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -1152,8 +1152,9 @@ static struct nf_ct_ext_type nf_ct_zone_extend __read_mostly = { int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb, const struct nf_conntrack_tuple *tuple) { - NLA_PUT_BE16(skb, CTA_PROTO_SRC_PORT, tuple->src.u.tcp.port); - NLA_PUT_BE16(skb, CTA_PROTO_DST_PORT, tuple->dst.u.tcp.port); + if (nla_put_be16(skb, CTA_PROTO_SRC_PORT, tuple->src.u.tcp.port) || + nla_put_be16(skb, CTA_PROTO_DST_PORT, tuple->dst.u.tcp.port)) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 722291f..471b054 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -1230,7 +1230,7 @@ static struct nf_conntrack_expect *find_expect(struct nf_conn *ct, /****************************************************************************/ static int set_expect_timeout(struct nf_conntrack_expect *exp, - unsigned timeout) + unsigned int timeout) { if (!exp || !del_timer(&exp->timeout)) return 0; diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index ca7e835..462ec2d 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -66,7 +66,8 @@ ctnetlink_dump_tuples_proto(struct sk_buff *skb, nest_parms = nla_nest_start(skb, CTA_TUPLE_PROTO | NLA_F_NESTED); if (!nest_parms) goto nla_put_failure; - NLA_PUT_U8(skb, CTA_PROTO_NUM, tuple->dst.protonum); + if (nla_put_u8(skb, CTA_PROTO_NUM, tuple->dst.protonum)) + goto nla_put_failure; if (likely(l4proto->tuple_to_nlattr)) ret = l4proto->tuple_to_nlattr(skb, tuple); @@ -126,7 +127,8 @@ ctnetlink_dump_tuples(struct sk_buff *skb, static inline int ctnetlink_dump_status(struct sk_buff *skb, const struct nf_conn *ct) { - NLA_PUT_BE32(skb, CTA_STATUS, htonl(ct->status)); + if (nla_put_be32(skb, CTA_STATUS, htonl(ct->status))) + goto nla_put_failure; return 0; nla_put_failure: @@ -141,7 +143,8 @@ ctnetlink_dump_timeout(struct sk_buff *skb, const struct nf_conn *ct) if (timeout < 0) timeout = 0; - NLA_PUT_BE32(skb, CTA_TIMEOUT, htonl(timeout)); + if (nla_put_be32(skb, CTA_TIMEOUT, htonl(timeout))) + goto nla_put_failure; return 0; nla_put_failure: @@ -190,7 +193,8 @@ ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct) nest_helper = nla_nest_start(skb, CTA_HELP | NLA_F_NESTED); if (!nest_helper) goto nla_put_failure; - NLA_PUT_STRING(skb, CTA_HELP_NAME, helper->name); + if (nla_put_string(skb, CTA_HELP_NAME, helper->name)) + goto nla_put_failure; if (helper->to_nlattr) helper->to_nlattr(skb, ct); @@ -214,8 +218,9 @@ dump_counters(struct sk_buff *skb, u64 pkts, u64 bytes, if (!nest_count) goto nla_put_failure; - NLA_PUT_BE64(skb, CTA_COUNTERS_PACKETS, cpu_to_be64(pkts)); - NLA_PUT_BE64(skb, CTA_COUNTERS_BYTES, cpu_to_be64(bytes)); + if (nla_put_be64(skb, CTA_COUNTERS_PACKETS, cpu_to_be64(pkts)) || + nla_put_be64(skb, CTA_COUNTERS_BYTES, cpu_to_be64(bytes))) + goto nla_put_failure; nla_nest_end(skb, nest_count); @@ -260,11 +265,10 @@ ctnetlink_dump_timestamp(struct sk_buff *skb, const struct nf_conn *ct) if (!nest_count) goto nla_put_failure; - NLA_PUT_BE64(skb, CTA_TIMESTAMP_START, cpu_to_be64(tstamp->start)); - if (tstamp->stop != 0) { - NLA_PUT_BE64(skb, CTA_TIMESTAMP_STOP, - cpu_to_be64(tstamp->stop)); - } + if (nla_put_be64(skb, CTA_TIMESTAMP_START, cpu_to_be64(tstamp->start)) || + (tstamp->stop != 0 && nla_put_be64(skb, CTA_TIMESTAMP_STOP, + cpu_to_be64(tstamp->stop)))) + goto nla_put_failure; nla_nest_end(skb, nest_count); return 0; @@ -277,7 +281,8 @@ nla_put_failure: static inline int ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct) { - NLA_PUT_BE32(skb, CTA_MARK, htonl(ct->mark)); + if (nla_put_be32(skb, CTA_MARK, htonl(ct->mark))) + goto nla_put_failure; return 0; nla_put_failure: @@ -304,7 +309,8 @@ ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct) if (!nest_secctx) goto nla_put_failure; - NLA_PUT_STRING(skb, CTA_SECCTX_NAME, secctx); + if (nla_put_string(skb, CTA_SECCTX_NAME, secctx)) + goto nla_put_failure; nla_nest_end(skb, nest_secctx); ret = 0; @@ -349,12 +355,13 @@ dump_nat_seq_adj(struct sk_buff *skb, const struct nf_nat_seq *natseq, int type) if (!nest_parms) goto nla_put_failure; - NLA_PUT_BE32(skb, CTA_NAT_SEQ_CORRECTION_POS, - htonl(natseq->correction_pos)); - NLA_PUT_BE32(skb, CTA_NAT_SEQ_OFFSET_BEFORE, - htonl(natseq->offset_before)); - NLA_PUT_BE32(skb, CTA_NAT_SEQ_OFFSET_AFTER, - htonl(natseq->offset_after)); + if (nla_put_be32(skb, CTA_NAT_SEQ_CORRECTION_POS, + htonl(natseq->correction_pos)) || + nla_put_be32(skb, CTA_NAT_SEQ_OFFSET_BEFORE, + htonl(natseq->offset_before)) || + nla_put_be32(skb, CTA_NAT_SEQ_OFFSET_AFTER, + htonl(natseq->offset_after))) + goto nla_put_failure; nla_nest_end(skb, nest_parms); @@ -390,7 +397,8 @@ ctnetlink_dump_nat_seq_adj(struct sk_buff *skb, const struct nf_conn *ct) static inline int ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct) { - NLA_PUT_BE32(skb, CTA_ID, htonl((unsigned long)ct)); + if (nla_put_be32(skb, CTA_ID, htonl((unsigned long)ct))) + goto nla_put_failure; return 0; nla_put_failure: @@ -400,7 +408,8 @@ nla_put_failure: static inline int ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct) { - NLA_PUT_BE32(skb, CTA_USE, htonl(atomic_read(&ct->ct_general.use))); + if (nla_put_be32(skb, CTA_USE, htonl(atomic_read(&ct->ct_general.use)))) + goto nla_put_failure; return 0; nla_put_failure: @@ -440,8 +449,9 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type, goto nla_put_failure; nla_nest_end(skb, nest_parms); - if (nf_ct_zone(ct)) - NLA_PUT_BE16(skb, CTA_ZONE, htons(nf_ct_zone(ct))); + if (nf_ct_zone(ct) && + nla_put_be16(skb, CTA_ZONE, htons(nf_ct_zone(ct)))) + goto nla_put_failure; if (ctnetlink_dump_status(skb, ct) < 0 || ctnetlink_dump_timeout(skb, ct) < 0 || @@ -617,8 +627,9 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) goto nla_put_failure; nla_nest_end(skb, nest_parms); - if (nf_ct_zone(ct)) - NLA_PUT_BE16(skb, CTA_ZONE, htons(nf_ct_zone(ct))); + if (nf_ct_zone(ct) && + nla_put_be16(skb, CTA_ZONE, htons(nf_ct_zone(ct)))) + goto nla_put_failure; if (ctnetlink_dump_id(skb, ct) < 0) goto nla_put_failure; @@ -1705,7 +1716,8 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb, if (!nest_parms) goto nla_put_failure; - NLA_PUT_BE32(skb, CTA_EXPECT_NAT_DIR, htonl(exp->dir)); + if (nla_put_be32(skb, CTA_EXPECT_NAT_DIR, htonl(exp->dir))) + goto nla_put_failure; nat_tuple.src.l3num = nf_ct_l3num(master); nat_tuple.src.u3.ip = exp->saved_ip; @@ -1718,21 +1730,24 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb, nla_nest_end(skb, nest_parms); } #endif - NLA_PUT_BE32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout)); - NLA_PUT_BE32(skb, CTA_EXPECT_ID, htonl((unsigned long)exp)); - NLA_PUT_BE32(skb, CTA_EXPECT_FLAGS, htonl(exp->flags)); - NLA_PUT_BE32(skb, CTA_EXPECT_CLASS, htonl(exp->class)); + if (nla_put_be32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout)) || + nla_put_be32(skb, CTA_EXPECT_ID, htonl((unsigned long)exp)) || + nla_put_be32(skb, CTA_EXPECT_FLAGS, htonl(exp->flags)) || + nla_put_be32(skb, CTA_EXPECT_CLASS, htonl(exp->class))) + goto nla_put_failure; help = nfct_help(master); if (help) { struct nf_conntrack_helper *helper; helper = rcu_dereference(help->helper); - if (helper) - NLA_PUT_STRING(skb, CTA_EXPECT_HELP_NAME, helper->name); + if (helper && + nla_put_string(skb, CTA_EXPECT_HELP_NAME, helper->name)) + goto nla_put_failure; } expfn = nf_ct_helper_expectfn_find_by_symbol(exp->expectfn); - if (expfn != NULL) - NLA_PUT_STRING(skb, CTA_EXPECT_FN, expfn->name); + if (expfn != NULL && + nla_put_string(skb, CTA_EXPECT_FN, expfn->name)) + goto nla_put_failure; return 0; diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index 24fdce2..a58998d 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c @@ -643,11 +643,12 @@ static int dccp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, nest_parms = nla_nest_start(skb, CTA_PROTOINFO_DCCP | NLA_F_NESTED); if (!nest_parms) goto nla_put_failure; - NLA_PUT_U8(skb, CTA_PROTOINFO_DCCP_STATE, ct->proto.dccp.state); - NLA_PUT_U8(skb, CTA_PROTOINFO_DCCP_ROLE, - ct->proto.dccp.role[IP_CT_DIR_ORIGINAL]); - NLA_PUT_BE64(skb, CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ, - cpu_to_be64(ct->proto.dccp.handshake_seq)); + if (nla_put_u8(skb, CTA_PROTOINFO_DCCP_STATE, ct->proto.dccp.state) || + nla_put_u8(skb, CTA_PROTOINFO_DCCP_ROLE, + ct->proto.dccp.role[IP_CT_DIR_ORIGINAL]) || + nla_put_be64(skb, CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ, + cpu_to_be64(ct->proto.dccp.handshake_seq))) + goto nla_put_failure; nla_nest_end(skb, nest_parms); spin_unlock_bh(&ct->lock); return 0; @@ -739,9 +740,10 @@ dccp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data) const unsigned int *timeouts = data; int i; - for (i=CTA_TIMEOUT_DCCP_UNSPEC+1; i<CTA_TIMEOUT_DCCP_MAX+1; i++) - NLA_PUT_BE32(skb, i, htonl(timeouts[i] / HZ)); - + for (i=CTA_TIMEOUT_DCCP_UNSPEC+1; i<CTA_TIMEOUT_DCCP_MAX+1; i++) { + if (nla_put_be32(skb, i, htonl(timeouts[i] / HZ))) + goto nla_put_failure; + } return 0; nla_put_failure: diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c index 835e24c..d8923d5 100644 --- a/net/netfilter/nf_conntrack_proto_generic.c +++ b/net/netfilter/nf_conntrack_proto_generic.c @@ -90,7 +90,8 @@ generic_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data) { const unsigned int *timeout = data; - NLA_PUT_BE32(skb, CTA_TIMEOUT_GENERIC_TIMEOUT, htonl(*timeout / HZ)); + if (nla_put_be32(skb, CTA_TIMEOUT_GENERIC_TIMEOUT, htonl(*timeout / HZ))) + goto nla_put_failure; return 0; diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index 659648c..4bf6b4e 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c @@ -321,10 +321,11 @@ gre_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data) { const unsigned int *timeouts = data; - NLA_PUT_BE32(skb, CTA_TIMEOUT_GRE_UNREPLIED, - htonl(timeouts[GRE_CT_UNREPLIED] / HZ)); - NLA_PUT_BE32(skb, CTA_TIMEOUT_GRE_REPLIED, - htonl(timeouts[GRE_CT_REPLIED] / HZ)); + if (nla_put_be32(skb, CTA_TIMEOUT_GRE_UNREPLIED, + htonl(timeouts[GRE_CT_UNREPLIED] / HZ)) || + nla_put_be32(skb, CTA_TIMEOUT_GRE_REPLIED, + htonl(timeouts[GRE_CT_REPLIED] / HZ))) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 72b5088..996db2f 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -482,15 +482,12 @@ static int sctp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, if (!nest_parms) goto nla_put_failure; - NLA_PUT_U8(skb, CTA_PROTOINFO_SCTP_STATE, ct->proto.sctp.state); - - NLA_PUT_BE32(skb, - CTA_PROTOINFO_SCTP_VTAG_ORIGINAL, - ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL]); - - NLA_PUT_BE32(skb, - CTA_PROTOINFO_SCTP_VTAG_REPLY, - ct->proto.sctp.vtag[IP_CT_DIR_REPLY]); + if (nla_put_u8(skb, CTA_PROTOINFO_SCTP_STATE, ct->proto.sctp.state) || + nla_put_be32(skb, CTA_PROTOINFO_SCTP_VTAG_ORIGINAL, + ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL]) || + nla_put_be32(skb, CTA_PROTOINFO_SCTP_VTAG_REPLY, + ct->proto.sctp.vtag[IP_CT_DIR_REPLY])) + goto nla_put_failure; spin_unlock_bh(&ct->lock); @@ -578,9 +575,10 @@ sctp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data) const unsigned int *timeouts = data; int i; - for (i=CTA_TIMEOUT_SCTP_UNSPEC+1; i<CTA_TIMEOUT_SCTP_MAX+1; i++) - NLA_PUT_BE32(skb, i, htonl(timeouts[i] / HZ)); - + for (i=CTA_TIMEOUT_SCTP_UNSPEC+1; i<CTA_TIMEOUT_SCTP_MAX+1; i++) { + if (nla_put_be32(skb, i, htonl(timeouts[i] / HZ))) + goto nla_put_failure; + } return 0; nla_put_failure: diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 0d07a1d..4dfbfa8 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -1147,21 +1147,22 @@ static int tcp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, if (!nest_parms) goto nla_put_failure; - NLA_PUT_U8(skb, CTA_PROTOINFO_TCP_STATE, ct->proto.tcp.state); - - NLA_PUT_U8(skb, CTA_PROTOINFO_TCP_WSCALE_ORIGINAL, - ct->proto.tcp.seen[0].td_scale); - - NLA_PUT_U8(skb, CTA_PROTOINFO_TCP_WSCALE_REPLY, - ct->proto.tcp.seen[1].td_scale); + if (nla_put_u8(skb, CTA_PROTOINFO_TCP_STATE, ct->proto.tcp.state) || + nla_put_u8(skb, CTA_PROTOINFO_TCP_WSCALE_ORIGINAL, + ct->proto.tcp.seen[0].td_scale) || + nla_put_u8(skb, CTA_PROTOINFO_TCP_WSCALE_REPLY, + ct->proto.tcp.seen[1].td_scale)) + goto nla_put_failure; tmp.flags = ct->proto.tcp.seen[0].flags; - NLA_PUT(skb, CTA_PROTOINFO_TCP_FLAGS_ORIGINAL, - sizeof(struct nf_ct_tcp_flags), &tmp); + if (nla_put(skb, CTA_PROTOINFO_TCP_FLAGS_ORIGINAL, + sizeof(struct nf_ct_tcp_flags), &tmp)) + goto nla_put_failure; tmp.flags = ct->proto.tcp.seen[1].flags; - NLA_PUT(skb, CTA_PROTOINFO_TCP_FLAGS_REPLY, - sizeof(struct nf_ct_tcp_flags), &tmp); + if (nla_put(skb, CTA_PROTOINFO_TCP_FLAGS_REPLY, + sizeof(struct nf_ct_tcp_flags), &tmp)) + goto nla_put_failure; spin_unlock_bh(&ct->lock); nla_nest_end(skb, nest_parms); @@ -1310,28 +1311,29 @@ tcp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data) { const unsigned int *timeouts = data; - NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_SYN_SENT, - htonl(timeouts[TCP_CONNTRACK_SYN_SENT] / HZ)); - NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_SYN_RECV, - htonl(timeouts[TCP_CONNTRACK_SYN_RECV] / HZ)); - NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_ESTABLISHED, - htonl(timeouts[TCP_CONNTRACK_ESTABLISHED] / HZ)); - NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_FIN_WAIT, - htonl(timeouts[TCP_CONNTRACK_FIN_WAIT] / HZ)); - NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_CLOSE_WAIT, - htonl(timeouts[TCP_CONNTRACK_CLOSE_WAIT] / HZ)); - NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_LAST_ACK, - htonl(timeouts[TCP_CONNTRACK_LAST_ACK] / HZ)); - NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_TIME_WAIT, - htonl(timeouts[TCP_CONNTRACK_TIME_WAIT] / HZ)); - NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_CLOSE, - htonl(timeouts[TCP_CONNTRACK_CLOSE] / HZ)); - NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_SYN_SENT2, - htonl(timeouts[TCP_CONNTRACK_SYN_SENT2] / HZ)); - NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_RETRANS, - htonl(timeouts[TCP_CONNTRACK_RETRANS] / HZ)); - NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_UNACK, - htonl(timeouts[TCP_CONNTRACK_UNACK] / HZ)); + if (nla_put_be32(skb, CTA_TIMEOUT_TCP_SYN_SENT, + htonl(timeouts[TCP_CONNTRACK_SYN_SENT] / HZ)) || + nla_put_be32(skb, CTA_TIMEOUT_TCP_SYN_RECV, + htonl(timeouts[TCP_CONNTRACK_SYN_RECV] / HZ)) || + nla_put_be32(skb, CTA_TIMEOUT_TCP_ESTABLISHED, + htonl(timeouts[TCP_CONNTRACK_ESTABLISHED] / HZ)) || + nla_put_be32(skb, CTA_TIMEOUT_TCP_FIN_WAIT, + htonl(timeouts[TCP_CONNTRACK_FIN_WAIT] / HZ)) || + nla_put_be32(skb, CTA_TIMEOUT_TCP_CLOSE_WAIT, + htonl(timeouts[TCP_CONNTRACK_CLOSE_WAIT] / HZ)) || + nla_put_be32(skb, CTA_TIMEOUT_TCP_LAST_ACK, + htonl(timeouts[TCP_CONNTRACK_LAST_ACK] / HZ)) || + nla_put_be32(skb, CTA_TIMEOUT_TCP_TIME_WAIT, + htonl(timeouts[TCP_CONNTRACK_TIME_WAIT] / HZ)) || + nla_put_be32(skb, CTA_TIMEOUT_TCP_CLOSE, + htonl(timeouts[TCP_CONNTRACK_CLOSE] / HZ)) || + nla_put_be32(skb, CTA_TIMEOUT_TCP_SYN_SENT2, + htonl(timeouts[TCP_CONNTRACK_SYN_SENT2] / HZ)) || + nla_put_be32(skb, CTA_TIMEOUT_TCP_RETRANS, + htonl(timeouts[TCP_CONNTRACK_RETRANS] / HZ)) || + nla_put_be32(skb, CTA_TIMEOUT_TCP_UNACK, + htonl(timeouts[TCP_CONNTRACK_UNACK] / HZ))) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index a9073dc..7259a6b 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c @@ -181,10 +181,11 @@ udp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data) { const unsigned int *timeouts = data; - NLA_PUT_BE32(skb, CTA_TIMEOUT_UDP_UNREPLIED, - htonl(timeouts[UDP_CT_UNREPLIED] / HZ)); - NLA_PUT_BE32(skb, CTA_TIMEOUT_UDP_REPLIED, - htonl(timeouts[UDP_CT_REPLIED] / HZ)); + if (nla_put_be32(skb, CTA_TIMEOUT_UDP_UNREPLIED, + htonl(timeouts[UDP_CT_UNREPLIED] / HZ)) || + nla_put_be32(skb, CTA_TIMEOUT_UDP_REPLIED, + htonl(timeouts[UDP_CT_REPLIED] / HZ))) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c index e060639..4d60a53 100644 --- a/net/netfilter/nf_conntrack_proto_udplite.c +++ b/net/netfilter/nf_conntrack_proto_udplite.c @@ -185,10 +185,11 @@ udplite_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data) { const unsigned int *timeouts = data; - NLA_PUT_BE32(skb, CTA_TIMEOUT_UDPLITE_UNREPLIED, - htonl(timeouts[UDPLITE_CT_UNREPLIED] / HZ)); - NLA_PUT_BE32(skb, CTA_TIMEOUT_UDPLITE_REPLIED, - htonl(timeouts[UDPLITE_CT_REPLIED] / HZ)); + if (nla_put_be32(skb, CTA_TIMEOUT_UDPLITE_UNREPLIED, + htonl(timeouts[UDPLITE_CT_UNREPLIED] / HZ)) || + nla_put_be32(skb, CTA_TIMEOUT_UDPLITE_REPLIED, + htonl(timeouts[UDPLITE_CT_REPLIED] / HZ))) + goto nla_put_failure; return 0; nla_put_failure: diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index e6ddde1..3e797d1 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -103,7 +103,7 @@ int nfnetlink_has_listeners(struct net *net, unsigned int group) EXPORT_SYMBOL_GPL(nfnetlink_has_listeners); int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, - unsigned group, int echo, gfp_t flags) + unsigned int group, int echo, gfp_t flags) { return nlmsg_notify(net->nfnl, skb, pid, group, echo, flags); } diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c index d98c868..b2e7310 100644 --- a/net/netfilter/nfnetlink_acct.c +++ b/net/netfilter/nfnetlink_acct.c @@ -109,7 +109,8 @@ nfnl_acct_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type, nfmsg->version = NFNETLINK_V0; nfmsg->res_id = 0; - NLA_PUT_STRING(skb, NFACCT_NAME, acct->name); + if (nla_put_string(skb, NFACCT_NAME, acct->name)) + goto nla_put_failure; if (type == NFNL_MSG_ACCT_GET_CTRZERO) { pkts = atomic64_xchg(&acct->pkts, 0); @@ -118,9 +119,10 @@ nfnl_acct_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type, pkts = atomic64_read(&acct->pkts); bytes = atomic64_read(&acct->bytes); } - NLA_PUT_BE64(skb, NFACCT_PKTS, cpu_to_be64(pkts)); - NLA_PUT_BE64(skb, NFACCT_BYTES, cpu_to_be64(bytes)); - NLA_PUT_BE32(skb, NFACCT_USE, htonl(atomic_read(&acct->refcnt))); + if (nla_put_be64(skb, NFACCT_PKTS, cpu_to_be64(pkts)) || + nla_put_be64(skb, NFACCT_BYTES, cpu_to_be64(bytes)) || + nla_put_be32(skb, NFACCT_USE, htonl(atomic_read(&acct->refcnt)))) + goto nla_put_failure; nlmsg_end(skb, nlh); return skb->len; diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c index 2b9e79f..3e65528 100644 --- a/net/netfilter/nfnetlink_cttimeout.c +++ b/net/netfilter/nfnetlink_cttimeout.c @@ -170,11 +170,12 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type, nfmsg->version = NFNETLINK_V0; nfmsg->res_id = 0; - NLA_PUT_STRING(skb, CTA_TIMEOUT_NAME, timeout->name); - NLA_PUT_BE16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num)); - NLA_PUT_U8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4proto->l4proto); - NLA_PUT_BE32(skb, CTA_TIMEOUT_USE, - htonl(atomic_read(&timeout->refcnt))); + if (nla_put_string(skb, CTA_TIMEOUT_NAME, timeout->name) || + nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num)) || + nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4proto->l4proto) || + nla_put_be32(skb, CTA_TIMEOUT_USE, + htonl(atomic_read(&timeout->refcnt)))) + goto nla_put_failure; if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) { struct nlattr *nest_parms; diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 66b2c54..3c3cfc0 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -391,67 +391,78 @@ __build_packet_message(struct nfulnl_instance *inst, pmsg.hw_protocol = skb->protocol; pmsg.hook = hooknum; - NLA_PUT(inst->skb, NFULA_PACKET_HDR, sizeof(pmsg), &pmsg); + if (nla_put(inst->skb, NFULA_PACKET_HDR, sizeof(pmsg), &pmsg)) + goto nla_put_failure; - if (prefix) - NLA_PUT(inst->skb, NFULA_PREFIX, plen, prefix); + if (prefix && + nla_put(inst->skb, NFULA_PREFIX, plen, prefix)) + goto nla_put_failure; if (indev) { #ifndef CONFIG_BRIDGE_NETFILTER - NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV, - htonl(indev->ifindex)); + if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV, + htonl(indev->ifindex))) + goto nla_put_failure; #else if (pf == PF_BRIDGE) { /* Case 1: outdev is physical input device, we need to * look for bridge group (when called from * netfilter_bridge) */ - NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSINDEV, - htonl(indev->ifindex)); + if (nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV, + htonl(indev->ifindex)) || /* this is the bridge group "brX" */ /* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */ - NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV, - htonl(br_port_get_rcu(indev)->br->dev->ifindex)); + nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV, + htonl(br_port_get_rcu(indev)->br->dev->ifindex))) + goto nla_put_failure; } else { /* Case 2: indev is bridge group, we need to look for * physical device (when called from ipv4) */ - NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV, - htonl(indev->ifindex)); - if (skb->nf_bridge && skb->nf_bridge->physindev) - NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSINDEV, - htonl(skb->nf_bridge->physindev->ifindex)); + if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV, + htonl(indev->ifindex))) + goto nla_put_failure; + if (skb->nf_bridge && skb->nf_bridge->physindev && + nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV, + htonl(skb->nf_bridge->physindev->ifindex))) + goto nla_put_failure; } #endif } if (outdev) { #ifndef CONFIG_BRIDGE_NETFILTER - NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV, - htonl(outdev->ifindex)); + if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV, + htonl(outdev->ifindex))) + goto nla_put_failure; #else if (pf == PF_BRIDGE) { /* Case 1: outdev is physical output device, we need to * look for bridge group (when called from * netfilter_bridge) */ - NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV, - htonl(outdev->ifindex)); + if (nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV, + htonl(outdev->ifindex)) || /* this is the bridge group "brX" */ /* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */ - NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV, - htonl(br_port_get_rcu(outdev)->br->dev->ifindex)); + nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV, + htonl(br_port_get_rcu(outdev)->br->dev->ifindex))) + goto nla_put_failure; } else { /* Case 2: indev is a bridge group, we need to look * for physical device (when called from ipv4) */ - NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV, - htonl(outdev->ifindex)); - if (skb->nf_bridge && skb->nf_bridge->physoutdev) - NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV, - htonl(skb->nf_bridge->physoutdev->ifindex)); + if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV, + htonl(outdev->ifindex))) + goto nla_put_failure; + if (skb->nf_bridge && skb->nf_bridge->physoutdev && + nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV, + htonl(skb->nf_bridge->physoutdev->ifindex))) + goto nla_put_failure; } #endif } - if (skb->mark) - NLA_PUT_BE32(inst->skb, NFULA_MARK, htonl(skb->mark)); + if (skb->mark && + nla_put_be32(inst->skb, NFULA_MARK, htonl(skb->mark))) + goto nla_put_failure; if (indev && skb->dev && skb->mac_header != skb->network_header) { @@ -459,16 +470,18 @@ __build_packet_message(struct nfulnl_instance *inst, int len = dev_parse_header(skb, phw.hw_addr); if (len > 0) { phw.hw_addrlen = htons(len); - NLA_PUT(inst->skb, NFULA_HWADDR, sizeof(phw), &phw); + if (nla_put(inst->skb, NFULA_HWADDR, sizeof(phw), &phw)) + goto nla_put_failure; } } if (indev && skb_mac_header_was_set(skb)) { - NLA_PUT_BE16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)); - NLA_PUT_BE16(inst->skb, NFULA_HWLEN, - htons(skb->dev->hard_header_len)); - NLA_PUT(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len, - skb_mac_header(skb)); + if (nla_put_be32(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) || + nla_put_be16(inst->skb, NFULA_HWLEN, + htons(skb->dev->hard_header_len)) || + nla_put(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len, + skb_mac_header(skb))) + goto nla_put_failure; } if (skb->tstamp.tv64) { @@ -477,7 +490,8 @@ __build_packet_message(struct nfulnl_instance *inst, ts.sec = cpu_to_be64(tv.tv_sec); ts.usec = cpu_to_be64(tv.tv_usec); - NLA_PUT(inst->skb, NFULA_TIMESTAMP, sizeof(ts), &ts); + if (nla_put(inst->skb, NFULA_TIMESTAMP, sizeof(ts), &ts)) + goto nla_put_failure; } /* UID */ @@ -487,22 +501,24 @@ __build_packet_message(struct nfulnl_instance *inst, struct file *file = skb->sk->sk_socket->file; __be32 uid = htonl(file->f_cred->fsuid); __be32 gid = htonl(file->f_cred->fsgid); - /* need to unlock here since NLA_PUT may goto */ read_unlock_bh(&skb->sk->sk_callback_lock); - NLA_PUT_BE32(inst->skb, NFULA_UID, uid); - NLA_PUT_BE32(inst->skb, NFULA_GID, gid); + if (nla_put_be32(inst->skb, NFULA_UID, uid) || + nla_put_be32(inst->skb, NFULA_GID, gid)) + goto nla_put_failure; } else read_unlock_bh(&skb->sk->sk_callback_lock); } /* local sequence number */ - if (inst->flags & NFULNL_CFG_F_SEQ) - NLA_PUT_BE32(inst->skb, NFULA_SEQ, htonl(inst->seq++)); + if ((inst->flags & NFULNL_CFG_F_SEQ) && + nla_put_be32(inst->skb, NFULA_SEQ, htonl(inst->seq++))) + goto nla_put_failure; /* global sequence number */ - if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) - NLA_PUT_BE32(inst->skb, NFULA_SEQ_GLOBAL, - htonl(atomic_inc_return(&global_seq))); + if ((inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) && + nla_put_be32(inst->skb, NFULA_SEQ_GLOBAL, + htonl(atomic_inc_return(&global_seq)))) + goto nla_put_failure; if (data_len) { struct nlattr *nla; diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index a80b0cb..8d6bcf3 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -288,58 +288,67 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, indev = entry->indev; if (indev) { #ifndef CONFIG_BRIDGE_NETFILTER - NLA_PUT_BE32(skb, NFQA_IFINDEX_INDEV, htonl(indev->ifindex)); + if (nla_put_be32(skb, NFQA_IFINDEX_INDEV, htonl(indev->ifindex))) + goto nla_put_failure; #else if (entry->pf == PF_BRIDGE) { /* Case 1: indev is physical input device, we need to * look for bridge group (when called from * netfilter_bridge) */ - NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSINDEV, - htonl(indev->ifindex)); + if (nla_put_be32(skb, NFQA_IFINDEX_PHYSINDEV, + htonl(indev->ifindex)) || /* this is the bridge group "brX" */ /* rcu_read_lock()ed by __nf_queue */ - NLA_PUT_BE32(skb, NFQA_IFINDEX_INDEV, - htonl(br_port_get_rcu(indev)->br->dev->ifindex)); + nla_put_be32(skb, NFQA_IFINDEX_INDEV, + htonl(br_port_get_rcu(indev)->br->dev->ifindex))) + goto nla_put_failure; } else { /* Case 2: indev is bridge group, we need to look for * physical device (when called from ipv4) */ - NLA_PUT_BE32(skb, NFQA_IFINDEX_INDEV, - htonl(indev->ifindex)); - if (entskb->nf_bridge && entskb->nf_bridge->physindev) - NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSINDEV, - htonl(entskb->nf_bridge->physindev->ifindex)); + if (nla_put_be32(skb, NFQA_IFINDEX_INDEV, + htonl(indev->ifindex))) + goto nla_put_failure; + if (entskb->nf_bridge && entskb->nf_bridge->physindev && + nla_put_be32(skb, NFQA_IFINDEX_PHYSINDEV, + htonl(entskb->nf_bridge->physindev->ifindex))) + goto nla_put_failure; } #endif } if (outdev) { #ifndef CONFIG_BRIDGE_NETFILTER - NLA_PUT_BE32(skb, NFQA_IFINDEX_OUTDEV, htonl(outdev->ifindex)); + if (nla_put_be32(skb, NFQA_IFINDEX_OUTDEV, htonl(outdev->ifindex))) + goto nla_put_failure; #else if (entry->pf == PF_BRIDGE) { /* Case 1: outdev is physical output device, we need to * look for bridge group (when called from * netfilter_bridge) */ - NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSOUTDEV, - htonl(outdev->ifindex)); + if (nla_put_be32(skb, NFQA_IFINDEX_PHYSOUTDEV, + htonl(outdev->ifindex)) || /* this is the bridge group "brX" */ /* rcu_read_lock()ed by __nf_queue */ - NLA_PUT_BE32(skb, NFQA_IFINDEX_OUTDEV, - htonl(br_port_get_rcu(outdev)->br->dev->ifindex)); + nla_put_be32(skb, NFQA_IFINDEX_OUTDEV, + htonl(br_port_get_rcu(outdev)->br->dev->ifindex))) + goto nla_put_failure; } else { /* Case 2: outdev is bridge group, we need to look for * physical output device (when called from ipv4) */ - NLA_PUT_BE32(skb, NFQA_IFINDEX_OUTDEV, - htonl(outdev->ifindex)); - if (entskb->nf_bridge && entskb->nf_bridge->physoutdev) - NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSOUTDEV, - htonl(entskb->nf_bridge->physoutdev->ifindex)); + if (nla_put_be32(skb, NFQA_IFINDEX_OUTDEV, + htonl(outdev->ifindex))) + goto nla_put_failure; + if (entskb->nf_bridge && entskb->nf_bridge->physoutdev && + nla_put_be32(skb, NFQA_IFINDEX_PHYSOUTDEV, + htonl(entskb->nf_bridge->physoutdev->ifindex))) + goto nla_put_failure; } #endif } - if (entskb->mark) - NLA_PUT_BE32(skb, NFQA_MARK, htonl(entskb->mark)); + if (entskb->mark && + nla_put_be32(skb, NFQA_MARK, htonl(entskb->mark))) + goto nla_put_failure; if (indev && entskb->dev && entskb->mac_header != entskb->network_header) { @@ -347,7 +356,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, int len = dev_parse_header(entskb, phw.hw_addr); if (len) { phw.hw_addrlen = htons(len); - NLA_PUT(skb, NFQA_HWADDR, sizeof(phw), &phw); + if (nla_put(skb, NFQA_HWADDR, sizeof(phw), &phw)) + goto nla_put_failure; } } @@ -357,7 +367,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, ts.sec = cpu_to_be64(tv.tv_sec); ts.usec = cpu_to_be64(tv.tv_usec); - NLA_PUT(skb, NFQA_TIMESTAMP, sizeof(ts), &ts); + if (nla_put(skb, NFQA_TIMESTAMP, sizeof(ts), &ts)) + goto nla_put_failure; } if (data_len) { diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index d2ff15a..fc0d6db 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c @@ -314,7 +314,7 @@ static int recent_mt_check(const struct xt_mtchk_param *par) #ifdef CONFIG_PROC_FS struct proc_dir_entry *pde; #endif - unsigned i; + unsigned int i; int ret = -EINVAL; if (unlikely(!hash_rnd_inited)) { diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 9f40441..8340ace 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -635,11 +635,12 @@ static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq, if (hdr == NULL) return -1; - NLA_PUT_STRING(skb, CTRL_ATTR_FAMILY_NAME, family->name); - NLA_PUT_U16(skb, CTRL_ATTR_FAMILY_ID, family->id); - NLA_PUT_U32(skb, CTRL_ATTR_VERSION, family->version); - NLA_PUT_U32(skb, CTRL_ATTR_HDRSIZE, family->hdrsize); - NLA_PUT_U32(skb, CTRL_ATTR_MAXATTR, family->maxattr); + if (nla_put_string(skb, CTRL_ATTR_FAMILY_NAME, family->name) || + nla_put_u16(skb, CTRL_ATTR_FAMILY_ID, family->id) || + nla_put_u32(skb, CTRL_ATTR_VERSION, family->version) || + nla_put_u32(skb, CTRL_ATTR_HDRSIZE, family->hdrsize) || + nla_put_u32(skb, CTRL_ATTR_MAXATTR, family->maxattr)) + goto nla_put_failure; if (!list_empty(&family->ops_list)) { struct nlattr *nla_ops; @@ -657,8 +658,9 @@ static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq, if (nest == NULL) goto nla_put_failure; - NLA_PUT_U32(skb, CTRL_ATTR_OP_ID, ops->cmd); - NLA_PUT_U32(skb, CTRL_ATTR_OP_FLAGS, ops->flags); + if (nla_put_u32(skb, CTRL_ATTR_OP_ID, ops->cmd) || + nla_put_u32(skb, CTRL_ATTR_OP_FLAGS, ops->flags)) + goto nla_put_failure; nla_nest_end(skb, nest); } @@ -682,9 +684,10 @@ static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq, if (nest == NULL) goto nla_put_failure; - NLA_PUT_U32(skb, CTRL_ATTR_MCAST_GRP_ID, grp->id); - NLA_PUT_STRING(skb, CTRL_ATTR_MCAST_GRP_NAME, - grp->name); + if (nla_put_u32(skb, CTRL_ATTR_MCAST_GRP_ID, grp->id) || + nla_put_string(skb, CTRL_ATTR_MCAST_GRP_NAME, + grp->name)) + goto nla_put_failure; nla_nest_end(skb, nest); } @@ -710,8 +713,9 @@ static int ctrl_fill_mcgrp_info(struct genl_multicast_group *grp, u32 pid, if (hdr == NULL) return -1; - NLA_PUT_STRING(skb, CTRL_ATTR_FAMILY_NAME, grp->family->name); - NLA_PUT_U16(skb, CTRL_ATTR_FAMILY_ID, grp->family->id); + if (nla_put_string(skb, CTRL_ATTR_FAMILY_NAME, grp->family->name) || + nla_put_u16(skb, CTRL_ATTR_FAMILY_ID, grp->family->id)) + goto nla_put_failure; nla_grps = nla_nest_start(skb, CTRL_ATTR_MCAST_GROUPS); if (nla_grps == NULL) @@ -721,9 +725,10 @@ static int ctrl_fill_mcgrp_info(struct genl_multicast_group *grp, u32 pid, if (nest == NULL) goto nla_put_failure; - NLA_PUT_U32(skb, CTRL_ATTR_MCAST_GRP_ID, grp->id); - NLA_PUT_STRING(skb, CTRL_ATTR_MCAST_GRP_NAME, - grp->name); + if (nla_put_u32(skb, CTRL_ATTR_MCAST_GRP_ID, grp->id) || + nla_put_string(skb, CTRL_ATTR_MCAST_GRP_NAME, + grp->name)) + goto nla_put_failure; nla_nest_end(skb, nest); nla_nest_end(skb, nla_grps); diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c index 1c51d7a..743262b 100644 --- a/net/netrom/nr_dev.c +++ b/net/netrom/nr_dev.c @@ -97,7 +97,7 @@ static int nr_rebuild_header(struct sk_buff *skb) static int nr_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, - const void *daddr, const void *saddr, unsigned len) + const void *daddr, const void *saddr, unsigned int len) { unsigned char *buff = skb_push(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN); diff --git a/net/nfc/core.c b/net/nfc/core.c index 295d129..32a7b61 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -475,12 +475,12 @@ EXPORT_SYMBOL(nfc_class); static int match_idx(struct device *d, void *data) { struct nfc_dev *dev = to_nfc_dev(d); - unsigned *idx = data; + unsigned int *idx = data; return dev->idx == *idx; } -struct nfc_dev *nfc_get_device(unsigned idx) +struct nfc_dev *nfc_get_device(unsigned int idx) { struct device *d; diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 6404052..8937664 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -63,19 +63,23 @@ static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, genl_dump_check_consistent(cb, hdr, &nfc_genl_family); - NLA_PUT_U32(msg, NFC_ATTR_TARGET_INDEX, target->idx); - NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, target->supported_protocols); - NLA_PUT_U16(msg, NFC_ATTR_TARGET_SENS_RES, target->sens_res); - NLA_PUT_U8(msg, NFC_ATTR_TARGET_SEL_RES, target->sel_res); - if (target->nfcid1_len > 0) - NLA_PUT(msg, NFC_ATTR_TARGET_NFCID1, target->nfcid1_len, - target->nfcid1); - if (target->sensb_res_len > 0) - NLA_PUT(msg, NFC_ATTR_TARGET_SENSB_RES, target->sensb_res_len, - target->sensb_res); - if (target->sensf_res_len > 0) - NLA_PUT(msg, NFC_ATTR_TARGET_SENSF_RES, target->sensf_res_len, - target->sensf_res); + if (nla_put_u32(msg, NFC_ATTR_TARGET_INDEX, target->idx) || + nla_put_u32(msg, NFC_ATTR_PROTOCOLS, target->supported_protocols) || + nla_put_u16(msg, NFC_ATTR_TARGET_SENS_RES, target->sens_res) || + nla_put_u8(msg, NFC_ATTR_TARGET_SEL_RES, target->sel_res)) + goto nla_put_failure; + if (target->nfcid1_len > 0 && + nla_put(msg, NFC_ATTR_TARGET_NFCID1, target->nfcid1_len, + target->nfcid1)) + goto nla_put_failure; + if (target->sensb_res_len > 0 && + nla_put(msg, NFC_ATTR_TARGET_SENSB_RES, target->sensb_res_len, + target->sensb_res)) + goto nla_put_failure; + if (target->sensf_res_len > 0 && + nla_put(msg, NFC_ATTR_TARGET_SENSF_RES, target->sensf_res_len, + target->sensf_res)) + goto nla_put_failure; return genlmsg_end(msg, hdr); @@ -170,7 +174,8 @@ int nfc_genl_targets_found(struct nfc_dev *dev) if (!hdr) goto free_msg; - NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx); + if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) + goto nla_put_failure; genlmsg_end(msg, hdr); @@ -197,10 +202,11 @@ int nfc_genl_device_added(struct nfc_dev *dev) if (!hdr) goto free_msg; - NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)); - NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx); - NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols); - NLA_PUT_U8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up); + if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)) || + nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) || + nla_put_u32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols) || + nla_put_u8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up)) + goto nla_put_failure; genlmsg_end(msg, hdr); @@ -229,7 +235,8 @@ int nfc_genl_device_removed(struct nfc_dev *dev) if (!hdr) goto free_msg; - NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx); + if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) + goto nla_put_failure; genlmsg_end(msg, hdr); @@ -259,10 +266,11 @@ static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, if (cb) genl_dump_check_consistent(cb, hdr, &nfc_genl_family); - NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)); - NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx); - NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols); - NLA_PUT_U8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up); + if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)) || + nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) || + nla_put_u32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols) || + nla_put_u8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up)) + goto nla_put_failure; return genlmsg_end(msg, hdr); @@ -339,11 +347,14 @@ int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx, if (!hdr) goto free_msg; - NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx); - if (rf_mode == NFC_RF_INITIATOR) - NLA_PUT_U32(msg, NFC_ATTR_TARGET_INDEX, target_idx); - NLA_PUT_U8(msg, NFC_ATTR_COMM_MODE, comm_mode); - NLA_PUT_U8(msg, NFC_ATTR_RF_MODE, rf_mode); + if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) + goto nla_put_failure; + if (rf_mode == NFC_RF_INITIATOR && + nla_put_u32(msg, NFC_ATTR_TARGET_INDEX, target_idx)) + goto nla_put_failure; + if (nla_put_u8(msg, NFC_ATTR_COMM_MODE, comm_mode) || + nla_put_u8(msg, NFC_ATTR_RF_MODE, rf_mode)) + goto nla_put_failure; genlmsg_end(msg, hdr); @@ -376,7 +387,8 @@ int nfc_genl_dep_link_down_event(struct nfc_dev *dev) if (!hdr) goto free_msg; - NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx); + if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) + goto nla_put_failure; genlmsg_end(msg, hdr); diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index ec8794c..061a830 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h @@ -127,7 +127,7 @@ int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx, u8 comm_mode, u8 rf_mode); int nfc_genl_dep_link_down_event(struct nfc_dev *dev); -struct nfc_dev *nfc_get_device(unsigned idx); +struct nfc_dev *nfc_get_device(unsigned int idx); static inline void nfc_put_device(struct nfc_dev *dev) { diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index e44e631..f86de29 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -778,15 +778,18 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp, tcp_flags = flow->tcp_flags; spin_unlock_bh(&flow->lock); - if (used) - NLA_PUT_U64(skb, OVS_FLOW_ATTR_USED, ovs_flow_used_time(used)); + if (used && + nla_put_u64(skb, OVS_FLOW_ATTR_USED, ovs_flow_used_time(used))) + goto nla_put_failure; - if (stats.n_packets) - NLA_PUT(skb, OVS_FLOW_ATTR_STATS, - sizeof(struct ovs_flow_stats), &stats); + if (stats.n_packets && + nla_put(skb, OVS_FLOW_ATTR_STATS, + sizeof(struct ovs_flow_stats), &stats)) + goto nla_put_failure; - if (tcp_flags) - NLA_PUT_U8(skb, OVS_FLOW_ATTR_TCP_FLAGS, tcp_flags); + if (tcp_flags && + nla_put_u8(skb, OVS_FLOW_ATTR_TCP_FLAGS, tcp_flags)) + goto nla_put_failure; /* If OVS_FLOW_ATTR_ACTIONS doesn't fit, skip dumping the actions if * this is the first flow to be dumped into 'skb'. This is unusual for @@ -1168,7 +1171,8 @@ static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb, goto nla_put_failure; get_dp_stats(dp, &dp_stats); - NLA_PUT(skb, OVS_DP_ATTR_STATS, sizeof(struct ovs_dp_stats), &dp_stats); + if (nla_put(skb, OVS_DP_ATTR_STATS, sizeof(struct ovs_dp_stats), &dp_stats)) + goto nla_put_failure; return genlmsg_end(skb, ovs_header); @@ -1468,14 +1472,16 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb, ovs_header->dp_ifindex = get_dpifindex(vport->dp); - NLA_PUT_U32(skb, OVS_VPORT_ATTR_PORT_NO, vport->port_no); - NLA_PUT_U32(skb, OVS_VPORT_ATTR_TYPE, vport->ops->type); - NLA_PUT_STRING(skb, OVS_VPORT_ATTR_NAME, vport->ops->get_name(vport)); - NLA_PUT_U32(skb, OVS_VPORT_ATTR_UPCALL_PID, vport->upcall_pid); + if (nla_put_u32(skb, OVS_VPORT_ATTR_PORT_NO, vport->port_no) || + nla_put_u32(skb, OVS_VPORT_ATTR_TYPE, vport->ops->type) || + nla_put_string(skb, OVS_VPORT_ATTR_NAME, vport->ops->get_name(vport)) || + nla_put_u32(skb, OVS_VPORT_ATTR_UPCALL_PID, vport->upcall_pid)) + goto nla_put_failure; ovs_vport_get_stats(vport, &vport_stats); - NLA_PUT(skb, OVS_VPORT_ATTR_STATS, sizeof(struct ovs_vport_stats), - &vport_stats); + if (nla_put(skb, OVS_VPORT_ATTR_STATS, sizeof(struct ovs_vport_stats), + &vport_stats)) + goto nla_put_failure; err = ovs_vport_get_options(vport, skb); if (err == -EMSGSIZE) diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index 1252c30..7cb4163 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c @@ -1174,11 +1174,13 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb) struct ovs_key_ethernet *eth_key; struct nlattr *nla, *encap; - if (swkey->phy.priority) - NLA_PUT_U32(skb, OVS_KEY_ATTR_PRIORITY, swkey->phy.priority); + if (swkey->phy.priority && + nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, swkey->phy.priority)) + goto nla_put_failure; - if (swkey->phy.in_port != USHRT_MAX) - NLA_PUT_U32(skb, OVS_KEY_ATTR_IN_PORT, swkey->phy.in_port); + if (swkey->phy.in_port != USHRT_MAX && + nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT, swkey->phy.in_port)) + goto nla_put_failure; nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key)); if (!nla) @@ -1188,8 +1190,9 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb) memcpy(eth_key->eth_dst, swkey->eth.dst, ETH_ALEN); if (swkey->eth.tci || swkey->eth.type == htons(ETH_P_8021Q)) { - NLA_PUT_BE16(skb, OVS_KEY_ATTR_ETHERTYPE, htons(ETH_P_8021Q)); - NLA_PUT_BE16(skb, OVS_KEY_ATTR_VLAN, swkey->eth.tci); + if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, htons(ETH_P_8021Q)) || + nla_put_be16(skb, OVS_KEY_ATTR_VLAN, swkey->eth.tci)) + goto nla_put_failure; encap = nla_nest_start(skb, OVS_KEY_ATTR_ENCAP); if (!swkey->eth.tci) goto unencap; @@ -1200,7 +1203,8 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb) if (swkey->eth.type == htons(ETH_P_802_2)) goto unencap; - NLA_PUT_BE16(skb, OVS_KEY_ATTR_ETHERTYPE, swkey->eth.type); + if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, swkey->eth.type)) + goto nla_put_failure; if (swkey->eth.type == htons(ETH_P_IP)) { struct ovs_key_ipv4 *ipv4_key; diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c index c1068ae..5920bda 100644 --- a/net/openvswitch/vport-netdev.c +++ b/net/openvswitch/vport-netdev.c @@ -140,9 +140,9 @@ int ovs_netdev_get_ifindex(const struct vport *vport) return netdev_vport->dev->ifindex; } -static unsigned packet_length(const struct sk_buff *skb) +static unsigned int packet_length(const struct sk_buff *skb) { - unsigned length = skb->len - ETH_HLEN; + unsigned int length = skb->len - ETH_HLEN; if (skb->protocol == htons(ETH_P_8021Q)) length -= VLAN_HLEN; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 4f2c0df..d2b5f65 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1764,7 +1764,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, macoff = netoff = TPACKET_ALIGN(po->tp_hdrlen) + 16 + po->tp_reserve; } else { - unsigned maclen = skb_network_offset(skb); + unsigned int maclen = skb_network_offset(skb); netoff = TPACKET_ALIGN(po->tp_hdrlen + (maclen < 16 ? 16 : maclen)) + po->tp_reserve; diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index d65f699..779ce4f 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c @@ -129,7 +129,7 @@ static const struct net_proto_family phonet_proto_family = { /* Phonet device header operations */ static int pn_header_create(struct sk_buff *skb, struct net_device *dev, unsigned short type, const void *daddr, - const void *saddr, unsigned len) + const void *saddr, unsigned int len) { u8 *media = skb_push(skb, 1); diff --git a/net/phonet/pep.c b/net/phonet/pep.c index 9726fe6..9dd4f92 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c @@ -273,7 +273,7 @@ static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb) hdr = pnp_hdr(skb); if (hdr->data[0] != PN_PEP_TYPE_COMMON) { LIMIT_NETDEBUG(KERN_DEBUG"Phonet unknown PEP type: %u\n", - (unsigned)hdr->data[0]); + (unsigned int)hdr->data[0]); return -EOPNOTSUPP; } @@ -305,7 +305,7 @@ static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb) default: LIMIT_NETDEBUG(KERN_DEBUG"Phonet unknown PEP indication: %u\n", - (unsigned)hdr->data[1]); + (unsigned int)hdr->data[1]); return -EOPNOTSUPP; } if (wake) @@ -478,9 +478,9 @@ static void pipe_destruct(struct sock *sk) skb_queue_purge(&pn->ctrlreq_queue); } -static u8 pipe_negotiate_fc(const u8 *fcs, unsigned n) +static u8 pipe_negotiate_fc(const u8 *fcs, unsigned int n) { - unsigned i; + unsigned int i; u8 final_fc = PN_NO_FLOW_CONTROL; for (i = 0; i < n; i++) { diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index bf5cf69..36f75a9 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -44,7 +44,7 @@ struct phonet_net { struct phonet_routes routes; }; -int phonet_net_id __read_mostly; +static int phonet_net_id __read_mostly; static struct phonet_net *phonet_pernet(struct net *net) { @@ -268,7 +268,7 @@ static int phonet_device_autoconf(struct net_device *dev) static void phonet_route_autodel(struct net_device *dev) { struct phonet_net *pnn = phonet_pernet(dev_net(dev)); - unsigned i; + unsigned int i; DECLARE_BITMAP(deleted, 64); /* Remove left-over Phonet routes */ diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c index d61f676..cfdf135 100644 --- a/net/phonet/pn_netlink.c +++ b/net/phonet/pn_netlink.c @@ -116,7 +116,8 @@ static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr, ifm->ifa_flags = IFA_F_PERMANENT; ifm->ifa_scope = RT_SCOPE_LINK; ifm->ifa_index = dev->ifindex; - NLA_PUT_U8(skb, IFA_LOCAL, addr); + if (nla_put_u8(skb, IFA_LOCAL, addr)) + goto nla_put_failure; return nlmsg_end(skb, nlh); nla_put_failure: @@ -183,8 +184,9 @@ static int fill_route(struct sk_buff *skb, struct net_device *dev, u8 dst, rtm->rtm_scope = RT_SCOPE_UNIVERSE; rtm->rtm_type = RTN_UNICAST; rtm->rtm_flags = 0; - NLA_PUT_U8(skb, RTA_DST, dst); - NLA_PUT_U32(skb, RTA_OIF, dev->ifindex); + if (nla_put_u8(skb, RTA_DST, dst) || + nla_put_u32(skb, RTA_OIF, dev->ifindex)) + goto nla_put_failure; return nlmsg_end(skb, nlh); nla_put_failure: diff --git a/net/phonet/socket.c b/net/phonet/socket.c index 4c7eff3..89cfa9c 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c @@ -58,7 +58,7 @@ static struct { void __init pn_sock_init(void) { - unsigned i; + unsigned int i; for (i = 0; i < PN_HASHSIZE; i++) INIT_HLIST_HEAD(pnsocks.hlist + i); @@ -116,7 +116,7 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn) void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb) { struct hlist_head *hlist = pnsocks.hlist; - unsigned h; + unsigned int h; rcu_read_lock(); for (h = 0; h < PN_HASHSIZE; h++) { @@ -545,7 +545,7 @@ static struct sock *pn_sock_get_idx(struct seq_file *seq, loff_t pos) struct hlist_head *hlist = pnsocks.hlist; struct hlist_node *node; struct sock *sknode; - unsigned h; + unsigned int h; for (h = 0; h < PN_HASHSIZE; h++) { sk_for_each_rcu(sknode, node, hlist) { @@ -710,7 +710,7 @@ int pn_sock_unbind_res(struct sock *sk, u8 res) void pn_sock_unbind_all_res(struct sock *sk) { - unsigned res, match = 0; + unsigned int res, match = 0; mutex_lock(&resource_mutex); for (res = 0; res < 256; res++) { @@ -732,7 +732,7 @@ void pn_sock_unbind_all_res(struct sock *sk) static struct sock **pn_res_get_idx(struct seq_file *seq, loff_t pos) { struct net *net = seq_file_net(seq); - unsigned i; + unsigned int i; if (!net_eq(net, &init_net)) return NULL; @@ -750,7 +750,7 @@ static struct sock **pn_res_get_idx(struct seq_file *seq, loff_t pos) static struct sock **pn_res_get_next(struct seq_file *seq, struct sock **sk) { struct net *net = seq_file_net(seq); - unsigned i; + unsigned int i; BUG_ON(!net_eq(net, &init_net)); diff --git a/net/phonet/sysctl.c b/net/phonet/sysctl.c index cea1c7d..8bed767 100644 --- a/net/phonet/sysctl.c +++ b/net/phonet/sysctl.c @@ -27,6 +27,10 @@ #include <linux/errno.h> #include <linux/init.h> +#include <net/sock.h> +#include <linux/phonet.h> +#include <net/phonet/phonet.h> + #define DYNAMIC_PORT_MIN 0x40 #define DYNAMIC_PORT_MAX 0x7f @@ -46,7 +50,8 @@ static void set_local_port_range(int range[2]) void phonet_get_local_port_range(int *min, int *max) { - unsigned seq; + unsigned int seq; + do { seq = read_seqbegin(&local_port_range_lock); if (min) diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c index 906cc05..28dbdb9 100644 --- a/net/rose/rose_dev.c +++ b/net/rose/rose_dev.c @@ -37,7 +37,7 @@ static int rose_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, - const void *daddr, const void *saddr, unsigned len) + const void *daddr, const void *saddr, unsigned int len) { unsigned char *buff = skb_push(skb, ROSE_MIN_LEN + 2); diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c index 47f1fdb..7ca5774 100644 --- a/net/rose/rose_subr.c +++ b/net/rose/rose_subr.c @@ -399,7 +399,7 @@ int rose_parse_facilities(unsigned char *p, unsigned packet_len, facilities_len = *p++; - if (facilities_len == 0 || (unsigned)facilities_len > packet_len) + if (facilities_len == 0 || (unsigned int)facilities_len > packet_len) return 0; while (facilities_len >= 3 && *p == 0x00) { diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index 74c064c..05996d0 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c @@ -26,7 +26,7 @@ MODULE_AUTHOR("Red Hat, Inc."); MODULE_LICENSE("GPL"); MODULE_ALIAS_NETPROTO(PF_RXRPC); -unsigned rxrpc_debug; // = RXRPC_DEBUG_KPROTO; +unsigned int rxrpc_debug; // = RXRPC_DEBUG_KPROTO; module_param_named(debug, rxrpc_debug, uint, S_IWUSR | S_IRUGO); MODULE_PARM_DESC(debug, "RxRPC debugging mask"); @@ -513,7 +513,7 @@ static int rxrpc_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) { struct rxrpc_sock *rx = rxrpc_sk(sock->sk); - unsigned min_sec_level; + unsigned int min_sec_level; int ret; _enter(",%d,%d,,%d", level, optname, optlen); @@ -555,13 +555,13 @@ static int rxrpc_setsockopt(struct socket *sock, int level, int optname, case RXRPC_MIN_SECURITY_LEVEL: ret = -EINVAL; - if (optlen != sizeof(unsigned)) + if (optlen != sizeof(unsigned int)) goto error; ret = -EISCONN; if (rx->sk.sk_state != RXRPC_UNCONNECTED) goto error; ret = get_user(min_sec_level, - (unsigned __user *) optval); + (unsigned int __user *) optval); if (ret < 0) goto error; ret = -EINVAL; diff --git a/net/rxrpc/ar-ack.c b/net/rxrpc/ar-ack.c index c3126e8..e4d9cbc 100644 --- a/net/rxrpc/ar-ack.c +++ b/net/rxrpc/ar-ack.c @@ -19,7 +19,7 @@ #include <net/af_rxrpc.h> #include "ar-internal.h" -static unsigned rxrpc_ack_defer = 1; +static unsigned int rxrpc_ack_defer = 1; static const char *const rxrpc_acks[] = { "---", "REQ", "DUP", "OOS", "WIN", "MEM", "PNG", "PNR", "DLY", "IDL", @@ -548,11 +548,11 @@ static void rxrpc_zap_tx_window(struct rxrpc_call *call) * process the extra information that may be appended to an ACK packet */ static void rxrpc_extract_ackinfo(struct rxrpc_call *call, struct sk_buff *skb, - unsigned latest, int nAcks) + unsigned int latest, int nAcks) { struct rxrpc_ackinfo ackinfo; struct rxrpc_peer *peer; - unsigned mtu; + unsigned int mtu; if (skb_copy_bits(skb, nAcks + 3, &ackinfo, sizeof(ackinfo)) < 0) { _leave(" [no ackinfo]"); diff --git a/net/rxrpc/ar-call.c b/net/rxrpc/ar-call.c index bf656c2..a3bbb36 100644 --- a/net/rxrpc/ar-call.c +++ b/net/rxrpc/ar-call.c @@ -38,8 +38,8 @@ const char *const rxrpc_call_states[] = { struct kmem_cache *rxrpc_call_jar; LIST_HEAD(rxrpc_calls); DEFINE_RWLOCK(rxrpc_call_lock); -static unsigned rxrpc_call_max_lifetime = 60; -static unsigned rxrpc_dead_call_timeout = 2; +static unsigned int rxrpc_call_max_lifetime = 60; +static unsigned int rxrpc_dead_call_timeout = 2; static void rxrpc_destroy_call(struct work_struct *work); static void rxrpc_call_life_expired(unsigned long _call); diff --git a/net/rxrpc/ar-input.c b/net/rxrpc/ar-input.c index 1a2b0633..529572f 100644 --- a/net/rxrpc/ar-input.c +++ b/net/rxrpc/ar-input.c @@ -76,7 +76,7 @@ int rxrpc_queue_rcv_skb(struct rxrpc_call *call, struct sk_buff *skb, * --ANK */ // ret = -ENOBUFS; // if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= -// (unsigned) sk->sk_rcvbuf) +// (unsigned int) sk->sk_rcvbuf) // goto out; ret = sk_filter(sk, skb); diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 8e22bd3..a693aca 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -83,7 +83,7 @@ struct rxrpc_skb_priv { struct rxrpc_call *call; /* call with which associated */ unsigned long resend_at; /* time in jiffies at which to resend */ union { - unsigned offset; /* offset into buffer of next read */ + unsigned int offset; /* offset into buffer of next read */ int remain; /* amount of space remaining for next write */ u32 error; /* network error code */ bool need_resend; /* T if needs resending */ @@ -176,9 +176,9 @@ struct rxrpc_peer { struct list_head error_targets; /* targets for net error distribution */ spinlock_t lock; /* access lock */ atomic_t usage; - unsigned if_mtu; /* interface MTU for this peer */ - unsigned mtu; /* network MTU for this peer */ - unsigned maxdata; /* data size (MTU - hdrsize) */ + unsigned int if_mtu; /* interface MTU for this peer */ + unsigned int mtu; /* network MTU for this peer */ + unsigned int maxdata; /* data size (MTU - hdrsize) */ unsigned short hdrsize; /* header size (IP + UDP + RxRPC) */ int debug_id; /* debug ID for printks */ int net_error; /* network error distributed */ @@ -187,8 +187,8 @@ struct rxrpc_peer { /* calculated RTT cache */ #define RXRPC_RTT_CACHE_SIZE 32 suseconds_t rtt; /* current RTT estimate (in uS) */ - unsigned rtt_point; /* next entry at which to insert */ - unsigned rtt_usage; /* amount of cache actually used */ + unsigned int rtt_point; /* next entry at which to insert */ + unsigned int rtt_usage; /* amount of cache actually used */ suseconds_t rtt_cache[RXRPC_RTT_CACHE_SIZE]; /* calculated RTT cache */ }; @@ -271,7 +271,7 @@ struct rxrpc_connection { } state; int error; /* error code for local abort */ int debug_id; /* debug ID for printks */ - unsigned call_counter; /* call ID counter */ + unsigned int call_counter; /* call ID counter */ atomic_t serial; /* packet serial number counter */ atomic_t hi_serial; /* highest serial number received */ u8 avail_calls; /* number of calls available */ @@ -592,7 +592,7 @@ extern struct rxrpc_transport *rxrpc_find_transport(struct rxrpc_local *, /* * debug tracing */ -extern unsigned rxrpc_debug; +extern unsigned int rxrpc_debug; #define dbgprintk(FMT,...) \ printk("[%-6.6s] "FMT"\n", current->comm ,##__VA_ARGS__) diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index ae3a035..8b1f9f4 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c @@ -82,7 +82,7 @@ static int rxrpc_vet_description_s(const char *desc) * - the caller guarantees we have at least 4 words */ static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr, - unsigned toklen) + unsigned int toklen) { struct rxrpc_key_token *token, **pptoken; size_t plen; @@ -210,10 +210,10 @@ static void rxrpc_rxk5_free(struct rxk5_key *rxk5) */ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ, const __be32 **_xdr, - unsigned *_toklen) + unsigned int *_toklen) { const __be32 *xdr = *_xdr; - unsigned toklen = *_toklen, n_parts, loop, tmp; + unsigned int toklen = *_toklen, n_parts, loop, tmp; /* there must be at least one name, and at least #names+1 length * words */ @@ -286,10 +286,10 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ, static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td, size_t max_data_size, const __be32 **_xdr, - unsigned *_toklen) + unsigned int *_toklen) { const __be32 *xdr = *_xdr; - unsigned toklen = *_toklen, len; + unsigned int toklen = *_toklen, len; /* there must be at least one tag and one length word */ if (toklen <= 8) @@ -330,11 +330,11 @@ static int rxrpc_krb5_decode_tagged_array(struct krb5_tagged_data **_td, u8 max_n_elem, size_t max_elem_size, const __be32 **_xdr, - unsigned *_toklen) + unsigned int *_toklen) { struct krb5_tagged_data *td; const __be32 *xdr = *_xdr; - unsigned toklen = *_toklen, n_elem, loop; + unsigned int toklen = *_toklen, n_elem, loop; int ret; /* there must be at least one count */ @@ -380,10 +380,10 @@ static int rxrpc_krb5_decode_tagged_array(struct krb5_tagged_data **_td, * extract a krb5 ticket */ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, - const __be32 **_xdr, unsigned *_toklen) + const __be32 **_xdr, unsigned int *_toklen) { const __be32 *xdr = *_xdr; - unsigned toklen = *_toklen, len; + unsigned int toklen = *_toklen, len; /* there must be at least one length word */ if (toklen <= 4) @@ -419,7 +419,7 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, * - the caller guarantees we have at least 4 words */ static int rxrpc_instantiate_xdr_rxk5(struct key *key, const __be32 *xdr, - unsigned toklen) + unsigned int toklen) { struct rxrpc_key_token *token, **pptoken; struct rxk5_key *rxk5; @@ -549,7 +549,7 @@ static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datal { const __be32 *xdr = data, *token; const char *cp; - unsigned len, tmp, loop, ntoken, toklen, sec_ix; + unsigned int len, tmp, loop, ntoken, toklen, sec_ix; int ret; _enter(",{%x,%x,%x,%x},%zu", diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c index 7635107..f226709 100644 --- a/net/rxrpc/rxkad.c +++ b/net/rxrpc/rxkad.c @@ -31,7 +31,7 @@ #define REALM_SZ 40 /* size of principal's auth domain */ #define SNAME_SZ 40 /* size of service name */ -unsigned rxrpc_debug; +unsigned int rxrpc_debug; module_param_named(debug, rxrpc_debug, uint, S_IWUSR | S_IRUGO); MODULE_PARM_DESC(debug, "rxkad debugging mask"); @@ -207,7 +207,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, struct rxrpc_crypt iv; struct scatterlist sg[16]; struct sk_buff *trailer; - unsigned len; + unsigned int len; u16 check; int nsg; @@ -826,7 +826,7 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn, struct rxrpc_crypt iv, key; struct scatterlist sg[1]; struct in_addr addr; - unsigned life; + unsigned int life; time_t issue, now; bool little_endian; int ret; diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 93fdf13..5cfb160 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -127,7 +127,8 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a, nest = nla_nest_start(skb, a->order); if (nest == NULL) goto nla_put_failure; - NLA_PUT_STRING(skb, TCA_KIND, a->ops->kind); + if (nla_put_string(skb, TCA_KIND, a->ops->kind)) + goto nla_put_failure; for (i = 0; i < (hinfo->hmask + 1); i++) { p = hinfo->htab[tcf_hash(i, hinfo->hmask)]; @@ -139,7 +140,8 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a, p = s_p; } } - NLA_PUT_U32(skb, TCA_FCNT, n_i); + if (nla_put_u32(skb, TCA_FCNT, n_i)) + goto nla_put_failure; nla_nest_end(skb, nest); return n_i; @@ -437,7 +439,8 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref) if (a->ops == NULL || a->ops->dump == NULL) return err; - NLA_PUT_STRING(skb, TCA_KIND, a->ops->kind); + if (nla_put_string(skb, TCA_KIND, a->ops->kind)) + goto nla_put_failure; if (tcf_action_copy_stats(skb, a, 0)) goto nla_put_failure; nest = nla_nest_start(skb, TCA_OPTIONS); diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c index 453a734..882124ceb 100644 --- a/net/sched/act_csum.c +++ b/net/sched/act_csum.c @@ -550,11 +550,13 @@ static int tcf_csum_dump(struct sk_buff *skb, }; struct tcf_t t; - NLA_PUT(skb, TCA_CSUM_PARMS, sizeof(opt), &opt); + if (nla_put(skb, TCA_CSUM_PARMS, sizeof(opt), &opt)) + goto nla_put_failure; t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install); t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse); t.expires = jiffies_to_clock_t(p->tcf_tm.expires); - NLA_PUT(skb, TCA_CSUM_TM, sizeof(t), &t); + if (nla_put(skb, TCA_CSUM_TM, sizeof(t), &t)) + goto nla_put_failure; return skb->len; diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c index b77f5a0..f10fb82 100644 --- a/net/sched/act_gact.c +++ b/net/sched/act_gact.c @@ -162,7 +162,8 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int }; struct tcf_t t; - NLA_PUT(skb, TCA_GACT_PARMS, sizeof(opt), &opt); + if (nla_put(skb, TCA_GACT_PARMS, sizeof(opt), &opt)) + goto nla_put_failure; #ifdef CONFIG_GACT_PROB if (gact->tcfg_ptype) { struct tc_gact_p p_opt = { @@ -171,13 +172,15 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int .ptype = gact->tcfg_ptype, }; - NLA_PUT(skb, TCA_GACT_PROB, sizeof(p_opt), &p_opt); + if (nla_put(skb, TCA_GACT_PROB, sizeof(p_opt), &p_opt)) + goto nla_put_failure; } #endif t.install = jiffies_to_clock_t(jiffies - gact->tcf_tm.install); t.lastuse = jiffies_to_clock_t(jiffies - gact->tcf_tm.lastuse); t.expires = jiffies_to_clock_t(gact->tcf_tm.expires); - NLA_PUT(skb, TCA_GACT_TM, sizeof(t), &t); + if (nla_put(skb, TCA_GACT_TM, sizeof(t), &t)) + goto nla_put_failure; return skb->len; nla_put_failure: diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 60f8f61..0beba0e 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c @@ -267,15 +267,17 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int c.refcnt = ipt->tcf_refcnt - ref; strcpy(t->u.user.name, ipt->tcfi_t->u.kernel.target->name); - NLA_PUT(skb, TCA_IPT_TARG, ipt->tcfi_t->u.user.target_size, t); - NLA_PUT_U32(skb, TCA_IPT_INDEX, ipt->tcf_index); - NLA_PUT_U32(skb, TCA_IPT_HOOK, ipt->tcfi_hook); - NLA_PUT(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c); - NLA_PUT_STRING(skb, TCA_IPT_TABLE, ipt->tcfi_tname); + if (nla_put(skb, TCA_IPT_TARG, ipt->tcfi_t->u.user.target_size, t) || + nla_put_u32(skb, TCA_IPT_INDEX, ipt->tcf_index) || + nla_put_u32(skb, TCA_IPT_HOOK, ipt->tcfi_hook) || + nla_put(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c) || + nla_put_string(skb, TCA_IPT_TABLE, ipt->tcfi_tname)) + goto nla_put_failure; tm.install = jiffies_to_clock_t(jiffies - ipt->tcf_tm.install); tm.lastuse = jiffies_to_clock_t(jiffies - ipt->tcf_tm.lastuse); tm.expires = jiffies_to_clock_t(ipt->tcf_tm.expires); - NLA_PUT(skb, TCA_IPT_TM, sizeof (tm), &tm); + if (nla_put(skb, TCA_IPT_TM, sizeof (tm), &tm)) + goto nla_put_failure; kfree(t); return skb->len; diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index e051398..d583aea 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c @@ -227,11 +227,13 @@ static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, i }; struct tcf_t t; - NLA_PUT(skb, TCA_MIRRED_PARMS, sizeof(opt), &opt); + if (nla_put(skb, TCA_MIRRED_PARMS, sizeof(opt), &opt)) + goto nla_put_failure; t.install = jiffies_to_clock_t(jiffies - m->tcf_tm.install); t.lastuse = jiffies_to_clock_t(jiffies - m->tcf_tm.lastuse); t.expires = jiffies_to_clock_t(m->tcf_tm.expires); - NLA_PUT(skb, TCA_MIRRED_TM, sizeof(t), &t); + if (nla_put(skb, TCA_MIRRED_TM, sizeof(t), &t)) + goto nla_put_failure; return skb->len; nla_put_failure: diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c index 001d1b3..b5d029e 100644 --- a/net/sched/act_nat.c +++ b/net/sched/act_nat.c @@ -284,11 +284,13 @@ static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a, }; struct tcf_t t; - NLA_PUT(skb, TCA_NAT_PARMS, sizeof(opt), &opt); + if (nla_put(skb, TCA_NAT_PARMS, sizeof(opt), &opt)) + goto nla_put_failure; t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install); t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse); t.expires = jiffies_to_clock_t(p->tcf_tm.expires); - NLA_PUT(skb, TCA_NAT_TM, sizeof(t), &t); + if (nla_put(skb, TCA_NAT_TM, sizeof(t), &t)) + goto nla_put_failure; return skb->len; diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 10d3aed..26aa2f6 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c @@ -215,11 +215,13 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a, opt->refcnt = p->tcf_refcnt - ref; opt->bindcnt = p->tcf_bindcnt - bind; - NLA_PUT(skb, TCA_PEDIT_PARMS, s, opt); + if (nla_put(skb, TCA_PEDIT_PARMS, s, opt)) + goto nla_put_failure; t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install); t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse); t.expires = jiffies_to_clock_t(p->tcf_tm.expires); - NLA_PUT(skb, TCA_PEDIT_TM, sizeof(t), &t); + if (nla_put(skb, TCA_PEDIT_TM, sizeof(t), &t)) + goto nla_put_failure; kfree(opt); return skb->len; diff --git a/net/sched/act_police.c b/net/sched/act_police.c index 6fb3f5a..a9de232 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c @@ -356,11 +356,14 @@ tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) opt.rate = police->tcfp_R_tab->rate; if (police->tcfp_P_tab) opt.peakrate = police->tcfp_P_tab->rate; - NLA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt); - if (police->tcfp_result) - NLA_PUT_U32(skb, TCA_POLICE_RESULT, police->tcfp_result); - if (police->tcfp_ewma_rate) - NLA_PUT_U32(skb, TCA_POLICE_AVRATE, police->tcfp_ewma_rate); + if (nla_put(skb, TCA_POLICE_TBF, sizeof(opt), &opt)) + goto nla_put_failure; + if (police->tcfp_result && + nla_put_u32(skb, TCA_POLICE_RESULT, police->tcfp_result)) + goto nla_put_failure; + if (police->tcfp_ewma_rate && + nla_put_u32(skb, TCA_POLICE_AVRATE, police->tcfp_ewma_rate)) + goto nla_put_failure; return skb->len; nla_put_failure: diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index 73e0a3a..3922f2a 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c @@ -172,12 +172,14 @@ static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, }; struct tcf_t t; - NLA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt); - NLA_PUT_STRING(skb, TCA_DEF_DATA, d->tcfd_defdata); + if (nla_put(skb, TCA_DEF_PARMS, sizeof(opt), &opt) || + nla_put_string(skb, TCA_DEF_DATA, d->tcfd_defdata)) + goto nla_put_failure; t.install = jiffies_to_clock_t(jiffies - d->tcf_tm.install); t.lastuse = jiffies_to_clock_t(jiffies - d->tcf_tm.lastuse); t.expires = jiffies_to_clock_t(d->tcf_tm.expires); - NLA_PUT(skb, TCA_DEF_TM, sizeof(t), &t); + if (nla_put(skb, TCA_DEF_TM, sizeof(t), &t)) + goto nla_put_failure; return skb->len; nla_put_failure: diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c index 35dbbe9..476e0fa 100644 --- a/net/sched/act_skbedit.c +++ b/net/sched/act_skbedit.c @@ -166,20 +166,25 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, }; struct tcf_t t; - NLA_PUT(skb, TCA_SKBEDIT_PARMS, sizeof(opt), &opt); - if (d->flags & SKBEDIT_F_PRIORITY) - NLA_PUT(skb, TCA_SKBEDIT_PRIORITY, sizeof(d->priority), - &d->priority); - if (d->flags & SKBEDIT_F_QUEUE_MAPPING) - NLA_PUT(skb, TCA_SKBEDIT_QUEUE_MAPPING, - sizeof(d->queue_mapping), &d->queue_mapping); - if (d->flags & SKBEDIT_F_MARK) - NLA_PUT(skb, TCA_SKBEDIT_MARK, sizeof(d->mark), - &d->mark); + if (nla_put(skb, TCA_SKBEDIT_PARMS, sizeof(opt), &opt)) + goto nla_put_failure; + if ((d->flags & SKBEDIT_F_PRIORITY) && + nla_put(skb, TCA_SKBEDIT_PRIORITY, sizeof(d->priority), + &d->priority)) + goto nla_put_failure; + if ((d->flags & SKBEDIT_F_QUEUE_MAPPING) && + nla_put(skb, TCA_SKBEDIT_QUEUE_MAPPING, + sizeof(d->queue_mapping), &d->queue_mapping)) + goto nla_put_failure; + if ((d->flags & SKBEDIT_F_MARK) && + nla_put(skb, TCA_SKBEDIT_MARK, sizeof(d->mark), + &d->mark)) + goto nla_put_failure; t.install = jiffies_to_clock_t(jiffies - d->tcf_tm.install); t.lastuse = jiffies_to_clock_t(jiffies - d->tcf_tm.lastuse); t.expires = jiffies_to_clock_t(d->tcf_tm.expires); - NLA_PUT(skb, TCA_SKBEDIT_TM, sizeof(t), &t); + if (nla_put(skb, TCA_SKBEDIT_TM, sizeof(t), &t)) + goto nla_put_failure; return skb->len; nla_put_failure: diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index a69d44f..f452f69 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -357,7 +357,8 @@ static int tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp, tcm->tcm_ifindex = qdisc_dev(tp->q)->ifindex; tcm->tcm_parent = tp->classid; tcm->tcm_info = TC_H_MAKE(tp->prio, tp->protocol); - NLA_PUT_STRING(skb, TCA_KIND, tp->ops->kind); + if (nla_put_string(skb, TCA_KIND, tp->ops->kind)) + goto nla_put_failure; tcm->tcm_handle = fh; if (RTM_DELTFILTER != event) { tcm->tcm_handle = 0; diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index ea1f70b..590960a 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c @@ -257,8 +257,9 @@ static int basic_dump(struct tcf_proto *tp, unsigned long fh, if (nest == NULL) goto nla_put_failure; - if (f->res.classid) - NLA_PUT_U32(skb, TCA_BASIC_CLASSID, f->res.classid); + if (f->res.classid && + nla_put_u32(skb, TCA_BASIC_CLASSID, f->res.classid)) + goto nla_put_failure; if (tcf_exts_dump(skb, &f->exts, &basic_ext_map) < 0 || tcf_em_tree_dump(skb, &f->ematches, TCA_BASIC_EMATCHES) < 0) diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c index 1d8bd0d..ccd08c8 100644 --- a/net/sched/cls_flow.c +++ b/net/sched/cls_flow.c @@ -572,25 +572,32 @@ static int flow_dump(struct tcf_proto *tp, unsigned long fh, if (nest == NULL) goto nla_put_failure; - NLA_PUT_U32(skb, TCA_FLOW_KEYS, f->keymask); - NLA_PUT_U32(skb, TCA_FLOW_MODE, f->mode); + if (nla_put_u32(skb, TCA_FLOW_KEYS, f->keymask) || + nla_put_u32(skb, TCA_FLOW_MODE, f->mode)) + goto nla_put_failure; if (f->mask != ~0 || f->xor != 0) { - NLA_PUT_U32(skb, TCA_FLOW_MASK, f->mask); - NLA_PUT_U32(skb, TCA_FLOW_XOR, f->xor); + if (nla_put_u32(skb, TCA_FLOW_MASK, f->mask) || + nla_put_u32(skb, TCA_FLOW_XOR, f->xor)) + goto nla_put_failure; } - if (f->rshift) - NLA_PUT_U32(skb, TCA_FLOW_RSHIFT, f->rshift); - if (f->addend) - NLA_PUT_U32(skb, TCA_FLOW_ADDEND, f->addend); + if (f->rshift && + nla_put_u32(skb, TCA_FLOW_RSHIFT, f->rshift)) + goto nla_put_failure; + if (f->addend && + nla_put_u32(skb, TCA_FLOW_ADDEND, f->addend)) + goto nla_put_failure; - if (f->divisor) - NLA_PUT_U32(skb, TCA_FLOW_DIVISOR, f->divisor); - if (f->baseclass) - NLA_PUT_U32(skb, TCA_FLOW_BASECLASS, f->baseclass); + if (f->divisor && + nla_put_u32(skb, TCA_FLOW_DIVISOR, f->divisor)) + goto nla_put_failure; + if (f->baseclass && + nla_put_u32(skb, TCA_FLOW_BASECLASS, f->baseclass)) + goto nla_put_failure; - if (f->perturb_period) - NLA_PUT_U32(skb, TCA_FLOW_PERTURB, f->perturb_period / HZ); + if (f->perturb_period && + nla_put_u32(skb, TCA_FLOW_PERTURB, f->perturb_period / HZ)) + goto nla_put_failure; if (tcf_exts_dump(skb, &f->exts, &flow_ext_map) < 0) goto nla_put_failure; diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index 389af15..8384a47 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c @@ -346,14 +346,17 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh, if (nest == NULL) goto nla_put_failure; - if (f->res.classid) - NLA_PUT_U32(skb, TCA_FW_CLASSID, f->res.classid); + if (f->res.classid && + nla_put_u32(skb, TCA_FW_CLASSID, f->res.classid)) + goto nla_put_failure; #ifdef CONFIG_NET_CLS_IND - if (strlen(f->indev)) - NLA_PUT_STRING(skb, TCA_FW_INDEV, f->indev); + if (strlen(f->indev) && + nla_put_string(skb, TCA_FW_INDEV, f->indev)) + goto nla_put_failure; #endif /* CONFIG_NET_CLS_IND */ - if (head->mask != 0xFFFFFFFF) - NLA_PUT_U32(skb, TCA_FW_MASK, head->mask); + if (head->mask != 0xFFFFFFFF && + nla_put_u32(skb, TCA_FW_MASK, head->mask)) + goto nla_put_failure; if (tcf_exts_dump(skb, &f->exts, &fw_ext_map) < 0) goto nla_put_failure; diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index 13ab66e..36fec42 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c @@ -571,17 +571,21 @@ static int route4_dump(struct tcf_proto *tp, unsigned long fh, if (!(f->handle & 0x8000)) { id = f->id & 0xFF; - NLA_PUT_U32(skb, TCA_ROUTE4_TO, id); + if (nla_put_u32(skb, TCA_ROUTE4_TO, id)) + goto nla_put_failure; } if (f->handle & 0x80000000) { - if ((f->handle >> 16) != 0xFFFF) - NLA_PUT_U32(skb, TCA_ROUTE4_IIF, f->iif); + if ((f->handle >> 16) != 0xFFFF && + nla_put_u32(skb, TCA_ROUTE4_IIF, f->iif)) + goto nla_put_failure; } else { id = f->id >> 16; - NLA_PUT_U32(skb, TCA_ROUTE4_FROM, id); + if (nla_put_u32(skb, TCA_ROUTE4_FROM, id)) + goto nla_put_failure; } - if (f->res.classid) - NLA_PUT_U32(skb, TCA_ROUTE4_CLASSID, f->res.classid); + if (f->res.classid && + nla_put_u32(skb, TCA_ROUTE4_CLASSID, f->res.classid)) + goto nla_put_failure; if (tcf_exts_dump(skb, &f->exts, &route_ext_map) < 0) goto nla_put_failure; diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h index b014279..18ab93e 100644 --- a/net/sched/cls_rsvp.h +++ b/net/sched/cls_rsvp.h @@ -615,18 +615,22 @@ static int rsvp_dump(struct tcf_proto *tp, unsigned long fh, if (nest == NULL) goto nla_put_failure; - NLA_PUT(skb, TCA_RSVP_DST, sizeof(s->dst), &s->dst); + if (nla_put(skb, TCA_RSVP_DST, sizeof(s->dst), &s->dst)) + goto nla_put_failure; pinfo.dpi = s->dpi; pinfo.spi = f->spi; pinfo.protocol = s->protocol; pinfo.tunnelid = s->tunnelid; pinfo.tunnelhdr = f->tunnelhdr; pinfo.pad = 0; - NLA_PUT(skb, TCA_RSVP_PINFO, sizeof(pinfo), &pinfo); - if (f->res.classid) - NLA_PUT_U32(skb, TCA_RSVP_CLASSID, f->res.classid); - if (((f->handle >> 8) & 0xFF) != 16) - NLA_PUT(skb, TCA_RSVP_SRC, sizeof(f->src), f->src); + if (nla_put(skb, TCA_RSVP_PINFO, sizeof(pinfo), &pinfo)) + goto nla_put_failure; + if (f->res.classid && + nla_put_u32(skb, TCA_RSVP_CLASSID, f->res.classid)) + goto nla_put_failure; + if (((f->handle >> 8) & 0xFF) != 16 && + nla_put(skb, TCA_RSVP_SRC, sizeof(f->src), f->src)) + goto nla_put_failure; if (tcf_exts_dump(skb, &f->exts, &rsvp_ext_map) < 0) goto nla_put_failure; diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index dbe1992..fe29420 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c @@ -438,10 +438,11 @@ static int tcindex_dump(struct tcf_proto *tp, unsigned long fh, if (!fh) { t->tcm_handle = ~0; /* whatever ... */ - NLA_PUT_U32(skb, TCA_TCINDEX_HASH, p->hash); - NLA_PUT_U16(skb, TCA_TCINDEX_MASK, p->mask); - NLA_PUT_U32(skb, TCA_TCINDEX_SHIFT, p->shift); - NLA_PUT_U32(skb, TCA_TCINDEX_FALL_THROUGH, p->fall_through); + if (nla_put_u32(skb, TCA_TCINDEX_HASH, p->hash) || + nla_put_u16(skb, TCA_TCINDEX_MASK, p->mask) || + nla_put_u32(skb, TCA_TCINDEX_SHIFT, p->shift) || + nla_put_u32(skb, TCA_TCINDEX_FALL_THROUGH, p->fall_through)) + goto nla_put_failure; nla_nest_end(skb, nest); } else { if (p->perfect) { @@ -460,8 +461,9 @@ static int tcindex_dump(struct tcf_proto *tp, unsigned long fh, } } pr_debug("handle = %d\n", t->tcm_handle); - if (r->res.class) - NLA_PUT_U32(skb, TCA_TCINDEX_CLASSID, r->res.classid); + if (r->res.class && + nla_put_u32(skb, TCA_TCINDEX_CLASSID, r->res.classid)) + goto nla_put_failure; if (tcf_exts_dump(skb, &r->exts, &tcindex_ext_map) < 0) goto nla_put_failure; diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 939b627..591b006 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -733,36 +733,44 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh, struct tc_u_hnode *ht = (struct tc_u_hnode *)fh; u32 divisor = ht->divisor + 1; - NLA_PUT_U32(skb, TCA_U32_DIVISOR, divisor); + if (nla_put_u32(skb, TCA_U32_DIVISOR, divisor)) + goto nla_put_failure; } else { - NLA_PUT(skb, TCA_U32_SEL, - sizeof(n->sel) + n->sel.nkeys*sizeof(struct tc_u32_key), - &n->sel); + if (nla_put(skb, TCA_U32_SEL, + sizeof(n->sel) + n->sel.nkeys*sizeof(struct tc_u32_key), + &n->sel)) + goto nla_put_failure; if (n->ht_up) { u32 htid = n->handle & 0xFFFFF000; - NLA_PUT_U32(skb, TCA_U32_HASH, htid); + if (nla_put_u32(skb, TCA_U32_HASH, htid)) + goto nla_put_failure; } - if (n->res.classid) - NLA_PUT_U32(skb, TCA_U32_CLASSID, n->res.classid); - if (n->ht_down) - NLA_PUT_U32(skb, TCA_U32_LINK, n->ht_down->handle); + if (n->res.classid && + nla_put_u32(skb, TCA_U32_CLASSID, n->res.classid)) + goto nla_put_failure; + if (n->ht_down && + nla_put_u32(skb, TCA_U32_LINK, n->ht_down->handle)) + goto nla_put_failure; #ifdef CONFIG_CLS_U32_MARK - if (n->mark.val || n->mark.mask) - NLA_PUT(skb, TCA_U32_MARK, sizeof(n->mark), &n->mark); + if ((n->mark.val || n->mark.mask) && + nla_put(skb, TCA_U32_MARK, sizeof(n->mark), &n->mark)) + goto nla_put_failure; #endif if (tcf_exts_dump(skb, &n->exts, &u32_ext_map) < 0) goto nla_put_failure; #ifdef CONFIG_NET_CLS_IND - if (strlen(n->indev)) - NLA_PUT_STRING(skb, TCA_U32_INDEV, n->indev); + if (strlen(n->indev) && + nla_put_string(skb, TCA_U32_INDEV, n->indev)) + goto nla_put_failure; #endif #ifdef CONFIG_CLS_U32_PERF - NLA_PUT(skb, TCA_U32_PCNT, - sizeof(struct tc_u32_pcnt) + n->sel.nkeys*sizeof(u64), - n->pf); + if (nla_put(skb, TCA_U32_PCNT, + sizeof(struct tc_u32_pcnt) + n->sel.nkeys*sizeof(u64), + n->pf)) + goto nla_put_failure; #endif } diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index 1363bf1..4790c69 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c @@ -585,8 +585,9 @@ static void meta_var_apply_extras(struct meta_value *v, static int meta_var_dump(struct sk_buff *skb, struct meta_value *v, int tlv) { - if (v->val && v->len) - NLA_PUT(skb, tlv, v->len, (void *) v->val); + if (v->val && v->len && + nla_put(skb, tlv, v->len, (void *) v->val)) + goto nla_put_failure; return 0; nla_put_failure: @@ -636,10 +637,13 @@ static void meta_int_apply_extras(struct meta_value *v, static int meta_int_dump(struct sk_buff *skb, struct meta_value *v, int tlv) { - if (v->len == sizeof(unsigned long)) - NLA_PUT(skb, tlv, sizeof(unsigned long), &v->val); - else if (v->len == sizeof(u32)) - NLA_PUT_U32(skb, tlv, v->val); + if (v->len == sizeof(unsigned long)) { + if (nla_put(skb, tlv, sizeof(unsigned long), &v->val)) + goto nla_put_failure; + } else if (v->len == sizeof(u32)) { + if (nla_put_u32(skb, tlv, v->val)) + goto nla_put_failure; + } return 0; @@ -831,7 +835,8 @@ static int em_meta_dump(struct sk_buff *skb, struct tcf_ematch *em) memcpy(&hdr.left, &meta->lvalue.hdr, sizeof(hdr.left)); memcpy(&hdr.right, &meta->rvalue.hdr, sizeof(hdr.right)); - NLA_PUT(skb, TCA_EM_META_HDR, sizeof(hdr), &hdr); + if (nla_put(skb, TCA_EM_META_HDR, sizeof(hdr), &hdr)) + goto nla_put_failure; ops = meta_type_ops(&meta->lvalue); if (ops->dump(skb, &meta->lvalue, TCA_EM_META_LVALUE) < 0 || diff --git a/net/sched/ematch.c b/net/sched/ematch.c index 88d93eb..aca233c 100644 --- a/net/sched/ematch.c +++ b/net/sched/ematch.c @@ -441,7 +441,8 @@ int tcf_em_tree_dump(struct sk_buff *skb, struct tcf_ematch_tree *tree, int tlv) if (top_start == NULL) goto nla_put_failure; - NLA_PUT(skb, TCA_EMATCH_TREE_HDR, sizeof(tree->hdr), &tree->hdr); + if (nla_put(skb, TCA_EMATCH_TREE_HDR, sizeof(tree->hdr), &tree->hdr)) + goto nla_put_failure; list_start = nla_nest_start(skb, TCA_EMATCH_TREE_LIST); if (list_start == NULL) @@ -457,7 +458,8 @@ int tcf_em_tree_dump(struct sk_buff *skb, struct tcf_ematch_tree *tree, int tlv) .flags = em->flags }; - NLA_PUT(skb, i + 1, sizeof(em_hdr), &em_hdr); + if (nla_put(skb, i + 1, sizeof(em_hdr), &em_hdr)) + goto nla_put_failure; if (em->ops && em->ops->dump) { if (em->ops->dump(skb, em) < 0) diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 3d8981f..d2daefc 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -426,7 +426,8 @@ static int qdisc_dump_stab(struct sk_buff *skb, struct qdisc_size_table *stab) nest = nla_nest_start(skb, TCA_STAB); if (nest == NULL) goto nla_put_failure; - NLA_PUT(skb, TCA_STAB_BASE, sizeof(stab->szopts), &stab->szopts); + if (nla_put(skb, TCA_STAB_BASE, sizeof(stab->szopts), &stab->szopts)) + goto nla_put_failure; nla_nest_end(skb, nest); return skb->len; @@ -1201,7 +1202,8 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid, tcm->tcm_parent = clid; tcm->tcm_handle = q->handle; tcm->tcm_info = atomic_read(&q->refcnt); - NLA_PUT_STRING(skb, TCA_KIND, q->ops->id); + if (nla_put_string(skb, TCA_KIND, q->ops->id)) + goto nla_put_failure; if (q->ops->dump && q->ops->dump(q, skb) < 0) goto nla_put_failure; q->qstats.qlen = q->q.qlen; @@ -1505,7 +1507,8 @@ static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q, tcm->tcm_parent = q->handle; tcm->tcm_handle = q->handle; tcm->tcm_info = 0; - NLA_PUT_STRING(skb, TCA_KIND, q->ops->id); + if (nla_put_string(skb, TCA_KIND, q->ops->id)) + goto nla_put_failure; if (cl_ops->dump && cl_ops->dump(q, cl, skb, tcm) < 0) goto nla_put_failure; diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index e25e490..a77a4fb 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c @@ -601,7 +601,8 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl, if (nest == NULL) goto nla_put_failure; - NLA_PUT(skb, TCA_ATM_HDR, flow->hdr_len, flow->hdr); + if (nla_put(skb, TCA_ATM_HDR, flow->hdr_len, flow->hdr)) + goto nla_put_failure; if (flow->vcc) { struct sockaddr_atmpvc pvc; int state; @@ -610,15 +611,19 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl, pvc.sap_addr.itf = flow->vcc->dev ? flow->vcc->dev->number : -1; pvc.sap_addr.vpi = flow->vcc->vpi; pvc.sap_addr.vci = flow->vcc->vci; - NLA_PUT(skb, TCA_ATM_ADDR, sizeof(pvc), &pvc); + if (nla_put(skb, TCA_ATM_ADDR, sizeof(pvc), &pvc)) + goto nla_put_failure; state = ATM_VF2VS(flow->vcc->flags); - NLA_PUT_U32(skb, TCA_ATM_STATE, state); + if (nla_put_u32(skb, TCA_ATM_STATE, state)) + goto nla_put_failure; + } + if (flow->excess) { + if (nla_put_u32(skb, TCA_ATM_EXCESS, flow->classid)) + goto nla_put_failure; + } else { + if (nla_put_u32(skb, TCA_ATM_EXCESS, 0)) + goto nla_put_failure; } - if (flow->excess) - NLA_PUT_U32(skb, TCA_ATM_EXCESS, flow->classid); - else - NLA_PUT_U32(skb, TCA_ATM_EXCESS, 0); - nla_nest_end(skb, nest); return skb->len; diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 24d94c0..6aabd77 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -1425,7 +1425,8 @@ static int cbq_dump_rate(struct sk_buff *skb, struct cbq_class *cl) { unsigned char *b = skb_tail_pointer(skb); - NLA_PUT(skb, TCA_CBQ_RATE, sizeof(cl->R_tab->rate), &cl->R_tab->rate); + if (nla_put(skb, TCA_CBQ_RATE, sizeof(cl->R_tab->rate), &cl->R_tab->rate)) + goto nla_put_failure; return skb->len; nla_put_failure: @@ -1450,7 +1451,8 @@ static int cbq_dump_lss(struct sk_buff *skb, struct cbq_class *cl) opt.minidle = (u32)(-cl->minidle); opt.offtime = cl->offtime; opt.change = ~0; - NLA_PUT(skb, TCA_CBQ_LSSOPT, sizeof(opt), &opt); + if (nla_put(skb, TCA_CBQ_LSSOPT, sizeof(opt), &opt)) + goto nla_put_failure; return skb->len; nla_put_failure: @@ -1468,7 +1470,8 @@ static int cbq_dump_wrr(struct sk_buff *skb, struct cbq_class *cl) opt.priority = cl->priority + 1; opt.cpriority = cl->cpriority + 1; opt.weight = cl->weight; - NLA_PUT(skb, TCA_CBQ_WRROPT, sizeof(opt), &opt); + if (nla_put(skb, TCA_CBQ_WRROPT, sizeof(opt), &opt)) + goto nla_put_failure; return skb->len; nla_put_failure: @@ -1485,7 +1488,8 @@ static int cbq_dump_ovl(struct sk_buff *skb, struct cbq_class *cl) opt.priority2 = cl->priority2 + 1; opt.pad = 0; opt.penalty = cl->penalty; - NLA_PUT(skb, TCA_CBQ_OVL_STRATEGY, sizeof(opt), &opt); + if (nla_put(skb, TCA_CBQ_OVL_STRATEGY, sizeof(opt), &opt)) + goto nla_put_failure; return skb->len; nla_put_failure: @@ -1502,7 +1506,8 @@ static int cbq_dump_fopt(struct sk_buff *skb, struct cbq_class *cl) opt.split = cl->split ? cl->split->common.classid : 0; opt.defmap = cl->defmap; opt.defchange = ~0; - NLA_PUT(skb, TCA_CBQ_FOPT, sizeof(opt), &opt); + if (nla_put(skb, TCA_CBQ_FOPT, sizeof(opt), &opt)) + goto nla_put_failure; } return skb->len; @@ -1521,7 +1526,8 @@ static int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl) opt.police = cl->police; opt.__res1 = 0; opt.__res2 = 0; - NLA_PUT(skb, TCA_CBQ_POLICE, sizeof(opt), &opt); + if (nla_put(skb, TCA_CBQ_POLICE, sizeof(opt), &opt)) + goto nla_put_failure; } return skb->len; diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c index 7e267d7..81445cc 100644 --- a/net/sched/sch_choke.c +++ b/net/sched/sch_choke.c @@ -515,8 +515,9 @@ static int choke_dump(struct Qdisc *sch, struct sk_buff *skb) if (opts == NULL) goto nla_put_failure; - NLA_PUT(skb, TCA_CHOKE_PARMS, sizeof(opt), &opt); - NLA_PUT_U32(skb, TCA_CHOKE_MAX_P, q->parms.max_P); + if (nla_put(skb, TCA_CHOKE_PARMS, sizeof(opt), &opt) || + nla_put_u32(skb, TCA_CHOKE_MAX_P, q->parms.max_P)) + goto nla_put_failure; return nla_nest_end(skb, opts); nla_put_failure: diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c index 6b7fe4a..c218987 100644 --- a/net/sched/sch_drr.c +++ b/net/sched/sch_drr.c @@ -260,7 +260,8 @@ static int drr_dump_class(struct Qdisc *sch, unsigned long arg, nest = nla_nest_start(skb, TCA_OPTIONS); if (nest == NULL) goto nla_put_failure; - NLA_PUT_U32(skb, TCA_DRR_QUANTUM, cl->quantum); + if (nla_put_u32(skb, TCA_DRR_QUANTUM, cl->quantum)) + goto nla_put_failure; return nla_nest_end(skb, nest); nla_put_failure: diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index 2c79020..389b856 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c @@ -429,8 +429,9 @@ static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl, opts = nla_nest_start(skb, TCA_OPTIONS); if (opts == NULL) goto nla_put_failure; - NLA_PUT_U8(skb, TCA_DSMARK_MASK, p->mask[cl - 1]); - NLA_PUT_U8(skb, TCA_DSMARK_VALUE, p->value[cl - 1]); + if (nla_put_u8(skb, TCA_DSMARK_MASK, p->mask[cl - 1]) || + nla_put_u8(skb, TCA_DSMARK_VALUE, p->value[cl - 1])) + goto nla_put_failure; return nla_nest_end(skb, opts); @@ -447,13 +448,16 @@ static int dsmark_dump(struct Qdisc *sch, struct sk_buff *skb) opts = nla_nest_start(skb, TCA_OPTIONS); if (opts == NULL) goto nla_put_failure; - NLA_PUT_U16(skb, TCA_DSMARK_INDICES, p->indices); + if (nla_put_u16(skb, TCA_DSMARK_INDICES, p->indices)) + goto nla_put_failure; - if (p->default_index != NO_DEFAULT_INDEX) - NLA_PUT_U16(skb, TCA_DSMARK_DEFAULT_INDEX, p->default_index); + if (p->default_index != NO_DEFAULT_INDEX && + nla_put_u16(skb, TCA_DSMARK_DEFAULT_INDEX, p->default_index)) + goto nla_put_failure; - if (p->set_tc_index) - NLA_PUT_FLAG(skb, TCA_DSMARK_SET_TC_INDEX); + if (p->set_tc_index && + nla_put_flag(skb, TCA_DSMARK_SET_TC_INDEX)) + goto nla_put_failure; return nla_nest_end(skb, opts); diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c index 66effe2..e15a9eb 100644 --- a/net/sched/sch_fifo.c +++ b/net/sched/sch_fifo.c @@ -85,7 +85,8 @@ static int fifo_dump(struct Qdisc *sch, struct sk_buff *skb) { struct tc_fifo_qopt opt = { .limit = sch->limit }; - NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); + if (nla_put(skb, TCA_OPTIONS, sizeof(opt), &opt)) + goto nla_put_failure; return skb->len; nla_put_failure: diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 67fc573..0eb1202 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -512,7 +512,8 @@ static int pfifo_fast_dump(struct Qdisc *qdisc, struct sk_buff *skb) struct tc_prio_qopt opt = { .bands = PFIFO_FAST_BANDS }; memcpy(&opt.priomap, prio2band, TC_PRIO_MAX + 1); - NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); + if (nla_put(skb, TCA_OPTIONS, sizeof(opt), &opt)) + goto nla_put_failure; return skb->len; nla_put_failure: diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 0b15236..55e3310 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -521,14 +521,16 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) opts = nla_nest_start(skb, TCA_OPTIONS); if (opts == NULL) goto nla_put_failure; - NLA_PUT(skb, TCA_GRED_DPS, sizeof(sopt), &sopt); + if (nla_put(skb, TCA_GRED_DPS, sizeof(sopt), &sopt)) + goto nla_put_failure; for (i = 0; i < MAX_DPs; i++) { struct gred_sched_data *q = table->tab[i]; max_p[i] = q ? q->parms.max_P : 0; } - NLA_PUT(skb, TCA_GRED_MAX_P, sizeof(max_p), max_p); + if (nla_put(skb, TCA_GRED_MAX_P, sizeof(max_p), max_p)) + goto nla_put_failure; parms = nla_nest_start(skb, TCA_GRED_PARMS); if (parms == NULL) diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 9bdca2e..8db3e2c 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -1305,7 +1305,8 @@ hfsc_dump_sc(struct sk_buff *skb, int attr, struct internal_sc *sc) tsc.m1 = sm2m(sc->sm1); tsc.d = dx2d(sc->dx); tsc.m2 = sm2m(sc->sm2); - NLA_PUT(skb, attr, sizeof(tsc), &tsc); + if (nla_put(skb, attr, sizeof(tsc), &tsc)) + goto nla_put_failure; return skb->len; @@ -1573,7 +1574,8 @@ hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb) } qopt.defcls = q->defcls; - NLA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt); + if (nla_put(skb, TCA_OPTIONS, sizeof(qopt), &qopt)) + goto nla_put_failure; return skb->len; nla_put_failure: diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 29b942c..2ea6f19 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -1051,7 +1051,8 @@ static int htb_dump(struct Qdisc *sch, struct sk_buff *skb) nest = nla_nest_start(skb, TCA_OPTIONS); if (nest == NULL) goto nla_put_failure; - NLA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt); + if (nla_put(skb, TCA_HTB_INIT, sizeof(gopt), &gopt)) + goto nla_put_failure; nla_nest_end(skb, nest); spin_unlock_bh(root_lock); @@ -1090,7 +1091,8 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg, opt.quantum = cl->quantum; opt.prio = cl->prio; opt.level = cl->level; - NLA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt); + if (nla_put(skb, TCA_HTB_PARMS, sizeof(opt), &opt)) + goto nla_put_failure; nla_nest_end(skb, nest); spin_unlock_bh(root_lock); diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c index 28de430..d1831ca 100644 --- a/net/sched/sch_mqprio.c +++ b/net/sched/sch_mqprio.c @@ -247,7 +247,8 @@ static int mqprio_dump(struct Qdisc *sch, struct sk_buff *skb) opt.offset[i] = dev->tc_to_txq[i].offset; } - NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); + if (nla_put(skb, TCA_OPTIONS, sizeof(opt), &opt)) + goto nla_put_failure; return skb->len; nla_put_failure: diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c index 49131d7..2a2b096 100644 --- a/net/sched/sch_multiq.c +++ b/net/sched/sch_multiq.c @@ -284,7 +284,8 @@ static int multiq_dump(struct Qdisc *sch, struct sk_buff *skb) opt.bands = q->bands; opt.max_bands = q->max_bands; - NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); + if (nla_put(skb, TCA_OPTIONS, sizeof(opt), &opt)) + goto nla_put_failure; return skb->len; diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 5da548f..1109731 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -834,7 +834,8 @@ static int dump_loss_model(const struct netem_sched_data *q, .p23 = q->clg.a5, }; - NLA_PUT(skb, NETEM_LOSS_GI, sizeof(gi), &gi); + if (nla_put(skb, NETEM_LOSS_GI, sizeof(gi), &gi)) + goto nla_put_failure; break; } case CLG_GILB_ELL: { @@ -845,7 +846,8 @@ static int dump_loss_model(const struct netem_sched_data *q, .k1 = q->clg.a4, }; - NLA_PUT(skb, NETEM_LOSS_GE, sizeof(ge), &ge); + if (nla_put(skb, NETEM_LOSS_GE, sizeof(ge), &ge)) + goto nla_put_failure; break; } } @@ -874,26 +876,31 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb) qopt.loss = q->loss; qopt.gap = q->gap; qopt.duplicate = q->duplicate; - NLA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt); + if (nla_put(skb, TCA_OPTIONS, sizeof(qopt), &qopt)) + goto nla_put_failure; cor.delay_corr = q->delay_cor.rho; cor.loss_corr = q->loss_cor.rho; cor.dup_corr = q->dup_cor.rho; - NLA_PUT(skb, TCA_NETEM_CORR, sizeof(cor), &cor); + if (nla_put(skb, TCA_NETEM_CORR, sizeof(cor), &cor)) + goto nla_put_failure; reorder.probability = q->reorder; reorder.correlation = q->reorder_cor.rho; - NLA_PUT(skb, TCA_NETEM_REORDER, sizeof(reorder), &reorder); + if (nla_put(skb, TCA_NETEM_REORDER, sizeof(reorder), &reorder)) + goto nla_put_failure; corrupt.probability = q->corrupt; corrupt.correlation = q->corrupt_cor.rho; - NLA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt); + if (nla_put(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt)) + goto nla_put_failure; rate.rate = q->rate; rate.packet_overhead = q->packet_overhead; rate.cell_size = q->cell_size; rate.cell_overhead = q->cell_overhead; - NLA_PUT(skb, TCA_NETEM_RATE, sizeof(rate), &rate); + if (nla_put(skb, TCA_NETEM_RATE, sizeof(rate), &rate)) + goto nla_put_failure; if (dump_loss_model(q, skb) != 0) goto nla_put_failure; diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index b5d56a2..79359b6 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c @@ -247,7 +247,8 @@ static int prio_dump(struct Qdisc *sch, struct sk_buff *skb) opt.bands = q->bands; memcpy(&opt.priomap, q->prio2band, TC_PRIO_MAX + 1); - NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); + if (nla_put(skb, TCA_OPTIONS, sizeof(opt), &opt)) + goto nla_put_failure; return skb->len; diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index e68cb44..9af01f3 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c @@ -429,8 +429,9 @@ static int qfq_dump_class(struct Qdisc *sch, unsigned long arg, nest = nla_nest_start(skb, TCA_OPTIONS); if (nest == NULL) goto nla_put_failure; - NLA_PUT_U32(skb, TCA_QFQ_WEIGHT, ONE_FP/cl->inv_w); - NLA_PUT_U32(skb, TCA_QFQ_LMAX, cl->lmax); + if (nla_put_u32(skb, TCA_QFQ_WEIGHT, ONE_FP/cl->inv_w) || + nla_put_u32(skb, TCA_QFQ_LMAX, cl->lmax)) + goto nla_put_failure; return nla_nest_end(skb, nest); nla_put_failure: diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index a5cc301..633e32d 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -272,8 +272,9 @@ static int red_dump(struct Qdisc *sch, struct sk_buff *skb) opts = nla_nest_start(skb, TCA_OPTIONS); if (opts == NULL) goto nla_put_failure; - NLA_PUT(skb, TCA_RED_PARMS, sizeof(opt), &opt); - NLA_PUT_U32(skb, TCA_RED_MAX_P, q->parms.max_P); + if (nla_put(skb, TCA_RED_PARMS, sizeof(opt), &opt) || + nla_put_u32(skb, TCA_RED_MAX_P, q->parms.max_P)) + goto nla_put_failure; return nla_nest_end(skb, opts); nla_put_failure: diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c index d7eea99..74305c8 100644 --- a/net/sched/sch_sfb.c +++ b/net/sched/sch_sfb.c @@ -570,7 +570,8 @@ static int sfb_dump(struct Qdisc *sch, struct sk_buff *skb) sch->qstats.backlog = q->qdisc->qstats.backlog; opts = nla_nest_start(skb, TCA_OPTIONS); - NLA_PUT(skb, TCA_SFB_PARMS, sizeof(opt), &opt); + if (nla_put(skb, TCA_SFB_PARMS, sizeof(opt), &opt)) + goto nla_put_failure; return nla_nest_end(skb, opts); nla_put_failure: diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 02a21ab..d3a1bc2 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -812,7 +812,8 @@ static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb) memcpy(&opt.stats, &q->stats, sizeof(opt.stats)); opt.flags = q->flags; - NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); + if (nla_put(skb, TCA_OPTIONS, sizeof(opt), &opt)) + goto nla_put_failure; return skb->len; diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index b8e1563..4b056c15 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -359,7 +359,8 @@ static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb) memset(&opt.peakrate, 0, sizeof(opt.peakrate)); opt.mtu = q->mtu; opt.buffer = q->buffer; - NLA_PUT(skb, TCA_TBF_PARMS, sizeof(opt), &opt); + if (nla_put(skb, TCA_TBF_PARMS, sizeof(opt), &opt)) + goto nla_put_failure; nla_nest_end(skb, nest); return skb->len; diff --git a/net/sctp/associola.c b/net/sctp/associola.c index acd2edb..5bc9ab1 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1408,7 +1408,7 @@ static inline int sctp_peer_needs_update(struct sctp_association *asoc) } /* Increase asoc's rwnd by len and send any window update SACK if needed. */ -void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned len) +void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len) { struct sctp_chunk *sack; struct timer_list *timer; @@ -1465,7 +1465,7 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned len) } /* Decrease asoc's rwnd by len. */ -void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned len) +void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len) { int rx_count; int over = 0; diff --git a/net/sctp/output.c b/net/sctp/output.c index 817174e..69534c5 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -663,8 +663,8 @@ static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet, */ if (!sctp_sk(asoc->base.sk)->nodelay && sctp_packet_empty(packet) && inflight && sctp_state(asoc, ESTABLISHED)) { - unsigned max = transport->pathmtu - packet->overhead; - unsigned len = chunk->skb->len + q->out_qlen; + unsigned int max = transport->pathmtu - packet->overhead; + unsigned int len = chunk->skb->len + q->out_qlen; /* Check whether this chunk and all the rest of pending * data will fit or delay in hopes of bundling a full diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index cfeb1d4..a0fa19f 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -1147,7 +1147,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) __u32 sack_ctsn, ctsn, tsn; __u32 highest_tsn, highest_new_tsn; __u32 sack_a_rwnd; - unsigned outstanding; + unsigned int outstanding; struct sctp_transport *primary = asoc->peer.primary_path; int count_of_newacks = 0; int gap_ack_blocks; diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 1ff51c9..fbb374c 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -524,7 +524,7 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, /* Worker routine to handle INIT command failure. */ static void sctp_cmd_init_failed(sctp_cmd_seq_t *commands, struct sctp_association *asoc, - unsigned error) + unsigned int error) { struct sctp_ulpevent *event; @@ -550,7 +550,7 @@ static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands, sctp_event_t event_type, sctp_subtype_t subtype, struct sctp_chunk *chunk, - unsigned error) + unsigned int error) { struct sctp_ulpevent *event; diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 891f5db..a147b4d 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -2410,7 +2410,7 @@ static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, sctp_cmd_seq_t *commands) { struct sctp_chunk *chunk = arg; - unsigned len; + unsigned int len; __be16 error = SCTP_ERROR_NO_ERROR; /* See if we have an error cause code in the chunk. */ @@ -2446,7 +2446,7 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep, sctp_cmd_seq_t *commands) { struct sctp_chunk *chunk = arg; - unsigned len; + unsigned int len; __be16 error = SCTP_ERROR_NO_ERROR; if (!sctp_vtag_verify_either(chunk, asoc)) diff --git a/net/socket.c b/net/socket.c index 851edcd..d6c1af9 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1479,7 +1479,7 @@ SYSCALL_DEFINE2(listen, int, fd, int, backlog) sock = sockfd_lookup_light(fd, &err, &fput_needed); if (sock) { somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn; - if ((unsigned)backlog > somaxconn) + if ((unsigned int)backlog > somaxconn) backlog = somaxconn; err = security_socket_listen(sock, backlog); @@ -1691,7 +1691,7 @@ SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr, */ SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len, - unsigned, flags, struct sockaddr __user *, addr, + unsigned int, flags, struct sockaddr __user *, addr, int, addr_len) { struct socket *sock; @@ -1738,7 +1738,7 @@ out: */ SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len, - unsigned, flags) + unsigned int, flags) { return sys_sendto(fd, buff, len, flags, NULL, 0); } @@ -1750,7 +1750,7 @@ SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len, */ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, - unsigned, flags, struct sockaddr __user *, addr, + unsigned int, flags, struct sockaddr __user *, addr, int __user *, addr_len) { struct socket *sock; @@ -1795,7 +1795,7 @@ out: */ asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size, - unsigned flags) + unsigned int flags) { return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL); } @@ -1897,7 +1897,7 @@ struct used_address { }; static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg, - struct msghdr *msg_sys, unsigned flags, + struct msghdr *msg_sys, unsigned int flags, struct used_address *used_address) { struct compat_msghdr __user *msg_compat = @@ -2014,7 +2014,7 @@ out: * BSD sendmsg interface */ -SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags) +SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags) { int fput_needed, err; struct msghdr msg_sys; @@ -2096,7 +2096,7 @@ SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg, } static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, - struct msghdr *msg_sys, unsigned flags, int nosec) + struct msghdr *msg_sys, unsigned int flags, int nosec) { struct compat_msghdr __user *msg_compat = (struct compat_msghdr __user *)msg; @@ -3223,7 +3223,7 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, return -ENOIOCTLCMD; } -static long compat_sock_ioctl(struct file *file, unsigned cmd, +static long compat_sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct socket *sock = file->private_data; diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 8eff8c3..d3611f1 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -624,7 +624,7 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, ctx->seq_send = ctx->seq_send64; if (ctx->seq_send64 != ctx->seq_send) { dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__, - (long unsigned)ctx->seq_send64, ctx->seq_send); + (unsigned long)ctx->seq_send64, ctx->seq_send); p = ERR_PTR(-EINVAL); goto out_err; } diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index de0b0f3..47ad266 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1273,7 +1273,7 @@ static void *c_start(struct seq_file *m, loff_t *pos) __acquires(cd->hash_lock) { loff_t n = *pos; - unsigned hash, entry; + unsigned int hash, entry; struct cache_head *ch; struct cache_detail *cd = ((struct handle*)m->private)->cd; diff --git a/net/sunrpc/timer.c b/net/sunrpc/timer.c index dd82434..08881d0 100644 --- a/net/sunrpc/timer.c +++ b/net/sunrpc/timer.c @@ -34,7 +34,7 @@ void rpc_init_rtt(struct rpc_rtt *rt, unsigned long timeo) { unsigned long init = 0; - unsigned i; + unsigned int i; rt->timeo = timeo; @@ -57,7 +57,7 @@ EXPORT_SYMBOL_GPL(rpc_init_rtt); * NB: When computing the smoothed RTT and standard deviation, * be careful not to produce negative intermediate results. */ -void rpc_update_rtt(struct rpc_rtt *rt, unsigned timer, long m) +void rpc_update_rtt(struct rpc_rtt *rt, unsigned int timer, long m) { long *srtt, *sdrtt; @@ -106,7 +106,7 @@ EXPORT_SYMBOL_GPL(rpc_update_rtt); * read, write, commit - A+4D * other - timeo */ -unsigned long rpc_calc_rto(struct rpc_rtt *rt, unsigned timer) +unsigned long rpc_calc_rto(struct rpc_rtt *rt, unsigned int timer) { unsigned long res; diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index b97a3dd..fddcccf 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -1204,7 +1204,7 @@ xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, int (*actor)(struct scatterlist *, void *), void *data) { int i, ret = 0; - unsigned page_len, thislen, page_offset; + unsigned int page_len, thislen, page_offset; struct scatterlist sg[1]; sg_init_table(sg, 1); diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 0cbcd1a..6fe2dce 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -783,7 +783,7 @@ static void xprt_update_rtt(struct rpc_task *task) { struct rpc_rqst *req = task->tk_rqstp; struct rpc_rtt *rtt = task->tk_client->cl_rtt; - unsigned timer = task->tk_msg.rpc_proc->p_timer; + unsigned int timer = task->tk_msg.rpc_proc->p_timer; long m = usecs_to_jiffies(ktime_to_us(req->rq_rtt)); if (timer) { diff --git a/net/tipc/link.c b/net/tipc/link.c index b4b9b30..33cecd6 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -612,7 +612,7 @@ static void link_activate(struct tipc_link *l_ptr) * @event: state machine event to process */ -static void link_state_event(struct tipc_link *l_ptr, unsigned event) +static void link_state_event(struct tipc_link *l_ptr, unsigned int event) { struct tipc_link *other; u32 cont_intv = l_ptr->continuity_interval; diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 29e957f..bcb3314 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -535,7 +535,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, (dest->family != AF_TIPC))) return -EINVAL; if ((total_len > TIPC_MAX_USER_MSG_SIZE) || - (m->msg_iovlen > (unsigned)INT_MAX)) + (m->msg_iovlen > (unsigned int)INT_MAX)) return -EMSGSIZE; if (iocb) @@ -647,7 +647,7 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, return send_msg(iocb, sock, m, total_len); if ((total_len > TIPC_MAX_USER_MSG_SIZE) || - (m->msg_iovlen > (unsigned)INT_MAX)) + (m->msg_iovlen > (unsigned int)INT_MAX)) return -EMSGSIZE; if (iocb) @@ -734,8 +734,8 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, goto exit; } - if ((total_len > (unsigned)INT_MAX) || - (m->msg_iovlen > (unsigned)INT_MAX)) { + if ((total_len > (unsigned int)INT_MAX) || + (m->msg_iovlen > (unsigned int)INT_MAX)) { res = -EMSGSIZE; goto exit; } diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index d510353..641f2e4 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -149,9 +149,10 @@ static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) * each socket state is protected by separate spin lock. */ -static inline unsigned unix_hash_fold(__wsum n) +static inline unsigned int unix_hash_fold(__wsum n) { - unsigned hash = (__force unsigned)n; + unsigned int hash = (__force unsigned int)n; + hash ^= hash>>16; hash ^= hash>>8; return hash&(UNIX_HASH_SIZE-1); @@ -200,7 +201,7 @@ static inline void unix_release_addr(struct unix_address *addr) * - if started by zero, it is abstract name. */ -static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned *hashp) +static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned int *hashp) { if (len <= sizeof(short) || len > sizeof(*sunaddr)) return -EINVAL; @@ -250,7 +251,7 @@ static inline void unix_insert_socket(struct hlist_head *list, struct sock *sk) static struct sock *__unix_find_socket_byname(struct net *net, struct sockaddr_un *sunname, - int len, int type, unsigned hash) + int len, int type, unsigned int hash) { struct sock *s; struct hlist_node *node; @@ -273,7 +274,7 @@ found: static inline struct sock *unix_find_socket_byname(struct net *net, struct sockaddr_un *sunname, int len, int type, - unsigned hash) + unsigned int hash) { struct sock *s; @@ -760,7 +761,7 @@ out: mutex_unlock(&u->readlock); static struct sock *unix_find_other(struct net *net, struct sockaddr_un *sunname, int len, - int type, unsigned hash, int *error) + int type, unsigned int hash, int *error) { struct sock *u; struct path path; @@ -824,7 +825,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) struct dentry *dentry = NULL; struct path path; int err; - unsigned hash; + unsigned int hash; struct unix_address *addr; struct hlist_head *list; @@ -964,7 +965,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, struct net *net = sock_net(sk); struct sockaddr_un *sunaddr = (struct sockaddr_un *)addr; struct sock *other; - unsigned hash; + unsigned int hash; int err; if (addr->sa_family != AF_UNSPEC) { @@ -1062,7 +1063,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, struct sock *newsk = NULL; struct sock *other = NULL; struct sk_buff *skb = NULL; - unsigned hash; + unsigned int hash; int st; int err; long timeo; @@ -1437,11 +1438,12 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, struct sock *other = NULL; int namelen = 0; /* fake GCC */ int err; - unsigned hash; + unsigned int hash; struct sk_buff *skb; long timeo; struct scm_cookie tmp_scm; int max_level; + int data_len = 0; if (NULL == siocb->scm) siocb->scm = &tmp_scm; @@ -1475,7 +1477,13 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, if (len > sk->sk_sndbuf - 32) goto out; - skb = sock_alloc_send_skb(sk, len, msg->msg_flags&MSG_DONTWAIT, &err); + if (len > SKB_MAX_ALLOC) + data_len = min_t(size_t, + len - SKB_MAX_ALLOC, + MAX_SKB_FRAGS * PAGE_SIZE); + + skb = sock_alloc_send_pskb(sk, len - data_len, data_len, + msg->msg_flags & MSG_DONTWAIT, &err); if (skb == NULL) goto out; @@ -1485,8 +1493,10 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, max_level = err + 1; unix_get_secdata(siocb->scm, skb); - skb_reset_transport_header(skb); - err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); + skb_put(skb, len - data_len); + skb->data_len = data_len; + skb->len = len; + err = skb_copy_datagram_from_iovec(skb, 0, msg->msg_iov, 0, len); if (err) goto out_free; diff --git a/net/wimax/stack.c b/net/wimax/stack.c index 3c65eae..a6470ac 100644 --- a/net/wimax/stack.c +++ b/net/wimax/stack.c @@ -187,7 +187,7 @@ out: static void __check_new_state(enum wimax_st old_state, enum wimax_st new_state, - unsigned allowed_states_bm) + unsigned int allowed_states_bm) { if (WARN_ON(((1 << new_state) & allowed_states_bm) == 0)) { printk(KERN_ERR "SW BUG! Forbidden state change %u -> %u\n", @@ -425,7 +425,8 @@ static size_t wimax_addr_scnprint(char *addr_str, size_t addr_str_size, unsigned char *addr, size_t addr_len) { - unsigned cnt, total; + unsigned int cnt, total; + for (total = cnt = 0; cnt < addr_len; cnt++) total += scnprintf(addr_str + total, addr_str_size - total, "%02x%c", addr[cnt], diff --git a/net/wireless/core.c b/net/wireless/core.c index ccdfed8..59f4a7e 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -708,6 +708,10 @@ void wiphy_unregister(struct wiphy *wiphy) flush_work(&rdev->scan_done_wk); cancel_work_sync(&rdev->conn_work); flush_work(&rdev->event_work); + + if (rdev->wowlan && rdev->ops->set_wakeup) + rdev->ops->set_wakeup(&rdev->wiphy, false); + cfg80211_rdev_free_wowlan(rdev); } EXPORT_SYMBOL(wiphy_unregister); @@ -720,7 +724,6 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev) mutex_destroy(&rdev->sched_scan_mtx); list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) cfg80211_put_bss(&scan->pub); - cfg80211_rdev_free_wowlan(rdev); kfree(rdev); } diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index ba21ab2..8c747fa 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c @@ -38,6 +38,7 @@ #define MESH_MAX_PREQ_RETRIES 4 +#define MESH_SYNC_NEIGHBOR_OFFSET_MAX 50 const struct mesh_config default_mesh_config = { .dot11MeshRetryTimeout = MESH_RET_T, @@ -48,6 +49,7 @@ const struct mesh_config default_mesh_config = { .element_ttl = MESH_DEFAULT_ELEMENT_TTL, .auto_open_plinks = true, .dot11MeshMaxPeerLinks = MESH_MAX_ESTAB_PLINKS, + .dot11MeshNbrOffsetMaxNeighbor = MESH_SYNC_NEIGHBOR_OFFSET_MAX, .dot11MeshHWMPactivePathTimeout = MESH_PATH_TIMEOUT, .dot11MeshHWMPpreqMinInterval = MESH_PREQ_MIN_INT, .dot11MeshHWMPperrMinInterval = MESH_PERR_MIN_INT, @@ -62,6 +64,7 @@ const struct mesh_config default_mesh_config = { }; const struct mesh_setup default_mesh_setup = { + .sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET, .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, .path_metric = IEEE80211_PATH_METRIC_AIRTIME, .ie = NULL, diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index f5a7ac3..6801d96 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -6,6 +6,7 @@ #include <linux/kernel.h> #include <linux/module.h> +#include <linux/etherdevice.h> #include <linux/netdevice.h> #include <linux/nl80211.h> #include <linux/slab.h> @@ -100,7 +101,7 @@ void __cfg80211_send_deauth(struct net_device *dev, ASSERT_WDEV_LOCK(wdev); if (wdev->current_bss && - memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { + compare_ether_addr(wdev->current_bss->pub.bssid, bssid) == 0) { cfg80211_unhold_bss(wdev->current_bss); cfg80211_put_bss(&wdev->current_bss->pub); wdev->current_bss = NULL; @@ -115,7 +116,7 @@ void __cfg80211_send_deauth(struct net_device *dev, reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); - from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0; + from_ap = compare_ether_addr(mgmt->sa, dev->dev_addr) != 0; __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); } else if (wdev->sme_state == CFG80211_SME_CONNECTING) { __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, @@ -154,7 +155,7 @@ void __cfg80211_send_disassoc(struct net_device *dev, return; if (wdev->current_bss && - memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { + compare_ether_addr(wdev->current_bss->pub.bssid, bssid) == 0) { cfg80211_sme_disassoc(dev, wdev->current_bss); cfg80211_unhold_bss(wdev->current_bss); cfg80211_put_bss(&wdev->current_bss->pub); @@ -165,7 +166,7 @@ void __cfg80211_send_disassoc(struct net_device *dev, reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); - from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0; + from_ap = compare_ether_addr(mgmt->sa, dev->dev_addr) != 0; __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); } EXPORT_SYMBOL(__cfg80211_send_disassoc); @@ -285,7 +286,7 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, return -EINVAL; if (wdev->current_bss && - memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0) + compare_ether_addr(bssid, wdev->current_bss->pub.bssid) == 0) return -EALREADY; memset(&req, 0, sizeof(req)); @@ -362,7 +363,7 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, memset(&req, 0, sizeof(req)); if (wdev->current_bss && prev_bssid && - memcmp(wdev->current_bss->pub.bssid, prev_bssid, ETH_ALEN) == 0) { + compare_ether_addr(wdev->current_bss->pub.bssid, prev_bssid) == 0) { /* * Trying to reassociate: Allow this to proceed and let the old * association to be dropped when the new one is completed. @@ -446,7 +447,8 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, if (local_state_change) { if (wdev->current_bss && - memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { + compare_ether_addr(wdev->current_bss->pub.bssid, bssid) + == 0) { cfg80211_unhold_bss(wdev->current_bss); cfg80211_put_bss(&wdev->current_bss->pub); wdev->current_bss = NULL; @@ -495,7 +497,7 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, req.local_state_change = local_state_change; req.ie = ie; req.ie_len = ie_len; - if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) + if (compare_ether_addr(wdev->current_bss->pub.bssid, bssid) == 0) req.bss = &wdev->current_bss->pub; else return -ENOTCONN; @@ -758,8 +760,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, break; } - if (memcmp(wdev->current_bss->pub.bssid, - mgmt->bssid, ETH_ALEN)) { + if (compare_ether_addr(wdev->current_bss->pub.bssid, + mgmt->bssid)) { err = -ENOTCONN; break; } @@ -772,8 +774,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, break; /* for station, check that DA is the AP */ - if (memcmp(wdev->current_bss->pub.bssid, - mgmt->da, ETH_ALEN)) { + if (compare_ether_addr(wdev->current_bss->pub.bssid, + mgmt->da)) { err = -ENOTCONN; break; } @@ -781,11 +783,11 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: case NL80211_IFTYPE_AP_VLAN: - if (memcmp(mgmt->bssid, dev->dev_addr, ETH_ALEN)) + if (compare_ether_addr(mgmt->bssid, dev->dev_addr)) err = -EINVAL; break; case NL80211_IFTYPE_MESH_POINT: - if (memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN)) { + if (compare_ether_addr(mgmt->sa, mgmt->bssid)) { err = -EINVAL; break; } @@ -804,7 +806,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, return err; } - if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0) + if (compare_ether_addr(mgmt->sa, dev->dev_addr) != 0) return -EINVAL; /* Transmit the Action frame as requested by user space */ @@ -928,6 +930,33 @@ void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index, } EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify); +void cfg80211_ch_switch_notify(struct net_device *dev, int freq, + enum nl80211_channel_type type) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + struct ieee80211_channel *chan; + + wdev_lock(wdev); + + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && + wdev->iftype != NL80211_IFTYPE_P2P_GO)) + goto out; + + chan = rdev_freq_to_chan(rdev, freq, type); + if (WARN_ON(!chan)) + goto out; + + wdev->channel = chan; + + nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL); +out: + wdev_unlock(wdev); + return; +} +EXPORT_SYMBOL(cfg80211_ch_switch_notify); + bool cfg80211_rx_spurious_frame(struct net_device *dev, const u8 *addr, gfp_t gfp) { diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index f432c57..ff1a6c7 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -356,20 +356,26 @@ static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq, static int nl80211_msg_put_channel(struct sk_buff *msg, struct ieee80211_channel *chan) { - NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ, - chan->center_freq); + if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_FREQ, + chan->center_freq)) + goto nla_put_failure; - if (chan->flags & IEEE80211_CHAN_DISABLED) - NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED); - if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) - NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN); - if (chan->flags & IEEE80211_CHAN_NO_IBSS) - NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS); - if (chan->flags & IEEE80211_CHAN_RADAR) - NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR); + if ((chan->flags & IEEE80211_CHAN_DISABLED) && + nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED)) + goto nla_put_failure; + if ((chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) && + nla_put_flag(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN)) + goto nla_put_failure; + if ((chan->flags & IEEE80211_CHAN_NO_IBSS) && + nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS)) + goto nla_put_failure; + if ((chan->flags & IEEE80211_CHAN_RADAR) && + nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) + goto nla_put_failure; - NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, - DBM_TO_MBM(chan->max_power)); + if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, + DBM_TO_MBM(chan->max_power))) + goto nla_put_failure; return 0; @@ -621,8 +627,8 @@ static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes) i = 0; while (ifmodes) { - if (ifmodes & 1) - NLA_PUT_FLAG(msg, i); + if ((ifmodes & 1) && nla_put_flag(msg, i)) + goto nla_put_failure; ifmodes >>= 1; i++; } @@ -665,8 +671,9 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy, nl_limit = nla_nest_start(msg, j + 1); if (!nl_limit) goto nla_put_failure; - NLA_PUT_U32(msg, NL80211_IFACE_LIMIT_MAX, - c->limits[j].max); + if (nla_put_u32(msg, NL80211_IFACE_LIMIT_MAX, + c->limits[j].max)) + goto nla_put_failure; if (nl80211_put_iftypes(msg, NL80211_IFACE_LIMIT_TYPES, c->limits[j].types)) goto nla_put_failure; @@ -675,13 +682,14 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy, nla_nest_end(msg, nl_limits); - if (c->beacon_int_infra_match) - NLA_PUT_FLAG(msg, - NL80211_IFACE_COMB_STA_AP_BI_MATCH); - NLA_PUT_U32(msg, NL80211_IFACE_COMB_NUM_CHANNELS, - c->num_different_channels); - NLA_PUT_U32(msg, NL80211_IFACE_COMB_MAXNUM, - c->max_interfaces); + if (c->beacon_int_infra_match && + nla_put_flag(msg, NL80211_IFACE_COMB_STA_AP_BI_MATCH)) + goto nla_put_failure; + if (nla_put_u32(msg, NL80211_IFACE_COMB_NUM_CHANNELS, + c->num_different_channels) || + nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM, + c->max_interfaces)) + goto nla_put_failure; nla_nest_end(msg, nl_combi); } @@ -712,64 +720,74 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, if (!hdr) return -1; - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx); - NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); - - NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, - cfg80211_rdev_list_generation); - - NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, - dev->wiphy.retry_short); - NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_LONG, - dev->wiphy.retry_long); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, - dev->wiphy.frag_threshold); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, - dev->wiphy.rts_threshold); - NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, - dev->wiphy.coverage_class); - NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, - dev->wiphy.max_scan_ssids); - NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS, - dev->wiphy.max_sched_scan_ssids); - NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, - dev->wiphy.max_scan_ie_len); - NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, - dev->wiphy.max_sched_scan_ie_len); - NLA_PUT_U8(msg, NL80211_ATTR_MAX_MATCH_SETS, - dev->wiphy.max_match_sets); - - if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) - NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN); - if (dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) - NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_MESH_AUTH); - if (dev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) - NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_AP_UAPSD); - if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) - NLA_PUT_FLAG(msg, NL80211_ATTR_ROAM_SUPPORT); - if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) - NLA_PUT_FLAG(msg, NL80211_ATTR_TDLS_SUPPORT); - if (dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) - NLA_PUT_FLAG(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP); - - NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES, - sizeof(u32) * dev->wiphy.n_cipher_suites, - dev->wiphy.cipher_suites); - - NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_PMKIDS, - dev->wiphy.max_num_pmkids); - - if (dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) - NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE); - - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX, - dev->wiphy.available_antennas_tx); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, - dev->wiphy.available_antennas_rx); - - if (dev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) - NLA_PUT_U32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD, - dev->wiphy.probe_resp_offload); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx) || + nla_put_string(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)) || + nla_put_u32(msg, NL80211_ATTR_GENERATION, + cfg80211_rdev_list_generation) || + nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, + dev->wiphy.retry_short) || + nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG, + dev->wiphy.retry_long) || + nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, + dev->wiphy.frag_threshold) || + nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, + dev->wiphy.rts_threshold) || + nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, + dev->wiphy.coverage_class) || + nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, + dev->wiphy.max_scan_ssids) || + nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS, + dev->wiphy.max_sched_scan_ssids) || + nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, + dev->wiphy.max_scan_ie_len) || + nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, + dev->wiphy.max_sched_scan_ie_len) || + nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS, + dev->wiphy.max_match_sets)) + goto nla_put_failure; + + if ((dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) && + nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN)) + goto nla_put_failure; + if ((dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) && + nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH)) + goto nla_put_failure; + if ((dev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && + nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD)) + goto nla_put_failure; + if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) && + nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT)) + goto nla_put_failure; + if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) && + nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT)) + goto nla_put_failure; + if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) && + nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) + goto nla_put_failure; + + if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES, + sizeof(u32) * dev->wiphy.n_cipher_suites, + dev->wiphy.cipher_suites)) + goto nla_put_failure; + + if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS, + dev->wiphy.max_num_pmkids)) + goto nla_put_failure; + + if ((dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) && + nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE)) + goto nla_put_failure; + + if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX, + dev->wiphy.available_antennas_tx) || + nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, + dev->wiphy.available_antennas_rx)) + goto nla_put_failure; + + if ((dev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) && + nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD, + dev->wiphy.probe_resp_offload)) + goto nla_put_failure; if ((dev->wiphy.available_antennas_tx || dev->wiphy.available_antennas_rx) && dev->ops->get_antenna) { @@ -777,8 +795,11 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, int res; res = dev->ops->get_antenna(&dev->wiphy, &tx_ant, &rx_ant); if (!res) { - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_TX, tx_ant); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_RX, rx_ant); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_TX, + tx_ant) || + nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_RX, + rx_ant)) + goto nla_put_failure; } } @@ -799,17 +820,17 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, goto nla_put_failure; /* add HT info */ - if (dev->wiphy.bands[band]->ht_cap.ht_supported) { - NLA_PUT(msg, NL80211_BAND_ATTR_HT_MCS_SET, - sizeof(dev->wiphy.bands[band]->ht_cap.mcs), - &dev->wiphy.bands[band]->ht_cap.mcs); - NLA_PUT_U16(msg, NL80211_BAND_ATTR_HT_CAPA, - dev->wiphy.bands[band]->ht_cap.cap); - NLA_PUT_U8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR, - dev->wiphy.bands[band]->ht_cap.ampdu_factor); - NLA_PUT_U8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY, - dev->wiphy.bands[band]->ht_cap.ampdu_density); - } + if (dev->wiphy.bands[band]->ht_cap.ht_supported && + (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET, + sizeof(dev->wiphy.bands[band]->ht_cap.mcs), + &dev->wiphy.bands[band]->ht_cap.mcs) || + nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA, + dev->wiphy.bands[band]->ht_cap.cap) || + nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR, + dev->wiphy.bands[band]->ht_cap.ampdu_factor) || + nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY, + dev->wiphy.bands[band]->ht_cap.ampdu_density))) + goto nla_put_failure; /* add frequencies */ nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS); @@ -842,11 +863,13 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, goto nla_put_failure; rate = &dev->wiphy.bands[band]->bitrates[i]; - NLA_PUT_U32(msg, NL80211_BITRATE_ATTR_RATE, - rate->bitrate); - if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) - NLA_PUT_FLAG(msg, - NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE); + if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE, + rate->bitrate)) + goto nla_put_failure; + if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) && + nla_put_flag(msg, + NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE)) + goto nla_put_failure; nla_nest_end(msg, nl_rate); } @@ -866,7 +889,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, do { \ if (dev->ops->op) { \ i++; \ - NLA_PUT_U32(msg, i, NL80211_CMD_ ## n); \ + if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \ + goto nla_put_failure; \ } \ } while (0) @@ -894,7 +918,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL); if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { i++; - NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); + if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS)) + goto nla_put_failure; } CMD(set_channel, SET_CHANNEL); CMD(set_wds_peer, SET_WDS_PEER); @@ -908,7 +933,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, CMD(set_noack_map, SET_NOACK_MAP); if (dev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) { i++; - NLA_PUT_U32(msg, i, NL80211_CMD_REGISTER_BEACONS); + if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS)) + goto nla_put_failure; } #ifdef CONFIG_NL80211_TESTMODE @@ -919,23 +945,27 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, if (dev->ops->connect || dev->ops->auth) { i++; - NLA_PUT_U32(msg, i, NL80211_CMD_CONNECT); + if (nla_put_u32(msg, i, NL80211_CMD_CONNECT)) + goto nla_put_failure; } if (dev->ops->disconnect || dev->ops->deauth) { i++; - NLA_PUT_U32(msg, i, NL80211_CMD_DISCONNECT); + if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT)) + goto nla_put_failure; } nla_nest_end(msg, nl_cmds); if (dev->ops->remain_on_channel && - dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) - NLA_PUT_U32(msg, NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION, - dev->wiphy.max_remain_on_channel_duration); + (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) && + nla_put_u32(msg, NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION, + dev->wiphy.max_remain_on_channel_duration)) + goto nla_put_failure; - if (dev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) - NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK); + if ((dev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) && + nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK)) + goto nla_put_failure; if (mgmt_stypes) { u16 stypes; @@ -953,9 +983,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, i = 0; stypes = mgmt_stypes[ift].tx; while (stypes) { - if (stypes & 1) - NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, - (i << 4) | IEEE80211_FTYPE_MGMT); + if ((stypes & 1) && + nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, + (i << 4) | IEEE80211_FTYPE_MGMT)) + goto nla_put_failure; stypes >>= 1; i++; } @@ -975,9 +1006,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, i = 0; stypes = mgmt_stypes[ift].rx; while (stypes) { - if (stypes & 1) - NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, - (i << 4) | IEEE80211_FTYPE_MGMT); + if ((stypes & 1) && + nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, + (i << 4) | IEEE80211_FTYPE_MGMT)) + goto nla_put_failure; stypes >>= 1; i++; } @@ -994,22 +1026,23 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, if (!nl_wowlan) goto nla_put_failure; - if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_ANY) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_ANY); - if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_DISCONNECT) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT); - if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT); - if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED); - if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE); - if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST); - if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE); - if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE); + if (((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_ANY) && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || + ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_DISCONNECT) && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || + ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || + ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) || + ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || + ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || + ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || + ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE) && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) + goto nla_put_failure; if (dev->wiphy.wowlan.n_patterns) { struct nl80211_wowlan_pattern_support pat = { .max_patterns = dev->wiphy.wowlan.n_patterns, @@ -1018,8 +1051,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, .max_pattern_len = dev->wiphy.wowlan.pattern_max_len, }; - NLA_PUT(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, - sizeof(pat), &pat); + if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, + sizeof(pat), &pat)) + goto nla_put_failure; } nla_nest_end(msg, nl_wowlan); @@ -1032,16 +1066,20 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, if (nl80211_put_iface_combinations(&dev->wiphy, msg)) goto nla_put_failure; - if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) - NLA_PUT_U32(msg, NL80211_ATTR_DEVICE_AP_SME, - dev->wiphy.ap_sme_capa); + if ((dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) && + nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME, + dev->wiphy.ap_sme_capa)) + goto nla_put_failure; - NLA_PUT_U32(msg, NL80211_ATTR_FEATURE_FLAGS, dev->wiphy.features); + if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, + dev->wiphy.features)) + goto nla_put_failure; - if (dev->wiphy.ht_capa_mod_mask) - NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY_MASK, - sizeof(*dev->wiphy.ht_capa_mod_mask), - dev->wiphy.ht_capa_mod_mask); + if (dev->wiphy.ht_capa_mod_mask && + nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK, + sizeof(*dev->wiphy.ht_capa_mod_mask), + dev->wiphy.ht_capa_mod_mask)) + goto nla_put_failure; return genlmsg_end(msg, hdr); @@ -1104,17 +1142,20 @@ static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = { static int parse_txq_params(struct nlattr *tb[], struct ieee80211_txq_params *txq_params) { - if (!tb[NL80211_TXQ_ATTR_QUEUE] || !tb[NL80211_TXQ_ATTR_TXOP] || + if (!tb[NL80211_TXQ_ATTR_AC] || !tb[NL80211_TXQ_ATTR_TXOP] || !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] || !tb[NL80211_TXQ_ATTR_AIFS]) return -EINVAL; - txq_params->queue = nla_get_u8(tb[NL80211_TXQ_ATTR_QUEUE]); + txq_params->ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]); txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]); txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]); txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]); txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]); + if (txq_params->ac >= NL80211_NUM_ACS) + return -EINVAL; + return 0; } @@ -1489,14 +1530,15 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, if (!hdr) return -1; - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name); - NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype); - - NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, - rdev->devlist_generation ^ - (cfg80211_rdev_list_generation << 2)); + if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || + nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name) || + nla_put_u32(msg, NL80211_ATTR_IFTYPE, + dev->ieee80211_ptr->iftype) || + nla_put_u32(msg, NL80211_ATTR_GENERATION, + rdev->devlist_generation ^ + (cfg80211_rdev_list_generation << 2))) + goto nla_put_failure; return genlmsg_end(msg, hdr); @@ -1794,35 +1836,34 @@ static void get_key_callback(void *c, struct key_params *params) struct nlattr *key; struct get_key_cookie *cookie = c; - if (params->key) - NLA_PUT(cookie->msg, NL80211_ATTR_KEY_DATA, - params->key_len, params->key); - - if (params->seq) - NLA_PUT(cookie->msg, NL80211_ATTR_KEY_SEQ, - params->seq_len, params->seq); - - if (params->cipher) - NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER, - params->cipher); + if ((params->key && + nla_put(cookie->msg, NL80211_ATTR_KEY_DATA, + params->key_len, params->key)) || + (params->seq && + nla_put(cookie->msg, NL80211_ATTR_KEY_SEQ, + params->seq_len, params->seq)) || + (params->cipher && + nla_put_u32(cookie->msg, NL80211_ATTR_KEY_CIPHER, + params->cipher))) + goto nla_put_failure; key = nla_nest_start(cookie->msg, NL80211_ATTR_KEY); if (!key) goto nla_put_failure; - if (params->key) - NLA_PUT(cookie->msg, NL80211_KEY_DATA, - params->key_len, params->key); - - if (params->seq) - NLA_PUT(cookie->msg, NL80211_KEY_SEQ, - params->seq_len, params->seq); - - if (params->cipher) - NLA_PUT_U32(cookie->msg, NL80211_KEY_CIPHER, - params->cipher); + if ((params->key && + nla_put(cookie->msg, NL80211_KEY_DATA, + params->key_len, params->key)) || + (params->seq && + nla_put(cookie->msg, NL80211_KEY_SEQ, + params->seq_len, params->seq)) || + (params->cipher && + nla_put_u32(cookie->msg, NL80211_KEY_CIPHER, + params->cipher))) + goto nla_put_failure; - NLA_PUT_U8(cookie->msg, NL80211_ATTR_KEY_IDX, cookie->idx); + if (nla_put_u8(cookie->msg, NL80211_ATTR_KEY_IDX, cookie->idx)) + goto nla_put_failure; nla_nest_end(cookie->msg, key); @@ -1880,10 +1921,12 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) cookie.msg = msg; cookie.idx = key_idx; - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); - NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx); - if (mac_addr) - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); + if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || + nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx)) + goto nla_put_failure; + if (mac_addr && + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr)) + goto nla_put_failure; if (pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) @@ -2373,15 +2416,15 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */ bitrate = cfg80211_calculate_bitrate(info); - if (bitrate > 0) - NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate); - - if (info->flags & RATE_INFO_FLAGS_MCS) - NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS, info->mcs); - if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) - NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH); - if (info->flags & RATE_INFO_FLAGS_SHORT_GI) - NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI); + if ((bitrate > 0 && + nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate)) || + ((info->flags & RATE_INFO_FLAGS_MCS) && + nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs)) || + ((info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) && + nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH)) || + ((info->flags & RATE_INFO_FLAGS_SHORT_GI) && + nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))) + goto nla_put_failure; nla_nest_end(msg, rate); return true; @@ -2403,43 +2446,50 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, if (!hdr) return -1; - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); - - NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, sinfo->generation); + if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) || + nla_put_u32(msg, NL80211_ATTR_GENERATION, sinfo->generation)) + goto nla_put_failure; sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO); if (!sinfoattr) goto nla_put_failure; - if (sinfo->filled & STATION_INFO_CONNECTED_TIME) - NLA_PUT_U32(msg, NL80211_STA_INFO_CONNECTED_TIME, - sinfo->connected_time); - if (sinfo->filled & STATION_INFO_INACTIVE_TIME) - NLA_PUT_U32(msg, NL80211_STA_INFO_INACTIVE_TIME, - sinfo->inactive_time); - if (sinfo->filled & STATION_INFO_RX_BYTES) - NLA_PUT_U32(msg, NL80211_STA_INFO_RX_BYTES, - sinfo->rx_bytes); - if (sinfo->filled & STATION_INFO_TX_BYTES) - NLA_PUT_U32(msg, NL80211_STA_INFO_TX_BYTES, - sinfo->tx_bytes); - if (sinfo->filled & STATION_INFO_LLID) - NLA_PUT_U16(msg, NL80211_STA_INFO_LLID, - sinfo->llid); - if (sinfo->filled & STATION_INFO_PLID) - NLA_PUT_U16(msg, NL80211_STA_INFO_PLID, - sinfo->plid); - if (sinfo->filled & STATION_INFO_PLINK_STATE) - NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE, - sinfo->plink_state); + if ((sinfo->filled & STATION_INFO_CONNECTED_TIME) && + nla_put_u32(msg, NL80211_STA_INFO_CONNECTED_TIME, + sinfo->connected_time)) + goto nla_put_failure; + if ((sinfo->filled & STATION_INFO_INACTIVE_TIME) && + nla_put_u32(msg, NL80211_STA_INFO_INACTIVE_TIME, + sinfo->inactive_time)) + goto nla_put_failure; + if ((sinfo->filled & STATION_INFO_RX_BYTES) && + nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES, + sinfo->rx_bytes)) + goto nla_put_failure; + if ((sinfo->filled & STATION_INFO_TX_BYTES) && + nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES, + sinfo->tx_bytes)) + goto nla_put_failure; + if ((sinfo->filled & STATION_INFO_LLID) && + nla_put_u16(msg, NL80211_STA_INFO_LLID, sinfo->llid)) + goto nla_put_failure; + if ((sinfo->filled & STATION_INFO_PLID) && + nla_put_u16(msg, NL80211_STA_INFO_PLID, sinfo->plid)) + goto nla_put_failure; + if ((sinfo->filled & STATION_INFO_PLINK_STATE) && + nla_put_u8(msg, NL80211_STA_INFO_PLINK_STATE, + sinfo->plink_state)) + goto nla_put_failure; switch (rdev->wiphy.signal_type) { case CFG80211_SIGNAL_TYPE_MBM: - if (sinfo->filled & STATION_INFO_SIGNAL) - NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL, - sinfo->signal); - if (sinfo->filled & STATION_INFO_SIGNAL_AVG) - NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG, - sinfo->signal_avg); + if ((sinfo->filled & STATION_INFO_SIGNAL) && + nla_put_u8(msg, NL80211_STA_INFO_SIGNAL, + sinfo->signal)) + goto nla_put_failure; + if ((sinfo->filled & STATION_INFO_SIGNAL_AVG) && + nla_put_u8(msg, NL80211_STA_INFO_SIGNAL_AVG, + sinfo->signal_avg)) + goto nla_put_failure; break; default: break; @@ -2454,49 +2504,60 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, NL80211_STA_INFO_RX_BITRATE)) goto nla_put_failure; } - if (sinfo->filled & STATION_INFO_RX_PACKETS) - NLA_PUT_U32(msg, NL80211_STA_INFO_RX_PACKETS, - sinfo->rx_packets); - if (sinfo->filled & STATION_INFO_TX_PACKETS) - NLA_PUT_U32(msg, NL80211_STA_INFO_TX_PACKETS, - sinfo->tx_packets); - if (sinfo->filled & STATION_INFO_TX_RETRIES) - NLA_PUT_U32(msg, NL80211_STA_INFO_TX_RETRIES, - sinfo->tx_retries); - if (sinfo->filled & STATION_INFO_TX_FAILED) - NLA_PUT_U32(msg, NL80211_STA_INFO_TX_FAILED, - sinfo->tx_failed); - if (sinfo->filled & STATION_INFO_BEACON_LOSS_COUNT) - NLA_PUT_U32(msg, NL80211_STA_INFO_BEACON_LOSS, - sinfo->beacon_loss_count); + if ((sinfo->filled & STATION_INFO_RX_PACKETS) && + nla_put_u32(msg, NL80211_STA_INFO_RX_PACKETS, + sinfo->rx_packets)) + goto nla_put_failure; + if ((sinfo->filled & STATION_INFO_TX_PACKETS) && + nla_put_u32(msg, NL80211_STA_INFO_TX_PACKETS, + sinfo->tx_packets)) + goto nla_put_failure; + if ((sinfo->filled & STATION_INFO_TX_RETRIES) && + nla_put_u32(msg, NL80211_STA_INFO_TX_RETRIES, + sinfo->tx_retries)) + goto nla_put_failure; + if ((sinfo->filled & STATION_INFO_TX_FAILED) && + nla_put_u32(msg, NL80211_STA_INFO_TX_FAILED, + sinfo->tx_failed)) + goto nla_put_failure; + if ((sinfo->filled & STATION_INFO_BEACON_LOSS_COUNT) && + nla_put_u32(msg, NL80211_STA_INFO_BEACON_LOSS, + sinfo->beacon_loss_count)) + goto nla_put_failure; if (sinfo->filled & STATION_INFO_BSS_PARAM) { bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM); if (!bss_param) goto nla_put_failure; - if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) - NLA_PUT_FLAG(msg, NL80211_STA_BSS_PARAM_CTS_PROT); - if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) - NLA_PUT_FLAG(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE); - if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) - NLA_PUT_FLAG(msg, - NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME); - NLA_PUT_U8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD, - sinfo->bss_param.dtim_period); - NLA_PUT_U16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL, - sinfo->bss_param.beacon_interval); + if (((sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) && + nla_put_flag(msg, NL80211_STA_BSS_PARAM_CTS_PROT)) || + ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) && + nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE)) || + ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) && + nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME)) || + nla_put_u8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD, + sinfo->bss_param.dtim_period) || + nla_put_u16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL, + sinfo->bss_param.beacon_interval)) + goto nla_put_failure; nla_nest_end(msg, bss_param); } - if (sinfo->filled & STATION_INFO_STA_FLAGS) - NLA_PUT(msg, NL80211_STA_INFO_STA_FLAGS, - sizeof(struct nl80211_sta_flag_update), - &sinfo->sta_flags); + if ((sinfo->filled & STATION_INFO_STA_FLAGS) && + nla_put(msg, NL80211_STA_INFO_STA_FLAGS, + sizeof(struct nl80211_sta_flag_update), + &sinfo->sta_flags)) + goto nla_put_failure; + if ((sinfo->filled & STATION_INFO_T_OFFSET) && + nla_put_u64(msg, NL80211_STA_INFO_T_OFFSET, + sinfo->t_offset)) + goto nla_put_failure; nla_nest_end(msg, sinfoattr); - if (sinfo->filled & STATION_INFO_ASSOC_REQ_IES) - NLA_PUT(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len, - sinfo->assoc_req_ies); + if ((sinfo->filled & STATION_INFO_ASSOC_REQ_IES) && + nla_put(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len, + sinfo->assoc_req_ies)) + goto nla_put_failure; return genlmsg_end(msg, hdr); @@ -2918,36 +2979,37 @@ static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq, if (!hdr) return -1; - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst); - NLA_PUT(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop); - - NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, pinfo->generation); + if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dst) || + nla_put(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop) || + nla_put_u32(msg, NL80211_ATTR_GENERATION, pinfo->generation)) + goto nla_put_failure; pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO); if (!pinfoattr) goto nla_put_failure; - if (pinfo->filled & MPATH_INFO_FRAME_QLEN) - NLA_PUT_U32(msg, NL80211_MPATH_INFO_FRAME_QLEN, - pinfo->frame_qlen); - if (pinfo->filled & MPATH_INFO_SN) - NLA_PUT_U32(msg, NL80211_MPATH_INFO_SN, - pinfo->sn); - if (pinfo->filled & MPATH_INFO_METRIC) - NLA_PUT_U32(msg, NL80211_MPATH_INFO_METRIC, - pinfo->metric); - if (pinfo->filled & MPATH_INFO_EXPTIME) - NLA_PUT_U32(msg, NL80211_MPATH_INFO_EXPTIME, - pinfo->exptime); - if (pinfo->filled & MPATH_INFO_FLAGS) - NLA_PUT_U8(msg, NL80211_MPATH_INFO_FLAGS, - pinfo->flags); - if (pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT) - NLA_PUT_U32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT, - pinfo->discovery_timeout); - if (pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES) - NLA_PUT_U8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES, - pinfo->discovery_retries); + if ((pinfo->filled & MPATH_INFO_FRAME_QLEN) && + nla_put_u32(msg, NL80211_MPATH_INFO_FRAME_QLEN, + pinfo->frame_qlen)) + goto nla_put_failure; + if (((pinfo->filled & MPATH_INFO_SN) && + nla_put_u32(msg, NL80211_MPATH_INFO_SN, pinfo->sn)) || + ((pinfo->filled & MPATH_INFO_METRIC) && + nla_put_u32(msg, NL80211_MPATH_INFO_METRIC, + pinfo->metric)) || + ((pinfo->filled & MPATH_INFO_EXPTIME) && + nla_put_u32(msg, NL80211_MPATH_INFO_EXPTIME, + pinfo->exptime)) || + ((pinfo->filled & MPATH_INFO_FLAGS) && + nla_put_u8(msg, NL80211_MPATH_INFO_FLAGS, + pinfo->flags)) || + ((pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT) && + nla_put_u32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT, + pinfo->discovery_timeout)) || + ((pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES) && + nla_put_u8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES, + pinfo->discovery_retries))) + goto nla_put_failure; nla_nest_end(msg, pinfoattr); @@ -3273,47 +3335,50 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG); if (!pinfoattr) goto nla_put_failure; - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); - NLA_PUT_U16(msg, NL80211_MESHCONF_RETRY_TIMEOUT, - cur_params.dot11MeshRetryTimeout); - NLA_PUT_U16(msg, NL80211_MESHCONF_CONFIRM_TIMEOUT, - cur_params.dot11MeshConfirmTimeout); - NLA_PUT_U16(msg, NL80211_MESHCONF_HOLDING_TIMEOUT, - cur_params.dot11MeshHoldingTimeout); - NLA_PUT_U16(msg, NL80211_MESHCONF_MAX_PEER_LINKS, - cur_params.dot11MeshMaxPeerLinks); - NLA_PUT_U8(msg, NL80211_MESHCONF_MAX_RETRIES, - cur_params.dot11MeshMaxRetries); - NLA_PUT_U8(msg, NL80211_MESHCONF_TTL, - cur_params.dot11MeshTTL); - NLA_PUT_U8(msg, NL80211_MESHCONF_ELEMENT_TTL, - cur_params.element_ttl); - NLA_PUT_U8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS, - cur_params.auto_open_plinks); - NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, - cur_params.dot11MeshHWMPmaxPREQretries); - NLA_PUT_U32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME, - cur_params.path_refresh_time); - NLA_PUT_U16(msg, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, - cur_params.min_discovery_timeout); - NLA_PUT_U32(msg, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, - cur_params.dot11MeshHWMPactivePathTimeout); - NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, - cur_params.dot11MeshHWMPpreqMinInterval); - NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, - cur_params.dot11MeshHWMPperrMinInterval); - NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, - cur_params.dot11MeshHWMPnetDiameterTraversalTime); - NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_ROOTMODE, - cur_params.dot11MeshHWMPRootMode); - NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL, - cur_params.dot11MeshHWMPRannInterval); - NLA_PUT_U8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS, - cur_params.dot11MeshGateAnnouncementProtocol); - NLA_PUT_U8(msg, NL80211_MESHCONF_FORWARDING, - cur_params.dot11MeshForwarding); - NLA_PUT_U32(msg, NL80211_MESHCONF_RSSI_THRESHOLD, - cur_params.rssi_threshold); + if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || + nla_put_u16(msg, NL80211_MESHCONF_RETRY_TIMEOUT, + cur_params.dot11MeshRetryTimeout) || + nla_put_u16(msg, NL80211_MESHCONF_CONFIRM_TIMEOUT, + cur_params.dot11MeshConfirmTimeout) || + nla_put_u16(msg, NL80211_MESHCONF_HOLDING_TIMEOUT, + cur_params.dot11MeshHoldingTimeout) || + nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS, + cur_params.dot11MeshMaxPeerLinks) || + nla_put_u8(msg, NL80211_MESHCONF_MAX_RETRIES, + cur_params.dot11MeshMaxRetries) || + nla_put_u8(msg, NL80211_MESHCONF_TTL, + cur_params.dot11MeshTTL) || + nla_put_u8(msg, NL80211_MESHCONF_ELEMENT_TTL, + cur_params.element_ttl) || + nla_put_u8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS, + cur_params.auto_open_plinks) || + nla_put_u32(msg, NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, + cur_params.dot11MeshNbrOffsetMaxNeighbor) || + nla_put_u8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, + cur_params.dot11MeshHWMPmaxPREQretries) || + nla_put_u32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME, + cur_params.path_refresh_time) || + nla_put_u16(msg, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, + cur_params.min_discovery_timeout) || + nla_put_u32(msg, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, + cur_params.dot11MeshHWMPactivePathTimeout) || + nla_put_u16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, + cur_params.dot11MeshHWMPpreqMinInterval) || + nla_put_u16(msg, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, + cur_params.dot11MeshHWMPperrMinInterval) || + nla_put_u16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, + cur_params.dot11MeshHWMPnetDiameterTraversalTime) || + nla_put_u8(msg, NL80211_MESHCONF_HWMP_ROOTMODE, + cur_params.dot11MeshHWMPRootMode) || + nla_put_u16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL, + cur_params.dot11MeshHWMPRannInterval) || + nla_put_u8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS, + cur_params.dot11MeshGateAnnouncementProtocol) || + nla_put_u8(msg, NL80211_MESHCONF_FORWARDING, + cur_params.dot11MeshForwarding) || + nla_put_u32(msg, NL80211_MESHCONF_RSSI_THRESHOLD, + cur_params.rssi_threshold)) + goto nla_put_failure; nla_nest_end(msg, pinfoattr); genlmsg_end(msg, hdr); return genlmsg_reply(msg, info); @@ -3334,6 +3399,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A [NL80211_MESHCONF_TTL] = { .type = NLA_U8 }, [NL80211_MESHCONF_ELEMENT_TTL] = { .type = NLA_U8 }, [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 }, + [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] = { .type = NLA_U32 }, [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 }, [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 }, @@ -3351,6 +3417,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A static const struct nla_policy nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = { + [NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC] = { .type = NLA_U8 }, [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, @@ -3403,6 +3470,9 @@ do {\ mask, NL80211_MESHCONF_ELEMENT_TTL, nla_get_u8); FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS, nla_get_u8); + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor, + mask, NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, + nla_get_u32); FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, nla_get_u8); @@ -3460,6 +3530,12 @@ static int nl80211_parse_mesh_setup(struct genl_info *info, nl80211_mesh_setup_params_policy)) return -EINVAL; + if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC]) + setup->sync_method = + (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])) ? + IEEE80211_SYNC_METHOD_VENDOR : + IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET; + if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL]) setup->path_sel_proto = (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])) ? @@ -3544,11 +3620,12 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) if (!hdr) goto put_failure; - NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, - cfg80211_regdomain->alpha2); - if (cfg80211_regdomain->dfs_region) - NLA_PUT_U8(msg, NL80211_ATTR_DFS_REGION, - cfg80211_regdomain->dfs_region); + if (nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, + cfg80211_regdomain->alpha2) || + (cfg80211_regdomain->dfs_region && + nla_put_u8(msg, NL80211_ATTR_DFS_REGION, + cfg80211_regdomain->dfs_region))) + goto nla_put_failure; nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES); if (!nl_reg_rules) @@ -3568,18 +3645,19 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) if (!nl_reg_rule) goto nla_put_failure; - NLA_PUT_U32(msg, NL80211_ATTR_REG_RULE_FLAGS, - reg_rule->flags); - NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_START, - freq_range->start_freq_khz); - NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_END, - freq_range->end_freq_khz); - NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW, - freq_range->max_bandwidth_khz); - NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, - power_rule->max_antenna_gain); - NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, - power_rule->max_eirp); + if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS, + reg_rule->flags) || + nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_START, + freq_range->start_freq_khz) || + nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_END, + freq_range->end_freq_khz) || + nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW, + freq_range->max_bandwidth_khz) || + nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, + power_rule->max_antenna_gain) || + nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, + power_rule->max_eirp)) + goto nla_put_failure; nla_nest_end(msg, nl_reg_rule); } @@ -4150,37 +4228,44 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, genl_dump_check_consistent(cb, hdr, &nl80211_fam); - NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex); + if (nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex)) + goto nla_put_failure; bss = nla_nest_start(msg, NL80211_ATTR_BSS); if (!bss) goto nla_put_failure; - if (!is_zero_ether_addr(res->bssid)) - NLA_PUT(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid); - if (res->information_elements && res->len_information_elements) - NLA_PUT(msg, NL80211_BSS_INFORMATION_ELEMENTS, - res->len_information_elements, - res->information_elements); - if (res->beacon_ies && res->len_beacon_ies && - res->beacon_ies != res->information_elements) - NLA_PUT(msg, NL80211_BSS_BEACON_IES, - res->len_beacon_ies, res->beacon_ies); - if (res->tsf) - NLA_PUT_U64(msg, NL80211_BSS_TSF, res->tsf); - if (res->beacon_interval) - NLA_PUT_U16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval); - NLA_PUT_U16(msg, NL80211_BSS_CAPABILITY, res->capability); - NLA_PUT_U32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq); - NLA_PUT_U32(msg, NL80211_BSS_SEEN_MS_AGO, - jiffies_to_msecs(jiffies - intbss->ts)); + if ((!is_zero_ether_addr(res->bssid) && + nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid)) || + (res->information_elements && res->len_information_elements && + nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS, + res->len_information_elements, + res->information_elements)) || + (res->beacon_ies && res->len_beacon_ies && + res->beacon_ies != res->information_elements && + nla_put(msg, NL80211_BSS_BEACON_IES, + res->len_beacon_ies, res->beacon_ies))) + goto nla_put_failure; + if (res->tsf && + nla_put_u64(msg, NL80211_BSS_TSF, res->tsf)) + goto nla_put_failure; + if (res->beacon_interval && + nla_put_u16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval)) + goto nla_put_failure; + if (nla_put_u16(msg, NL80211_BSS_CAPABILITY, res->capability) || + nla_put_u32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq) || + nla_put_u32(msg, NL80211_BSS_SEEN_MS_AGO, + jiffies_to_msecs(jiffies - intbss->ts))) + goto nla_put_failure; switch (rdev->wiphy.signal_type) { case CFG80211_SIGNAL_TYPE_MBM: - NLA_PUT_U32(msg, NL80211_BSS_SIGNAL_MBM, res->signal); + if (nla_put_u32(msg, NL80211_BSS_SIGNAL_MBM, res->signal)) + goto nla_put_failure; break; case CFG80211_SIGNAL_TYPE_UNSPEC: - NLA_PUT_U8(msg, NL80211_BSS_SIGNAL_UNSPEC, res->signal); + if (nla_put_u8(msg, NL80211_BSS_SIGNAL_UNSPEC, res->signal)) + goto nla_put_failure; break; default: break; @@ -4189,14 +4274,16 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, switch (wdev->iftype) { case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_STATION: - if (intbss == wdev->current_bss) - NLA_PUT_U32(msg, NL80211_BSS_STATUS, - NL80211_BSS_STATUS_ASSOCIATED); + if (intbss == wdev->current_bss && + nla_put_u32(msg, NL80211_BSS_STATUS, + NL80211_BSS_STATUS_ASSOCIATED)) + goto nla_put_failure; break; case NL80211_IFTYPE_ADHOC: - if (intbss == wdev->current_bss) - NLA_PUT_U32(msg, NL80211_BSS_STATUS, - NL80211_BSS_STATUS_IBSS_JOINED); + if (intbss == wdev->current_bss && + nla_put_u32(msg, NL80211_BSS_STATUS, + NL80211_BSS_STATUS_IBSS_JOINED)) + goto nla_put_failure; break; default: break; @@ -4265,34 +4352,43 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 pid, u32 seq, if (!hdr) return -ENOMEM; - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); + if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex)) + goto nla_put_failure; infoattr = nla_nest_start(msg, NL80211_ATTR_SURVEY_INFO); if (!infoattr) goto nla_put_failure; - NLA_PUT_U32(msg, NL80211_SURVEY_INFO_FREQUENCY, - survey->channel->center_freq); - if (survey->filled & SURVEY_INFO_NOISE_DBM) - NLA_PUT_U8(msg, NL80211_SURVEY_INFO_NOISE, - survey->noise); - if (survey->filled & SURVEY_INFO_IN_USE) - NLA_PUT_FLAG(msg, NL80211_SURVEY_INFO_IN_USE); - if (survey->filled & SURVEY_INFO_CHANNEL_TIME) - NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME, - survey->channel_time); - if (survey->filled & SURVEY_INFO_CHANNEL_TIME_BUSY) - NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY, - survey->channel_time_busy); - if (survey->filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY) - NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY, - survey->channel_time_ext_busy); - if (survey->filled & SURVEY_INFO_CHANNEL_TIME_RX) - NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_RX, - survey->channel_time_rx); - if (survey->filled & SURVEY_INFO_CHANNEL_TIME_TX) - NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_TX, - survey->channel_time_tx); + if (nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY, + survey->channel->center_freq)) + goto nla_put_failure; + + if ((survey->filled & SURVEY_INFO_NOISE_DBM) && + nla_put_u8(msg, NL80211_SURVEY_INFO_NOISE, survey->noise)) + goto nla_put_failure; + if ((survey->filled & SURVEY_INFO_IN_USE) && + nla_put_flag(msg, NL80211_SURVEY_INFO_IN_USE)) + goto nla_put_failure; + if ((survey->filled & SURVEY_INFO_CHANNEL_TIME) && + nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME, + survey->channel_time)) + goto nla_put_failure; + if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_BUSY) && + nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY, + survey->channel_time_busy)) + goto nla_put_failure; + if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY) && + nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY, + survey->channel_time_ext_busy)) + goto nla_put_failure; + if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_RX) && + nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_RX, + survey->channel_time_rx)) + goto nla_put_failure; + if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_TX) && + nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_TX, + survey->channel_time_tx)) + goto nla_put_failure; nla_nest_end(msg, infoattr); @@ -4973,7 +5069,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb, NL80211_CMD_TESTMODE); struct nlattr *tmdata; - if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx) < 0) { + if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx)) { genlmsg_cancel(skb, hdr); break; } @@ -5024,7 +5120,8 @@ __cfg80211_testmode_alloc_skb(struct cfg80211_registered_device *rdev, return NULL; } - NLA_PUT_U32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx); + if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx)) + goto nla_put_failure; data = nla_nest_start(skb, NL80211_ATTR_TESTDATA); ((void **)skb->cb)[0] = rdev; @@ -5403,7 +5500,8 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, if (err) goto free_msg; - NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); + if (nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie)) + goto nla_put_failure; genlmsg_end(msg, hdr); @@ -5690,7 +5788,8 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) goto free_msg; if (msg) { - NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); + if (nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie)) + goto nla_put_failure; genlmsg_end(msg, hdr); return genlmsg_reply(msg, info); @@ -5795,7 +5894,8 @@ static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info) else ps_state = NL80211_PS_DISABLED; - NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, ps_state); + if (nla_put_u32(msg, NL80211_ATTR_PS_STATE, ps_state)) + goto nla_put_failure; genlmsg_end(msg, hdr); return genlmsg_reply(msg, info); @@ -5942,20 +6042,21 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) if (!nl_wowlan) goto nla_put_failure; - if (rdev->wowlan->any) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_ANY); - if (rdev->wowlan->disconnect) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT); - if (rdev->wowlan->magic_pkt) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT); - if (rdev->wowlan->gtk_rekey_failure) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE); - if (rdev->wowlan->eap_identity_req) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST); - if (rdev->wowlan->four_way_handshake) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE); - if (rdev->wowlan->rfkill_release) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE); + if ((rdev->wowlan->any && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || + (rdev->wowlan->disconnect && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || + (rdev->wowlan->magic_pkt && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || + (rdev->wowlan->gtk_rekey_failure && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || + (rdev->wowlan->eap_identity_req && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || + (rdev->wowlan->four_way_handshake && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || + (rdev->wowlan->rfkill_release && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) + goto nla_put_failure; if (rdev->wowlan->n_patterns) { struct nlattr *nl_pats, *nl_pat; int i, pat_len; @@ -5970,12 +6071,13 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) if (!nl_pat) goto nla_put_failure; pat_len = rdev->wowlan->patterns[i].pattern_len; - NLA_PUT(msg, NL80211_WOWLAN_PKTPAT_MASK, - DIV_ROUND_UP(pat_len, 8), - rdev->wowlan->patterns[i].mask); - NLA_PUT(msg, NL80211_WOWLAN_PKTPAT_PATTERN, - pat_len, - rdev->wowlan->patterns[i].pattern); + if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK, + DIV_ROUND_UP(pat_len, 8), + rdev->wowlan->patterns[i].mask) || + nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN, + pat_len, + rdev->wowlan->patterns[i].pattern)) + goto nla_put_failure; nla_nest_end(msg, nl_pat); } nla_nest_end(msg, nl_pats); @@ -6000,6 +6102,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) struct cfg80211_wowlan new_triggers = {}; struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan; int err, i; + bool prev_enabled = rdev->wowlan; if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns) return -EOPNOTSUPP; @@ -6132,6 +6235,9 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) rdev->wowlan = NULL; } + if (rdev->ops->set_wakeup && prev_enabled != !!rdev->wowlan) + rdev->ops->set_wakeup(&rdev->wiphy, rdev->wowlan); + return 0; error: for (i = 0; i < new_triggers.n_patterns; i++) @@ -6248,7 +6354,8 @@ static int nl80211_probe_client(struct sk_buff *skb, if (err) goto free_msg; - NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); + if (nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie)) + goto nla_put_failure; genlmsg_end(msg, hdr); @@ -6916,19 +7023,24 @@ static int nl80211_add_scan_req(struct sk_buff *msg, nest = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS); if (!nest) goto nla_put_failure; - for (i = 0; i < req->n_ssids; i++) - NLA_PUT(msg, i, req->ssids[i].ssid_len, req->ssids[i].ssid); + for (i = 0; i < req->n_ssids; i++) { + if (nla_put(msg, i, req->ssids[i].ssid_len, req->ssids[i].ssid)) + goto nla_put_failure; + } nla_nest_end(msg, nest); nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES); if (!nest) goto nla_put_failure; - for (i = 0; i < req->n_channels; i++) - NLA_PUT_U32(msg, i, req->channels[i]->center_freq); + for (i = 0; i < req->n_channels; i++) { + if (nla_put_u32(msg, i, req->channels[i]->center_freq)) + goto nla_put_failure; + } nla_nest_end(msg, nest); - if (req->ie) - NLA_PUT(msg, NL80211_ATTR_IE, req->ie_len, req->ie); + if (req->ie && + nla_put(msg, NL80211_ATTR_IE, req->ie_len, req->ie)) + goto nla_put_failure; return 0; nla_put_failure: @@ -6947,8 +7059,9 @@ static int nl80211_send_scan_msg(struct sk_buff *msg, if (!hdr) return -1; - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) + goto nla_put_failure; /* ignore errors and send incomplete event anyway */ nl80211_add_scan_req(msg, rdev); @@ -6972,8 +7085,9 @@ nl80211_send_sched_scan_msg(struct sk_buff *msg, if (!hdr) return -1; - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) + goto nla_put_failure; return genlmsg_end(msg, hdr); @@ -7096,26 +7210,33 @@ void nl80211_send_reg_change_event(struct regulatory_request *request) } /* Userspace can always count this one always being set */ - NLA_PUT_U8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator); - - if (request->alpha2[0] == '0' && request->alpha2[1] == '0') - NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, - NL80211_REGDOM_TYPE_WORLD); - else if (request->alpha2[0] == '9' && request->alpha2[1] == '9') - NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, - NL80211_REGDOM_TYPE_CUSTOM_WORLD); - else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') || - request->intersect) - NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, - NL80211_REGDOM_TYPE_INTERSECTION); - else { - NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, - NL80211_REGDOM_TYPE_COUNTRY); - NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, request->alpha2); - } - - if (wiphy_idx_valid(request->wiphy_idx)) - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx); + if (nla_put_u8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator)) + goto nla_put_failure; + + if (request->alpha2[0] == '0' && request->alpha2[1] == '0') { + if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE, + NL80211_REGDOM_TYPE_WORLD)) + goto nla_put_failure; + } else if (request->alpha2[0] == '9' && request->alpha2[1] == '9') { + if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE, + NL80211_REGDOM_TYPE_CUSTOM_WORLD)) + goto nla_put_failure; + } else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') || + request->intersect) { + if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE, + NL80211_REGDOM_TYPE_INTERSECTION)) + goto nla_put_failure; + } else { + if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE, + NL80211_REGDOM_TYPE_COUNTRY) || + nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, + request->alpha2)) + goto nla_put_failure; + } + + if (wiphy_idx_valid(request->wiphy_idx) && + nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx)) + goto nla_put_failure; genlmsg_end(msg, hdr); @@ -7149,9 +7270,10 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev, return; } - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); - NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || + nla_put(msg, NL80211_ATTR_FRAME, len, buf)) + goto nla_put_failure; genlmsg_end(msg, hdr); @@ -7229,10 +7351,11 @@ static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, return; } - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); - NLA_PUT_FLAG(msg, NL80211_ATTR_TIMED_OUT); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || + nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) + goto nla_put_failure; genlmsg_end(msg, hdr); @@ -7280,15 +7403,15 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, return; } - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); - if (bssid) - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid); - NLA_PUT_U16(msg, NL80211_ATTR_STATUS_CODE, status); - if (req_ie) - NLA_PUT(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie); - if (resp_ie) - NLA_PUT(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || + (bssid && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid)) || + nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, status) || + (req_ie && + nla_put(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie)) || + (resp_ie && + nla_put(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie))) + goto nla_put_failure; genlmsg_end(msg, hdr); @@ -7320,13 +7443,14 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev, return; } - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid); - if (req_ie) - NLA_PUT(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie); - if (resp_ie) - NLA_PUT(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid) || + (req_ie && + nla_put(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie)) || + (resp_ie && + nla_put(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie))) + goto nla_put_failure; genlmsg_end(msg, hdr); @@ -7357,14 +7481,14 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, return; } - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); - if (from_ap && reason) - NLA_PUT_U16(msg, NL80211_ATTR_REASON_CODE, reason); - if (from_ap) - NLA_PUT_FLAG(msg, NL80211_ATTR_DISCONNECTED_BY_AP); - if (ie) - NLA_PUT(msg, NL80211_ATTR_IE, ie_len, ie); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || + (from_ap && reason && + nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason)) || + (from_ap && + nla_put_flag(msg, NL80211_ATTR_DISCONNECTED_BY_AP)) || + (ie && nla_put(msg, NL80211_ATTR_IE, ie_len, ie))) + goto nla_put_failure; genlmsg_end(msg, hdr); @@ -7395,9 +7519,10 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, return; } - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid)) + goto nla_put_failure; genlmsg_end(msg, hdr); @@ -7428,11 +7553,12 @@ void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, return; } - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, macaddr); - if (ie_len && ie) - NLA_PUT(msg, NL80211_ATTR_IE, ie_len , ie); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, macaddr) || + (ie_len && ie && + nla_put(msg, NL80211_ATTR_IE, ie_len , ie))) + goto nla_put_failure; genlmsg_end(msg, hdr); @@ -7463,15 +7589,14 @@ void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, return; } - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); - if (addr) - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - NLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE, key_type); - if (key_id != -1) - NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_id); - if (tsc) - NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, 6, tsc); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || + (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) || + nla_put_u32(msg, NL80211_ATTR_KEY_TYPE, key_type) || + (key_id != -1 && + nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_id)) || + (tsc && nla_put(msg, NL80211_ATTR_KEY_SEQ, 6, tsc))) + goto nla_put_failure; genlmsg_end(msg, hdr); @@ -7506,7 +7631,8 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy, * Since we are applying the beacon hint to a wiphy we know its * wiphy_idx is valid */ - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy))) + goto nla_put_failure; /* Before */ nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_BEFORE); @@ -7558,14 +7684,16 @@ static void nl80211_send_remain_on_chan_event( return; } - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, channel_type); - NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || + nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) || + nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, channel_type) || + nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie)) + goto nla_put_failure; - if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL) - NLA_PUT_U32(msg, NL80211_ATTR_DURATION, duration); + if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL && + nla_put_u32(msg, NL80211_ATTR_DURATION, duration)) + goto nla_put_failure; genlmsg_end(msg, hdr); @@ -7636,8 +7764,9 @@ void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, return; } - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); + if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr)) + goto nla_put_failure; genlmsg_end(msg, hdr); @@ -7673,9 +7802,10 @@ static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd, return true; } - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) + goto nla_put_failure; err = genlmsg_end(msg, hdr); if (err < 0) { @@ -7724,12 +7854,13 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, return -ENOMEM; } - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); - if (sig_dbm) - NLA_PUT_U32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm); - NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || + nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) || + (sig_dbm && + nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) || + nla_put(msg, NL80211_ATTR_FRAME, len, buf)) + goto nla_put_failure; genlmsg_end(msg, hdr); @@ -7759,12 +7890,12 @@ void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, return; } - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); - NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf); - NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); - if (ack) - NLA_PUT_FLAG(msg, NL80211_ATTR_ACK); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || + nla_put(msg, NL80211_ATTR_FRAME, len, buf) || + nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) || + (ack && nla_put_flag(msg, NL80211_ATTR_ACK))) + goto nla_put_failure; genlmsg_end(msg, hdr); @@ -7796,15 +7927,17 @@ nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, return; } - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) + goto nla_put_failure; pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM); if (!pinfoattr) goto nla_put_failure; - NLA_PUT_U32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, - rssi_event); + if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, + rssi_event)) + goto nla_put_failure; nla_nest_end(msg, pinfoattr); @@ -7837,16 +7970,18 @@ void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev, return; } - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid)) + goto nla_put_failure; rekey_attr = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA); if (!rekey_attr) goto nla_put_failure; - NLA_PUT(msg, NL80211_REKEY_DATA_REPLAY_CTR, - NL80211_REPLAY_CTR_LEN, replay_ctr); + if (nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR, + NL80211_REPLAY_CTR_LEN, replay_ctr)) + goto nla_put_failure; nla_nest_end(msg, rekey_attr); @@ -7879,17 +8014,19 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, return; } - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) + goto nla_put_failure; attr = nla_nest_start(msg, NL80211_ATTR_PMKSA_CANDIDATE); if (!attr) goto nla_put_failure; - NLA_PUT_U32(msg, NL80211_PMKSA_CANDIDATE_INDEX, index); - NLA_PUT(msg, NL80211_PMKSA_CANDIDATE_BSSID, ETH_ALEN, bssid); - if (preauth) - NLA_PUT_FLAG(msg, NL80211_PMKSA_CANDIDATE_PREAUTH); + if (nla_put_u32(msg, NL80211_PMKSA_CANDIDATE_INDEX, index) || + nla_put(msg, NL80211_PMKSA_CANDIDATE_BSSID, ETH_ALEN, bssid) || + (preauth && + nla_put_flag(msg, NL80211_PMKSA_CANDIDATE_PREAUTH))) + goto nla_put_failure; nla_nest_end(msg, attr); @@ -7904,6 +8041,39 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, nlmsg_free(msg); } +void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, + struct net_device *netdev, int freq, + enum nl80211_channel_type type, gfp_t gfp) +{ + struct sk_buff *msg; + void *hdr; + + msg = nlmsg_new(NLMSG_GOODSIZE, gfp); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CH_SWITCH_NOTIFY); + if (!hdr) { + nlmsg_free(msg); + return; + } + + if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || + nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) || + nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, type)) + goto nla_put_failure; + + genlmsg_end(msg, hdr); + + genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, + nl80211_mlme_mcgrp.id, gfp); + return; + + nla_put_failure: + genlmsg_cancel(msg, hdr); + nlmsg_free(msg); +} + void nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *peer, @@ -7923,15 +8093,17 @@ nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, return; } - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, peer); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer)) + goto nla_put_failure; pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM); if (!pinfoattr) goto nla_put_failure; - NLA_PUT_U32(msg, NL80211_ATTR_CQM_PKT_LOSS_EVENT, num_packets); + if (nla_put_u32(msg, NL80211_ATTR_CQM_PKT_LOSS_EVENT, num_packets)) + goto nla_put_failure; nla_nest_end(msg, pinfoattr); @@ -7965,12 +8137,12 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr, return; } - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); - if (acked) - NLA_PUT_FLAG(msg, NL80211_ATTR_ACK); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || + nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) || + (acked && nla_put_flag(msg, NL80211_ATTR_ACK))) + goto nla_put_failure; err = genlmsg_end(msg, hdr); if (err < 0) { @@ -8010,12 +8182,13 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy, return; } - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - if (freq) - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); - if (sig_dbm) - NLA_PUT_U32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm); - NLA_PUT(msg, NL80211_ATTR_FRAME, len, frame); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + (freq && + nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) || + (sig_dbm && + nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) || + nla_put(msg, NL80211_ATTR_FRAME, len, frame)) + goto nla_put_failure; genlmsg_end(msg, hdr); diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 4ffe50d..01a1122 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -118,6 +118,10 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, struct net_device *netdev, int index, const u8 *bssid, bool preauth, gfp_t gfp); +void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, + struct net_device *dev, int freq, + enum nl80211_channel_type type, gfp_t gfp); + bool nl80211_unexpected_frame(struct net_device *dev, const u8 *addr, gfp_t gfp); bool nl80211_unexpected_4addr_frame(struct net_device *dev, diff --git a/net/wireless/reg.c b/net/wireless/reg.c index e9a0ac8..15f3474 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -388,7 +388,15 @@ static void reg_regdb_query(const char *alpha2) schedule_work(®_regdb_work); } + +/* Feel free to add any other sanity checks here */ +static void reg_regdb_size_check(void) +{ + /* We should ideally BUILD_BUG_ON() but then random builds would fail */ + WARN_ONCE(!reg_regdb_size, "db.txt is empty, you should update it..."); +} #else +static inline void reg_regdb_size_check(void) {} static inline void reg_regdb_query(const char *alpha2) {} #endif /* CONFIG_CFG80211_INTERNAL_REGDB */ @@ -2322,6 +2330,8 @@ int __init regulatory_init(void) spin_lock_init(®_requests_lock); spin_lock_init(®_pending_beacons_lock); + reg_regdb_size_check(); + cfg80211_regdomain = cfg80211_world_regdom; user_alpha2[0] = '9'; diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 70faadf..fdbcfe6 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -378,7 +378,7 @@ static int cmp_bss_core(struct cfg80211_bss *a, b->len_information_elements); } - return memcmp(a->bssid, b->bssid, ETH_ALEN); + return compare_ether_addr(a->bssid, b->bssid); } static int cmp_bss(struct cfg80211_bss *a, diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index af648e0..b0eb7aa 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c @@ -256,7 +256,7 @@ static const struct iw_ioctl_description standard_ioctl[] = { .max_tokens = sizeof(struct iw_pmksa), }, }; -static const unsigned standard_ioctl_num = ARRAY_SIZE(standard_ioctl); +static const unsigned int standard_ioctl_num = ARRAY_SIZE(standard_ioctl); /* * Meta-data about all the additional standard Wireless Extension events @@ -306,7 +306,7 @@ static const struct iw_ioctl_description standard_event[] = { .max_tokens = sizeof(struct iw_pmkid_cand), }, }; -static const unsigned standard_event_num = ARRAY_SIZE(standard_event); +static const unsigned int standard_event_num = ARRAY_SIZE(standard_event); /* Size (in bytes) of various events */ static const int event_type_size[] = { @@ -402,7 +402,8 @@ static struct nlmsghdr *rtnetlink_ifinfo_prep(struct net_device *dev, r->ifi_flags = dev_get_flags(dev); r->ifi_change = 0; /* Wireless changes don't affect those flags */ - NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); + if (nla_put_string(skb, IFLA_IFNAME, dev->name)) + goto nla_put_failure; return nlh; nla_put_failure: @@ -428,7 +429,7 @@ void wireless_send_event(struct net_device * dev, int hdr_len; /* Size of the event header */ int wrqu_off = 0; /* Offset in wrqu */ /* Don't "optimise" the following variable, it will crash */ - unsigned cmd_index; /* *MUST* be unsigned */ + unsigned int cmd_index; /* *MUST* be unsigned */ struct sk_buff *skb; struct nlmsghdr *nlh; struct nlattr *nla; diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index 36384a1..66c63873 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c @@ -231,7 +231,7 @@ int x25_create_facilities(unsigned char *buffer, } if (dte_facs->calling_len && (facil_mask & X25_MASK_CALLING_AE)) { - unsigned bytecount = (dte_facs->calling_len + 1) >> 1; + unsigned int bytecount = (dte_facs->calling_len + 1) >> 1; *p++ = X25_FAC_CALLING_AE; *p++ = 1 + bytecount; *p++ = dte_facs->calling_len; @@ -240,7 +240,7 @@ int x25_create_facilities(unsigned char *buffer, } if (dte_facs->called_len && (facil_mask & X25_MASK_CALLED_AE)) { - unsigned bytecount = (dte_facs->called_len % 2) ? + unsigned int bytecount = (dte_facs->called_len % 2) ? dte_facs->called_len / 2 + 1 : dte_facs->called_len / 2; *p++ = X25_FAC_CALLED_AE; diff --git a/net/xfrm/xfrm_hash.h b/net/xfrm/xfrm_hash.h index 7199d78..716502a 100644 --- a/net/xfrm/xfrm_hash.h +++ b/net/xfrm/xfrm_hash.h @@ -45,10 +45,10 @@ static inline unsigned int __xfrm_dst_hash(const xfrm_address_t *daddr, return (h ^ (h >> 16)) & hmask; } -static inline unsigned __xfrm_src_hash(const xfrm_address_t *daddr, - const xfrm_address_t *saddr, - unsigned short family, - unsigned int hmask) +static inline unsigned int __xfrm_src_hash(const xfrm_address_t *daddr, + const xfrm_address_t *saddr, + unsigned short family, + unsigned int hmask) { unsigned int h = family; switch (family) { diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 7128dde..44293b3 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -756,40 +756,50 @@ static int copy_to_user_state_extra(struct xfrm_state *x, { copy_to_user_state(x, p); - if (x->coaddr) - NLA_PUT(skb, XFRMA_COADDR, sizeof(*x->coaddr), x->coaddr); + if (x->coaddr && + nla_put(skb, XFRMA_COADDR, sizeof(*x->coaddr), x->coaddr)) + goto nla_put_failure; - if (x->lastused) - NLA_PUT_U64(skb, XFRMA_LASTUSED, x->lastused); + if (x->lastused && + nla_put_u64(skb, XFRMA_LASTUSED, x->lastused)) + goto nla_put_failure; - if (x->aead) - NLA_PUT(skb, XFRMA_ALG_AEAD, aead_len(x->aead), x->aead); - if (x->aalg) { - if (copy_to_user_auth(x->aalg, skb)) - goto nla_put_failure; + if (x->aead && + nla_put(skb, XFRMA_ALG_AEAD, aead_len(x->aead), x->aead)) + goto nla_put_failure; - NLA_PUT(skb, XFRMA_ALG_AUTH_TRUNC, - xfrm_alg_auth_len(x->aalg), x->aalg); - } - if (x->ealg) - NLA_PUT(skb, XFRMA_ALG_CRYPT, xfrm_alg_len(x->ealg), x->ealg); - if (x->calg) - NLA_PUT(skb, XFRMA_ALG_COMP, sizeof(*(x->calg)), x->calg); + if (x->aalg && + (copy_to_user_auth(x->aalg, skb) || + nla_put(skb, XFRMA_ALG_AUTH_TRUNC, + xfrm_alg_auth_len(x->aalg), x->aalg))) + goto nla_put_failure; - if (x->encap) - NLA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap); + if (x->ealg && + nla_put(skb, XFRMA_ALG_CRYPT, xfrm_alg_len(x->ealg), x->ealg)) + goto nla_put_failure; - if (x->tfcpad) - NLA_PUT_U32(skb, XFRMA_TFCPAD, x->tfcpad); + if (x->calg && + nla_put(skb, XFRMA_ALG_COMP, sizeof(*(x->calg)), x->calg)) + goto nla_put_failure; + + if (x->encap && + nla_put(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap)) + goto nla_put_failure; + + if (x->tfcpad && + nla_put_u32(skb, XFRMA_TFCPAD, x->tfcpad)) + goto nla_put_failure; if (xfrm_mark_put(skb, &x->mark)) goto nla_put_failure; - if (x->replay_esn) - NLA_PUT(skb, XFRMA_REPLAY_ESN_VAL, - xfrm_replay_state_esn_len(x->replay_esn), x->replay_esn); + if (x->replay_esn && + nla_put(skb, XFRMA_REPLAY_ESN_VAL, + xfrm_replay_state_esn_len(x->replay_esn), + x->replay_esn)) + goto nla_put_failure; - if (x->security && copy_sec_ctx(x->security, skb) < 0) + if (x->security && copy_sec_ctx(x->security, skb)) goto nla_put_failure; return 0; @@ -912,8 +922,9 @@ static int build_spdinfo(struct sk_buff *skb, struct net *net, sph.spdhcnt = si.spdhcnt; sph.spdhmcnt = si.spdhmcnt; - NLA_PUT(skb, XFRMA_SPD_INFO, sizeof(spc), &spc); - NLA_PUT(skb, XFRMA_SPD_HINFO, sizeof(sph), &sph); + if (nla_put(skb, XFRMA_SPD_INFO, sizeof(spc), &spc) || + nla_put(skb, XFRMA_SPD_HINFO, sizeof(sph), &sph)) + goto nla_put_failure; return nlmsg_end(skb, nlh); @@ -967,8 +978,9 @@ static int build_sadinfo(struct sk_buff *skb, struct net *net, sh.sadhmcnt = si.sadhmcnt; sh.sadhcnt = si.sadhcnt; - NLA_PUT_U32(skb, XFRMA_SAD_CNT, si.sadcnt); - NLA_PUT(skb, XFRMA_SAD_HINFO, sizeof(sh), &sh); + if (nla_put_u32(skb, XFRMA_SAD_CNT, si.sadcnt) || + nla_put(skb, XFRMA_SAD_HINFO, sizeof(sh), &sh)) + goto nla_put_failure; return nlmsg_end(skb, nlh); @@ -1690,21 +1702,27 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, const struct id->reqid = x->props.reqid; id->flags = c->data.aevent; - if (x->replay_esn) - NLA_PUT(skb, XFRMA_REPLAY_ESN_VAL, - xfrm_replay_state_esn_len(x->replay_esn), - x->replay_esn); - else - NLA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay); - - NLA_PUT(skb, XFRMA_LTIME_VAL, sizeof(x->curlft), &x->curlft); + if (x->replay_esn) { + if (nla_put(skb, XFRMA_REPLAY_ESN_VAL, + xfrm_replay_state_esn_len(x->replay_esn), + x->replay_esn)) + goto nla_put_failure; + } else { + if (nla_put(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), + &x->replay)) + goto nla_put_failure; + } + if (nla_put(skb, XFRMA_LTIME_VAL, sizeof(x->curlft), &x->curlft)) + goto nla_put_failure; - if (id->flags & XFRM_AE_RTHR) - NLA_PUT_U32(skb, XFRMA_REPLAY_THRESH, x->replay_maxdiff); + if ((id->flags & XFRM_AE_RTHR) && + nla_put_u32(skb, XFRMA_REPLAY_THRESH, x->replay_maxdiff)) + goto nla_put_failure; - if (id->flags & XFRM_AE_ETHR) - NLA_PUT_U32(skb, XFRMA_ETIMER_THRESH, - x->replay_maxage * 10 / HZ); + if ((id->flags & XFRM_AE_ETHR) && + nla_put_u32(skb, XFRMA_ETIMER_THRESH, + x->replay_maxage * 10 / HZ)) + goto nla_put_failure; if (xfrm_mark_put(skb, &x->mark)) goto nla_put_failure; @@ -2835,8 +2853,9 @@ static int build_report(struct sk_buff *skb, u8 proto, ur->proto = proto; memcpy(&ur->sel, sel, sizeof(ur->sel)); - if (addr) - NLA_PUT(skb, XFRMA_COADDR, sizeof(*addr), addr); + if (addr && + nla_put(skb, XFRMA_COADDR, sizeof(*addr), addr)) + goto nla_put_failure; return nlmsg_end(skb, nlh); |