11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version.
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/socket.h>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/in.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
1470868eace5031298c6f6e991a40a2106957f582cRalf Baechle#include <linux/module.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sockios.h>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/net.h>
195a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/ax25.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/inet.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/if_arp.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/sock.h>
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fcntl.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/termios.h>	/* For TIOCINQ/OUTQ */
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/notifier.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/proc_fs.h>
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/stat.h>
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netfilter.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sysctl.h>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/ip.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/arp.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	IP over AX.25 encapsulation.
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Shove an AX.25 UI header on an IP packet and handle ARP
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_INET
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
493b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemmingerint ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
503b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger		     unsigned short type, const void *daddr,
5195c961747284a6b83a5e2d81240e214b0fa3464dEric Dumazet		     const void *saddr, unsigned int len)
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *buff;
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* they sometimes come back to us... */
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (type == ETH_P_AX25)
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
59528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	/* header is an AX.25 UI frame from us to them */
60528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	buff = skb_push(skb, AX25_HEADER_LEN);
61528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	*buff++ = 0x00;	/* KISS DATA */
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (daddr != NULL)
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(buff, daddr, dev->addr_len);	/* Address specified */
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
66528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	buff[6] &= ~AX25_CBIT;
67528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	buff[6] &= ~AX25_EBIT;
68528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	buff[6] |= AX25_SSSID_SPARE;
69528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	buff    += AX25_ADDR_LEN;
70528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki
71528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	if (saddr != NULL)
72528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki		memcpy(buff, saddr, dev->addr_len);
73528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	else
74528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki		memcpy(buff, dev->dev_addr, dev->addr_len);
75528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki
76528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	buff[6] &= ~AX25_CBIT;
77528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	buff[6] |= AX25_EBIT;
78528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	buff[6] |= AX25_SSSID_SPARE;
79528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	buff    += AX25_ADDR_LEN;
80528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki
81528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	*buff++  = AX25_UI;	/* UI */
82528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki
83528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	/* Append a suitable AX.25 PID */
84528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	switch (type) {
85528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	case ETH_P_IP:
86528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki		*buff++ = AX25_P_IP;
87528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki		break;
88528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	case ETH_P_ARP:
89528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki		*buff++ = AX25_P_ARP;
90528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki		break;
91528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	default:
92528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki		printk(KERN_ERR "AX.25: ax25_hard_header - wrong protocol type 0x%2.2x\n", type);
93528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki		*buff++ = 0;
94528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki		break;
95528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	}
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (daddr != NULL)
98528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki		return AX25_HEADER_LEN;
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -AX25_HEADER_LEN;	/* Unfinished header */
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ax25_rebuild_header(struct sk_buff *skb)
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *ourskb;
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *bp  = skb->data;
107006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle	ax25_route *route;
108006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle	struct net_device *dev = NULL;
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax25_address *src, *dst;
110006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle	ax25_digi *digipeat = NULL;
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax25_dev *ax25_dev;
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax25_cb *ax25;
113006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle	char ip_mode = ' ';
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dst = (ax25_address *)(bp + 1);
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	src = (ax25_address *)(bp + 8);
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
118528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	if (arp_find(bp + 1, skb))
119528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki		return 1;
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
121006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle	route = ax25_get_route(dst, NULL);
122006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle	if (route) {
123006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle		digipeat = route->digipeat;
124006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle		dev = route->dev;
125006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle		ip_mode = route->ip_mode;
1263ff50b7997fe06cd5d276b229967bb52d6b3b6c1Stephen Hemminger	}
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev == NULL)
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev = skb->dev;
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) {
132528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki		goto put;
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bp[16] == AX25_P_IP) {
136006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle		if (ip_mode == 'V' || (ip_mode == ' ' && ax25_dev->values[AX25_VALUES_IPDEFMODE])) {
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *	We copy the buffer and release the original thereby
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *	keeping it straight
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *	Note: we report 1 back so the caller will
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *	not feed the frame direct to the physical device
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *	We don't want that to happen. (It won't be upset
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *	as we have pulled the frame from the queue by
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *	freeing it).
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *	NB: TCP modifies buffers that are still
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *	on a device queue, thus we use skb_copy()
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *      instead of using skb_clone() unless this
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *	gets fixed.
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ax25_address src_c;
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ax25_address dst_c;
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((ourskb = skb_copy(skb, GFP_ATOMIC)) == NULL) {
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				kfree_skb(skb);
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto put;
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (skb->sk != NULL)
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				skb_set_owner_w(ourskb, skb->sk);
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kfree_skb(skb);
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* dl9sau: bugfix
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * after kfree_skb(), dst and src which were pointer
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * to bp which is part of skb->data would not be valid
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * anymore hope that after skb_pull(ourskb, ..) our
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * dsc_c and src_c will not become invalid
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bp  = ourskb->data;
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dst_c = *(ax25_address *)(bp + 1);
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			src_c = *(ax25_address *)(bp + 8);
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			skb_pull(ourskb, AX25_HEADER_LEN - 1);	/* Keep PID */
176c1d2bbe1cd6c7bbdc6d532cefebb66c7efb789ceArnaldo Carvalho de Melo			skb_reset_network_header(ourskb);
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ax25=ax25_send_frame(
179528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki			    ourskb,
180528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki			    ax25_dev->values[AX25_VALUES_PACLEN],
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    &src_c,
182006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle			    &dst_c, digipeat, dev);
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ax25) {
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ax25_cb_put(ax25);
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto put;
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
190528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	bp[7]  &= ~AX25_CBIT;
191528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	bp[7]  &= ~AX25_EBIT;
192528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	bp[7]  |= AX25_SSSID_SPARE;
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
194528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	bp[14] &= ~AX25_CBIT;
195528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	bp[14] |= AX25_EBIT;
196528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	bp[14] |= AX25_SSSID_SPARE;
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_pull(skb, AX25_KISS_HEADER_LEN);
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
200006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle	if (digipeat != NULL) {
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((ourskb = ax25_rt_build_path(skb, src, dst, route->digipeat)) == NULL) {
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kfree_skb(skb);
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto put;
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb = ourskb;
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20929c4be51e3fd52205d848248d38924941f22ca0eArnaldo Carvalho de Melo	ax25_queue_xmit(skb, dev);
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsput:
212006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle	if (route)
213006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle		ax25_put_route(route);
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
215528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki	return 1;
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else	/* INET */
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2203b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemmingerint ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
2213b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger		     unsigned short type, const void *daddr,
22295c961747284a6b83a5e2d81240e214b0fa3464dEric Dumazet		     const void *saddr, unsigned int len)
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -AX25_HEADER_LEN;
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ax25_rebuild_header(struct sk_buff *skb)
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2343b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemmingerconst struct header_ops ax25_header_ops = {
2353b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger	.create = ax25_hard_header,
2363b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger	.rebuild = ax25_rebuild_header,
2373b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger};
2383b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger
23970868eace5031298c6f6e991a40a2106957f582cRalf BaechleEXPORT_SYMBOL(ax25_hard_header);
24070868eace5031298c6f6e991a40a2106957f582cRalf BaechleEXPORT_SYMBOL(ax25_rebuild_header);
2413b04ddde02cf1b6f14f2697da5c20eca5715017fStephen HemmingerEXPORT_SYMBOL(ax25_header_ops);
2423b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger
243