1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * DECnet An implementation of the DECnet protocol suite for the LINUX
4*4882a593Smuzhiyun * operating system. DECnet is implemented using the BSD Socket
5*4882a593Smuzhiyun * interface as the means of communication with the user level.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * DECnet Network Services Protocol (Input)
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * Author: Eduardo Marcelo Serrat <emserrat@geocities.com>
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * Changes:
12*4882a593Smuzhiyun *
13*4882a593Smuzhiyun * Steve Whitehouse: Split into dn_nsp_in.c and dn_nsp_out.c from
14*4882a593Smuzhiyun * original dn_nsp.c.
15*4882a593Smuzhiyun * Steve Whitehouse: Updated to work with my new routing architecture.
16*4882a593Smuzhiyun * Steve Whitehouse: Add changes from Eduardo Serrat's patches.
17*4882a593Smuzhiyun * Steve Whitehouse: Put all ack handling code in a common routine.
18*4882a593Smuzhiyun * Steve Whitehouse: Put other common bits into dn_nsp_rx()
19*4882a593Smuzhiyun * Steve Whitehouse: More checks on skb->len to catch bogus packets
20*4882a593Smuzhiyun * Fixed various race conditions and possible nasties.
21*4882a593Smuzhiyun * Steve Whitehouse: Now handles returned conninit frames.
22*4882a593Smuzhiyun * David S. Miller: New socket locking
23*4882a593Smuzhiyun * Steve Whitehouse: Fixed lockup when socket filtering was enabled.
24*4882a593Smuzhiyun * Paul Koning: Fix to push CC sockets into RUN when acks are
25*4882a593Smuzhiyun * received.
26*4882a593Smuzhiyun * Steve Whitehouse:
27*4882a593Smuzhiyun * Patrick Caulfield: Checking conninits for correctness & sending of error
28*4882a593Smuzhiyun * responses.
29*4882a593Smuzhiyun * Steve Whitehouse: Added backlog congestion level return codes.
30*4882a593Smuzhiyun * Patrick Caulfield:
31*4882a593Smuzhiyun * Steve Whitehouse: Added flow control support (outbound)
32*4882a593Smuzhiyun * Steve Whitehouse: Prepare for nonlinear skbs
33*4882a593Smuzhiyun */
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun /******************************************************************************
36*4882a593Smuzhiyun (c) 1995-1998 E.M. Serrat emserrat@geocities.com
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun *******************************************************************************/
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun #include <linux/errno.h>
41*4882a593Smuzhiyun #include <linux/types.h>
42*4882a593Smuzhiyun #include <linux/socket.h>
43*4882a593Smuzhiyun #include <linux/in.h>
44*4882a593Smuzhiyun #include <linux/kernel.h>
45*4882a593Smuzhiyun #include <linux/timer.h>
46*4882a593Smuzhiyun #include <linux/string.h>
47*4882a593Smuzhiyun #include <linux/sockios.h>
48*4882a593Smuzhiyun #include <linux/net.h>
49*4882a593Smuzhiyun #include <linux/netdevice.h>
50*4882a593Smuzhiyun #include <linux/inet.h>
51*4882a593Smuzhiyun #include <linux/route.h>
52*4882a593Smuzhiyun #include <linux/slab.h>
53*4882a593Smuzhiyun #include <net/sock.h>
54*4882a593Smuzhiyun #include <net/tcp_states.h>
55*4882a593Smuzhiyun #include <linux/fcntl.h>
56*4882a593Smuzhiyun #include <linux/mm.h>
57*4882a593Smuzhiyun #include <linux/termios.h>
58*4882a593Smuzhiyun #include <linux/interrupt.h>
59*4882a593Smuzhiyun #include <linux/proc_fs.h>
60*4882a593Smuzhiyun #include <linux/stat.h>
61*4882a593Smuzhiyun #include <linux/init.h>
62*4882a593Smuzhiyun #include <linux/poll.h>
63*4882a593Smuzhiyun #include <linux/netfilter_decnet.h>
64*4882a593Smuzhiyun #include <net/neighbour.h>
65*4882a593Smuzhiyun #include <net/dst.h>
66*4882a593Smuzhiyun #include <net/dn.h>
67*4882a593Smuzhiyun #include <net/dn_nsp.h>
68*4882a593Smuzhiyun #include <net/dn_dev.h>
69*4882a593Smuzhiyun #include <net/dn_route.h>
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun extern int decnet_log_martians;
72*4882a593Smuzhiyun
dn_log_martian(struct sk_buff * skb,const char * msg)73*4882a593Smuzhiyun static void dn_log_martian(struct sk_buff *skb, const char *msg)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun if (decnet_log_martians) {
76*4882a593Smuzhiyun char *devname = skb->dev ? skb->dev->name : "???";
77*4882a593Smuzhiyun struct dn_skb_cb *cb = DN_SKB_CB(skb);
78*4882a593Smuzhiyun net_info_ratelimited("DECnet: Martian packet (%s) dev=%s src=0x%04hx dst=0x%04hx srcport=0x%04hx dstport=0x%04hx\n",
79*4882a593Smuzhiyun msg, devname,
80*4882a593Smuzhiyun le16_to_cpu(cb->src),
81*4882a593Smuzhiyun le16_to_cpu(cb->dst),
82*4882a593Smuzhiyun le16_to_cpu(cb->src_port),
83*4882a593Smuzhiyun le16_to_cpu(cb->dst_port));
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun /*
88*4882a593Smuzhiyun * For this function we've flipped the cross-subchannel bit
89*4882a593Smuzhiyun * if the message is an otherdata or linkservice message. Thus
90*4882a593Smuzhiyun * we can use it to work out what to update.
91*4882a593Smuzhiyun */
dn_ack(struct sock * sk,struct sk_buff * skb,unsigned short ack)92*4882a593Smuzhiyun static void dn_ack(struct sock *sk, struct sk_buff *skb, unsigned short ack)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun struct dn_scp *scp = DN_SK(sk);
95*4882a593Smuzhiyun unsigned short type = ((ack >> 12) & 0x0003);
96*4882a593Smuzhiyun int wakeup = 0;
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun switch (type) {
99*4882a593Smuzhiyun case 0: /* ACK - Data */
100*4882a593Smuzhiyun if (dn_after(ack, scp->ackrcv_dat)) {
101*4882a593Smuzhiyun scp->ackrcv_dat = ack & 0x0fff;
102*4882a593Smuzhiyun wakeup |= dn_nsp_check_xmit_queue(sk, skb,
103*4882a593Smuzhiyun &scp->data_xmit_queue,
104*4882a593Smuzhiyun ack);
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun break;
107*4882a593Smuzhiyun case 1: /* NAK - Data */
108*4882a593Smuzhiyun break;
109*4882a593Smuzhiyun case 2: /* ACK - OtherData */
110*4882a593Smuzhiyun if (dn_after(ack, scp->ackrcv_oth)) {
111*4882a593Smuzhiyun scp->ackrcv_oth = ack & 0x0fff;
112*4882a593Smuzhiyun wakeup |= dn_nsp_check_xmit_queue(sk, skb,
113*4882a593Smuzhiyun &scp->other_xmit_queue,
114*4882a593Smuzhiyun ack);
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun break;
117*4882a593Smuzhiyun case 3: /* NAK - OtherData */
118*4882a593Smuzhiyun break;
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun if (wakeup && !sock_flag(sk, SOCK_DEAD))
122*4882a593Smuzhiyun sk->sk_state_change(sk);
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun /*
126*4882a593Smuzhiyun * This function is a universal ack processor.
127*4882a593Smuzhiyun */
dn_process_ack(struct sock * sk,struct sk_buff * skb,int oth)128*4882a593Smuzhiyun static int dn_process_ack(struct sock *sk, struct sk_buff *skb, int oth)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun __le16 *ptr = (__le16 *)skb->data;
131*4882a593Smuzhiyun int len = 0;
132*4882a593Smuzhiyun unsigned short ack;
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun if (skb->len < 2)
135*4882a593Smuzhiyun return len;
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun if ((ack = le16_to_cpu(*ptr)) & 0x8000) {
138*4882a593Smuzhiyun skb_pull(skb, 2);
139*4882a593Smuzhiyun ptr++;
140*4882a593Smuzhiyun len += 2;
141*4882a593Smuzhiyun if ((ack & 0x4000) == 0) {
142*4882a593Smuzhiyun if (oth)
143*4882a593Smuzhiyun ack ^= 0x2000;
144*4882a593Smuzhiyun dn_ack(sk, skb, ack);
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun if (skb->len < 2)
149*4882a593Smuzhiyun return len;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun if ((ack = le16_to_cpu(*ptr)) & 0x8000) {
152*4882a593Smuzhiyun skb_pull(skb, 2);
153*4882a593Smuzhiyun len += 2;
154*4882a593Smuzhiyun if ((ack & 0x4000) == 0) {
155*4882a593Smuzhiyun if (oth)
156*4882a593Smuzhiyun ack ^= 0x2000;
157*4882a593Smuzhiyun dn_ack(sk, skb, ack);
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun return len;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun /**
166*4882a593Smuzhiyun * dn_check_idf - Check an image data field format is correct.
167*4882a593Smuzhiyun * @pptr: Pointer to pointer to image data
168*4882a593Smuzhiyun * @len: Pointer to length of image data
169*4882a593Smuzhiyun * @max: The maximum allowed length of the data in the image data field
170*4882a593Smuzhiyun * @follow_on: Check that this many bytes exist beyond the end of the image data
171*4882a593Smuzhiyun *
172*4882a593Smuzhiyun * Returns: 0 if ok, -1 on error
173*4882a593Smuzhiyun */
dn_check_idf(unsigned char ** pptr,int * len,unsigned char max,unsigned char follow_on)174*4882a593Smuzhiyun static inline int dn_check_idf(unsigned char **pptr, int *len, unsigned char max, unsigned char follow_on)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun unsigned char *ptr = *pptr;
177*4882a593Smuzhiyun unsigned char flen = *ptr++;
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun (*len)--;
180*4882a593Smuzhiyun if (flen > max)
181*4882a593Smuzhiyun return -1;
182*4882a593Smuzhiyun if ((flen + follow_on) > *len)
183*4882a593Smuzhiyun return -1;
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun *len -= flen;
186*4882a593Smuzhiyun *pptr = ptr + flen;
187*4882a593Smuzhiyun return 0;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun /*
191*4882a593Smuzhiyun * Table of reason codes to pass back to node which sent us a badly
192*4882a593Smuzhiyun * formed message, plus text messages for the log. A zero entry in
193*4882a593Smuzhiyun * the reason field means "don't reply" otherwise a disc init is sent with
194*4882a593Smuzhiyun * the specified reason code.
195*4882a593Smuzhiyun */
196*4882a593Smuzhiyun static struct {
197*4882a593Smuzhiyun unsigned short reason;
198*4882a593Smuzhiyun const char *text;
199*4882a593Smuzhiyun } ci_err_table[] = {
200*4882a593Smuzhiyun { 0, "CI: Truncated message" },
201*4882a593Smuzhiyun { NSP_REASON_ID, "CI: Destination username error" },
202*4882a593Smuzhiyun { NSP_REASON_ID, "CI: Destination username type" },
203*4882a593Smuzhiyun { NSP_REASON_US, "CI: Source username error" },
204*4882a593Smuzhiyun { 0, "CI: Truncated at menuver" },
205*4882a593Smuzhiyun { 0, "CI: Truncated before access or user data" },
206*4882a593Smuzhiyun { NSP_REASON_IO, "CI: Access data format error" },
207*4882a593Smuzhiyun { NSP_REASON_IO, "CI: User data format error" }
208*4882a593Smuzhiyun };
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun /*
211*4882a593Smuzhiyun * This function uses a slightly different lookup method
212*4882a593Smuzhiyun * to find its sockets, since it searches on object name/number
213*4882a593Smuzhiyun * rather than port numbers. Various tests are done to ensure that
214*4882a593Smuzhiyun * the incoming data is in the correct format before it is queued to
215*4882a593Smuzhiyun * a socket.
216*4882a593Smuzhiyun */
dn_find_listener(struct sk_buff * skb,unsigned short * reason)217*4882a593Smuzhiyun static struct sock *dn_find_listener(struct sk_buff *skb, unsigned short *reason)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun struct dn_skb_cb *cb = DN_SKB_CB(skb);
220*4882a593Smuzhiyun struct nsp_conn_init_msg *msg = (struct nsp_conn_init_msg *)skb->data;
221*4882a593Smuzhiyun struct sockaddr_dn dstaddr;
222*4882a593Smuzhiyun struct sockaddr_dn srcaddr;
223*4882a593Smuzhiyun unsigned char type = 0;
224*4882a593Smuzhiyun int dstlen;
225*4882a593Smuzhiyun int srclen;
226*4882a593Smuzhiyun unsigned char *ptr;
227*4882a593Smuzhiyun int len;
228*4882a593Smuzhiyun int err = 0;
229*4882a593Smuzhiyun unsigned char menuver;
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun memset(&dstaddr, 0, sizeof(struct sockaddr_dn));
232*4882a593Smuzhiyun memset(&srcaddr, 0, sizeof(struct sockaddr_dn));
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun /*
235*4882a593Smuzhiyun * 1. Decode & remove message header
236*4882a593Smuzhiyun */
237*4882a593Smuzhiyun cb->src_port = msg->srcaddr;
238*4882a593Smuzhiyun cb->dst_port = msg->dstaddr;
239*4882a593Smuzhiyun cb->services = msg->services;
240*4882a593Smuzhiyun cb->info = msg->info;
241*4882a593Smuzhiyun cb->segsize = le16_to_cpu(msg->segsize);
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun if (!pskb_may_pull(skb, sizeof(*msg)))
244*4882a593Smuzhiyun goto err_out;
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun skb_pull(skb, sizeof(*msg));
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun len = skb->len;
249*4882a593Smuzhiyun ptr = skb->data;
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun /*
252*4882a593Smuzhiyun * 2. Check destination end username format
253*4882a593Smuzhiyun */
254*4882a593Smuzhiyun dstlen = dn_username2sockaddr(ptr, len, &dstaddr, &type);
255*4882a593Smuzhiyun err++;
256*4882a593Smuzhiyun if (dstlen < 0)
257*4882a593Smuzhiyun goto err_out;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun err++;
260*4882a593Smuzhiyun if (type > 1)
261*4882a593Smuzhiyun goto err_out;
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun len -= dstlen;
264*4882a593Smuzhiyun ptr += dstlen;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun /*
267*4882a593Smuzhiyun * 3. Check source end username format
268*4882a593Smuzhiyun */
269*4882a593Smuzhiyun srclen = dn_username2sockaddr(ptr, len, &srcaddr, &type);
270*4882a593Smuzhiyun err++;
271*4882a593Smuzhiyun if (srclen < 0)
272*4882a593Smuzhiyun goto err_out;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun len -= srclen;
275*4882a593Smuzhiyun ptr += srclen;
276*4882a593Smuzhiyun err++;
277*4882a593Smuzhiyun if (len < 1)
278*4882a593Smuzhiyun goto err_out;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun menuver = *ptr;
281*4882a593Smuzhiyun ptr++;
282*4882a593Smuzhiyun len--;
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun /*
285*4882a593Smuzhiyun * 4. Check that optional data actually exists if menuver says it does
286*4882a593Smuzhiyun */
287*4882a593Smuzhiyun err++;
288*4882a593Smuzhiyun if ((menuver & (DN_MENUVER_ACC | DN_MENUVER_USR)) && (len < 1))
289*4882a593Smuzhiyun goto err_out;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun /*
292*4882a593Smuzhiyun * 5. Check optional access data format
293*4882a593Smuzhiyun */
294*4882a593Smuzhiyun err++;
295*4882a593Smuzhiyun if (menuver & DN_MENUVER_ACC) {
296*4882a593Smuzhiyun if (dn_check_idf(&ptr, &len, 39, 1))
297*4882a593Smuzhiyun goto err_out;
298*4882a593Smuzhiyun if (dn_check_idf(&ptr, &len, 39, 1))
299*4882a593Smuzhiyun goto err_out;
300*4882a593Smuzhiyun if (dn_check_idf(&ptr, &len, 39, (menuver & DN_MENUVER_USR) ? 1 : 0))
301*4882a593Smuzhiyun goto err_out;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun /*
305*4882a593Smuzhiyun * 6. Check optional user data format
306*4882a593Smuzhiyun */
307*4882a593Smuzhiyun err++;
308*4882a593Smuzhiyun if (menuver & DN_MENUVER_USR) {
309*4882a593Smuzhiyun if (dn_check_idf(&ptr, &len, 16, 0))
310*4882a593Smuzhiyun goto err_out;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun /*
314*4882a593Smuzhiyun * 7. Look up socket based on destination end username
315*4882a593Smuzhiyun */
316*4882a593Smuzhiyun return dn_sklist_find_listener(&dstaddr);
317*4882a593Smuzhiyun err_out:
318*4882a593Smuzhiyun dn_log_martian(skb, ci_err_table[err].text);
319*4882a593Smuzhiyun *reason = ci_err_table[err].reason;
320*4882a593Smuzhiyun return NULL;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun
dn_nsp_conn_init(struct sock * sk,struct sk_buff * skb)324*4882a593Smuzhiyun static void dn_nsp_conn_init(struct sock *sk, struct sk_buff *skb)
325*4882a593Smuzhiyun {
326*4882a593Smuzhiyun if (sk_acceptq_is_full(sk)) {
327*4882a593Smuzhiyun kfree_skb(skb);
328*4882a593Smuzhiyun return;
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun sk_acceptq_added(sk);
332*4882a593Smuzhiyun skb_queue_tail(&sk->sk_receive_queue, skb);
333*4882a593Smuzhiyun sk->sk_state_change(sk);
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun
dn_nsp_conn_conf(struct sock * sk,struct sk_buff * skb)336*4882a593Smuzhiyun static void dn_nsp_conn_conf(struct sock *sk, struct sk_buff *skb)
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun struct dn_skb_cb *cb = DN_SKB_CB(skb);
339*4882a593Smuzhiyun struct dn_scp *scp = DN_SK(sk);
340*4882a593Smuzhiyun unsigned char *ptr;
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun if (skb->len < 4)
343*4882a593Smuzhiyun goto out;
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun ptr = skb->data;
346*4882a593Smuzhiyun cb->services = *ptr++;
347*4882a593Smuzhiyun cb->info = *ptr++;
348*4882a593Smuzhiyun cb->segsize = le16_to_cpu(*(__le16 *)ptr);
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun if ((scp->state == DN_CI) || (scp->state == DN_CD)) {
351*4882a593Smuzhiyun scp->persist = 0;
352*4882a593Smuzhiyun scp->addrrem = cb->src_port;
353*4882a593Smuzhiyun sk->sk_state = TCP_ESTABLISHED;
354*4882a593Smuzhiyun scp->state = DN_RUN;
355*4882a593Smuzhiyun scp->services_rem = cb->services;
356*4882a593Smuzhiyun scp->info_rem = cb->info;
357*4882a593Smuzhiyun scp->segsize_rem = cb->segsize;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun if ((scp->services_rem & NSP_FC_MASK) == NSP_FC_NONE)
360*4882a593Smuzhiyun scp->max_window = decnet_no_fc_max_cwnd;
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun if (skb->len > 0) {
363*4882a593Smuzhiyun u16 dlen = *skb->data;
364*4882a593Smuzhiyun if ((dlen <= 16) && (dlen <= skb->len)) {
365*4882a593Smuzhiyun scp->conndata_in.opt_optl = cpu_to_le16(dlen);
366*4882a593Smuzhiyun skb_copy_from_linear_data_offset(skb, 1,
367*4882a593Smuzhiyun scp->conndata_in.opt_data, dlen);
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun dn_nsp_send_link(sk, DN_NOCHANGE, 0);
371*4882a593Smuzhiyun if (!sock_flag(sk, SOCK_DEAD))
372*4882a593Smuzhiyun sk->sk_state_change(sk);
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun out:
376*4882a593Smuzhiyun kfree_skb(skb);
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun
dn_nsp_conn_ack(struct sock * sk,struct sk_buff * skb)379*4882a593Smuzhiyun static void dn_nsp_conn_ack(struct sock *sk, struct sk_buff *skb)
380*4882a593Smuzhiyun {
381*4882a593Smuzhiyun struct dn_scp *scp = DN_SK(sk);
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun if (scp->state == DN_CI) {
384*4882a593Smuzhiyun scp->state = DN_CD;
385*4882a593Smuzhiyun scp->persist = 0;
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun kfree_skb(skb);
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun
dn_nsp_disc_init(struct sock * sk,struct sk_buff * skb)391*4882a593Smuzhiyun static void dn_nsp_disc_init(struct sock *sk, struct sk_buff *skb)
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun struct dn_scp *scp = DN_SK(sk);
394*4882a593Smuzhiyun struct dn_skb_cb *cb = DN_SKB_CB(skb);
395*4882a593Smuzhiyun unsigned short reason;
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun if (skb->len < 2)
398*4882a593Smuzhiyun goto out;
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun reason = le16_to_cpu(*(__le16 *)skb->data);
401*4882a593Smuzhiyun skb_pull(skb, 2);
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun scp->discdata_in.opt_status = cpu_to_le16(reason);
404*4882a593Smuzhiyun scp->discdata_in.opt_optl = 0;
405*4882a593Smuzhiyun memset(scp->discdata_in.opt_data, 0, 16);
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun if (skb->len > 0) {
408*4882a593Smuzhiyun u16 dlen = *skb->data;
409*4882a593Smuzhiyun if ((dlen <= 16) && (dlen <= skb->len)) {
410*4882a593Smuzhiyun scp->discdata_in.opt_optl = cpu_to_le16(dlen);
411*4882a593Smuzhiyun skb_copy_from_linear_data_offset(skb, 1, scp->discdata_in.opt_data, dlen);
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun scp->addrrem = cb->src_port;
416*4882a593Smuzhiyun sk->sk_state = TCP_CLOSE;
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun switch (scp->state) {
419*4882a593Smuzhiyun case DN_CI:
420*4882a593Smuzhiyun case DN_CD:
421*4882a593Smuzhiyun scp->state = DN_RJ;
422*4882a593Smuzhiyun sk->sk_err = ECONNREFUSED;
423*4882a593Smuzhiyun break;
424*4882a593Smuzhiyun case DN_RUN:
425*4882a593Smuzhiyun sk->sk_shutdown |= SHUTDOWN_MASK;
426*4882a593Smuzhiyun scp->state = DN_DN;
427*4882a593Smuzhiyun break;
428*4882a593Smuzhiyun case DN_DI:
429*4882a593Smuzhiyun scp->state = DN_DIC;
430*4882a593Smuzhiyun break;
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun if (!sock_flag(sk, SOCK_DEAD)) {
434*4882a593Smuzhiyun if (sk->sk_socket->state != SS_UNCONNECTED)
435*4882a593Smuzhiyun sk->sk_socket->state = SS_DISCONNECTING;
436*4882a593Smuzhiyun sk->sk_state_change(sk);
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun /*
440*4882a593Smuzhiyun * It appears that its possible for remote machines to send disc
441*4882a593Smuzhiyun * init messages with no port identifier if we are in the CI and
442*4882a593Smuzhiyun * possibly also the CD state. Obviously we shouldn't reply with
443*4882a593Smuzhiyun * a message if we don't know what the end point is.
444*4882a593Smuzhiyun */
445*4882a593Smuzhiyun if (scp->addrrem) {
446*4882a593Smuzhiyun dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, GFP_ATOMIC);
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun scp->persist_fxn = dn_destroy_timer;
449*4882a593Smuzhiyun scp->persist = dn_nsp_persist(sk);
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun out:
452*4882a593Smuzhiyun kfree_skb(skb);
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun /*
456*4882a593Smuzhiyun * disc_conf messages are also called no_resources or no_link
457*4882a593Smuzhiyun * messages depending upon the "reason" field.
458*4882a593Smuzhiyun */
dn_nsp_disc_conf(struct sock * sk,struct sk_buff * skb)459*4882a593Smuzhiyun static void dn_nsp_disc_conf(struct sock *sk, struct sk_buff *skb)
460*4882a593Smuzhiyun {
461*4882a593Smuzhiyun struct dn_scp *scp = DN_SK(sk);
462*4882a593Smuzhiyun unsigned short reason;
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun if (skb->len != 2)
465*4882a593Smuzhiyun goto out;
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun reason = le16_to_cpu(*(__le16 *)skb->data);
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun sk->sk_state = TCP_CLOSE;
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun switch (scp->state) {
472*4882a593Smuzhiyun case DN_CI:
473*4882a593Smuzhiyun scp->state = DN_NR;
474*4882a593Smuzhiyun break;
475*4882a593Smuzhiyun case DN_DR:
476*4882a593Smuzhiyun if (reason == NSP_REASON_DC)
477*4882a593Smuzhiyun scp->state = DN_DRC;
478*4882a593Smuzhiyun if (reason == NSP_REASON_NL)
479*4882a593Smuzhiyun scp->state = DN_CN;
480*4882a593Smuzhiyun break;
481*4882a593Smuzhiyun case DN_DI:
482*4882a593Smuzhiyun scp->state = DN_DIC;
483*4882a593Smuzhiyun break;
484*4882a593Smuzhiyun case DN_RUN:
485*4882a593Smuzhiyun sk->sk_shutdown |= SHUTDOWN_MASK;
486*4882a593Smuzhiyun fallthrough;
487*4882a593Smuzhiyun case DN_CC:
488*4882a593Smuzhiyun scp->state = DN_CN;
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun if (!sock_flag(sk, SOCK_DEAD)) {
492*4882a593Smuzhiyun if (sk->sk_socket->state != SS_UNCONNECTED)
493*4882a593Smuzhiyun sk->sk_socket->state = SS_DISCONNECTING;
494*4882a593Smuzhiyun sk->sk_state_change(sk);
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun scp->persist_fxn = dn_destroy_timer;
498*4882a593Smuzhiyun scp->persist = dn_nsp_persist(sk);
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun out:
501*4882a593Smuzhiyun kfree_skb(skb);
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun
dn_nsp_linkservice(struct sock * sk,struct sk_buff * skb)504*4882a593Smuzhiyun static void dn_nsp_linkservice(struct sock *sk, struct sk_buff *skb)
505*4882a593Smuzhiyun {
506*4882a593Smuzhiyun struct dn_scp *scp = DN_SK(sk);
507*4882a593Smuzhiyun unsigned short segnum;
508*4882a593Smuzhiyun unsigned char lsflags;
509*4882a593Smuzhiyun signed char fcval;
510*4882a593Smuzhiyun int wake_up = 0;
511*4882a593Smuzhiyun char *ptr = skb->data;
512*4882a593Smuzhiyun unsigned char fctype = scp->services_rem & NSP_FC_MASK;
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun if (skb->len != 4)
515*4882a593Smuzhiyun goto out;
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun segnum = le16_to_cpu(*(__le16 *)ptr);
518*4882a593Smuzhiyun ptr += 2;
519*4882a593Smuzhiyun lsflags = *(unsigned char *)ptr++;
520*4882a593Smuzhiyun fcval = *ptr;
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun /*
523*4882a593Smuzhiyun * Here we ignore erronous packets which should really
524*4882a593Smuzhiyun * should cause a connection abort. It is not critical
525*4882a593Smuzhiyun * for now though.
526*4882a593Smuzhiyun */
527*4882a593Smuzhiyun if (lsflags & 0xf8)
528*4882a593Smuzhiyun goto out;
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun if (seq_next(scp->numoth_rcv, segnum)) {
531*4882a593Smuzhiyun seq_add(&scp->numoth_rcv, 1);
532*4882a593Smuzhiyun switch(lsflags & 0x04) { /* FCVAL INT */
533*4882a593Smuzhiyun case 0x00: /* Normal Request */
534*4882a593Smuzhiyun switch(lsflags & 0x03) { /* FCVAL MOD */
535*4882a593Smuzhiyun case 0x00: /* Request count */
536*4882a593Smuzhiyun if (fcval < 0) {
537*4882a593Smuzhiyun unsigned char p_fcval = -fcval;
538*4882a593Smuzhiyun if ((scp->flowrem_dat > p_fcval) &&
539*4882a593Smuzhiyun (fctype == NSP_FC_SCMC)) {
540*4882a593Smuzhiyun scp->flowrem_dat -= p_fcval;
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun } else if (fcval > 0) {
543*4882a593Smuzhiyun scp->flowrem_dat += fcval;
544*4882a593Smuzhiyun wake_up = 1;
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun break;
547*4882a593Smuzhiyun case 0x01: /* Stop outgoing data */
548*4882a593Smuzhiyun scp->flowrem_sw = DN_DONTSEND;
549*4882a593Smuzhiyun break;
550*4882a593Smuzhiyun case 0x02: /* Ok to start again */
551*4882a593Smuzhiyun scp->flowrem_sw = DN_SEND;
552*4882a593Smuzhiyun dn_nsp_output(sk);
553*4882a593Smuzhiyun wake_up = 1;
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun break;
556*4882a593Smuzhiyun case 0x04: /* Interrupt Request */
557*4882a593Smuzhiyun if (fcval > 0) {
558*4882a593Smuzhiyun scp->flowrem_oth += fcval;
559*4882a593Smuzhiyun wake_up = 1;
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun break;
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun if (wake_up && !sock_flag(sk, SOCK_DEAD))
564*4882a593Smuzhiyun sk->sk_state_change(sk);
565*4882a593Smuzhiyun }
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun dn_nsp_send_oth_ack(sk);
568*4882a593Smuzhiyun
569*4882a593Smuzhiyun out:
570*4882a593Smuzhiyun kfree_skb(skb);
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun /*
574*4882a593Smuzhiyun * Copy of sock_queue_rcv_skb (from sock.h) without
575*4882a593Smuzhiyun * bh_lock_sock() (its already held when this is called) which
576*4882a593Smuzhiyun * also allows data and other data to be queued to a socket.
577*4882a593Smuzhiyun */
dn_queue_skb(struct sock * sk,struct sk_buff * skb,int sig,struct sk_buff_head * queue)578*4882a593Smuzhiyun static __inline__ int dn_queue_skb(struct sock *sk, struct sk_buff *skb, int sig, struct sk_buff_head *queue)
579*4882a593Smuzhiyun {
580*4882a593Smuzhiyun int err;
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
583*4882a593Smuzhiyun number of warnings when compiling with -W --ANK
584*4882a593Smuzhiyun */
585*4882a593Smuzhiyun if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
586*4882a593Smuzhiyun (unsigned int)sk->sk_rcvbuf) {
587*4882a593Smuzhiyun err = -ENOMEM;
588*4882a593Smuzhiyun goto out;
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun err = sk_filter(sk, skb);
592*4882a593Smuzhiyun if (err)
593*4882a593Smuzhiyun goto out;
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun skb_set_owner_r(skb, sk);
596*4882a593Smuzhiyun skb_queue_tail(queue, skb);
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun if (!sock_flag(sk, SOCK_DEAD))
599*4882a593Smuzhiyun sk->sk_data_ready(sk);
600*4882a593Smuzhiyun out:
601*4882a593Smuzhiyun return err;
602*4882a593Smuzhiyun }
603*4882a593Smuzhiyun
dn_nsp_otherdata(struct sock * sk,struct sk_buff * skb)604*4882a593Smuzhiyun static void dn_nsp_otherdata(struct sock *sk, struct sk_buff *skb)
605*4882a593Smuzhiyun {
606*4882a593Smuzhiyun struct dn_scp *scp = DN_SK(sk);
607*4882a593Smuzhiyun unsigned short segnum;
608*4882a593Smuzhiyun struct dn_skb_cb *cb = DN_SKB_CB(skb);
609*4882a593Smuzhiyun int queued = 0;
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun if (skb->len < 2)
612*4882a593Smuzhiyun goto out;
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun cb->segnum = segnum = le16_to_cpu(*(__le16 *)skb->data);
615*4882a593Smuzhiyun skb_pull(skb, 2);
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun if (seq_next(scp->numoth_rcv, segnum)) {
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun if (dn_queue_skb(sk, skb, SIGURG, &scp->other_receive_queue) == 0) {
620*4882a593Smuzhiyun seq_add(&scp->numoth_rcv, 1);
621*4882a593Smuzhiyun scp->other_report = 0;
622*4882a593Smuzhiyun queued = 1;
623*4882a593Smuzhiyun }
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun dn_nsp_send_oth_ack(sk);
627*4882a593Smuzhiyun out:
628*4882a593Smuzhiyun if (!queued)
629*4882a593Smuzhiyun kfree_skb(skb);
630*4882a593Smuzhiyun }
631*4882a593Smuzhiyun
dn_nsp_data(struct sock * sk,struct sk_buff * skb)632*4882a593Smuzhiyun static void dn_nsp_data(struct sock *sk, struct sk_buff *skb)
633*4882a593Smuzhiyun {
634*4882a593Smuzhiyun int queued = 0;
635*4882a593Smuzhiyun unsigned short segnum;
636*4882a593Smuzhiyun struct dn_skb_cb *cb = DN_SKB_CB(skb);
637*4882a593Smuzhiyun struct dn_scp *scp = DN_SK(sk);
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun if (skb->len < 2)
640*4882a593Smuzhiyun goto out;
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun cb->segnum = segnum = le16_to_cpu(*(__le16 *)skb->data);
643*4882a593Smuzhiyun skb_pull(skb, 2);
644*4882a593Smuzhiyun
645*4882a593Smuzhiyun if (seq_next(scp->numdat_rcv, segnum)) {
646*4882a593Smuzhiyun if (dn_queue_skb(sk, skb, SIGIO, &sk->sk_receive_queue) == 0) {
647*4882a593Smuzhiyun seq_add(&scp->numdat_rcv, 1);
648*4882a593Smuzhiyun queued = 1;
649*4882a593Smuzhiyun }
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun if ((scp->flowloc_sw == DN_SEND) && dn_congested(sk)) {
652*4882a593Smuzhiyun scp->flowloc_sw = DN_DONTSEND;
653*4882a593Smuzhiyun dn_nsp_send_link(sk, DN_DONTSEND, 0);
654*4882a593Smuzhiyun }
655*4882a593Smuzhiyun }
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun dn_nsp_send_data_ack(sk);
658*4882a593Smuzhiyun out:
659*4882a593Smuzhiyun if (!queued)
660*4882a593Smuzhiyun kfree_skb(skb);
661*4882a593Smuzhiyun }
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun /*
664*4882a593Smuzhiyun * If one of our conninit messages is returned, this function
665*4882a593Smuzhiyun * deals with it. It puts the socket into the NO_COMMUNICATION
666*4882a593Smuzhiyun * state.
667*4882a593Smuzhiyun */
dn_returned_conn_init(struct sock * sk,struct sk_buff * skb)668*4882a593Smuzhiyun static void dn_returned_conn_init(struct sock *sk, struct sk_buff *skb)
669*4882a593Smuzhiyun {
670*4882a593Smuzhiyun struct dn_scp *scp = DN_SK(sk);
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun if (scp->state == DN_CI) {
673*4882a593Smuzhiyun scp->state = DN_NC;
674*4882a593Smuzhiyun sk->sk_state = TCP_CLOSE;
675*4882a593Smuzhiyun if (!sock_flag(sk, SOCK_DEAD))
676*4882a593Smuzhiyun sk->sk_state_change(sk);
677*4882a593Smuzhiyun }
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun kfree_skb(skb);
680*4882a593Smuzhiyun }
681*4882a593Smuzhiyun
dn_nsp_no_socket(struct sk_buff * skb,unsigned short reason)682*4882a593Smuzhiyun static int dn_nsp_no_socket(struct sk_buff *skb, unsigned short reason)
683*4882a593Smuzhiyun {
684*4882a593Smuzhiyun struct dn_skb_cb *cb = DN_SKB_CB(skb);
685*4882a593Smuzhiyun int ret = NET_RX_DROP;
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun /* Must not reply to returned packets */
688*4882a593Smuzhiyun if (cb->rt_flags & DN_RT_F_RTS)
689*4882a593Smuzhiyun goto out;
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun if ((reason != NSP_REASON_OK) && ((cb->nsp_flags & 0x0c) == 0x08)) {
692*4882a593Smuzhiyun switch (cb->nsp_flags & 0x70) {
693*4882a593Smuzhiyun case 0x10:
694*4882a593Smuzhiyun case 0x60: /* (Retransmitted) Connect Init */
695*4882a593Smuzhiyun dn_nsp_return_disc(skb, NSP_DISCINIT, reason);
696*4882a593Smuzhiyun ret = NET_RX_SUCCESS;
697*4882a593Smuzhiyun break;
698*4882a593Smuzhiyun case 0x20: /* Connect Confirm */
699*4882a593Smuzhiyun dn_nsp_return_disc(skb, NSP_DISCCONF, reason);
700*4882a593Smuzhiyun ret = NET_RX_SUCCESS;
701*4882a593Smuzhiyun break;
702*4882a593Smuzhiyun }
703*4882a593Smuzhiyun }
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun out:
706*4882a593Smuzhiyun kfree_skb(skb);
707*4882a593Smuzhiyun return ret;
708*4882a593Smuzhiyun }
709*4882a593Smuzhiyun
dn_nsp_rx_packet(struct net * net,struct sock * sk2,struct sk_buff * skb)710*4882a593Smuzhiyun static int dn_nsp_rx_packet(struct net *net, struct sock *sk2,
711*4882a593Smuzhiyun struct sk_buff *skb)
712*4882a593Smuzhiyun {
713*4882a593Smuzhiyun struct dn_skb_cb *cb = DN_SKB_CB(skb);
714*4882a593Smuzhiyun struct sock *sk = NULL;
715*4882a593Smuzhiyun unsigned char *ptr = (unsigned char *)skb->data;
716*4882a593Smuzhiyun unsigned short reason = NSP_REASON_NL;
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun if (!pskb_may_pull(skb, 2))
719*4882a593Smuzhiyun goto free_out;
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun skb_reset_transport_header(skb);
722*4882a593Smuzhiyun cb->nsp_flags = *ptr++;
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun if (decnet_debug_level & 2)
725*4882a593Smuzhiyun printk(KERN_DEBUG "dn_nsp_rx: Message type 0x%02x\n", (int)cb->nsp_flags);
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun if (cb->nsp_flags & 0x83)
728*4882a593Smuzhiyun goto free_out;
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun /*
731*4882a593Smuzhiyun * Filter out conninits and useless packet types
732*4882a593Smuzhiyun */
733*4882a593Smuzhiyun if ((cb->nsp_flags & 0x0c) == 0x08) {
734*4882a593Smuzhiyun switch (cb->nsp_flags & 0x70) {
735*4882a593Smuzhiyun case 0x00: /* NOP */
736*4882a593Smuzhiyun case 0x70: /* Reserved */
737*4882a593Smuzhiyun case 0x50: /* Reserved, Phase II node init */
738*4882a593Smuzhiyun goto free_out;
739*4882a593Smuzhiyun case 0x10:
740*4882a593Smuzhiyun case 0x60:
741*4882a593Smuzhiyun if (unlikely(cb->rt_flags & DN_RT_F_RTS))
742*4882a593Smuzhiyun goto free_out;
743*4882a593Smuzhiyun sk = dn_find_listener(skb, &reason);
744*4882a593Smuzhiyun goto got_it;
745*4882a593Smuzhiyun }
746*4882a593Smuzhiyun }
747*4882a593Smuzhiyun
748*4882a593Smuzhiyun if (!pskb_may_pull(skb, 3))
749*4882a593Smuzhiyun goto free_out;
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun /*
752*4882a593Smuzhiyun * Grab the destination address.
753*4882a593Smuzhiyun */
754*4882a593Smuzhiyun cb->dst_port = *(__le16 *)ptr;
755*4882a593Smuzhiyun cb->src_port = 0;
756*4882a593Smuzhiyun ptr += 2;
757*4882a593Smuzhiyun
758*4882a593Smuzhiyun /*
759*4882a593Smuzhiyun * If not a connack, grab the source address too.
760*4882a593Smuzhiyun */
761*4882a593Smuzhiyun if (pskb_may_pull(skb, 5)) {
762*4882a593Smuzhiyun cb->src_port = *(__le16 *)ptr;
763*4882a593Smuzhiyun ptr += 2;
764*4882a593Smuzhiyun skb_pull(skb, 5);
765*4882a593Smuzhiyun }
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun /*
768*4882a593Smuzhiyun * Returned packets...
769*4882a593Smuzhiyun * Swap src & dst and look up in the normal way.
770*4882a593Smuzhiyun */
771*4882a593Smuzhiyun if (unlikely(cb->rt_flags & DN_RT_F_RTS)) {
772*4882a593Smuzhiyun swap(cb->dst_port, cb->src_port);
773*4882a593Smuzhiyun swap(cb->dst, cb->src);
774*4882a593Smuzhiyun }
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun /*
777*4882a593Smuzhiyun * Find the socket to which this skb is destined.
778*4882a593Smuzhiyun */
779*4882a593Smuzhiyun sk = dn_find_by_skb(skb);
780*4882a593Smuzhiyun got_it:
781*4882a593Smuzhiyun if (sk != NULL) {
782*4882a593Smuzhiyun struct dn_scp *scp = DN_SK(sk);
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun /* Reset backoff */
785*4882a593Smuzhiyun scp->nsp_rxtshift = 0;
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun /*
788*4882a593Smuzhiyun * We linearize everything except data segments here.
789*4882a593Smuzhiyun */
790*4882a593Smuzhiyun if (cb->nsp_flags & ~0x60) {
791*4882a593Smuzhiyun if (unlikely(skb_linearize(skb)))
792*4882a593Smuzhiyun goto free_out;
793*4882a593Smuzhiyun }
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun return sk_receive_skb(sk, skb, 0);
796*4882a593Smuzhiyun }
797*4882a593Smuzhiyun
798*4882a593Smuzhiyun return dn_nsp_no_socket(skb, reason);
799*4882a593Smuzhiyun
800*4882a593Smuzhiyun free_out:
801*4882a593Smuzhiyun kfree_skb(skb);
802*4882a593Smuzhiyun return NET_RX_DROP;
803*4882a593Smuzhiyun }
804*4882a593Smuzhiyun
dn_nsp_rx(struct sk_buff * skb)805*4882a593Smuzhiyun int dn_nsp_rx(struct sk_buff *skb)
806*4882a593Smuzhiyun {
807*4882a593Smuzhiyun return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_IN,
808*4882a593Smuzhiyun &init_net, NULL, skb, skb->dev, NULL,
809*4882a593Smuzhiyun dn_nsp_rx_packet);
810*4882a593Smuzhiyun }
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun /*
813*4882a593Smuzhiyun * This is the main receive routine for sockets. It is called
814*4882a593Smuzhiyun * from the above when the socket is not busy, and also from
815*4882a593Smuzhiyun * sock_release() when there is a backlog queued up.
816*4882a593Smuzhiyun */
dn_nsp_backlog_rcv(struct sock * sk,struct sk_buff * skb)817*4882a593Smuzhiyun int dn_nsp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
818*4882a593Smuzhiyun {
819*4882a593Smuzhiyun struct dn_scp *scp = DN_SK(sk);
820*4882a593Smuzhiyun struct dn_skb_cb *cb = DN_SKB_CB(skb);
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun if (cb->rt_flags & DN_RT_F_RTS) {
823*4882a593Smuzhiyun if (cb->nsp_flags == 0x18 || cb->nsp_flags == 0x68)
824*4882a593Smuzhiyun dn_returned_conn_init(sk, skb);
825*4882a593Smuzhiyun else
826*4882a593Smuzhiyun kfree_skb(skb);
827*4882a593Smuzhiyun return NET_RX_SUCCESS;
828*4882a593Smuzhiyun }
829*4882a593Smuzhiyun
830*4882a593Smuzhiyun /*
831*4882a593Smuzhiyun * Control packet.
832*4882a593Smuzhiyun */
833*4882a593Smuzhiyun if ((cb->nsp_flags & 0x0c) == 0x08) {
834*4882a593Smuzhiyun switch (cb->nsp_flags & 0x70) {
835*4882a593Smuzhiyun case 0x10:
836*4882a593Smuzhiyun case 0x60:
837*4882a593Smuzhiyun dn_nsp_conn_init(sk, skb);
838*4882a593Smuzhiyun break;
839*4882a593Smuzhiyun case 0x20:
840*4882a593Smuzhiyun dn_nsp_conn_conf(sk, skb);
841*4882a593Smuzhiyun break;
842*4882a593Smuzhiyun case 0x30:
843*4882a593Smuzhiyun dn_nsp_disc_init(sk, skb);
844*4882a593Smuzhiyun break;
845*4882a593Smuzhiyun case 0x40:
846*4882a593Smuzhiyun dn_nsp_disc_conf(sk, skb);
847*4882a593Smuzhiyun break;
848*4882a593Smuzhiyun }
849*4882a593Smuzhiyun
850*4882a593Smuzhiyun } else if (cb->nsp_flags == 0x24) {
851*4882a593Smuzhiyun /*
852*4882a593Smuzhiyun * Special for connacks, 'cos they don't have
853*4882a593Smuzhiyun * ack data or ack otherdata info.
854*4882a593Smuzhiyun */
855*4882a593Smuzhiyun dn_nsp_conn_ack(sk, skb);
856*4882a593Smuzhiyun } else {
857*4882a593Smuzhiyun int other = 1;
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun /* both data and ack frames can kick a CC socket into RUN */
860*4882a593Smuzhiyun if ((scp->state == DN_CC) && !sock_flag(sk, SOCK_DEAD)) {
861*4882a593Smuzhiyun scp->state = DN_RUN;
862*4882a593Smuzhiyun sk->sk_state = TCP_ESTABLISHED;
863*4882a593Smuzhiyun sk->sk_state_change(sk);
864*4882a593Smuzhiyun }
865*4882a593Smuzhiyun
866*4882a593Smuzhiyun if ((cb->nsp_flags & 0x1c) == 0)
867*4882a593Smuzhiyun other = 0;
868*4882a593Smuzhiyun if (cb->nsp_flags == 0x04)
869*4882a593Smuzhiyun other = 0;
870*4882a593Smuzhiyun
871*4882a593Smuzhiyun /*
872*4882a593Smuzhiyun * Read out ack data here, this applies equally
873*4882a593Smuzhiyun * to data, other data, link serivce and both
874*4882a593Smuzhiyun * ack data and ack otherdata.
875*4882a593Smuzhiyun */
876*4882a593Smuzhiyun dn_process_ack(sk, skb, other);
877*4882a593Smuzhiyun
878*4882a593Smuzhiyun /*
879*4882a593Smuzhiyun * If we've some sort of data here then call a
880*4882a593Smuzhiyun * suitable routine for dealing with it, otherwise
881*4882a593Smuzhiyun * the packet is an ack and can be discarded.
882*4882a593Smuzhiyun */
883*4882a593Smuzhiyun if ((cb->nsp_flags & 0x0c) == 0) {
884*4882a593Smuzhiyun
885*4882a593Smuzhiyun if (scp->state != DN_RUN)
886*4882a593Smuzhiyun goto free_out;
887*4882a593Smuzhiyun
888*4882a593Smuzhiyun switch (cb->nsp_flags) {
889*4882a593Smuzhiyun case 0x10: /* LS */
890*4882a593Smuzhiyun dn_nsp_linkservice(sk, skb);
891*4882a593Smuzhiyun break;
892*4882a593Smuzhiyun case 0x30: /* OD */
893*4882a593Smuzhiyun dn_nsp_otherdata(sk, skb);
894*4882a593Smuzhiyun break;
895*4882a593Smuzhiyun default:
896*4882a593Smuzhiyun dn_nsp_data(sk, skb);
897*4882a593Smuzhiyun }
898*4882a593Smuzhiyun
899*4882a593Smuzhiyun } else { /* Ack, chuck it out here */
900*4882a593Smuzhiyun free_out:
901*4882a593Smuzhiyun kfree_skb(skb);
902*4882a593Smuzhiyun }
903*4882a593Smuzhiyun }
904*4882a593Smuzhiyun
905*4882a593Smuzhiyun return NET_RX_SUCCESS;
906*4882a593Smuzhiyun }
907