int tlen = dev->needed_tailroom;
struct sock *sk = dev_net(dev)->ipv6.ndisc_sk;
struct sk_buff *skb;
- int err;
- skb = sock_alloc_send_skb(sk,
- hlen + sizeof(struct ipv6hdr) + len + tlen,
- 1, &err);
+ skb = alloc_skb(hlen + sizeof(struct ipv6hdr) + len + tlen, GFP_ATOMIC);
if (!skb) {
- ND_PRINTK(0, err, "ndisc: %s failed to allocate an skb, err=%d\n",
- __func__, err);
+ ND_PRINTK(0, err, "ndisc: %s failed to allocate an skb\n",
+ __func__);
return NULL;
}
skb_reserve(skb, hlen + sizeof(struct ipv6hdr));
skb_reset_transport_header(skb);
+ /* Manually assign socket ownership as we avoid calling
+ * sock_alloc_send_pskb() to bypass wmem buffer limits
+ */
+ skb_set_owner_w(skb, sk);
+
return skb;
}
if (rt)
rt6_set_expires(rt, jiffies + (HZ * lifetime));
if (ra_msg->icmph.icmp6_hop_limit) {
- in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
+ /* Only set hop_limit on the interface if it is higher than
+ * the current hop_limit.
+ */
+ if (in6_dev->cnf.hop_limit < ra_msg->icmph.icmp6_hop_limit) {
+ in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
+ } else {
+ ND_PRINTK(2, warn, "RA: Got route advertisement with lower hop_limit than current\n");
+ }
if (rt)
dst_metric_set(&rt->dst, RTAX_HOPLIMIT,
ra_msg->icmph.icmp6_hop_limit);
}
}
+#ifdef CONFIG_MTK_DHCPV6C_WIFI
+ if (in6_dev->if_flags & IF_RA_OTHERCONF){
+ printk(KERN_INFO "[mtk_net][ipv6]receive RA with o bit!\n");
+ in6_dev->cnf.ra_info_flag = 1;
+ }
+ if(in6_dev->if_flags & IF_RA_MANAGED){
+ printk(KERN_INFO "[mtk_net][ipv6]receive RA with m bit!\n");
+ in6_dev->cnf.ra_info_flag = 2;
+ }
+ if(in6_dev->cnf.ra_info_flag == 0){
+ printk(KERN_INFO "[mtk_net][ipv6]receive RA neither O nor M bit is set!\n");
+ in6_dev->cnf.ra_info_flag = 4;
+ }
+#endif
+
if (ndopts.nd_useropts) {
struct nd_opt_hdr *p;
for (p = ndopts.nd_useropts;
p;
p = ndisc_next_useropt(p, ndopts.nd_useropts_end)) {
ndisc_ra_useropt(skb, p);
+#ifdef CONFIG_MTK_DHCPV6C_WIFI
+ /* only clear ra_info_flag when O bit is set */
+ if (p->nd_opt_type == ND_OPT_RDNSS &&
+ in6_dev->if_flags & IF_RA_OTHERCONF) {
+ printk(KERN_INFO "[mtk_net][ipv6]RDNSS, ignore RA with o bit!\n");
+ in6_dev->cnf.ra_info_flag = 0;
+ }
+#endif
}
}
*/
if (ha)
- ndisc_fill_addr_option(skb, ND_OPT_TARGET_LL_ADDR, ha);
+ ndisc_fill_addr_option(buff, ND_OPT_TARGET_LL_ADDR, ha);
/*
* build redirect option and copy skb over to the new packet.
}
memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));
-
+
switch (msg->icmph.icmp6_type) {
case NDISC_NEIGHBOUR_SOLICITATION:
ndisc_recv_ns(skb);