--- zzzz-none-000/linux-4.1.52/net/phonet/socket.c 2018-05-28 02:26:45.000000000 +0000 +++ bcm63-7530ax-731/linux-4.1.52/net/phonet/socket.c 2022-03-02 11:37:14.000000000 +0000 @@ -70,6 +70,90 @@ return pnsocks.hlist + (obj & PN_HASHMASK); } +#ifdef CONFIG_BCM_KF_PHONET +/* + * Find address based on socket address, match only certain fields. + * Also grab sock if it was found. Remember to sock_put it later. + */ +struct sock *pn_find_sock_by_sa_and_skb(struct net *net, + const struct sockaddr_pn *spn, + struct sk_buff *skb) +{ + struct sock *sknode; + struct sock *rval = NULL; + u16 obj = pn_sockaddr_get_object(spn); + u8 res = spn->spn_resource; + struct hlist_head *hlist = pnsocks.hlist; + unsigned h; + u8 type; + u8 subtype; + + rcu_read_lock(); + + for (h = 0; h < PN_HASHSIZE; h++) { + sk_for_each_rcu(sknode, hlist) { + struct pn_sock *pn = pn_sk(sknode); + BUG_ON(!pn->sobject); /* unbound socket */ + if (!net_eq(sock_net(sknode), net)) + continue; + + if ((PN_PREFIX == pn->resource) && (PN_PREFIX == res)) { + + if (skb_shinfo(skb)->nr_frags) { + struct page *msg_page; + u8 *msg; + skb_frag_t *msg_frag = + &skb_shinfo(skb)->frags[0]; + + msg_page = skb_frag_page(msg_frag); + msg = page_address(msg_page); + + type = msg[msg_frag->page_offset + 2]; + subtype = + msg[msg_frag->page_offset + 3]; + + } else { + type = *(skb->data + 2); + subtype = *(skb->data + 3); + } + + if (type != pn->resource_type) + continue; + + if (subtype != pn->resource_subtype) + continue; + } + + /* If port is zero, look up by resource */ + if (pn_port(obj)) { + /* Look up socket by port */ + if (pn_port(pn->sobject) != pn_port(obj)) + continue; + } else { + + /* If port is zero, look up by resource */ + if (pn->resource != res) + continue; + } + + if (pn_addr(pn->sobject) && + pn_addr(pn->sobject) != pn_addr(obj)) + continue; + + rval = sknode; + sock_hold(sknode); + goto out; + } + hlist++; + } + +out: + rcu_read_unlock(); + + return rval; +} +#endif + /* * Find address based on socket address, match only certain fields. * Also grab sock if it was found. Remember to sock_put it later. @@ -369,6 +453,27 @@ struct sock *sk = sock->sk; struct pn_sock *pn = pn_sk(sk); +#ifdef CONFIG_BCM_KF_PHONET + if (cmd == SIOCCONFIGTYPE) { + u16 type; + if (get_user(type, (__u16 __user *) arg)) + return -EFAULT; + + pn->resource_type = type; + return 0; + } + + if (cmd == SIOCCONFIGSUBTYPE) { + u16 subtype; + + if (get_user(subtype, (__u16 __user *) arg)) + return -EFAULT; + + pn->resource_subtype = subtype; + return 0; + } +#endif + if (cmd == SIOCPNGETOBJECT) { struct net_device *dev; u16 handle; @@ -669,8 +774,10 @@ if (!net_eq(sock_net(sk), &init_net)) return -ENOIOCTLCMD; +#ifndef CONFIG_BCM_KF_PHONET if (!capable(CAP_SYS_ADMIN)) return -EPERM; +#endif if (pn_socket_autobind(sk->sk_socket)) return -EAGAIN; @@ -688,8 +795,10 @@ { int ret = -ENOENT; +#ifndef CONFIG_BCM_KF_PHONET if (!capable(CAP_SYS_ADMIN)) return -EPERM; +#endif mutex_lock(&resource_mutex); if (pnres.sk[res] == sk) {