Blame view

net/x25/x25_dev.c 4.41 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   *	X.25 Packet Layer release 002
   *
f8e1d2018   YOSHIFUJI Hideaki   [NET] X25: Fix wh...
4
5
   *	This is ALPHA test software. This code may break your machine, randomly fail to work with new
   *	releases, misbehave and/or generally screw up. It might even work.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
10
11
12
13
14
15
16
17
18
   *
   *	This code REQUIRES 2.1.15 or higher
   *
   *	This module:
   *		This module is free software; you can redistribute it and/or
   *		modify it under the terms of the GNU General Public License
   *		as published by the Free Software Foundation; either version
   *		2 of the License, or (at your option) any later version.
   *
   *	History
   *	X.25 001	Jonathan Naylor	Started coding.
   *      2000-09-04	Henner Eisen	Prevent freeing a dangling skb.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
  #include <linux/kernel.h>
  #include <linux/netdevice.h>
  #include <linux/skbuff.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
22
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
  #include <net/sock.h>
  #include <linux/if_arp.h>
  #include <net/x25.h>
5ebfbc06a   Andrew Hendry   X25: Add if_x25.h...
26
  #include <net/x25device.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
30
31
32
  
  static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *nb)
  {
  	struct sock *sk;
  	unsigned short frametype;
  	unsigned int lci;
cb101ed2c   Matthew Daley   x25: Handle under...
33
34
  	if (!pskb_may_pull(skb, X25_STD_MIN_LEN))
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  	frametype = skb->data[2];
f8e1d2018   YOSHIFUJI Hideaki   [NET] X25: Fix wh...
36
  	lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  
  	/*
  	 *	LCI of zero is always for us, and its always a link control
  	 *	frame.
  	 */
  	if (lci == 0) {
  		x25_link_control(skb, nb, frametype);
  		return 0;
  	}
  
  	/*
  	 *	Find an existing socket.
  	 */
  	if ((sk = x25_find_socket(lci, nb)) != NULL) {
  		int queued = 1;
badff6d01   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
52
  		skb_reset_transport_header(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
54
55
56
  		bh_lock_sock(sk);
  		if (!sock_owned_by_user(sk)) {
  			queued = x25_process_rx_frame(sk, skb);
  		} else {
a3a858ff1   Zhu Yi   net: backlog func...
57
  			queued = !sk_add_backlog(sk, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
  		}
  		bh_unlock_sock(sk);
9d0f7d29f   Andrew Hendry   [X.25]: Add missi...
60
  		sock_put(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
62
63
64
65
66
67
68
69
70
  		return queued;
  	}
  
  	/*
  	 *	Is is a Call Request ? if so process it.
  	 */
  	if (frametype == X25_CALL_REQUEST)
  		return x25_rx_call_request(skb, nb, lci);
  
  	/*
95a9dc439   Andrew Hendry   [X.25]: Add call ...
71
72
  	 * 	Its not a Call Request, nor is it a control frame.
  	 *	Can we forward it?
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
  	 */
95a9dc439   Andrew Hendry   [X.25]: Add call ...
74
75
76
77
78
79
80
81
  
  	if (x25_forward_data(lci, nb, skb)) {
  		if (frametype == X25_CLEAR_CONFIRMATION) {
  			x25_clear_forward_by_lci(lci);
  		}
  		kfree_skb(skb);
  		return 1;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
83
84
85
86
87
88
89
90
91
92
93
  /*
  	x25_transmit_clear_request(nb, lci, 0x0D);
  */
  
  	if (frametype != X25_CLEAR_CONFIRMATION)
  		printk(KERN_DEBUG "x25_receive_data(): unknown frame type %2x
  ",frametype);
  
  	return 0;
  }
  
  int x25_lapb_receive_frame(struct sk_buff *skb, struct net_device *dev,
f2ccd8fa0   David S. Miller   [NET]: Kill skb->...
94
  			   struct packet_type *ptype, struct net_device *orig_dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
97
  {
  	struct sk_buff *nskb;
  	struct x25_neigh *nb;
721499e89   YOSHIFUJI Hideaki   netns: Use net_eq...
98
  	if (!net_eq(dev_net(dev), &init_net))
e730c1551   Eric W. Biederman   [NET]: Make packe...
99
  		goto drop;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
  	nskb = skb_copy(skb, GFP_ATOMIC);
  	if (!nskb)
  		goto drop;
  	kfree_skb(skb);
  	skb = nskb;
  
  	/*
  	 * Packet received from unrecognised device, throw it away.
  	 */
  	nb = x25_get_neigh(dev);
  	if (!nb) {
  		printk(KERN_DEBUG "X.25: unknown neighbour - %s
  ", dev->name);
  		goto drop;
  	}
cb101ed2c   Matthew Daley   x25: Handle under...
115
116
  	if (!pskb_may_pull(skb, 1))
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
  	switch (skb->data[0]) {
5ebfbc06a   Andrew Hendry   X25: Add if_x25.h...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
  
  	case X25_IFACE_DATA:
  		skb_pull(skb, 1);
  		if (x25_receive_data(skb, nb)) {
  			x25_neigh_put(nb);
  			goto out;
  		}
  		break;
  
  	case X25_IFACE_CONNECT:
  		x25_link_established(nb);
  		break;
  
  	case X25_IFACE_DISCONNECT:
  		x25_link_terminated(nb);
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
136
137
138
139
140
141
142
143
144
145
146
147
  	}
  	x25_neigh_put(nb);
  drop:
  	kfree_skb(skb);
  out:
  	return 0;
  }
  
  void x25_establish_link(struct x25_neigh *nb)
  {
  	struct sk_buff *skb;
  	unsigned char *ptr;
  
  	switch (nb->dev->type) {
fddc5f3e9   Joe Perches   x25: Reduce switc...
148
149
150
151
152
153
154
155
156
  	case ARPHRD_X25:
  		if ((skb = alloc_skb(1, GFP_ATOMIC)) == NULL) {
  			printk(KERN_ERR "x25_dev: out of memory
  ");
  			return;
  		}
  		ptr  = skb_put(skb, 1);
  		*ptr = X25_IFACE_CONNECT;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157

29c362623   Igor Maravić   net:x25: use IS_E...
158
  #if IS_ENABLED(CONFIG_LLC)
fddc5f3e9   Joe Perches   x25: Reduce switc...
159
160
  	case ARPHRD_ETHER:
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
  #endif
fddc5f3e9   Joe Perches   x25: Reduce switc...
162
163
  	default:
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
166
167
168
169
170
171
172
173
174
175
  	}
  
  	skb->protocol = htons(ETH_P_X25);
  	skb->dev      = nb->dev;
  
  	dev_queue_xmit(skb);
  }
  
  void x25_terminate_link(struct x25_neigh *nb)
  {
  	struct sk_buff *skb;
  	unsigned char *ptr;
29c362623   Igor Maravić   net:x25: use IS_E...
176
  #if IS_ENABLED(CONFIG_LLC)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
178
179
180
181
182
183
184
185
186
187
188
189
190
  	if (nb->dev->type == ARPHRD_ETHER)
  		return;
  #endif
  	if (nb->dev->type != ARPHRD_X25)
  		return;
  
  	skb = alloc_skb(1, GFP_ATOMIC);
  	if (!skb) {
  		printk(KERN_ERR "x25_dev: out of memory
  ");
  		return;
  	}
  
  	ptr  = skb_put(skb, 1);
5ebfbc06a   Andrew Hendry   X25: Add if_x25.h...
191
  	*ptr = X25_IFACE_DISCONNECT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
194
195
196
197
198
199
200
  
  	skb->protocol = htons(ETH_P_X25);
  	skb->dev      = nb->dev;
  	dev_queue_xmit(skb);
  }
  
  void x25_send_frame(struct sk_buff *skb, struct x25_neigh *nb)
  {
  	unsigned char *dptr;
c1d2bbe1c   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
201
  	skb_reset_network_header(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
203
  
  	switch (nb->dev->type) {
fddc5f3e9   Joe Perches   x25: Reduce switc...
204
205
206
207
  	case ARPHRD_X25:
  		dptr  = skb_push(skb, 1);
  		*dptr = X25_IFACE_DATA;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208

29c362623   Igor Maravić   net:x25: use IS_E...
209
  #if IS_ENABLED(CONFIG_LLC)
fddc5f3e9   Joe Perches   x25: Reduce switc...
210
211
212
  	case ARPHRD_ETHER:
  		kfree_skb(skb);
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
  #endif
fddc5f3e9   Joe Perches   x25: Reduce switc...
214
215
216
  	default:
  		kfree_skb(skb);
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
219
220
221
222
223
  	}
  
  	skb->protocol = htons(ETH_P_X25);
  	skb->dev      = nb->dev;
  
  	dev_queue_xmit(skb);
  }