Loading net/batman-adv/bat_sysfs.c +2 −2 Original line number Diff line number Diff line Loading @@ -174,7 +174,7 @@ static int store_uint_attr(const char *buff, size_t count, unsigned long uint_val; int ret; ret = strict_strtoul(buff, 10, &uint_val); ret = kstrtoul(buff, 10, &uint_val); if (ret) { bat_info(net_dev, "%s: Invalid parameter received: %s\n", Loading Loading @@ -239,7 +239,7 @@ static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr, unsigned long val; int ret, vis_mode_tmp = -1; ret = strict_strtoul(buff, 10, &val); ret = kstrtoul(buff, 10, &val); if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) || (strncmp(buff, "client", 6) == 0) || Loading net/batman-adv/bitarray.c +1 −1 Original line number Diff line number Diff line Loading @@ -155,7 +155,7 @@ int bit_get_packet(void *priv, unsigned long *seq_bits, /* sequence number is much newer, probably missed a lot of packets */ if ((seq_num_diff >= TQ_LOCAL_WINDOW_SIZE) || (seq_num_diff < EXPECTED_SEQNO_RANGE)) { && (seq_num_diff < EXPECTED_SEQNO_RANGE)) { bat_dbg(DBG_BATMAN, bat_priv, "We missed a lot of packets (%i) !\n", seq_num_diff - 1); Loading net/batman-adv/gateway_client.c +94 −59 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include "gateway_common.h" #include "hard-interface.h" #include "originator.h" #include "translation-table.h" #include "routing.h" #include <linux/ip.h> #include <linux/ipv6.h> Loading Loading @@ -572,108 +573,142 @@ static bool is_type_dhcprequest(struct sk_buff *skb, int header_len) return ret; } int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb, struct orig_node *old_gw) bool gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len) { struct ethhdr *ethhdr; struct iphdr *iphdr; struct ipv6hdr *ipv6hdr; struct udphdr *udphdr; struct gw_node *curr_gw; struct neigh_node *neigh_curr = NULL, *neigh_old = NULL; unsigned int header_len = 0; int ret = 1; if (atomic_read(&bat_priv->gw_mode) == GW_MODE_OFF) return 0; /* check for ethernet header */ if (!pskb_may_pull(skb, header_len + ETH_HLEN)) return 0; if (!pskb_may_pull(skb, *header_len + ETH_HLEN)) return false; ethhdr = (struct ethhdr *)skb->data; header_len += ETH_HLEN; *header_len += ETH_HLEN; /* check for initial vlan header */ if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) { if (!pskb_may_pull(skb, header_len + VLAN_HLEN)) return 0; if (!pskb_may_pull(skb, *header_len + VLAN_HLEN)) return false; ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN); header_len += VLAN_HLEN; *header_len += VLAN_HLEN; } /* check for ip header */ switch (ntohs(ethhdr->h_proto)) { case ETH_P_IP: if (!pskb_may_pull(skb, header_len + sizeof(*iphdr))) return 0; iphdr = (struct iphdr *)(skb->data + header_len); header_len += iphdr->ihl * 4; if (!pskb_may_pull(skb, *header_len + sizeof(*iphdr))) return false; iphdr = (struct iphdr *)(skb->data + *header_len); *header_len += iphdr->ihl * 4; /* check for udp header */ if (iphdr->protocol != IPPROTO_UDP) return 0; return false; break; case ETH_P_IPV6: if (!pskb_may_pull(skb, header_len + sizeof(*ipv6hdr))) return 0; ipv6hdr = (struct ipv6hdr *)(skb->data + header_len); header_len += sizeof(*ipv6hdr); if (!pskb_may_pull(skb, *header_len + sizeof(*ipv6hdr))) return false; ipv6hdr = (struct ipv6hdr *)(skb->data + *header_len); *header_len += sizeof(*ipv6hdr); /* check for udp header */ if (ipv6hdr->nexthdr != IPPROTO_UDP) return 0; return false; break; default: return 0; return false; } if (!pskb_may_pull(skb, header_len + sizeof(*udphdr))) return 0; udphdr = (struct udphdr *)(skb->data + header_len); header_len += sizeof(*udphdr); if (!pskb_may_pull(skb, *header_len + sizeof(*udphdr))) return false; udphdr = (struct udphdr *)(skb->data + *header_len); *header_len += sizeof(*udphdr); /* check for bootp port */ if ((ntohs(ethhdr->h_proto) == ETH_P_IP) && (ntohs(udphdr->dest) != 67)) return 0; return false; if ((ntohs(ethhdr->h_proto) == ETH_P_IPV6) && (ntohs(udphdr->dest) != 547)) return 0; return false; return true; } if (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER) return -1; bool gw_out_of_range(struct bat_priv *bat_priv, struct sk_buff *skb, struct ethhdr *ethhdr) { struct neigh_node *neigh_curr = NULL, *neigh_old = NULL; struct orig_node *orig_dst_node = NULL; struct gw_node *curr_gw = NULL; bool ret, out_of_range = false; unsigned int header_len = 0; uint8_t curr_tq_avg; ret = gw_is_dhcp_target(skb, &header_len); if (!ret) goto out; orig_dst_node = transtable_search(bat_priv, ethhdr->h_source, ethhdr->h_dest); if (!orig_dst_node) goto out; if (!orig_dst_node->gw_flags) goto out; ret = is_type_dhcprequest(skb, header_len); if (!ret) goto out; switch (atomic_read(&bat_priv->gw_mode)) { case GW_MODE_SERVER: /* If we are a GW then we are our best GW. We can artificially * set the tq towards ourself as the maximum value */ curr_tq_avg = TQ_MAX_VALUE; break; case GW_MODE_CLIENT: curr_gw = gw_get_selected_gw_node(bat_priv); if (!curr_gw) return 0; goto out; /* packet is going to our gateway */ if (curr_gw->orig_node == orig_dst_node) goto out; /* If old_gw != NULL then this packet is unicast. * So, at this point we have to check the message type: if it is a * DHCPREQUEST we have to decide whether to drop it or not */ if (old_gw && curr_gw->orig_node != old_gw) { if (is_type_dhcprequest(skb, header_len)) { /* If the dhcp packet has been sent to a different gw, * we have to evaluate whether the old gw is still * reliable enough */ neigh_curr = find_router(bat_priv, curr_gw->orig_node, NULL); neigh_old = find_router(bat_priv, old_gw, NULL); if (!neigh_curr || !neigh_old) goto free_neigh; if (neigh_curr->tq_avg - neigh_old->tq_avg < GW_THRESHOLD) ret = -1; } neigh_curr = find_router(bat_priv, curr_gw->orig_node, NULL); if (!neigh_curr) goto out; curr_tq_avg = neigh_curr->tq_avg; break; case GW_MODE_OFF: default: goto out; } free_neigh: neigh_old = find_router(bat_priv, orig_dst_node, NULL); if (!!neigh_old) goto out; if (curr_tq_avg - neigh_old->tq_avg > GW_THRESHOLD) out_of_range = true; out: if (orig_dst_node) orig_node_free_ref(orig_dst_node); if (curr_gw) gw_node_free_ref(curr_gw); if (neigh_old) neigh_node_free_ref(neigh_old); if (neigh_curr) neigh_node_free_ref(neigh_curr); if (curr_gw) gw_node_free_ref(curr_gw); return ret; return out_of_range; } net/batman-adv/gateway_client.h +3 −2 Original line number Diff line number Diff line Loading @@ -31,7 +31,8 @@ void gw_node_update(struct bat_priv *bat_priv, void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node); void gw_node_purge(struct bat_priv *bat_priv); int gw_client_seq_print_text(struct seq_file *seq, void *offset); int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb, struct orig_node *old_gw); bool gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len); bool gw_out_of_range(struct bat_priv *bat_priv, struct sk_buff *skb, struct ethhdr *ethhdr); #endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */ net/batman-adv/gateway_common.c +2 −2 Original line number Diff line number Diff line Loading @@ -97,7 +97,7 @@ static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff, *tmp_ptr = '\0'; } ret = strict_strtol(buff, 10, &ldown); ret = kstrtol(buff, 10, &ldown); if (ret) { bat_err(net_dev, "Download speed of gateway mode invalid: %s\n", Loading @@ -122,7 +122,7 @@ static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff, *tmp_ptr = '\0'; } ret = strict_strtol(slash_ptr + 1, 10, &lup); ret = kstrtol(slash_ptr + 1, 10, &lup); if (ret) { bat_err(net_dev, "Upload speed of gateway mode invalid: " Loading Loading
net/batman-adv/bat_sysfs.c +2 −2 Original line number Diff line number Diff line Loading @@ -174,7 +174,7 @@ static int store_uint_attr(const char *buff, size_t count, unsigned long uint_val; int ret; ret = strict_strtoul(buff, 10, &uint_val); ret = kstrtoul(buff, 10, &uint_val); if (ret) { bat_info(net_dev, "%s: Invalid parameter received: %s\n", Loading Loading @@ -239,7 +239,7 @@ static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr, unsigned long val; int ret, vis_mode_tmp = -1; ret = strict_strtoul(buff, 10, &val); ret = kstrtoul(buff, 10, &val); if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) || (strncmp(buff, "client", 6) == 0) || Loading
net/batman-adv/bitarray.c +1 −1 Original line number Diff line number Diff line Loading @@ -155,7 +155,7 @@ int bit_get_packet(void *priv, unsigned long *seq_bits, /* sequence number is much newer, probably missed a lot of packets */ if ((seq_num_diff >= TQ_LOCAL_WINDOW_SIZE) || (seq_num_diff < EXPECTED_SEQNO_RANGE)) { && (seq_num_diff < EXPECTED_SEQNO_RANGE)) { bat_dbg(DBG_BATMAN, bat_priv, "We missed a lot of packets (%i) !\n", seq_num_diff - 1); Loading
net/batman-adv/gateway_client.c +94 −59 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include "gateway_common.h" #include "hard-interface.h" #include "originator.h" #include "translation-table.h" #include "routing.h" #include <linux/ip.h> #include <linux/ipv6.h> Loading Loading @@ -572,108 +573,142 @@ static bool is_type_dhcprequest(struct sk_buff *skb, int header_len) return ret; } int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb, struct orig_node *old_gw) bool gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len) { struct ethhdr *ethhdr; struct iphdr *iphdr; struct ipv6hdr *ipv6hdr; struct udphdr *udphdr; struct gw_node *curr_gw; struct neigh_node *neigh_curr = NULL, *neigh_old = NULL; unsigned int header_len = 0; int ret = 1; if (atomic_read(&bat_priv->gw_mode) == GW_MODE_OFF) return 0; /* check for ethernet header */ if (!pskb_may_pull(skb, header_len + ETH_HLEN)) return 0; if (!pskb_may_pull(skb, *header_len + ETH_HLEN)) return false; ethhdr = (struct ethhdr *)skb->data; header_len += ETH_HLEN; *header_len += ETH_HLEN; /* check for initial vlan header */ if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) { if (!pskb_may_pull(skb, header_len + VLAN_HLEN)) return 0; if (!pskb_may_pull(skb, *header_len + VLAN_HLEN)) return false; ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN); header_len += VLAN_HLEN; *header_len += VLAN_HLEN; } /* check for ip header */ switch (ntohs(ethhdr->h_proto)) { case ETH_P_IP: if (!pskb_may_pull(skb, header_len + sizeof(*iphdr))) return 0; iphdr = (struct iphdr *)(skb->data + header_len); header_len += iphdr->ihl * 4; if (!pskb_may_pull(skb, *header_len + sizeof(*iphdr))) return false; iphdr = (struct iphdr *)(skb->data + *header_len); *header_len += iphdr->ihl * 4; /* check for udp header */ if (iphdr->protocol != IPPROTO_UDP) return 0; return false; break; case ETH_P_IPV6: if (!pskb_may_pull(skb, header_len + sizeof(*ipv6hdr))) return 0; ipv6hdr = (struct ipv6hdr *)(skb->data + header_len); header_len += sizeof(*ipv6hdr); if (!pskb_may_pull(skb, *header_len + sizeof(*ipv6hdr))) return false; ipv6hdr = (struct ipv6hdr *)(skb->data + *header_len); *header_len += sizeof(*ipv6hdr); /* check for udp header */ if (ipv6hdr->nexthdr != IPPROTO_UDP) return 0; return false; break; default: return 0; return false; } if (!pskb_may_pull(skb, header_len + sizeof(*udphdr))) return 0; udphdr = (struct udphdr *)(skb->data + header_len); header_len += sizeof(*udphdr); if (!pskb_may_pull(skb, *header_len + sizeof(*udphdr))) return false; udphdr = (struct udphdr *)(skb->data + *header_len); *header_len += sizeof(*udphdr); /* check for bootp port */ if ((ntohs(ethhdr->h_proto) == ETH_P_IP) && (ntohs(udphdr->dest) != 67)) return 0; return false; if ((ntohs(ethhdr->h_proto) == ETH_P_IPV6) && (ntohs(udphdr->dest) != 547)) return 0; return false; return true; } if (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER) return -1; bool gw_out_of_range(struct bat_priv *bat_priv, struct sk_buff *skb, struct ethhdr *ethhdr) { struct neigh_node *neigh_curr = NULL, *neigh_old = NULL; struct orig_node *orig_dst_node = NULL; struct gw_node *curr_gw = NULL; bool ret, out_of_range = false; unsigned int header_len = 0; uint8_t curr_tq_avg; ret = gw_is_dhcp_target(skb, &header_len); if (!ret) goto out; orig_dst_node = transtable_search(bat_priv, ethhdr->h_source, ethhdr->h_dest); if (!orig_dst_node) goto out; if (!orig_dst_node->gw_flags) goto out; ret = is_type_dhcprequest(skb, header_len); if (!ret) goto out; switch (atomic_read(&bat_priv->gw_mode)) { case GW_MODE_SERVER: /* If we are a GW then we are our best GW. We can artificially * set the tq towards ourself as the maximum value */ curr_tq_avg = TQ_MAX_VALUE; break; case GW_MODE_CLIENT: curr_gw = gw_get_selected_gw_node(bat_priv); if (!curr_gw) return 0; goto out; /* packet is going to our gateway */ if (curr_gw->orig_node == orig_dst_node) goto out; /* If old_gw != NULL then this packet is unicast. * So, at this point we have to check the message type: if it is a * DHCPREQUEST we have to decide whether to drop it or not */ if (old_gw && curr_gw->orig_node != old_gw) { if (is_type_dhcprequest(skb, header_len)) { /* If the dhcp packet has been sent to a different gw, * we have to evaluate whether the old gw is still * reliable enough */ neigh_curr = find_router(bat_priv, curr_gw->orig_node, NULL); neigh_old = find_router(bat_priv, old_gw, NULL); if (!neigh_curr || !neigh_old) goto free_neigh; if (neigh_curr->tq_avg - neigh_old->tq_avg < GW_THRESHOLD) ret = -1; } neigh_curr = find_router(bat_priv, curr_gw->orig_node, NULL); if (!neigh_curr) goto out; curr_tq_avg = neigh_curr->tq_avg; break; case GW_MODE_OFF: default: goto out; } free_neigh: neigh_old = find_router(bat_priv, orig_dst_node, NULL); if (!!neigh_old) goto out; if (curr_tq_avg - neigh_old->tq_avg > GW_THRESHOLD) out_of_range = true; out: if (orig_dst_node) orig_node_free_ref(orig_dst_node); if (curr_gw) gw_node_free_ref(curr_gw); if (neigh_old) neigh_node_free_ref(neigh_old); if (neigh_curr) neigh_node_free_ref(neigh_curr); if (curr_gw) gw_node_free_ref(curr_gw); return ret; return out_of_range; }
net/batman-adv/gateway_client.h +3 −2 Original line number Diff line number Diff line Loading @@ -31,7 +31,8 @@ void gw_node_update(struct bat_priv *bat_priv, void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node); void gw_node_purge(struct bat_priv *bat_priv); int gw_client_seq_print_text(struct seq_file *seq, void *offset); int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb, struct orig_node *old_gw); bool gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len); bool gw_out_of_range(struct bat_priv *bat_priv, struct sk_buff *skb, struct ethhdr *ethhdr); #endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */
net/batman-adv/gateway_common.c +2 −2 Original line number Diff line number Diff line Loading @@ -97,7 +97,7 @@ static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff, *tmp_ptr = '\0'; } ret = strict_strtol(buff, 10, &ldown); ret = kstrtol(buff, 10, &ldown); if (ret) { bat_err(net_dev, "Download speed of gateway mode invalid: %s\n", Loading @@ -122,7 +122,7 @@ static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff, *tmp_ptr = '\0'; } ret = strict_strtol(slash_ptr + 1, 10, &lup); ret = kstrtol(slash_ptr + 1, 10, &lup); if (ret) { bat_err(net_dev, "Upload speed of gateway mode invalid: " Loading