~ubuntu-branches/ubuntu/saucy/linux-n900/saucy

« back to all changes in this revision

Viewing changes to net/ax25/ax25_ip.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Poirier
  • Date: 2011-02-18 09:43:31 UTC
  • Revision ID: james.westby@ubuntu.com-20110218094331-eyubsja4f9k0yhmq
Tags: 2.6.35-1.1
Initial release.

Show diffs side-by-side

added added

removed removed

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