^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/socket.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/in.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/sockios.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/net.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <net/ax25.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/inet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/termios.h> /* For TIOCINQ/OUTQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/notifier.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/sysctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <net/ip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <net/arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * IP over AX.25 encapsulation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * Shove an AX.25 UI header on an IP packet and handle ARP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #ifdef CONFIG_INET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) unsigned short type, const void *daddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) const void *saddr, unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) unsigned char *buff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* they sometimes come back to us... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (type == ETH_P_AX25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* header is an AX.25 UI frame from us to them */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) buff = skb_push(skb, AX25_HEADER_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) *buff++ = 0x00; /* KISS DATA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (daddr != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) memcpy(buff, daddr, dev->addr_len); /* Address specified */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) buff[6] &= ~AX25_CBIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) buff[6] &= ~AX25_EBIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) buff[6] |= AX25_SSSID_SPARE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) buff += AX25_ADDR_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (saddr != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) memcpy(buff, saddr, dev->addr_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) memcpy(buff, dev->dev_addr, dev->addr_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) buff[6] &= ~AX25_CBIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) buff[6] |= AX25_EBIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) buff[6] |= AX25_SSSID_SPARE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) buff += AX25_ADDR_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) *buff++ = AX25_UI; /* UI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* Append a suitable AX.25 PID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) case ETH_P_IP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) *buff++ = AX25_P_IP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) case ETH_P_ARP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) *buff++ = AX25_P_ARP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) printk(KERN_ERR "AX.25: ax25_hard_header - wrong protocol type 0x%2.2x\n", type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) *buff++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (daddr != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return AX25_HEADER_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return -AX25_HEADER_LEN; /* Unfinished header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) netdev_tx_t ax25_ip_xmit(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct sk_buff *ourskb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) unsigned char *bp = skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) ax25_route *route;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct net_device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) ax25_address *src, *dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) ax25_digi *digipeat = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) ax25_dev *ax25_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) ax25_cb *ax25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) char ip_mode = ' ';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) dst = (ax25_address *)(bp + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) src = (ax25_address *)(bp + 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ax25_route_lock_use();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) route = ax25_get_route(dst, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (route) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) digipeat = route->digipeat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) dev = route->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) ip_mode = route->ip_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (dev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) dev = skb->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) goto put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (bp[16] == AX25_P_IP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (ip_mode == 'V' || (ip_mode == ' ' && ax25_dev->values[AX25_VALUES_IPDEFMODE])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * We copy the buffer and release the original thereby
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * keeping it straight
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * Note: we report 1 back so the caller will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * not feed the frame direct to the physical device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * We don't want that to happen. (It won't be upset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * as we have pulled the frame from the queue by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * freeing it).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * NB: TCP modifies buffers that are still
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * on a device queue, thus we use skb_copy()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * instead of using skb_clone() unless this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * gets fixed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ax25_address src_c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ax25_address dst_c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if ((ourskb = skb_copy(skb, GFP_ATOMIC)) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) goto put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (skb->sk != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) skb_set_owner_w(ourskb, skb->sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /* dl9sau: bugfix
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * after kfree_skb(), dst and src which were pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * to bp which is part of skb->data would not be valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * anymore hope that after skb_pull(ourskb, ..) our
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * dsc_c and src_c will not become invalid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) bp = ourskb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) dst_c = *(ax25_address *)(bp + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) src_c = *(ax25_address *)(bp + 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) skb_pull(ourskb, AX25_HEADER_LEN - 1); /* Keep PID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) skb_reset_network_header(ourskb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) ax25=ax25_send_frame(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ourskb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ax25_dev->values[AX25_VALUES_PACLEN],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) &src_c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) &dst_c, digipeat, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (ax25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ax25_cb_put(ax25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) goto put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) bp[7] &= ~AX25_CBIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) bp[7] &= ~AX25_EBIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) bp[7] |= AX25_SSSID_SPARE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) bp[14] &= ~AX25_CBIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) bp[14] |= AX25_EBIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) bp[14] |= AX25_SSSID_SPARE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) skb_pull(skb, AX25_KISS_HEADER_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (digipeat != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if ((ourskb = ax25_rt_build_path(skb, src, dst, route->digipeat)) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) goto put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) skb = ourskb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) ax25_queue_xmit(skb, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) ax25_route_lock_unuse();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) #else /* INET */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) unsigned short type, const void *daddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) const void *saddr, unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return -AX25_HEADER_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) netdev_tx_t ax25_ip_xmit(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static bool ax25_validate_header(const char *header, unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ax25_digi digi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (!len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (header[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return ax25_addr_parse(header + 1, len - 1, NULL, NULL, &digi, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) const struct header_ops ax25_header_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .create = ax25_hard_header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .validate = ax25_validate_header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) EXPORT_SYMBOL(ax25_header_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) EXPORT_SYMBOL(ax25_ip_xmit);