Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *
0004  * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
0005  */
0006 #include <linux/errno.h>
0007 #include <linux/types.h>
0008 #include <linux/socket.h>
0009 #include <linux/in.h>
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/timer.h>
0013 #include <linux/string.h>
0014 #include <linux/sockios.h>
0015 #include <linux/net.h>
0016 #include <linux/slab.h>
0017 #include <net/ax25.h>
0018 #include <linux/inet.h>
0019 #include <linux/netdevice.h>
0020 #include <linux/if_arp.h>
0021 #include <linux/skbuff.h>
0022 #include <net/sock.h>
0023 #include <linux/uaccess.h>
0024 #include <linux/fcntl.h>
0025 #include <linux/termios.h>  /* For TIOCINQ/OUTQ */
0026 #include <linux/mm.h>
0027 #include <linux/interrupt.h>
0028 #include <linux/notifier.h>
0029 #include <linux/proc_fs.h>
0030 #include <linux/stat.h>
0031 #include <linux/sysctl.h>
0032 #include <net/ip.h>
0033 #include <net/arp.h>
0034 
0035 /*
0036  *  IP over AX.25 encapsulation.
0037  */
0038 
0039 /*
0040  *  Shove an AX.25 UI header on an IP packet and handle ARP
0041  */
0042 
0043 #ifdef CONFIG_INET
0044 
0045 static int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
0046                 unsigned short type, const void *daddr,
0047                 const void *saddr, unsigned int len)
0048 {
0049     unsigned char *buff;
0050 
0051     /* they sometimes come back to us... */
0052     if (type == ETH_P_AX25)
0053         return 0;
0054 
0055     /* header is an AX.25 UI frame from us to them */
0056     buff = skb_push(skb, AX25_HEADER_LEN);
0057     *buff++ = 0x00; /* KISS DATA */
0058 
0059     if (daddr != NULL)
0060         memcpy(buff, daddr, dev->addr_len); /* Address specified */
0061 
0062     buff[6] &= ~AX25_CBIT;
0063     buff[6] &= ~AX25_EBIT;
0064     buff[6] |= AX25_SSSID_SPARE;
0065     buff    += AX25_ADDR_LEN;
0066 
0067     if (saddr != NULL)
0068         memcpy(buff, saddr, dev->addr_len);
0069     else
0070         memcpy(buff, dev->dev_addr, dev->addr_len);
0071 
0072     buff[6] &= ~AX25_CBIT;
0073     buff[6] |= AX25_EBIT;
0074     buff[6] |= AX25_SSSID_SPARE;
0075     buff    += AX25_ADDR_LEN;
0076 
0077     *buff++  = AX25_UI; /* UI */
0078 
0079     /* Append a suitable AX.25 PID */
0080     switch (type) {
0081     case ETH_P_IP:
0082         *buff++ = AX25_P_IP;
0083         break;
0084     case ETH_P_ARP:
0085         *buff++ = AX25_P_ARP;
0086         break;
0087     default:
0088         printk(KERN_ERR "AX.25: ax25_hard_header - wrong protocol type 0x%2.2x\n", type);
0089         *buff++ = 0;
0090         break;
0091     }
0092 
0093     if (daddr != NULL)
0094         return AX25_HEADER_LEN;
0095 
0096     return -AX25_HEADER_LEN;    /* Unfinished header */
0097 }
0098 
0099 netdev_tx_t ax25_ip_xmit(struct sk_buff *skb)
0100 {
0101     struct sk_buff *ourskb;
0102     unsigned char *bp  = skb->data;
0103     ax25_route *route;
0104     struct net_device *dev = NULL;
0105     ax25_address *src, *dst;
0106     ax25_digi *digipeat = NULL;
0107     ax25_dev *ax25_dev;
0108     ax25_cb *ax25;
0109     char ip_mode = ' ';
0110 
0111     dst = (ax25_address *)(bp + 1);
0112     src = (ax25_address *)(bp + 8);
0113 
0114     ax25_route_lock_use();
0115     route = ax25_get_route(dst, NULL);
0116     if (route) {
0117         digipeat = route->digipeat;
0118         dev = route->dev;
0119         ip_mode = route->ip_mode;
0120     }
0121 
0122     if (dev == NULL)
0123         dev = skb->dev;
0124 
0125     if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) {
0126         kfree_skb(skb);
0127         goto put;
0128     }
0129 
0130     if (bp[16] == AX25_P_IP) {
0131         if (ip_mode == 'V' || (ip_mode == ' ' && ax25_dev->values[AX25_VALUES_IPDEFMODE])) {
0132             /*
0133              *  We copy the buffer and release the original thereby
0134              *  keeping it straight
0135              *
0136              *  Note: we report 1 back so the caller will
0137              *  not feed the frame direct to the physical device
0138              *  We don't want that to happen. (It won't be upset
0139              *  as we have pulled the frame from the queue by
0140              *  freeing it).
0141              *
0142              *  NB: TCP modifies buffers that are still
0143              *  on a device queue, thus we use skb_copy()
0144              *      instead of using skb_clone() unless this
0145              *  gets fixed.
0146              */
0147 
0148             ax25_address src_c;
0149             ax25_address dst_c;
0150 
0151             if ((ourskb = skb_copy(skb, GFP_ATOMIC)) == NULL) {
0152                 kfree_skb(skb);
0153                 goto put;
0154             }
0155 
0156             if (skb->sk != NULL)
0157                 skb_set_owner_w(ourskb, skb->sk);
0158 
0159             kfree_skb(skb);
0160             /* dl9sau: bugfix
0161              * after kfree_skb(), dst and src which were pointer
0162              * to bp which is part of skb->data would not be valid
0163              * anymore hope that after skb_pull(ourskb, ..) our
0164              * dsc_c and src_c will not become invalid
0165              */
0166             bp  = ourskb->data;
0167             dst_c = *(ax25_address *)(bp + 1);
0168             src_c = *(ax25_address *)(bp + 8);
0169 
0170             skb_pull(ourskb, AX25_HEADER_LEN - 1);  /* Keep PID */
0171             skb_reset_network_header(ourskb);
0172 
0173             ax25=ax25_send_frame(
0174                 ourskb,
0175                 ax25_dev->values[AX25_VALUES_PACLEN],
0176                 &src_c,
0177                 &dst_c, digipeat, dev);
0178             if (ax25) {
0179                 ax25_cb_put(ax25);
0180             }
0181             goto put;
0182         }
0183     }
0184 
0185     bp[7]  &= ~AX25_CBIT;
0186     bp[7]  &= ~AX25_EBIT;
0187     bp[7]  |= AX25_SSSID_SPARE;
0188 
0189     bp[14] &= ~AX25_CBIT;
0190     bp[14] |= AX25_EBIT;
0191     bp[14] |= AX25_SSSID_SPARE;
0192 
0193     skb_pull(skb, AX25_KISS_HEADER_LEN);
0194 
0195     if (digipeat != NULL) {
0196         if ((ourskb = ax25_rt_build_path(skb, src, dst, route->digipeat)) == NULL)
0197             goto put;
0198 
0199         skb = ourskb;
0200     }
0201 
0202     ax25_queue_xmit(skb, dev);
0203 
0204 put:
0205 
0206     ax25_route_lock_unuse();
0207     return NETDEV_TX_OK;
0208 }
0209 
0210 #else   /* INET */
0211 
0212 static int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
0213                 unsigned short type, const void *daddr,
0214                 const void *saddr, unsigned int len)
0215 {
0216     return -AX25_HEADER_LEN;
0217 }
0218 
0219 netdev_tx_t ax25_ip_xmit(struct sk_buff *skb)
0220 {
0221     kfree_skb(skb);
0222     return NETDEV_TX_OK;
0223 }
0224 #endif
0225 
0226 static bool ax25_validate_header(const char *header, unsigned int len)
0227 {
0228     ax25_digi digi;
0229 
0230     if (!len)
0231         return false;
0232 
0233     if (header[0])
0234         return true;
0235 
0236     return ax25_addr_parse(header + 1, len - 1, NULL, NULL, &digi, NULL,
0237                    NULL);
0238 }
0239 
0240 const struct header_ops ax25_header_ops = {
0241     .create = ax25_hard_header,
0242     .validate = ax25_validate_header,
0243 };
0244 
0245 EXPORT_SYMBOL(ax25_header_ops);
0246 EXPORT_SYMBOL(ax25_ip_xmit);