^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * DECnet An implementation of the DECnet protocol suite for the LINUX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * operating system. DECnet is implemented using the BSD Socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * interface as the means of communication with the user level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * DECnet Neighbour Functions (Adjacency Database and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * On-Ethernet Cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Author: Steve Whitehouse <SteveW@ACM.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Changes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Steve Whitehouse : Fixed router listing routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Steve Whitehouse : Added error_report functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Steve Whitehouse : Added default router detection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Steve Whitehouse : Hop counts in outgoing messages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Steve Whitehouse : Fixed src/dst in outgoing messages so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * forwarding now stands a good chance of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * working.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Steve Whitehouse : Fixed neighbour states (for now anyway).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * Steve Whitehouse : Made error_report functions dummies. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * is not the right place to return skbs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Steve Whitehouse : Convert to seq_file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/net.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/socket.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/if_ether.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/netfilter_decnet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/rcupdate.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/jhash.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <net/net_namespace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <net/neighbour.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <net/dst.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <net/flow.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <net/dn.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <net/dn_dev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <net/dn_neigh.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <net/dn_route.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static int dn_neigh_construct(struct neighbour *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static void dn_neigh_error_report(struct neighbour *, struct sk_buff *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static int dn_neigh_output(struct neighbour *neigh, struct sk_buff *skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * Operations for adding the link layer header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static const struct neigh_ops dn_neigh_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .family = AF_DECnet,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .error_report = dn_neigh_error_report,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .output = dn_neigh_output,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) .connected_output = dn_neigh_output,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static u32 dn_neigh_hash(const void *pkey,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) const struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) __u32 *hash_rnd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return jhash_2words(*(__u16 *)pkey, 0, hash_rnd[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static bool dn_key_eq(const struct neighbour *neigh, const void *pkey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return neigh_key_eq16(neigh, pkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct neigh_table dn_neigh_table = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .family = PF_DECnet,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .entry_size = NEIGH_ENTRY_SIZE(sizeof(struct dn_neigh)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .key_len = sizeof(__le16),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .protocol = cpu_to_be16(ETH_P_DNA_RT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .hash = dn_neigh_hash,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .key_eq = dn_key_eq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .constructor = dn_neigh_construct,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) .id = "dn_neigh_cache",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) .parms ={
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .tbl = &dn_neigh_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .reachable_time = 30 * HZ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) [NEIGH_VAR_MCAST_PROBES] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) [NEIGH_VAR_UCAST_PROBES] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) [NEIGH_VAR_APP_PROBES] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) [NEIGH_VAR_RETRANS_TIME] = 1 * HZ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) [NEIGH_VAR_BASE_REACHABLE_TIME] = 30 * HZ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) [NEIGH_VAR_DELAY_PROBE_TIME] = 5 * HZ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) [NEIGH_VAR_GC_STALETIME] = 60 * HZ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) [NEIGH_VAR_QUEUE_LEN_BYTES] = SK_WMEM_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) [NEIGH_VAR_PROXY_QLEN] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) [NEIGH_VAR_ANYCAST_DELAY] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) [NEIGH_VAR_PROXY_DELAY] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) [NEIGH_VAR_LOCKTIME] = 1 * HZ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) .gc_interval = 30 * HZ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .gc_thresh1 = 128,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .gc_thresh2 = 512,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .gc_thresh3 = 1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static int dn_neigh_construct(struct neighbour *neigh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct net_device *dev = neigh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct dn_neigh *dn = container_of(neigh, struct dn_neigh, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct dn_dev *dn_db;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct neigh_parms *parms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) dn_db = rcu_dereference(dev->dn_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (dn_db == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) parms = dn_db->neigh_parms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (!parms) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) __neigh_parms_put(neigh->parms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) neigh->parms = neigh_parms_clone(parms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) neigh->ops = &dn_neigh_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) neigh->nud_state = NUD_NOARP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) neigh->output = neigh->ops->connected_output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if ((dev->type == ARPHRD_IPGRE) || (dev->flags & IFF_POINTOPOINT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) memcpy(neigh->ha, dev->broadcast, dev->addr_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) else if ((dev->type == ARPHRD_ETHER) || (dev->type == ARPHRD_LOOPBACK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) dn_dn2eth(neigh->ha, dn->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) net_dbg_ratelimited("Trying to create neigh for hw %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) dev->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * Make an estimate of the remote block size by assuming that its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * two less then the device mtu, which it true for ethernet (and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * other things which support long format headers) since there is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * an extra length field (of 16 bits) which isn't part of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * ethernet headers and which the DECnet specs won't admit is part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * of the DECnet routing headers either.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * If we over estimate here its no big deal, the NSP negotiations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * will prevent us from sending packets which are too large for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * remote node to handle. In any case this figure is normally updated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * by a hello message in most cases.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) dn->blksize = dev->mtu - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static void dn_neigh_error_report(struct neighbour *neigh, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) printk(KERN_DEBUG "dn_neigh_error_report: called\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static int dn_neigh_output(struct neighbour *neigh, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct dst_entry *dst = skb_dst(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct dn_route *rt = (struct dn_route *)dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct net_device *dev = neigh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) char mac_addr[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) unsigned int seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) dn_dn2eth(mac_addr, rt->rt_local_src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) seq = read_seqbegin(&neigh->ha_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) err = dev_hard_header(skb, dev, ntohs(skb->protocol),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) neigh->ha, mac_addr, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) } while (read_seqretry(&neigh->ha_lock, seq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) err = dev_queue_xmit(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static int dn_neigh_output_packet(struct net *net, struct sock *sk, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct dst_entry *dst = skb_dst(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct dn_route *rt = (struct dn_route *)dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct neighbour *neigh = rt->n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return neigh->output(neigh, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * For talking to broadcast devices: Ethernet & PPP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static int dn_long_output(struct neighbour *neigh, struct sock *sk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct net_device *dev = neigh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) unsigned char *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct dn_long_packet *lp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct dn_skb_cb *cb = DN_SKB_CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (skb_headroom(skb) < headroom) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (skb2 == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) net_crit_ratelimited("dn_long_output: no memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) consume_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) skb = skb2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) net_info_ratelimited("dn_long_output: Increasing headroom\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) data = skb_push(skb, sizeof(struct dn_long_packet) + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) lp = (struct dn_long_packet *)(data+3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) *((__le16 *)data) = cpu_to_le16(skb->len - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) *(data + 2) = 1 | DN_RT_F_PF; /* Padding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) lp->msgflg = DN_RT_PKT_LONG|(cb->rt_flags&(DN_RT_F_IE|DN_RT_F_RQR|DN_RT_F_RTS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) lp->d_area = lp->d_subarea = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) dn_dn2eth(lp->d_id, cb->dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) lp->s_area = lp->s_subarea = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) dn_dn2eth(lp->s_id, cb->src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) lp->nl2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) lp->visit_ct = cb->hops & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) lp->s_class = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) lp->pt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) skb_reset_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) &init_net, sk, skb, NULL, neigh->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) dn_neigh_output_packet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * For talking to pointopoint and multidrop devices: DDCMP and X.25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static int dn_short_output(struct neighbour *neigh, struct sock *sk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct net_device *dev = neigh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct dn_short_packet *sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) unsigned char *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) struct dn_skb_cb *cb = DN_SKB_CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (skb_headroom(skb) < headroom) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (skb2 == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) net_crit_ratelimited("dn_short_output: no memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) consume_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) skb = skb2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) net_info_ratelimited("dn_short_output: Increasing headroom\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) data = skb_push(skb, sizeof(struct dn_short_packet) + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) *((__le16 *)data) = cpu_to_le16(skb->len - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) sp = (struct dn_short_packet *)(data+2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) sp->msgflg = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) sp->dstnode = cb->dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) sp->srcnode = cb->src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) sp->forward = cb->hops & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) skb_reset_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) &init_net, sk, skb, NULL, neigh->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) dn_neigh_output_packet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * For talking to DECnet phase III nodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * Phase 3 output is the same as short output, execpt that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * it clears the area bits before transmission.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) static int dn_phase3_output(struct neighbour *neigh, struct sock *sk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) struct net_device *dev = neigh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) struct dn_short_packet *sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) unsigned char *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct dn_skb_cb *cb = DN_SKB_CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (skb_headroom(skb) < headroom) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (skb2 == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) net_crit_ratelimited("dn_phase3_output: no memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) consume_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) skb = skb2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) net_info_ratelimited("dn_phase3_output: Increasing headroom\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) data = skb_push(skb, sizeof(struct dn_short_packet) + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) *((__le16 *)data) = cpu_to_le16(skb->len - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) sp = (struct dn_short_packet *)(data + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) sp->msgflg = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) sp->dstnode = cb->dst & cpu_to_le16(0x03ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) sp->srcnode = cb->src & cpu_to_le16(0x03ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) sp->forward = cb->hops & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) skb_reset_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) &init_net, sk, skb, NULL, neigh->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) dn_neigh_output_packet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int dn_to_neigh_output(struct net *net, struct sock *sk, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) struct dst_entry *dst = skb_dst(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct dn_route *rt = (struct dn_route *) dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) struct neighbour *neigh = rt->n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) struct dn_neigh *dn = container_of(neigh, struct dn_neigh, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct dn_dev *dn_db;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) bool use_long;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) dn_db = rcu_dereference(neigh->dev->dn_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (dn_db == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) use_long = dn_db->use_long;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (dn->flags & DN_NDFLAG_P3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return dn_phase3_output(neigh, sk, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (use_long)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return dn_long_output(neigh, sk, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return dn_short_output(neigh, sk, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * Unfortunately, the neighbour code uses the device in its hash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * function, so we don't get any advantage from it. This function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * basically does a neigh_lookup(), but without comparing the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * field. This is required for the On-Ethernet cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * Pointopoint link receives a hello message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) void dn_neigh_pointopoint_hello(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * Ethernet router hello message received
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) int dn_neigh_router_hello(struct net *net, struct sock *sk, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct rtnode_hello_message *msg = (struct rtnode_hello_message *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) struct neighbour *neigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) struct dn_neigh *dn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) struct dn_dev *dn_db;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) __le16 src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) src = dn_eth2dn(msg->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) dn = container_of(neigh, struct dn_neigh, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (neigh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) write_lock(&neigh->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) neigh->used = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) dn_db = rcu_dereference(neigh->dev->dn_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (!(neigh->nud_state & NUD_PERMANENT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) neigh->updated = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (neigh->dev->type == ARPHRD_ETHER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) memcpy(neigh->ha, ð_hdr(skb)->h_source, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) dn->blksize = le16_to_cpu(msg->blksize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) dn->priority = msg->priority;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) dn->flags &= ~DN_NDFLAG_P3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) switch (msg->iinfo & DN_RT_INFO_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) case DN_RT_INFO_L1RT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) dn->flags &=~DN_NDFLAG_R2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) dn->flags |= DN_NDFLAG_R1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) case DN_RT_INFO_L2RT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) dn->flags |= DN_NDFLAG_R2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /* Only use routers in our area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if ((le16_to_cpu(src)>>10) == (le16_to_cpu((decnet_address))>>10)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (!dn_db->router) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) dn_db->router = neigh_clone(neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (msg->priority > ((struct dn_neigh *)dn_db->router)->priority)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) neigh_release(xchg(&dn_db->router, neigh_clone(neigh)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) write_unlock(&neigh->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) neigh_release(neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * Endnode hello message received
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) int dn_neigh_endnode_hello(struct net *net, struct sock *sk, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) struct endnode_hello_message *msg = (struct endnode_hello_message *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) struct neighbour *neigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) struct dn_neigh *dn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) __le16 src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) src = dn_eth2dn(msg->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) dn = container_of(neigh, struct dn_neigh, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (neigh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) write_lock(&neigh->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) neigh->used = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (!(neigh->nud_state & NUD_PERMANENT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) neigh->updated = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (neigh->dev->type == ARPHRD_ETHER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) memcpy(neigh->ha, ð_hdr(skb)->h_source, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) dn->flags &= ~(DN_NDFLAG_R1 | DN_NDFLAG_R2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) dn->blksize = le16_to_cpu(msg->blksize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) dn->priority = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) write_unlock(&neigh->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) neigh_release(neigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) static char *dn_find_slot(char *base, int max, int priority)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) unsigned char *min = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) base += 6; /* skip first id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) for(i = 0; i < max; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (!min || (*base < *min))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) min = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) base += 7; /* find next priority */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (!min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) return (*min < priority) ? (min - 6) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) struct elist_cb_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) unsigned char *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) unsigned char *rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) int t, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static void neigh_elist_cb(struct neighbour *neigh, void *_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) struct elist_cb_state *s = _info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) struct dn_neigh *dn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (neigh->dev != s->dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) dn = container_of(neigh, struct dn_neigh, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (s->t == s->n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) s->rs = dn_find_slot(s->ptr, s->n, dn->priority);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) s->t++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if (s->rs == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) dn_dn2eth(s->rs, dn->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) s->rs += 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) *(s->rs) = neigh->nud_state & NUD_CONNECTED ? 0x80 : 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) *(s->rs) |= dn->priority;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) s->rs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) struct elist_cb_state state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) state.dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) state.t = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) state.n = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) state.ptr = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) state.rs = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) neigh_for_each(&dn_neigh_table, neigh_elist_cb, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return state.t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) #ifdef CONFIG_PROC_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) static inline void dn_neigh_format_entry(struct seq_file *seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) struct neighbour *n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) struct dn_neigh *dn = container_of(n, struct dn_neigh, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) char buf[DN_ASCBUF_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) read_lock(&n->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) seq_printf(seq, "%-7s %s%s%s %02x %02d %07ld %-8s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) dn_addr2asc(le16_to_cpu(dn->addr), buf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) (dn->flags&DN_NDFLAG_R1) ? "1" : "-",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) (dn->flags&DN_NDFLAG_R2) ? "2" : "-",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) (dn->flags&DN_NDFLAG_P3) ? "3" : "-",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) dn->n.nud_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) refcount_read(&dn->n.refcnt),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) dn->blksize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) (dn->n.dev) ? dn->n.dev->name : "?");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) read_unlock(&n->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) static int dn_neigh_seq_show(struct seq_file *seq, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (v == SEQ_START_TOKEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) seq_puts(seq, "Addr Flags State Use Blksize Dev\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) dn_neigh_format_entry(seq, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) static void *dn_neigh_seq_start(struct seq_file *seq, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return neigh_seq_start(seq, pos, &dn_neigh_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) NEIGH_SEQ_NEIGH_ONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) static const struct seq_operations dn_neigh_seq_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) .start = dn_neigh_seq_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) .next = neigh_seq_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) .stop = neigh_seq_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) .show = dn_neigh_seq_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) void __init dn_neigh_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) neigh_table_init(NEIGH_DN_TABLE, &dn_neigh_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) proc_create_net("decnet_neigh", 0444, init_net.proc_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) &dn_neigh_seq_ops, sizeof(struct neigh_seq_state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) void __exit dn_neigh_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) remove_proc_entry("decnet_neigh", init_net.proc_net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) neigh_table_clear(NEIGH_DN_TABLE, &dn_neigh_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }