xref: /openbmc/linux/net/rose/af_rose.c (revision 360823a09426347ea8f232b0b0b5156d0aed0302)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
51da177e4SLinus Torvalds  * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
61da177e4SLinus Torvalds  * Copyright (C) Terry Dawson VK2KTJ (terry@animats.net)
71da177e4SLinus Torvalds  * Copyright (C) Tomi Manninen OH2BNS (oh2bns@sral.fi)
81da177e4SLinus Torvalds  */
94fc268d2SRandy Dunlap 
104fc268d2SRandy Dunlap #include <linux/capability.h>
111da177e4SLinus Torvalds #include <linux/module.h>
121da177e4SLinus Torvalds #include <linux/moduleparam.h>
131da177e4SLinus Torvalds #include <linux/init.h>
141da177e4SLinus Torvalds #include <linux/errno.h>
151da177e4SLinus Torvalds #include <linux/types.h>
161da177e4SLinus Torvalds #include <linux/socket.h>
171da177e4SLinus Torvalds #include <linux/in.h>
185a0e3ad6STejun Heo #include <linux/slab.h>
191da177e4SLinus Torvalds #include <linux/kernel.h>
203f07c014SIngo Molnar #include <linux/sched/signal.h>
211da177e4SLinus Torvalds #include <linux/spinlock.h>
221da177e4SLinus Torvalds #include <linux/timer.h>
231da177e4SLinus Torvalds #include <linux/string.h>
241da177e4SLinus Torvalds #include <linux/sockios.h>
251da177e4SLinus Torvalds #include <linux/net.h>
261da177e4SLinus Torvalds #include <linux/stat.h>
27457c4cbcSEric W. Biederman #include <net/net_namespace.h>
281da177e4SLinus Torvalds #include <net/ax25.h>
291da177e4SLinus Torvalds #include <linux/inet.h>
301da177e4SLinus Torvalds #include <linux/netdevice.h>
311da177e4SLinus Torvalds #include <linux/if_arp.h>
321da177e4SLinus Torvalds #include <linux/skbuff.h>
331da177e4SLinus Torvalds #include <net/sock.h>
347c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
351da177e4SLinus Torvalds #include <linux/fcntl.h>
361da177e4SLinus Torvalds #include <linux/termios.h>
371da177e4SLinus Torvalds #include <linux/mm.h>
381da177e4SLinus Torvalds #include <linux/interrupt.h>
391da177e4SLinus Torvalds #include <linux/notifier.h>
401da177e4SLinus Torvalds #include <net/rose.h>
411da177e4SLinus Torvalds #include <linux/proc_fs.h>
421da177e4SLinus Torvalds #include <linux/seq_file.h>
43c752f073SArnaldo Carvalho de Melo #include <net/tcp_states.h>
441da177e4SLinus Torvalds #include <net/ip.h>
451da177e4SLinus Torvalds #include <net/arp.h>
461da177e4SLinus Torvalds 
471da177e4SLinus Torvalds static int rose_ndevs = 10;
481da177e4SLinus Torvalds 
491da177e4SLinus Torvalds int sysctl_rose_restart_request_timeout = ROSE_DEFAULT_T0;
501da177e4SLinus Torvalds int sysctl_rose_call_request_timeout    = ROSE_DEFAULT_T1;
511da177e4SLinus Torvalds int sysctl_rose_reset_request_timeout   = ROSE_DEFAULT_T2;
521da177e4SLinus Torvalds int sysctl_rose_clear_request_timeout   = ROSE_DEFAULT_T3;
531da177e4SLinus Torvalds int sysctl_rose_no_activity_timeout     = ROSE_DEFAULT_IDLE;
541da177e4SLinus Torvalds int sysctl_rose_ack_hold_back_timeout   = ROSE_DEFAULT_HB;
551da177e4SLinus Torvalds int sysctl_rose_routing_control         = ROSE_DEFAULT_ROUTING;
561da177e4SLinus Torvalds int sysctl_rose_link_fail_timeout       = ROSE_DEFAULT_FAIL_TIMEOUT;
571da177e4SLinus Torvalds int sysctl_rose_maximum_vcs             = ROSE_DEFAULT_MAXVC;
581da177e4SLinus Torvalds int sysctl_rose_window_size             = ROSE_DEFAULT_WINDOW_SIZE;
591da177e4SLinus Torvalds 
601da177e4SLinus Torvalds static HLIST_HEAD(rose_list);
611da177e4SLinus Torvalds static DEFINE_SPINLOCK(rose_list_lock);
621da177e4SLinus Torvalds 
635708e868SAlexey Dobriyan static const struct proto_ops rose_proto_ops;
641da177e4SLinus Torvalds 
651da177e4SLinus Torvalds ax25_address rose_callsign;
661da177e4SLinus Torvalds 
671da177e4SLinus Torvalds /*
681a33e10eSCong Wang  * ROSE network devices are virtual network devices encapsulating ROSE
691a33e10eSCong Wang  * frames into AX.25 which will be sent through an AX.25 device, so form a
701a33e10eSCong Wang  * special "super class" of normal net devices; split their locks off into a
711a33e10eSCong Wang  * separate class since they always nest.
721a33e10eSCong Wang  */
731a33e10eSCong Wang static struct lock_class_key rose_netdev_xmit_lock_key;
74845e0ebbSCong Wang static struct lock_class_key rose_netdev_addr_lock_key;
751a33e10eSCong Wang 
rose_set_lockdep_one(struct net_device * dev,struct netdev_queue * txq,void * _unused)761a33e10eSCong Wang static void rose_set_lockdep_one(struct net_device *dev,
771a33e10eSCong Wang 				 struct netdev_queue *txq,
781a33e10eSCong Wang 				 void *_unused)
791a33e10eSCong Wang {
801a33e10eSCong Wang 	lockdep_set_class(&txq->_xmit_lock, &rose_netdev_xmit_lock_key);
811a33e10eSCong Wang }
821a33e10eSCong Wang 
rose_set_lockdep_key(struct net_device * dev)831a33e10eSCong Wang static void rose_set_lockdep_key(struct net_device *dev)
841a33e10eSCong Wang {
85845e0ebbSCong Wang 	lockdep_set_class(&dev->addr_list_lock, &rose_netdev_addr_lock_key);
861a33e10eSCong Wang 	netdev_for_each_tx_queue(dev, rose_set_lockdep_one, NULL);
871a33e10eSCong Wang }
881a33e10eSCong Wang 
891a33e10eSCong Wang /*
901da177e4SLinus Torvalds  *	Convert a ROSE address into text.
911da177e4SLinus Torvalds  */
rose2asc(char * buf,const rose_address * addr)92dcf777f6SRalf Baechle char *rose2asc(char *buf, const rose_address *addr)
931da177e4SLinus Torvalds {
941da177e4SLinus Torvalds 	if (addr->rose_addr[0] == 0x00 && addr->rose_addr[1] == 0x00 &&
951da177e4SLinus Torvalds 	    addr->rose_addr[2] == 0x00 && addr->rose_addr[3] == 0x00 &&
961da177e4SLinus Torvalds 	    addr->rose_addr[4] == 0x00) {
97dcf777f6SRalf Baechle 		strcpy(buf, "*");
981da177e4SLinus Torvalds 	} else {
99dcf777f6SRalf Baechle 		sprintf(buf, "%02X%02X%02X%02X%02X", addr->rose_addr[0] & 0xFF,
1001da177e4SLinus Torvalds 						addr->rose_addr[1] & 0xFF,
1011da177e4SLinus Torvalds 						addr->rose_addr[2] & 0xFF,
1021da177e4SLinus Torvalds 						addr->rose_addr[3] & 0xFF,
1031da177e4SLinus Torvalds 						addr->rose_addr[4] & 0xFF);
1041da177e4SLinus Torvalds 	}
1051da177e4SLinus Torvalds 
106dcf777f6SRalf Baechle 	return buf;
1071da177e4SLinus Torvalds }
1081da177e4SLinus Torvalds 
1091da177e4SLinus Torvalds /*
1101da177e4SLinus Torvalds  *	Compare two ROSE addresses, 0 == equal.
1111da177e4SLinus Torvalds  */
rosecmp(const rose_address * addr1,const rose_address * addr2)112db957324SJakub Kicinski int rosecmp(const rose_address *addr1, const rose_address *addr2)
1131da177e4SLinus Torvalds {
1141da177e4SLinus Torvalds 	int i;
1151da177e4SLinus Torvalds 
1161da177e4SLinus Torvalds 	for (i = 0; i < 5; i++)
1171da177e4SLinus Torvalds 		if (addr1->rose_addr[i] != addr2->rose_addr[i])
1181da177e4SLinus Torvalds 			return 1;
1191da177e4SLinus Torvalds 
1201da177e4SLinus Torvalds 	return 0;
1211da177e4SLinus Torvalds }
1221da177e4SLinus Torvalds 
1231da177e4SLinus Torvalds /*
1241da177e4SLinus Torvalds  *	Compare two ROSE addresses for only mask digits, 0 == equal.
1251da177e4SLinus Torvalds  */
rosecmpm(const rose_address * addr1,const rose_address * addr2,unsigned short mask)126db957324SJakub Kicinski int rosecmpm(const rose_address *addr1, const rose_address *addr2,
127db957324SJakub Kicinski 	     unsigned short mask)
1281da177e4SLinus Torvalds {
12995b7d924SEric Dumazet 	unsigned int i, j;
1301da177e4SLinus Torvalds 
1311da177e4SLinus Torvalds 	if (mask > 10)
1321da177e4SLinus Torvalds 		return 1;
1331da177e4SLinus Torvalds 
1341da177e4SLinus Torvalds 	for (i = 0; i < mask; i++) {
1351da177e4SLinus Torvalds 		j = i / 2;
1361da177e4SLinus Torvalds 
1371da177e4SLinus Torvalds 		if ((i % 2) != 0) {
1381da177e4SLinus Torvalds 			if ((addr1->rose_addr[j] & 0x0F) != (addr2->rose_addr[j] & 0x0F))
1391da177e4SLinus Torvalds 				return 1;
1401da177e4SLinus Torvalds 		} else {
1411da177e4SLinus Torvalds 			if ((addr1->rose_addr[j] & 0xF0) != (addr2->rose_addr[j] & 0xF0))
1421da177e4SLinus Torvalds 				return 1;
1431da177e4SLinus Torvalds 		}
1441da177e4SLinus Torvalds 	}
1451da177e4SLinus Torvalds 
1461da177e4SLinus Torvalds 	return 0;
1471da177e4SLinus Torvalds }
1481da177e4SLinus Torvalds 
1491da177e4SLinus Torvalds /*
1501da177e4SLinus Torvalds  *	Socket removal during an interrupt is now safe.
1511da177e4SLinus Torvalds  */
rose_remove_socket(struct sock * sk)1521da177e4SLinus Torvalds static void rose_remove_socket(struct sock *sk)
1531da177e4SLinus Torvalds {
1541da177e4SLinus Torvalds 	spin_lock_bh(&rose_list_lock);
1551da177e4SLinus Torvalds 	sk_del_node_init(sk);
1561da177e4SLinus Torvalds 	spin_unlock_bh(&rose_list_lock);
1571da177e4SLinus Torvalds }
1581da177e4SLinus Torvalds 
1591da177e4SLinus Torvalds /*
1601da177e4SLinus Torvalds  *	Kill all bound sockets on a broken link layer connection to a
1611da177e4SLinus Torvalds  *	particular neighbour.
1621da177e4SLinus Torvalds  */
rose_kill_by_neigh(struct rose_neigh * neigh)1631da177e4SLinus Torvalds void rose_kill_by_neigh(struct rose_neigh *neigh)
1641da177e4SLinus Torvalds {
1651da177e4SLinus Torvalds 	struct sock *s;
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds 	spin_lock_bh(&rose_list_lock);
168b67bfe0dSSasha Levin 	sk_for_each(s, &rose_list) {
1691da177e4SLinus Torvalds 		struct rose_sock *rose = rose_sk(s);
1701da177e4SLinus Torvalds 
1711da177e4SLinus Torvalds 		if (rose->neighbour == neigh) {
1721da177e4SLinus Torvalds 			rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0);
1731da177e4SLinus Torvalds 			rose->neighbour->use--;
1741da177e4SLinus Torvalds 			rose->neighbour = NULL;
1751da177e4SLinus Torvalds 		}
1761da177e4SLinus Torvalds 	}
1771da177e4SLinus Torvalds 	spin_unlock_bh(&rose_list_lock);
1781da177e4SLinus Torvalds }
1791da177e4SLinus Torvalds 
1801da177e4SLinus Torvalds /*
1811da177e4SLinus Torvalds  *	Kill all bound sockets on a dropped device.
1821da177e4SLinus Torvalds  */
rose_kill_by_device(struct net_device * dev)1831da177e4SLinus Torvalds static void rose_kill_by_device(struct net_device *dev)
1841da177e4SLinus Torvalds {
185ffced266SEric Dumazet 	struct sock *sk, *array[16];
186ffced266SEric Dumazet 	struct rose_sock *rose;
187ffced266SEric Dumazet 	bool rescan;
188ffced266SEric Dumazet 	int i, cnt;
1891da177e4SLinus Torvalds 
190ffced266SEric Dumazet start:
191ffced266SEric Dumazet 	rescan = false;
192ffced266SEric Dumazet 	cnt = 0;
1931da177e4SLinus Torvalds 	spin_lock_bh(&rose_list_lock);
194ffced266SEric Dumazet 	sk_for_each(sk, &rose_list) {
195ffced266SEric Dumazet 		rose = rose_sk(sk);
1961da177e4SLinus Torvalds 		if (rose->device == dev) {
197ffced266SEric Dumazet 			if (cnt == ARRAY_SIZE(array)) {
198ffced266SEric Dumazet 				rescan = true;
199ffced266SEric Dumazet 				break;
200ffced266SEric Dumazet 			}
201ffced266SEric Dumazet 			sock_hold(sk);
202ffced266SEric Dumazet 			array[cnt++] = sk;
203ffced266SEric Dumazet 		}
204ffced266SEric Dumazet 	}
205ffced266SEric Dumazet 	spin_unlock_bh(&rose_list_lock);
206ffced266SEric Dumazet 
207ffced266SEric Dumazet 	for (i = 0; i < cnt; i++) {
208ffced266SEric Dumazet 		sk = array[cnt];
209ffced266SEric Dumazet 		rose = rose_sk(sk);
210ffced266SEric Dumazet 		lock_sock(sk);
211ffced266SEric Dumazet 		spin_lock_bh(&rose_list_lock);
212ffced266SEric Dumazet 		if (rose->device == dev) {
213ffced266SEric Dumazet 			rose_disconnect(sk, ENETUNREACH, ROSE_OUT_OF_ORDER, 0);
214d496f784SRalf Baechle 			if (rose->neighbour)
2151da177e4SLinus Torvalds 				rose->neighbour->use--;
2162df91e39SEric Dumazet 			netdev_put(rose->device, &rose->dev_tracker);
2171da177e4SLinus Torvalds 			rose->device = NULL;
2181da177e4SLinus Torvalds 		}
2191da177e4SLinus Torvalds 		spin_unlock_bh(&rose_list_lock);
220ffced266SEric Dumazet 		release_sock(sk);
221ffced266SEric Dumazet 		sock_put(sk);
222ffced266SEric Dumazet 		cond_resched();
223ffced266SEric Dumazet 	}
224ffced266SEric Dumazet 	if (rescan)
225ffced266SEric Dumazet 		goto start;
2261da177e4SLinus Torvalds }
2271da177e4SLinus Torvalds 
2281da177e4SLinus Torvalds /*
2291da177e4SLinus Torvalds  *	Handle device status changes.
2301da177e4SLinus Torvalds  */
rose_device_event(struct notifier_block * this,unsigned long event,void * ptr)231351638e7SJiri Pirko static int rose_device_event(struct notifier_block *this,
232351638e7SJiri Pirko 			     unsigned long event, void *ptr)
2331da177e4SLinus Torvalds {
234351638e7SJiri Pirko 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
2351da177e4SLinus Torvalds 
236721499e8SYOSHIFUJI Hideaki 	if (!net_eq(dev_net(dev), &init_net))
237e9dc8653SEric W. Biederman 		return NOTIFY_DONE;
238e9dc8653SEric W. Biederman 
2391da177e4SLinus Torvalds 	if (event != NETDEV_DOWN)
2401da177e4SLinus Torvalds 		return NOTIFY_DONE;
2411da177e4SLinus Torvalds 
2421da177e4SLinus Torvalds 	switch (dev->type) {
2431da177e4SLinus Torvalds 	case ARPHRD_ROSE:
2441da177e4SLinus Torvalds 		rose_kill_by_device(dev);
2451da177e4SLinus Torvalds 		break;
2461da177e4SLinus Torvalds 	case ARPHRD_AX25:
2471da177e4SLinus Torvalds 		rose_link_device_down(dev);
2481da177e4SLinus Torvalds 		rose_rt_device_down(dev);
2491da177e4SLinus Torvalds 		break;
2501da177e4SLinus Torvalds 	}
2511da177e4SLinus Torvalds 
2521da177e4SLinus Torvalds 	return NOTIFY_DONE;
2531da177e4SLinus Torvalds }
2541da177e4SLinus Torvalds 
2551da177e4SLinus Torvalds /*
2561da177e4SLinus Torvalds  *	Add a socket to the bound sockets list.
2571da177e4SLinus Torvalds  */
rose_insert_socket(struct sock * sk)2581da177e4SLinus Torvalds static void rose_insert_socket(struct sock *sk)
2591da177e4SLinus Torvalds {
2601da177e4SLinus Torvalds 
2611da177e4SLinus Torvalds 	spin_lock_bh(&rose_list_lock);
2621da177e4SLinus Torvalds 	sk_add_node(sk, &rose_list);
2631da177e4SLinus Torvalds 	spin_unlock_bh(&rose_list_lock);
2641da177e4SLinus Torvalds }
2651da177e4SLinus Torvalds 
2661da177e4SLinus Torvalds /*
2671da177e4SLinus Torvalds  *	Find a socket that wants to accept the Call Request we just
2681da177e4SLinus Torvalds  *	received.
2691da177e4SLinus Torvalds  */
rose_find_listener(rose_address * addr,ax25_address * call)2701da177e4SLinus Torvalds static struct sock *rose_find_listener(rose_address *addr, ax25_address *call)
2711da177e4SLinus Torvalds {
2721da177e4SLinus Torvalds 	struct sock *s;
2731da177e4SLinus Torvalds 
2741da177e4SLinus Torvalds 	spin_lock_bh(&rose_list_lock);
275b67bfe0dSSasha Levin 	sk_for_each(s, &rose_list) {
2761da177e4SLinus Torvalds 		struct rose_sock *rose = rose_sk(s);
2771da177e4SLinus Torvalds 
2781da177e4SLinus Torvalds 		if (!rosecmp(&rose->source_addr, addr) &&
2791da177e4SLinus Torvalds 		    !ax25cmp(&rose->source_call, call) &&
2801da177e4SLinus Torvalds 		    !rose->source_ndigis && s->sk_state == TCP_LISTEN)
2811da177e4SLinus Torvalds 			goto found;
2821da177e4SLinus Torvalds 	}
2831da177e4SLinus Torvalds 
284b67bfe0dSSasha Levin 	sk_for_each(s, &rose_list) {
2851da177e4SLinus Torvalds 		struct rose_sock *rose = rose_sk(s);
2861da177e4SLinus Torvalds 
2871da177e4SLinus Torvalds 		if (!rosecmp(&rose->source_addr, addr) &&
2881da177e4SLinus Torvalds 		    !ax25cmp(&rose->source_call, &null_ax25_address) &&
2891da177e4SLinus Torvalds 		    s->sk_state == TCP_LISTEN)
2901da177e4SLinus Torvalds 			goto found;
2911da177e4SLinus Torvalds 	}
2921da177e4SLinus Torvalds 	s = NULL;
2931da177e4SLinus Torvalds found:
2941da177e4SLinus Torvalds 	spin_unlock_bh(&rose_list_lock);
2951da177e4SLinus Torvalds 	return s;
2961da177e4SLinus Torvalds }
2971da177e4SLinus Torvalds 
2981da177e4SLinus Torvalds /*
2991da177e4SLinus Torvalds  *	Find a connected ROSE socket given my LCI and device.
3001da177e4SLinus Torvalds  */
rose_find_socket(unsigned int lci,struct rose_neigh * neigh)3011da177e4SLinus Torvalds struct sock *rose_find_socket(unsigned int lci, struct rose_neigh *neigh)
3021da177e4SLinus Torvalds {
3031da177e4SLinus Torvalds 	struct sock *s;
3041da177e4SLinus Torvalds 
3051da177e4SLinus Torvalds 	spin_lock_bh(&rose_list_lock);
306b67bfe0dSSasha Levin 	sk_for_each(s, &rose_list) {
3071da177e4SLinus Torvalds 		struct rose_sock *rose = rose_sk(s);
3081da177e4SLinus Torvalds 
3091da177e4SLinus Torvalds 		if (rose->lci == lci && rose->neighbour == neigh)
3101da177e4SLinus Torvalds 			goto found;
3111da177e4SLinus Torvalds 	}
3121da177e4SLinus Torvalds 	s = NULL;
3131da177e4SLinus Torvalds found:
3141da177e4SLinus Torvalds 	spin_unlock_bh(&rose_list_lock);
3151da177e4SLinus Torvalds 	return s;
3161da177e4SLinus Torvalds }
3171da177e4SLinus Torvalds 
3181da177e4SLinus Torvalds /*
3191da177e4SLinus Torvalds  *	Find a unique LCI for a given device.
3201da177e4SLinus Torvalds  */
rose_new_lci(struct rose_neigh * neigh)3211da177e4SLinus Torvalds unsigned int rose_new_lci(struct rose_neigh *neigh)
3221da177e4SLinus Torvalds {
3231da177e4SLinus Torvalds 	int lci;
3241da177e4SLinus Torvalds 
3251da177e4SLinus Torvalds 	if (neigh->dce_mode) {
3261da177e4SLinus Torvalds 		for (lci = 1; lci <= sysctl_rose_maximum_vcs; lci++)
3271da177e4SLinus Torvalds 			if (rose_find_socket(lci, neigh) == NULL && rose_route_free_lci(lci, neigh) == NULL)
3281da177e4SLinus Torvalds 				return lci;
3291da177e4SLinus Torvalds 	} else {
3301da177e4SLinus Torvalds 		for (lci = sysctl_rose_maximum_vcs; lci > 0; lci--)
3311da177e4SLinus Torvalds 			if (rose_find_socket(lci, neigh) == NULL && rose_route_free_lci(lci, neigh) == NULL)
3321da177e4SLinus Torvalds 				return lci;
3331da177e4SLinus Torvalds 	}
3341da177e4SLinus Torvalds 
3351da177e4SLinus Torvalds 	return 0;
3361da177e4SLinus Torvalds }
3371da177e4SLinus Torvalds 
3381da177e4SLinus Torvalds /*
3391da177e4SLinus Torvalds  *	Deferred destroy.
3401da177e4SLinus Torvalds  */
3411da177e4SLinus Torvalds void rose_destroy_socket(struct sock *);
3421da177e4SLinus Torvalds 
3431da177e4SLinus Torvalds /*
3441da177e4SLinus Torvalds  *	Handler for deferred kills.
3451da177e4SLinus Torvalds  */
rose_destroy_timer(struct timer_list * t)3464966babdSKees Cook static void rose_destroy_timer(struct timer_list *t)
3471da177e4SLinus Torvalds {
3484966babdSKees Cook 	struct sock *sk = from_timer(sk, t, sk_timer);
3494966babdSKees Cook 
3504966babdSKees Cook 	rose_destroy_socket(sk);
3511da177e4SLinus Torvalds }
3521da177e4SLinus Torvalds 
3531da177e4SLinus Torvalds /*
3541da177e4SLinus Torvalds  *	This is called from user mode and the timers. Thus it protects itself
3551da177e4SLinus Torvalds  *	against interrupt users but doesn't worry about being called during
3561da177e4SLinus Torvalds  *	work.  Once it is removed from the queue no interrupt or bottom half
3571da177e4SLinus Torvalds  *	will touch it and we are (fairly 8-) ) safe.
3581da177e4SLinus Torvalds  */
rose_destroy_socket(struct sock * sk)3591da177e4SLinus Torvalds void rose_destroy_socket(struct sock *sk)
3601da177e4SLinus Torvalds {
3611da177e4SLinus Torvalds 	struct sk_buff *skb;
3621da177e4SLinus Torvalds 
3631da177e4SLinus Torvalds 	rose_remove_socket(sk);
3641da177e4SLinus Torvalds 	rose_stop_heartbeat(sk);
3651da177e4SLinus Torvalds 	rose_stop_idletimer(sk);
3661da177e4SLinus Torvalds 	rose_stop_timer(sk);
3671da177e4SLinus Torvalds 
3681da177e4SLinus Torvalds 	rose_clear_queues(sk);		/* Flush the queues */
3691da177e4SLinus Torvalds 
3701da177e4SLinus Torvalds 	while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
3711da177e4SLinus Torvalds 		if (skb->sk != sk) {	/* A pending connection */
3721da177e4SLinus Torvalds 			/* Queue the unaccepted socket for death */
3731da177e4SLinus Torvalds 			sock_set_flag(skb->sk, SOCK_DEAD);
3741da177e4SLinus Torvalds 			rose_start_heartbeat(skb->sk);
3751da177e4SLinus Torvalds 			rose_sk(skb->sk)->state = ROSE_STATE_0;
3761da177e4SLinus Torvalds 		}
3771da177e4SLinus Torvalds 
3781da177e4SLinus Torvalds 		kfree_skb(skb);
3791da177e4SLinus Torvalds 	}
3801da177e4SLinus Torvalds 
381c564039fSEric Dumazet 	if (sk_has_allocations(sk)) {
3821da177e4SLinus Torvalds 		/* Defer: outstanding buffers */
3834966babdSKees Cook 		timer_setup(&sk->sk_timer, rose_destroy_timer, 0);
3841da177e4SLinus Torvalds 		sk->sk_timer.expires  = jiffies + 10 * HZ;
3851da177e4SLinus Torvalds 		add_timer(&sk->sk_timer);
3861da177e4SLinus Torvalds 	} else
3871da177e4SLinus Torvalds 		sock_put(sk);
3881da177e4SLinus Torvalds }
3891da177e4SLinus Torvalds 
3901da177e4SLinus Torvalds /*
3911da177e4SLinus Torvalds  *	Handling for system calls applied via the various interfaces to a
3921da177e4SLinus Torvalds  *	ROSE socket object.
3931da177e4SLinus Torvalds  */
3941da177e4SLinus Torvalds 
rose_setsockopt(struct socket * sock,int level,int optname,sockptr_t optval,unsigned int optlen)3951da177e4SLinus Torvalds static int rose_setsockopt(struct socket *sock, int level, int optname,
396a7b75c5aSChristoph Hellwig 		sockptr_t optval, unsigned int optlen)
3971da177e4SLinus Torvalds {
3981da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
3991da177e4SLinus Torvalds 	struct rose_sock *rose = rose_sk(sk);
400352daa50SNikita Zhandarovich 	unsigned int opt;
4011da177e4SLinus Torvalds 
4021da177e4SLinus Torvalds 	if (level != SOL_ROSE)
4031da177e4SLinus Torvalds 		return -ENOPROTOOPT;
4041da177e4SLinus Torvalds 
405352daa50SNikita Zhandarovich 	if (optlen < sizeof(unsigned int))
4061da177e4SLinus Torvalds 		return -EINVAL;
4071da177e4SLinus Torvalds 
408352daa50SNikita Zhandarovich 	if (copy_from_sockptr(&opt, optval, sizeof(unsigned int)))
4091da177e4SLinus Torvalds 		return -EFAULT;
4101da177e4SLinus Torvalds 
4111da177e4SLinus Torvalds 	switch (optname) {
4121da177e4SLinus Torvalds 	case ROSE_DEFER:
4131da177e4SLinus Torvalds 		rose->defer = opt ? 1 : 0;
4141da177e4SLinus Torvalds 		return 0;
4151da177e4SLinus Torvalds 
4161da177e4SLinus Torvalds 	case ROSE_T1:
417352daa50SNikita Zhandarovich 		if (opt < 1 || opt > UINT_MAX / HZ)
4181da177e4SLinus Torvalds 			return -EINVAL;
4191da177e4SLinus Torvalds 		rose->t1 = opt * HZ;
4201da177e4SLinus Torvalds 		return 0;
4211da177e4SLinus Torvalds 
4221da177e4SLinus Torvalds 	case ROSE_T2:
423352daa50SNikita Zhandarovich 		if (opt < 1 || opt > UINT_MAX / HZ)
4241da177e4SLinus Torvalds 			return -EINVAL;
4251da177e4SLinus Torvalds 		rose->t2 = opt * HZ;
4261da177e4SLinus Torvalds 		return 0;
4271da177e4SLinus Torvalds 
4281da177e4SLinus Torvalds 	case ROSE_T3:
429352daa50SNikita Zhandarovich 		if (opt < 1 || opt > UINT_MAX / HZ)
4301da177e4SLinus Torvalds 			return -EINVAL;
4311da177e4SLinus Torvalds 		rose->t3 = opt * HZ;
4321da177e4SLinus Torvalds 		return 0;
4331da177e4SLinus Torvalds 
4341da177e4SLinus Torvalds 	case ROSE_HOLDBACK:
435352daa50SNikita Zhandarovich 		if (opt < 1 || opt > UINT_MAX / HZ)
4361da177e4SLinus Torvalds 			return -EINVAL;
4371da177e4SLinus Torvalds 		rose->hb = opt * HZ;
4381da177e4SLinus Torvalds 		return 0;
4391da177e4SLinus Torvalds 
4401da177e4SLinus Torvalds 	case ROSE_IDLE:
441352daa50SNikita Zhandarovich 		if (opt > UINT_MAX / (60 * HZ))
4421da177e4SLinus Torvalds 			return -EINVAL;
4431da177e4SLinus Torvalds 		rose->idle = opt * 60 * HZ;
4441da177e4SLinus Torvalds 		return 0;
4451da177e4SLinus Torvalds 
4461da177e4SLinus Torvalds 	case ROSE_QBITINCL:
4471da177e4SLinus Torvalds 		rose->qbitincl = opt ? 1 : 0;
4481da177e4SLinus Torvalds 		return 0;
4491da177e4SLinus Torvalds 
4501da177e4SLinus Torvalds 	default:
4511da177e4SLinus Torvalds 		return -ENOPROTOOPT;
4521da177e4SLinus Torvalds 	}
4531da177e4SLinus Torvalds }
4541da177e4SLinus Torvalds 
rose_getsockopt(struct socket * sock,int level,int optname,char __user * optval,int __user * optlen)4551da177e4SLinus Torvalds static int rose_getsockopt(struct socket *sock, int level, int optname,
4561da177e4SLinus Torvalds 	char __user *optval, int __user *optlen)
4571da177e4SLinus Torvalds {
4581da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
4591da177e4SLinus Torvalds 	struct rose_sock *rose = rose_sk(sk);
4601da177e4SLinus Torvalds 	int val = 0;
4611da177e4SLinus Torvalds 	int len;
4621da177e4SLinus Torvalds 
4631da177e4SLinus Torvalds 	if (level != SOL_ROSE)
4641da177e4SLinus Torvalds 		return -ENOPROTOOPT;
4651da177e4SLinus Torvalds 
4661da177e4SLinus Torvalds 	if (get_user(len, optlen))
4671da177e4SLinus Torvalds 		return -EFAULT;
4681da177e4SLinus Torvalds 
4691da177e4SLinus Torvalds 	if (len < 0)
4701da177e4SLinus Torvalds 		return -EINVAL;
4711da177e4SLinus Torvalds 
4721da177e4SLinus Torvalds 	switch (optname) {
4731da177e4SLinus Torvalds 	case ROSE_DEFER:
4741da177e4SLinus Torvalds 		val = rose->defer;
4751da177e4SLinus Torvalds 		break;
4761da177e4SLinus Torvalds 
4771da177e4SLinus Torvalds 	case ROSE_T1:
4781da177e4SLinus Torvalds 		val = rose->t1 / HZ;
4791da177e4SLinus Torvalds 		break;
4801da177e4SLinus Torvalds 
4811da177e4SLinus Torvalds 	case ROSE_T2:
4821da177e4SLinus Torvalds 		val = rose->t2 / HZ;
4831da177e4SLinus Torvalds 		break;
4841da177e4SLinus Torvalds 
4851da177e4SLinus Torvalds 	case ROSE_T3:
4861da177e4SLinus Torvalds 		val = rose->t3 / HZ;
4871da177e4SLinus Torvalds 		break;
4881da177e4SLinus Torvalds 
4891da177e4SLinus Torvalds 	case ROSE_HOLDBACK:
4901da177e4SLinus Torvalds 		val = rose->hb / HZ;
4911da177e4SLinus Torvalds 		break;
4921da177e4SLinus Torvalds 
4931da177e4SLinus Torvalds 	case ROSE_IDLE:
4941da177e4SLinus Torvalds 		val = rose->idle / (60 * HZ);
4951da177e4SLinus Torvalds 		break;
4961da177e4SLinus Torvalds 
4971da177e4SLinus Torvalds 	case ROSE_QBITINCL:
4981da177e4SLinus Torvalds 		val = rose->qbitincl;
4991da177e4SLinus Torvalds 		break;
5001da177e4SLinus Torvalds 
5011da177e4SLinus Torvalds 	default:
5021da177e4SLinus Torvalds 		return -ENOPROTOOPT;
5031da177e4SLinus Torvalds 	}
5041da177e4SLinus Torvalds 
5051da177e4SLinus Torvalds 	len = min_t(unsigned int, len, sizeof(int));
5061da177e4SLinus Torvalds 
5071da177e4SLinus Torvalds 	if (put_user(len, optlen))
5081da177e4SLinus Torvalds 		return -EFAULT;
5091da177e4SLinus Torvalds 
5101da177e4SLinus Torvalds 	return copy_to_user(optval, &val, len) ? -EFAULT : 0;
5111da177e4SLinus Torvalds }
5121da177e4SLinus Torvalds 
rose_listen(struct socket * sock,int backlog)5131da177e4SLinus Torvalds static int rose_listen(struct socket *sock, int backlog)
5141da177e4SLinus Torvalds {
5151da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
5161da177e4SLinus Torvalds 
51714caefcfSHyunwoo Kim 	lock_sock(sk);
51814caefcfSHyunwoo Kim 	if (sock->state != SS_UNCONNECTED) {
51914caefcfSHyunwoo Kim 		release_sock(sk);
52014caefcfSHyunwoo Kim 		return -EINVAL;
52114caefcfSHyunwoo Kim 	}
52214caefcfSHyunwoo Kim 
5231da177e4SLinus Torvalds 	if (sk->sk_state != TCP_LISTEN) {
5241da177e4SLinus Torvalds 		struct rose_sock *rose = rose_sk(sk);
5251da177e4SLinus Torvalds 
5261da177e4SLinus Torvalds 		rose->dest_ndigis = 0;
5271da177e4SLinus Torvalds 		memset(&rose->dest_addr, 0, ROSE_ADDR_LEN);
5281da177e4SLinus Torvalds 		memset(&rose->dest_call, 0, AX25_ADDR_LEN);
5291da177e4SLinus Torvalds 		memset(rose->dest_digis, 0, AX25_ADDR_LEN * ROSE_MAX_DIGIS);
5301da177e4SLinus Torvalds 		sk->sk_max_ack_backlog = backlog;
5311da177e4SLinus Torvalds 		sk->sk_state           = TCP_LISTEN;
53214caefcfSHyunwoo Kim 		release_sock(sk);
5331da177e4SLinus Torvalds 		return 0;
5341da177e4SLinus Torvalds 	}
53514caefcfSHyunwoo Kim 	release_sock(sk);
5361da177e4SLinus Torvalds 
5371da177e4SLinus Torvalds 	return -EOPNOTSUPP;
5381da177e4SLinus Torvalds }
5391da177e4SLinus Torvalds 
5401da177e4SLinus Torvalds static struct proto rose_proto = {
5411da177e4SLinus Torvalds 	.name	  = "ROSE",
5421da177e4SLinus Torvalds 	.owner	  = THIS_MODULE,
5431da177e4SLinus Torvalds 	.obj_size = sizeof(struct rose_sock),
5441da177e4SLinus Torvalds };
5451da177e4SLinus Torvalds 
rose_create(struct net * net,struct socket * sock,int protocol,int kern)5463f378b68SEric Paris static int rose_create(struct net *net, struct socket *sock, int protocol,
5473f378b68SEric Paris 		       int kern)
5481da177e4SLinus Torvalds {
5491da177e4SLinus Torvalds 	struct sock *sk;
5501da177e4SLinus Torvalds 	struct rose_sock *rose;
5511da177e4SLinus Torvalds 
55209ad9bc7SOctavian Purdila 	if (!net_eq(net, &init_net))
5531b8d7ae4SEric W. Biederman 		return -EAFNOSUPPORT;
5541b8d7ae4SEric W. Biederman 
5551da177e4SLinus Torvalds 	if (sock->type != SOCK_SEQPACKET || protocol != 0)
5561da177e4SLinus Torvalds 		return -ESOCKTNOSUPPORT;
5571da177e4SLinus Torvalds 
55811aa9c28SEric W. Biederman 	sk = sk_alloc(net, PF_ROSE, GFP_ATOMIC, &rose_proto, kern);
5596257ff21SPavel Emelyanov 	if (sk == NULL)
5601da177e4SLinus Torvalds 		return -ENOMEM;
5611da177e4SLinus Torvalds 
5621da177e4SLinus Torvalds 	rose = rose_sk(sk);
5631da177e4SLinus Torvalds 
5641da177e4SLinus Torvalds 	sock_init_data(sock, sk);
5651da177e4SLinus Torvalds 
5661da177e4SLinus Torvalds 	skb_queue_head_init(&rose->ack_queue);
5671da177e4SLinus Torvalds #ifdef M_BIT
5681da177e4SLinus Torvalds 	skb_queue_head_init(&rose->frag_queue);
5691da177e4SLinus Torvalds 	rose->fraglen    = 0;
5701da177e4SLinus Torvalds #endif
5711da177e4SLinus Torvalds 
5721da177e4SLinus Torvalds 	sock->ops    = &rose_proto_ops;
5731da177e4SLinus Torvalds 	sk->sk_protocol = protocol;
5741da177e4SLinus Torvalds 
5754966babdSKees Cook 	timer_setup(&rose->timer, NULL, 0);
5764966babdSKees Cook 	timer_setup(&rose->idletimer, NULL, 0);
5771da177e4SLinus Torvalds 
57882e84249SRalf Baechle 	rose->t1   = msecs_to_jiffies(sysctl_rose_call_request_timeout);
57982e84249SRalf Baechle 	rose->t2   = msecs_to_jiffies(sysctl_rose_reset_request_timeout);
58082e84249SRalf Baechle 	rose->t3   = msecs_to_jiffies(sysctl_rose_clear_request_timeout);
58182e84249SRalf Baechle 	rose->hb   = msecs_to_jiffies(sysctl_rose_ack_hold_back_timeout);
58282e84249SRalf Baechle 	rose->idle = msecs_to_jiffies(sysctl_rose_no_activity_timeout);
5831da177e4SLinus Torvalds 
5841da177e4SLinus Torvalds 	rose->state = ROSE_STATE_0;
5851da177e4SLinus Torvalds 
5861da177e4SLinus Torvalds 	return 0;
5871da177e4SLinus Torvalds }
5881da177e4SLinus Torvalds 
rose_make_new(struct sock * osk)5891da177e4SLinus Torvalds static struct sock *rose_make_new(struct sock *osk)
5901da177e4SLinus Torvalds {
5911da177e4SLinus Torvalds 	struct sock *sk;
5921da177e4SLinus Torvalds 	struct rose_sock *rose, *orose;
5931da177e4SLinus Torvalds 
5941da177e4SLinus Torvalds 	if (osk->sk_type != SOCK_SEQPACKET)
5951da177e4SLinus Torvalds 		return NULL;
5961da177e4SLinus Torvalds 
59711aa9c28SEric W. Biederman 	sk = sk_alloc(sock_net(osk), PF_ROSE, GFP_ATOMIC, &rose_proto, 0);
5986257ff21SPavel Emelyanov 	if (sk == NULL)
5991da177e4SLinus Torvalds 		return NULL;
6001da177e4SLinus Torvalds 
6011da177e4SLinus Torvalds 	rose = rose_sk(sk);
6021da177e4SLinus Torvalds 
6031da177e4SLinus Torvalds 	sock_init_data(NULL, sk);
6041da177e4SLinus Torvalds 
6051da177e4SLinus Torvalds 	skb_queue_head_init(&rose->ack_queue);
6061da177e4SLinus Torvalds #ifdef M_BIT
6071da177e4SLinus Torvalds 	skb_queue_head_init(&rose->frag_queue);
6081da177e4SLinus Torvalds 	rose->fraglen  = 0;
6091da177e4SLinus Torvalds #endif
6101da177e4SLinus Torvalds 
6111da177e4SLinus Torvalds 	sk->sk_type     = osk->sk_type;
6121da177e4SLinus Torvalds 	sk->sk_priority = osk->sk_priority;
6131da177e4SLinus Torvalds 	sk->sk_protocol = osk->sk_protocol;
6141da177e4SLinus Torvalds 	sk->sk_rcvbuf   = osk->sk_rcvbuf;
6151da177e4SLinus Torvalds 	sk->sk_sndbuf   = osk->sk_sndbuf;
6161da177e4SLinus Torvalds 	sk->sk_state    = TCP_ESTABLISHED;
61753b924b3SRalf Baechle 	sock_copy_flags(sk, osk);
6181da177e4SLinus Torvalds 
6194966babdSKees Cook 	timer_setup(&rose->timer, NULL, 0);
6204966babdSKees Cook 	timer_setup(&rose->idletimer, NULL, 0);
6211da177e4SLinus Torvalds 
6221da177e4SLinus Torvalds 	orose		= rose_sk(osk);
6231da177e4SLinus Torvalds 	rose->t1	= orose->t1;
6241da177e4SLinus Torvalds 	rose->t2	= orose->t2;
6251da177e4SLinus Torvalds 	rose->t3	= orose->t3;
6261da177e4SLinus Torvalds 	rose->hb	= orose->hb;
6271da177e4SLinus Torvalds 	rose->idle	= orose->idle;
6281da177e4SLinus Torvalds 	rose->defer	= orose->defer;
6291da177e4SLinus Torvalds 	rose->device	= orose->device;
63093102782SEric Dumazet 	if (rose->device)
6312df91e39SEric Dumazet 		netdev_hold(rose->device, &rose->dev_tracker, GFP_ATOMIC);
6321da177e4SLinus Torvalds 	rose->qbitincl	= orose->qbitincl;
6331da177e4SLinus Torvalds 
6341da177e4SLinus Torvalds 	return sk;
6351da177e4SLinus Torvalds }
6361da177e4SLinus Torvalds 
rose_release(struct socket * sock)6371da177e4SLinus Torvalds static int rose_release(struct socket *sock)
6381da177e4SLinus Torvalds {
6391da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
6401da177e4SLinus Torvalds 	struct rose_sock *rose;
6411da177e4SLinus Torvalds 
6421da177e4SLinus Torvalds 	if (sk == NULL) return 0;
6431da177e4SLinus Torvalds 
6444965291aSJarek Poplawski 	sock_hold(sk);
6454965291aSJarek Poplawski 	sock_orphan(sk);
6464965291aSJarek Poplawski 	lock_sock(sk);
6471da177e4SLinus Torvalds 	rose = rose_sk(sk);
6481da177e4SLinus Torvalds 
6491da177e4SLinus Torvalds 	switch (rose->state) {
6501da177e4SLinus Torvalds 	case ROSE_STATE_0:
6514965291aSJarek Poplawski 		release_sock(sk);
6521da177e4SLinus Torvalds 		rose_disconnect(sk, 0, -1, -1);
6534965291aSJarek Poplawski 		lock_sock(sk);
6541da177e4SLinus Torvalds 		rose_destroy_socket(sk);
6551da177e4SLinus Torvalds 		break;
6561da177e4SLinus Torvalds 
6571da177e4SLinus Torvalds 	case ROSE_STATE_2:
6581da177e4SLinus Torvalds 		rose->neighbour->use--;
6594965291aSJarek Poplawski 		release_sock(sk);
6601da177e4SLinus Torvalds 		rose_disconnect(sk, 0, -1, -1);
6614965291aSJarek Poplawski 		lock_sock(sk);
6621da177e4SLinus Torvalds 		rose_destroy_socket(sk);
6631da177e4SLinus Torvalds 		break;
6641da177e4SLinus Torvalds 
6651da177e4SLinus Torvalds 	case ROSE_STATE_1:
6661da177e4SLinus Torvalds 	case ROSE_STATE_3:
6671da177e4SLinus Torvalds 	case ROSE_STATE_4:
6681da177e4SLinus Torvalds 	case ROSE_STATE_5:
6691da177e4SLinus Torvalds 		rose_clear_queues(sk);
6701da177e4SLinus Torvalds 		rose_stop_idletimer(sk);
6711da177e4SLinus Torvalds 		rose_write_internal(sk, ROSE_CLEAR_REQUEST);
6721da177e4SLinus Torvalds 		rose_start_t3timer(sk);
6731da177e4SLinus Torvalds 		rose->state  = ROSE_STATE_2;
6741da177e4SLinus Torvalds 		sk->sk_state    = TCP_CLOSE;
6751da177e4SLinus Torvalds 		sk->sk_shutdown |= SEND_SHUTDOWN;
6761da177e4SLinus Torvalds 		sk->sk_state_change(sk);
6771da177e4SLinus Torvalds 		sock_set_flag(sk, SOCK_DEAD);
6781da177e4SLinus Torvalds 		sock_set_flag(sk, SOCK_DESTROY);
6791da177e4SLinus Torvalds 		break;
6801da177e4SLinus Torvalds 
6811da177e4SLinus Torvalds 	default:
6821da177e4SLinus Torvalds 		break;
6831da177e4SLinus Torvalds 	}
6841da177e4SLinus Torvalds 
685ffced266SEric Dumazet 	spin_lock_bh(&rose_list_lock);
6862df91e39SEric Dumazet 	netdev_put(rose->device, &rose->dev_tracker);
687ffced266SEric Dumazet 	rose->device = NULL;
688ffced266SEric Dumazet 	spin_unlock_bh(&rose_list_lock);
6891da177e4SLinus Torvalds 	sock->sk = NULL;
6904965291aSJarek Poplawski 	release_sock(sk);
6914965291aSJarek Poplawski 	sock_put(sk);
6921da177e4SLinus Torvalds 
6931da177e4SLinus Torvalds 	return 0;
6941da177e4SLinus Torvalds }
6951da177e4SLinus Torvalds 
rose_bind(struct socket * sock,struct sockaddr * uaddr,int addr_len)6961da177e4SLinus Torvalds static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
6971da177e4SLinus Torvalds {
6981da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
6991da177e4SLinus Torvalds 	struct rose_sock *rose = rose_sk(sk);
7001da177e4SLinus Torvalds 	struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr;
7011da177e4SLinus Torvalds 	struct net_device *dev;
70201d7dd0eSRalf Baechle 	ax25_address *source;
70301d7dd0eSRalf Baechle 	ax25_uid_assoc *user;
704*e0384efdSEric Dumazet 	int err = -EINVAL;
7051da177e4SLinus Torvalds 	int n;
7061da177e4SLinus Torvalds 
7071da177e4SLinus Torvalds 	if (addr_len != sizeof(struct sockaddr_rose) && addr_len != sizeof(struct full_sockaddr_rose))
7081da177e4SLinus Torvalds 		return -EINVAL;
7091da177e4SLinus Torvalds 
7101da177e4SLinus Torvalds 	if (addr->srose_family != AF_ROSE)
7111da177e4SLinus Torvalds 		return -EINVAL;
7121da177e4SLinus Torvalds 
7131da177e4SLinus Torvalds 	if (addr_len == sizeof(struct sockaddr_rose) && addr->srose_ndigis > 1)
7141da177e4SLinus Torvalds 		return -EINVAL;
7151da177e4SLinus Torvalds 
7169828e6e6SDavid S. Miller 	if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS)
7171da177e4SLinus Torvalds 		return -EINVAL;
7181da177e4SLinus Torvalds 
719*e0384efdSEric Dumazet 	lock_sock(sk);
720*e0384efdSEric Dumazet 
721*e0384efdSEric Dumazet 	if (!sock_flag(sk, SOCK_ZAPPED))
722*e0384efdSEric Dumazet 		goto out_release;
723*e0384efdSEric Dumazet 
724*e0384efdSEric Dumazet 	err = -EADDRNOTAVAIL;
725*e0384efdSEric Dumazet 	dev = rose_dev_get(&addr->srose_addr);
726*e0384efdSEric Dumazet 	if (!dev)
727*e0384efdSEric Dumazet 		goto out_release;
7281da177e4SLinus Torvalds 
7291da177e4SLinus Torvalds 	source = &addr->srose_call;
7301da177e4SLinus Torvalds 
731c2a2b8d3SDavid Howells 	user = ax25_findbyuid(current_euid());
73201d7dd0eSRalf Baechle 	if (user) {
73301d7dd0eSRalf Baechle 		rose->source_call = user->call;
73401d7dd0eSRalf Baechle 		ax25_uid_put(user);
73501d7dd0eSRalf Baechle 	} else {
7363b9c9f3bSYueHaibing 		if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) {
7373b9c9f3bSYueHaibing 			dev_put(dev);
738*e0384efdSEric Dumazet 			err = -EACCES;
739*e0384efdSEric Dumazet 			goto out_release;
7403b9c9f3bSYueHaibing 		}
74101d7dd0eSRalf Baechle 		rose->source_call   = *source;
7421da177e4SLinus Torvalds 	}
7431da177e4SLinus Torvalds 
7441da177e4SLinus Torvalds 	rose->source_addr   = addr->srose_addr;
7451da177e4SLinus Torvalds 	rose->device        = dev;
7462df91e39SEric Dumazet 	netdev_tracker_alloc(rose->device, &rose->dev_tracker, GFP_KERNEL);
7471da177e4SLinus Torvalds 	rose->source_ndigis = addr->srose_ndigis;
7481da177e4SLinus Torvalds 
7491da177e4SLinus Torvalds 	if (addr_len == sizeof(struct full_sockaddr_rose)) {
7501da177e4SLinus Torvalds 		struct full_sockaddr_rose *full_addr = (struct full_sockaddr_rose *)uaddr;
7511da177e4SLinus Torvalds 		for (n = 0 ; n < addr->srose_ndigis ; n++)
7521da177e4SLinus Torvalds 			rose->source_digis[n] = full_addr->srose_digis[n];
7531da177e4SLinus Torvalds 	} else {
7541da177e4SLinus Torvalds 		if (rose->source_ndigis == 1) {
7551da177e4SLinus Torvalds 			rose->source_digis[0] = addr->srose_digi;
7561da177e4SLinus Torvalds 		}
7571da177e4SLinus Torvalds 	}
7581da177e4SLinus Torvalds 
7591da177e4SLinus Torvalds 	rose_insert_socket(sk);
7601da177e4SLinus Torvalds 
7611da177e4SLinus Torvalds 	sock_reset_flag(sk, SOCK_ZAPPED);
762*e0384efdSEric Dumazet 	err = 0;
763*e0384efdSEric Dumazet out_release:
764*e0384efdSEric Dumazet 	release_sock(sk);
765*e0384efdSEric Dumazet 	return err;
7661da177e4SLinus Torvalds }
7671da177e4SLinus Torvalds 
rose_connect(struct socket * sock,struct sockaddr * uaddr,int addr_len,int flags)7681da177e4SLinus Torvalds static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags)
7691da177e4SLinus Torvalds {
7701da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
7711da177e4SLinus Torvalds 	struct rose_sock *rose = rose_sk(sk);
7721da177e4SLinus Torvalds 	struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr;
7731da177e4SLinus Torvalds 	unsigned char cause, diagnostic;
77401d7dd0eSRalf Baechle 	ax25_uid_assoc *user;
7752536b94aSRalf Baechle 	int n, err = 0;
7761da177e4SLinus Torvalds 
7771da177e4SLinus Torvalds 	if (addr_len != sizeof(struct sockaddr_rose) && addr_len != sizeof(struct full_sockaddr_rose))
7781da177e4SLinus Torvalds 		return -EINVAL;
7791da177e4SLinus Torvalds 
7801da177e4SLinus Torvalds 	if (addr->srose_family != AF_ROSE)
7811da177e4SLinus Torvalds 		return -EINVAL;
7821da177e4SLinus Torvalds 
7831da177e4SLinus Torvalds 	if (addr_len == sizeof(struct sockaddr_rose) && addr->srose_ndigis > 1)
7841da177e4SLinus Torvalds 		return -EINVAL;
7851da177e4SLinus Torvalds 
7869828e6e6SDavid S. Miller 	if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS)
7871da177e4SLinus Torvalds 		return -EINVAL;
7881da177e4SLinus Torvalds 
7891da177e4SLinus Torvalds 	/* Source + Destination digis should not exceed ROSE_MAX_DIGIS */
7901da177e4SLinus Torvalds 	if ((rose->source_ndigis + addr->srose_ndigis) > ROSE_MAX_DIGIS)
7911da177e4SLinus Torvalds 		return -EINVAL;
7921da177e4SLinus Torvalds 
7932536b94aSRalf Baechle 	lock_sock(sk);
7942536b94aSRalf Baechle 
7952536b94aSRalf Baechle 	if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
7962536b94aSRalf Baechle 		/* Connect completed during a ERESTARTSYS event */
7972536b94aSRalf Baechle 		sock->state = SS_CONNECTED;
7982536b94aSRalf Baechle 		goto out_release;
7992536b94aSRalf Baechle 	}
8002536b94aSRalf Baechle 
8012536b94aSRalf Baechle 	if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) {
8022536b94aSRalf Baechle 		sock->state = SS_UNCONNECTED;
8032536b94aSRalf Baechle 		err = -ECONNREFUSED;
8042536b94aSRalf Baechle 		goto out_release;
8052536b94aSRalf Baechle 	}
8062536b94aSRalf Baechle 
8072536b94aSRalf Baechle 	if (sk->sk_state == TCP_ESTABLISHED) {
8082536b94aSRalf Baechle 		/* No reconnect on a seqpacket socket */
8092536b94aSRalf Baechle 		err = -EISCONN;
8102536b94aSRalf Baechle 		goto out_release;
8112536b94aSRalf Baechle 	}
8122536b94aSRalf Baechle 
8132536b94aSRalf Baechle 	sk->sk_state   = TCP_CLOSE;
8142536b94aSRalf Baechle 	sock->state = SS_UNCONNECTED;
8152536b94aSRalf Baechle 
8161da177e4SLinus Torvalds 	rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause,
817fe2c802aSBernard Pidoux 					 &diagnostic, 0);
81843837b1eSBernard Pidoux 	if (!rose->neighbour) {
81943837b1eSBernard Pidoux 		err = -ENETUNREACH;
82043837b1eSBernard Pidoux 		goto out_release;
82143837b1eSBernard Pidoux 	}
8221da177e4SLinus Torvalds 
8231da177e4SLinus Torvalds 	rose->lci = rose_new_lci(rose->neighbour);
8242536b94aSRalf Baechle 	if (!rose->lci) {
8252536b94aSRalf Baechle 		err = -ENETUNREACH;
8262536b94aSRalf Baechle 		goto out_release;
8272536b94aSRalf Baechle 	}
8281da177e4SLinus Torvalds 
8291da177e4SLinus Torvalds 	if (sock_flag(sk, SOCK_ZAPPED)) {	/* Must bind first - autobinding in this may or may not work */
83093102782SEric Dumazet 		struct net_device *dev;
83193102782SEric Dumazet 
8321da177e4SLinus Torvalds 		sock_reset_flag(sk, SOCK_ZAPPED);
8331da177e4SLinus Torvalds 
83493102782SEric Dumazet 		dev = rose_dev_first();
83593102782SEric Dumazet 		if (!dev) {
8362536b94aSRalf Baechle 			err = -ENETUNREACH;
8372536b94aSRalf Baechle 			goto out_release;
8382536b94aSRalf Baechle 		}
8391da177e4SLinus Torvalds 
840c2a2b8d3SDavid Howells 		user = ax25_findbyuid(current_euid());
8412536b94aSRalf Baechle 		if (!user) {
8422536b94aSRalf Baechle 			err = -EINVAL;
84393102782SEric Dumazet 			dev_put(dev);
8442536b94aSRalf Baechle 			goto out_release;
8452536b94aSRalf Baechle 		}
8461da177e4SLinus Torvalds 
8471da177e4SLinus Torvalds 		memcpy(&rose->source_addr, dev->dev_addr, ROSE_ADDR_LEN);
84801d7dd0eSRalf Baechle 		rose->source_call = user->call;
8491da177e4SLinus Torvalds 		rose->device      = dev;
8502df91e39SEric Dumazet 		netdev_tracker_alloc(rose->device, &rose->dev_tracker,
8512df91e39SEric Dumazet 				     GFP_KERNEL);
85201d7dd0eSRalf Baechle 		ax25_uid_put(user);
8531da177e4SLinus Torvalds 
8541da177e4SLinus Torvalds 		rose_insert_socket(sk);		/* Finish the bind */
8551da177e4SLinus Torvalds 	}
8561da177e4SLinus Torvalds 	rose->dest_addr   = addr->srose_addr;
8571da177e4SLinus Torvalds 	rose->dest_call   = addr->srose_call;
8581da177e4SLinus Torvalds 	rose->rand        = ((long)rose & 0xFFFF) + rose->lci;
8591da177e4SLinus Torvalds 	rose->dest_ndigis = addr->srose_ndigis;
8601da177e4SLinus Torvalds 
8611da177e4SLinus Torvalds 	if (addr_len == sizeof(struct full_sockaddr_rose)) {
8621da177e4SLinus Torvalds 		struct full_sockaddr_rose *full_addr = (struct full_sockaddr_rose *)uaddr;
8631da177e4SLinus Torvalds 		for (n = 0 ; n < addr->srose_ndigis ; n++)
8641da177e4SLinus Torvalds 			rose->dest_digis[n] = full_addr->srose_digis[n];
8651da177e4SLinus Torvalds 	} else {
8661da177e4SLinus Torvalds 		if (rose->dest_ndigis == 1) {
8671da177e4SLinus Torvalds 			rose->dest_digis[0] = addr->srose_digi;
8681da177e4SLinus Torvalds 		}
8691da177e4SLinus Torvalds 	}
8701da177e4SLinus Torvalds 
8711da177e4SLinus Torvalds 	/* Move to connecting socket, start sending Connect Requests */
8721da177e4SLinus Torvalds 	sock->state   = SS_CONNECTING;
8731da177e4SLinus Torvalds 	sk->sk_state     = TCP_SYN_SENT;
8741da177e4SLinus Torvalds 
8751da177e4SLinus Torvalds 	rose->state = ROSE_STATE_1;
8761da177e4SLinus Torvalds 
8771da177e4SLinus Torvalds 	rose->neighbour->use++;
8781da177e4SLinus Torvalds 
8791da177e4SLinus Torvalds 	rose_write_internal(sk, ROSE_CALL_REQUEST);
8801da177e4SLinus Torvalds 	rose_start_heartbeat(sk);
8811da177e4SLinus Torvalds 	rose_start_t1timer(sk);
8821da177e4SLinus Torvalds 
8831da177e4SLinus Torvalds 	/* Now the loop */
8842536b94aSRalf Baechle 	if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) {
8852536b94aSRalf Baechle 		err = -EINPROGRESS;
8862536b94aSRalf Baechle 		goto out_release;
8872536b94aSRalf Baechle 	}
8881da177e4SLinus Torvalds 
8891da177e4SLinus Torvalds 	/*
8901da177e4SLinus Torvalds 	 * A Connect Ack with Choke or timeout or failed routing will go to
8911da177e4SLinus Torvalds 	 * closed.
8921da177e4SLinus Torvalds 	 */
8931da177e4SLinus Torvalds 	if (sk->sk_state == TCP_SYN_SENT) {
89475606dc6SRalf Baechle 		DEFINE_WAIT(wait);
8951da177e4SLinus Torvalds 
8961da177e4SLinus Torvalds 		for (;;) {
897aa395145SEric Dumazet 			prepare_to_wait(sk_sleep(sk), &wait,
89875606dc6SRalf Baechle 					TASK_INTERRUPTIBLE);
8991da177e4SLinus Torvalds 			if (sk->sk_state != TCP_SYN_SENT)
9001da177e4SLinus Torvalds 				break;
90175606dc6SRalf Baechle 			if (!signal_pending(current)) {
9022536b94aSRalf Baechle 				release_sock(sk);
9031da177e4SLinus Torvalds 				schedule();
9042536b94aSRalf Baechle 				lock_sock(sk);
9051da177e4SLinus Torvalds 				continue;
9061da177e4SLinus Torvalds 			}
90775606dc6SRalf Baechle 			err = -ERESTARTSYS;
90875606dc6SRalf Baechle 			break;
9091da177e4SLinus Torvalds 		}
910aa395145SEric Dumazet 		finish_wait(sk_sleep(sk), &wait);
91175606dc6SRalf Baechle 
91275606dc6SRalf Baechle 		if (err)
91375606dc6SRalf Baechle 			goto out_release;
9141da177e4SLinus Torvalds 	}
9151da177e4SLinus Torvalds 
9161da177e4SLinus Torvalds 	if (sk->sk_state != TCP_ESTABLISHED) {
9171da177e4SLinus Torvalds 		sock->state = SS_UNCONNECTED;
9182536b94aSRalf Baechle 		err = sock_error(sk);	/* Always set at this point */
9192536b94aSRalf Baechle 		goto out_release;
9201da177e4SLinus Torvalds 	}
9211da177e4SLinus Torvalds 
9221da177e4SLinus Torvalds 	sock->state = SS_CONNECTED;
9231da177e4SLinus Torvalds 
9242536b94aSRalf Baechle out_release:
9252536b94aSRalf Baechle 	release_sock(sk);
9262536b94aSRalf Baechle 
9272536b94aSRalf Baechle 	return err;
9281da177e4SLinus Torvalds }
9291da177e4SLinus Torvalds 
rose_accept(struct socket * sock,struct socket * newsock,int flags,bool kern)930cdfbabfbSDavid Howells static int rose_accept(struct socket *sock, struct socket *newsock, int flags,
931cdfbabfbSDavid Howells 		       bool kern)
9321da177e4SLinus Torvalds {
9331da177e4SLinus Torvalds 	struct sk_buff *skb;
9341da177e4SLinus Torvalds 	struct sock *newsk;
93575606dc6SRalf Baechle 	DEFINE_WAIT(wait);
9361da177e4SLinus Torvalds 	struct sock *sk;
9371da177e4SLinus Torvalds 	int err = 0;
9381da177e4SLinus Torvalds 
9391da177e4SLinus Torvalds 	if ((sk = sock->sk) == NULL)
9401da177e4SLinus Torvalds 		return -EINVAL;
9411da177e4SLinus Torvalds 
9421da177e4SLinus Torvalds 	lock_sock(sk);
9431da177e4SLinus Torvalds 	if (sk->sk_type != SOCK_SEQPACKET) {
9441da177e4SLinus Torvalds 		err = -EOPNOTSUPP;
94575606dc6SRalf Baechle 		goto out_release;
9461da177e4SLinus Torvalds 	}
9471da177e4SLinus Torvalds 
9481da177e4SLinus Torvalds 	if (sk->sk_state != TCP_LISTEN) {
9491da177e4SLinus Torvalds 		err = -EINVAL;
95075606dc6SRalf Baechle 		goto out_release;
9511da177e4SLinus Torvalds 	}
9521da177e4SLinus Torvalds 
9531da177e4SLinus Torvalds 	/*
9541da177e4SLinus Torvalds 	 *	The write queue this time is holding sockets ready to use
9551da177e4SLinus Torvalds 	 *	hooked into the SABM we saved
9561da177e4SLinus Torvalds 	 */
9571da177e4SLinus Torvalds 	for (;;) {
958aa395145SEric Dumazet 		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
95975606dc6SRalf Baechle 
9601da177e4SLinus Torvalds 		skb = skb_dequeue(&sk->sk_receive_queue);
9611da177e4SLinus Torvalds 		if (skb)
9621da177e4SLinus Torvalds 			break;
9631da177e4SLinus Torvalds 
9641da177e4SLinus Torvalds 		if (flags & O_NONBLOCK) {
96575606dc6SRalf Baechle 			err = -EWOULDBLOCK;
96675606dc6SRalf Baechle 			break;
9671da177e4SLinus Torvalds 		}
96875606dc6SRalf Baechle 		if (!signal_pending(current)) {
96975606dc6SRalf Baechle 			release_sock(sk);
9701da177e4SLinus Torvalds 			schedule();
9711da177e4SLinus Torvalds 			lock_sock(sk);
9721da177e4SLinus Torvalds 			continue;
9731da177e4SLinus Torvalds 		}
97475606dc6SRalf Baechle 		err = -ERESTARTSYS;
97575606dc6SRalf Baechle 		break;
9761da177e4SLinus Torvalds 	}
977aa395145SEric Dumazet 	finish_wait(sk_sleep(sk), &wait);
97875606dc6SRalf Baechle 	if (err)
97975606dc6SRalf Baechle 		goto out_release;
9801da177e4SLinus Torvalds 
9811da177e4SLinus Torvalds 	newsk = skb->sk;
98244ccff1fSDavid S. Miller 	sock_graft(newsk, newsock);
9831da177e4SLinus Torvalds 
9841da177e4SLinus Torvalds 	/* Now attach up the new socket */
9851da177e4SLinus Torvalds 	skb->sk = NULL;
9861da177e4SLinus Torvalds 	kfree_skb(skb);
9877976a11bSEric Dumazet 	sk_acceptq_removed(sk);
9881da177e4SLinus Torvalds 
98975606dc6SRalf Baechle out_release:
9901da177e4SLinus Torvalds 	release_sock(sk);
9911da177e4SLinus Torvalds 
9921da177e4SLinus Torvalds 	return err;
9931da177e4SLinus Torvalds }
9941da177e4SLinus Torvalds 
rose_getname(struct socket * sock,struct sockaddr * uaddr,int peer)9951da177e4SLinus Torvalds static int rose_getname(struct socket *sock, struct sockaddr *uaddr,
9969b2c45d4SDenys Vlasenko 	int peer)
9971da177e4SLinus Torvalds {
9981da177e4SLinus Torvalds 	struct full_sockaddr_rose *srose = (struct full_sockaddr_rose *)uaddr;
9991da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
10001da177e4SLinus Torvalds 	struct rose_sock *rose = rose_sk(sk);
10011da177e4SLinus Torvalds 	int n;
10021da177e4SLinus Torvalds 
100317ac2e9cSEric Dumazet 	memset(srose, 0, sizeof(*srose));
10041da177e4SLinus Torvalds 	if (peer != 0) {
10051da177e4SLinus Torvalds 		if (sk->sk_state != TCP_ESTABLISHED)
10061da177e4SLinus Torvalds 			return -ENOTCONN;
10071da177e4SLinus Torvalds 		srose->srose_family = AF_ROSE;
10081da177e4SLinus Torvalds 		srose->srose_addr   = rose->dest_addr;
10091da177e4SLinus Torvalds 		srose->srose_call   = rose->dest_call;
10101da177e4SLinus Torvalds 		srose->srose_ndigis = rose->dest_ndigis;
10111da177e4SLinus Torvalds 		for (n = 0; n < rose->dest_ndigis; n++)
10121da177e4SLinus Torvalds 			srose->srose_digis[n] = rose->dest_digis[n];
10131da177e4SLinus Torvalds 	} else {
10141da177e4SLinus Torvalds 		srose->srose_family = AF_ROSE;
10151da177e4SLinus Torvalds 		srose->srose_addr   = rose->source_addr;
10161da177e4SLinus Torvalds 		srose->srose_call   = rose->source_call;
10171da177e4SLinus Torvalds 		srose->srose_ndigis = rose->source_ndigis;
10181da177e4SLinus Torvalds 		for (n = 0; n < rose->source_ndigis; n++)
10191da177e4SLinus Torvalds 			srose->srose_digis[n] = rose->source_digis[n];
10201da177e4SLinus Torvalds 	}
10211da177e4SLinus Torvalds 
10229b2c45d4SDenys Vlasenko 	return sizeof(struct full_sockaddr_rose);
10231da177e4SLinus Torvalds }
10241da177e4SLinus Torvalds 
rose_rx_call_request(struct sk_buff * skb,struct net_device * dev,struct rose_neigh * neigh,unsigned int lci)10251da177e4SLinus Torvalds int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct rose_neigh *neigh, unsigned int lci)
10261da177e4SLinus Torvalds {
10271da177e4SLinus Torvalds 	struct sock *sk;
10281da177e4SLinus Torvalds 	struct sock *make;
10291da177e4SLinus Torvalds 	struct rose_sock *make_rose;
10301da177e4SLinus Torvalds 	struct rose_facilities_struct facilities;
1031e0bccd31SBen Hutchings 	int n;
10321da177e4SLinus Torvalds 
10331da177e4SLinus Torvalds 	skb->sk = NULL;		/* Initially we don't know who it's for */
10341da177e4SLinus Torvalds 
10351da177e4SLinus Torvalds 	/*
10361da177e4SLinus Torvalds 	 *	skb->data points to the rose frame start
10371da177e4SLinus Torvalds 	 */
10381da177e4SLinus Torvalds 	memset(&facilities, 0x00, sizeof(struct rose_facilities_struct));
10391da177e4SLinus Torvalds 
1040e0bccd31SBen Hutchings 	if (!rose_parse_facilities(skb->data + ROSE_CALL_REQ_FACILITIES_OFF,
1041e0bccd31SBen Hutchings 				   skb->len - ROSE_CALL_REQ_FACILITIES_OFF,
1042e0bccd31SBen Hutchings 				   &facilities)) {
10431da177e4SLinus Torvalds 		rose_transmit_clear_request(neigh, lci, ROSE_INVALID_FACILITY, 76);
10441da177e4SLinus Torvalds 		return 0;
10451da177e4SLinus Torvalds 	}
10461da177e4SLinus Torvalds 
10471da177e4SLinus Torvalds 	sk = rose_find_listener(&facilities.source_addr, &facilities.source_call);
10481da177e4SLinus Torvalds 
10491da177e4SLinus Torvalds 	/*
10501da177e4SLinus Torvalds 	 * We can't accept the Call Request.
10511da177e4SLinus Torvalds 	 */
10521da177e4SLinus Torvalds 	if (sk == NULL || sk_acceptq_is_full(sk) ||
10531da177e4SLinus Torvalds 	    (make = rose_make_new(sk)) == NULL) {
10541da177e4SLinus Torvalds 		rose_transmit_clear_request(neigh, lci, ROSE_NETWORK_CONGESTION, 120);
10551da177e4SLinus Torvalds 		return 0;
10561da177e4SLinus Torvalds 	}
10571da177e4SLinus Torvalds 
10581da177e4SLinus Torvalds 	skb->sk     = make;
10591da177e4SLinus Torvalds 	make->sk_state = TCP_ESTABLISHED;
10601da177e4SLinus Torvalds 	make_rose = rose_sk(make);
10611da177e4SLinus Torvalds 
10621da177e4SLinus Torvalds 	make_rose->lci           = lci;
10631da177e4SLinus Torvalds 	make_rose->dest_addr     = facilities.dest_addr;
10641da177e4SLinus Torvalds 	make_rose->dest_call     = facilities.dest_call;
10651da177e4SLinus Torvalds 	make_rose->dest_ndigis   = facilities.dest_ndigis;
10661da177e4SLinus Torvalds 	for (n = 0 ; n < facilities.dest_ndigis ; n++)
10671da177e4SLinus Torvalds 		make_rose->dest_digis[n] = facilities.dest_digis[n];
10681da177e4SLinus Torvalds 	make_rose->source_addr   = facilities.source_addr;
10691da177e4SLinus Torvalds 	make_rose->source_call   = facilities.source_call;
10701da177e4SLinus Torvalds 	make_rose->source_ndigis = facilities.source_ndigis;
10711da177e4SLinus Torvalds 	for (n = 0 ; n < facilities.source_ndigis ; n++)
10721da177e4SLinus Torvalds 		make_rose->source_digis[n] = facilities.source_digis[n];
10731da177e4SLinus Torvalds 	make_rose->neighbour     = neigh;
10741da177e4SLinus Torvalds 	make_rose->device        = dev;
10752df91e39SEric Dumazet 	/* Caller got a reference for us. */
10762df91e39SEric Dumazet 	netdev_tracker_alloc(make_rose->device, &make_rose->dev_tracker,
10772df91e39SEric Dumazet 			     GFP_ATOMIC);
10781da177e4SLinus Torvalds 	make_rose->facilities    = facilities;
10791da177e4SLinus Torvalds 
10801da177e4SLinus Torvalds 	make_rose->neighbour->use++;
10811da177e4SLinus Torvalds 
10821da177e4SLinus Torvalds 	if (rose_sk(sk)->defer) {
10831da177e4SLinus Torvalds 		make_rose->state = ROSE_STATE_5;
10841da177e4SLinus Torvalds 	} else {
10851da177e4SLinus Torvalds 		rose_write_internal(make, ROSE_CALL_ACCEPTED);
10861da177e4SLinus Torvalds 		make_rose->state = ROSE_STATE_3;
10871da177e4SLinus Torvalds 		rose_start_idletimer(make);
10881da177e4SLinus Torvalds 	}
10891da177e4SLinus Torvalds 
10901da177e4SLinus Torvalds 	make_rose->condition = 0x00;
10911da177e4SLinus Torvalds 	make_rose->vs        = 0;
10921da177e4SLinus Torvalds 	make_rose->va        = 0;
10931da177e4SLinus Torvalds 	make_rose->vr        = 0;
10941da177e4SLinus Torvalds 	make_rose->vl        = 0;
10957976a11bSEric Dumazet 	sk_acceptq_added(sk);
10961da177e4SLinus Torvalds 
10971da177e4SLinus Torvalds 	rose_insert_socket(make);
10981da177e4SLinus Torvalds 
10991da177e4SLinus Torvalds 	skb_queue_head(&sk->sk_receive_queue, skb);
11001da177e4SLinus Torvalds 
11011da177e4SLinus Torvalds 	rose_start_heartbeat(make);
11021da177e4SLinus Torvalds 
11031da177e4SLinus Torvalds 	if (!sock_flag(sk, SOCK_DEAD))
1104676d2369SDavid S. Miller 		sk->sk_data_ready(sk);
11051da177e4SLinus Torvalds 
11061da177e4SLinus Torvalds 	return 1;
11071da177e4SLinus Torvalds }
11081da177e4SLinus Torvalds 
rose_sendmsg(struct socket * sock,struct msghdr * msg,size_t len)11091b784140SYing Xue static int rose_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
11101da177e4SLinus Torvalds {
11111da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
11121da177e4SLinus Torvalds 	struct rose_sock *rose = rose_sk(sk);
1113342dfc30SSteffen Hurrle 	DECLARE_SOCKADDR(struct sockaddr_rose *, usrose, msg->msg_name);
11141da177e4SLinus Torvalds 	int err;
11151da177e4SLinus Torvalds 	struct full_sockaddr_rose srose;
11161da177e4SLinus Torvalds 	struct sk_buff *skb;
11171da177e4SLinus Torvalds 	unsigned char *asmptr;
11181da177e4SLinus Torvalds 	int n, size, qbit = 0;
11191da177e4SLinus Torvalds 
11201da177e4SLinus Torvalds 	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_CMSG_COMPAT))
11211da177e4SLinus Torvalds 		return -EINVAL;
11221da177e4SLinus Torvalds 
11231da177e4SLinus Torvalds 	if (sock_flag(sk, SOCK_ZAPPED))
11241da177e4SLinus Torvalds 		return -EADDRNOTAVAIL;
11251da177e4SLinus Torvalds 
11261da177e4SLinus Torvalds 	if (sk->sk_shutdown & SEND_SHUTDOWN) {
11271da177e4SLinus Torvalds 		send_sig(SIGPIPE, current, 0);
11281da177e4SLinus Torvalds 		return -EPIPE;
11291da177e4SLinus Torvalds 	}
11301da177e4SLinus Torvalds 
11311da177e4SLinus Torvalds 	if (rose->neighbour == NULL || rose->device == NULL)
11321da177e4SLinus Torvalds 		return -ENETUNREACH;
11331da177e4SLinus Torvalds 
11341da177e4SLinus Torvalds 	if (usrose != NULL) {
11351da177e4SLinus Torvalds 		if (msg->msg_namelen != sizeof(struct sockaddr_rose) && msg->msg_namelen != sizeof(struct full_sockaddr_rose))
11361da177e4SLinus Torvalds 			return -EINVAL;
11371da177e4SLinus Torvalds 		memset(&srose, 0, sizeof(struct full_sockaddr_rose));
11381da177e4SLinus Torvalds 		memcpy(&srose, usrose, msg->msg_namelen);
11391da177e4SLinus Torvalds 		if (rosecmp(&rose->dest_addr, &srose.srose_addr) != 0 ||
11401da177e4SLinus Torvalds 		    ax25cmp(&rose->dest_call, &srose.srose_call) != 0)
11411da177e4SLinus Torvalds 			return -EISCONN;
11421da177e4SLinus Torvalds 		if (srose.srose_ndigis != rose->dest_ndigis)
11431da177e4SLinus Torvalds 			return -EISCONN;
11441da177e4SLinus Torvalds 		if (srose.srose_ndigis == rose->dest_ndigis) {
11451da177e4SLinus Torvalds 			for (n = 0 ; n < srose.srose_ndigis ; n++)
11461da177e4SLinus Torvalds 				if (ax25cmp(&rose->dest_digis[n],
11471da177e4SLinus Torvalds 					    &srose.srose_digis[n]))
11481da177e4SLinus Torvalds 					return -EISCONN;
11491da177e4SLinus Torvalds 		}
11501da177e4SLinus Torvalds 		if (srose.srose_family != AF_ROSE)
11511da177e4SLinus Torvalds 			return -EINVAL;
11521da177e4SLinus Torvalds 	} else {
11531da177e4SLinus Torvalds 		if (sk->sk_state != TCP_ESTABLISHED)
11541da177e4SLinus Torvalds 			return -ENOTCONN;
11551da177e4SLinus Torvalds 
11561da177e4SLinus Torvalds 		srose.srose_family = AF_ROSE;
11571da177e4SLinus Torvalds 		srose.srose_addr   = rose->dest_addr;
11581da177e4SLinus Torvalds 		srose.srose_call   = rose->dest_call;
11591da177e4SLinus Torvalds 		srose.srose_ndigis = rose->dest_ndigis;
11601da177e4SLinus Torvalds 		for (n = 0 ; n < rose->dest_ndigis ; n++)
11611da177e4SLinus Torvalds 			srose.srose_digis[n] = rose->dest_digis[n];
11621da177e4SLinus Torvalds 	}
11631da177e4SLinus Torvalds 
11641da177e4SLinus Torvalds 	/* Build a packet */
116583e0bbcbSAlan Cox 	/* Sanity check the packet size */
116683e0bbcbSAlan Cox 	if (len > 65535)
116783e0bbcbSAlan Cox 		return -EMSGSIZE;
116883e0bbcbSAlan Cox 
11691da177e4SLinus Torvalds 	size = len + AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN;
11701da177e4SLinus Torvalds 
11711da177e4SLinus Torvalds 	if ((skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL)
11721da177e4SLinus Torvalds 		return err;
11731da177e4SLinus Torvalds 
11741da177e4SLinus Torvalds 	skb_reserve(skb, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN);
11751da177e4SLinus Torvalds 
11761da177e4SLinus Torvalds 	/*
11771da177e4SLinus Torvalds 	 *	Put the data on the end
11781da177e4SLinus Torvalds 	 */
11791da177e4SLinus Torvalds 
1180eeeb0374SArnaldo Carvalho de Melo 	skb_reset_transport_header(skb);
1181eeeb0374SArnaldo Carvalho de Melo 	skb_put(skb, len);
11821da177e4SLinus Torvalds 
11836ce8e9ceSAl Viro 	err = memcpy_from_msg(skb_transport_header(skb), msg, len);
11841da177e4SLinus Torvalds 	if (err) {
11851da177e4SLinus Torvalds 		kfree_skb(skb);
11861da177e4SLinus Torvalds 		return err;
11871da177e4SLinus Torvalds 	}
11881da177e4SLinus Torvalds 
11891da177e4SLinus Torvalds 	/*
11901da177e4SLinus Torvalds 	 *	If the Q BIT Include socket option is in force, the first
11911da177e4SLinus Torvalds 	 *	byte of the user data is the logical value of the Q Bit.
11921da177e4SLinus Torvalds 	 */
11931da177e4SLinus Torvalds 	if (rose->qbitincl) {
11941da177e4SLinus Torvalds 		qbit = skb->data[0];
11951da177e4SLinus Torvalds 		skb_pull(skb, 1);
11961da177e4SLinus Torvalds 	}
11971da177e4SLinus Torvalds 
11981da177e4SLinus Torvalds 	/*
11991da177e4SLinus Torvalds 	 *	Push down the ROSE header
12001da177e4SLinus Torvalds 	 */
12011da177e4SLinus Torvalds 	asmptr = skb_push(skb, ROSE_MIN_LEN);
12021da177e4SLinus Torvalds 
12031da177e4SLinus Torvalds 	/* Build a ROSE Network header */
12041da177e4SLinus Torvalds 	asmptr[0] = ((rose->lci >> 8) & 0x0F) | ROSE_GFI;
12051da177e4SLinus Torvalds 	asmptr[1] = (rose->lci >> 0) & 0xFF;
12061da177e4SLinus Torvalds 	asmptr[2] = ROSE_DATA;
12071da177e4SLinus Torvalds 
12081da177e4SLinus Torvalds 	if (qbit)
12091da177e4SLinus Torvalds 		asmptr[0] |= ROSE_Q_BIT;
12101da177e4SLinus Torvalds 
12111da177e4SLinus Torvalds 	if (sk->sk_state != TCP_ESTABLISHED) {
12121da177e4SLinus Torvalds 		kfree_skb(skb);
12131da177e4SLinus Torvalds 		return -ENOTCONN;
12141da177e4SLinus Torvalds 	}
12151da177e4SLinus Torvalds 
12161da177e4SLinus Torvalds #ifdef M_BIT
12171da177e4SLinus Torvalds #define ROSE_PACLEN (256-ROSE_MIN_LEN)
12181da177e4SLinus Torvalds 	if (skb->len - ROSE_MIN_LEN > ROSE_PACLEN) {
12191da177e4SLinus Torvalds 		unsigned char header[ROSE_MIN_LEN];
12201da177e4SLinus Torvalds 		struct sk_buff *skbn;
12211da177e4SLinus Torvalds 		int frontlen;
12221da177e4SLinus Torvalds 		int lg;
12231da177e4SLinus Torvalds 
12241da177e4SLinus Torvalds 		/* Save a copy of the Header */
1225d626f62bSArnaldo Carvalho de Melo 		skb_copy_from_linear_data(skb, header, ROSE_MIN_LEN);
12261da177e4SLinus Torvalds 		skb_pull(skb, ROSE_MIN_LEN);
12271da177e4SLinus Torvalds 
12281da177e4SLinus Torvalds 		frontlen = skb_headroom(skb);
12291da177e4SLinus Torvalds 
12301da177e4SLinus Torvalds 		while (skb->len > 0) {
12311da177e4SLinus Torvalds 			if ((skbn = sock_alloc_send_skb(sk, frontlen + ROSE_PACLEN, 0, &err)) == NULL) {
12321da177e4SLinus Torvalds 				kfree_skb(skb);
12331da177e4SLinus Torvalds 				return err;
12341da177e4SLinus Torvalds 			}
12351da177e4SLinus Torvalds 
12361da177e4SLinus Torvalds 			skbn->sk   = sk;
12371da177e4SLinus Torvalds 			skbn->free = 1;
12381da177e4SLinus Torvalds 			skbn->arp  = 1;
12391da177e4SLinus Torvalds 
12401da177e4SLinus Torvalds 			skb_reserve(skbn, frontlen);
12411da177e4SLinus Torvalds 
12421da177e4SLinus Torvalds 			lg = (ROSE_PACLEN > skb->len) ? skb->len : ROSE_PACLEN;
12431da177e4SLinus Torvalds 
12441da177e4SLinus Torvalds 			/* Copy the user data */
1245d626f62bSArnaldo Carvalho de Melo 			skb_copy_from_linear_data(skb, skb_put(skbn, lg), lg);
12461da177e4SLinus Torvalds 			skb_pull(skb, lg);
12471da177e4SLinus Torvalds 
12481da177e4SLinus Torvalds 			/* Duplicate the Header */
12491da177e4SLinus Torvalds 			skb_push(skbn, ROSE_MIN_LEN);
125027d7ff46SArnaldo Carvalho de Melo 			skb_copy_to_linear_data(skbn, header, ROSE_MIN_LEN);
12511da177e4SLinus Torvalds 
12521da177e4SLinus Torvalds 			if (skb->len > 0)
12531da177e4SLinus Torvalds 				skbn->data[2] |= M_BIT;
12541da177e4SLinus Torvalds 
12551da177e4SLinus Torvalds 			skb_queue_tail(&sk->sk_write_queue, skbn); /* Throw it on the queue */
12561da177e4SLinus Torvalds 		}
12571da177e4SLinus Torvalds 
12581da177e4SLinus Torvalds 		skb->free = 1;
12591da177e4SLinus Torvalds 		kfree_skb(skb);
12601da177e4SLinus Torvalds 	} else {
12611da177e4SLinus Torvalds 		skb_queue_tail(&sk->sk_write_queue, skb);		/* Throw it on the queue */
12621da177e4SLinus Torvalds 	}
12631da177e4SLinus Torvalds #else
12641da177e4SLinus Torvalds 	skb_queue_tail(&sk->sk_write_queue, skb);	/* Shove it onto the queue */
12651da177e4SLinus Torvalds #endif
12661da177e4SLinus Torvalds 
12671da177e4SLinus Torvalds 	rose_kick(sk);
12681da177e4SLinus Torvalds 
12691da177e4SLinus Torvalds 	return len;
12701da177e4SLinus Torvalds }
12711da177e4SLinus Torvalds 
12721da177e4SLinus Torvalds 
rose_recvmsg(struct socket * sock,struct msghdr * msg,size_t size,int flags)12731b784140SYing Xue static int rose_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
12741b784140SYing Xue 			int flags)
12751da177e4SLinus Torvalds {
12761da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
12771da177e4SLinus Torvalds 	struct rose_sock *rose = rose_sk(sk);
12781da177e4SLinus Torvalds 	size_t copied;
12791da177e4SLinus Torvalds 	unsigned char *asmptr;
12801da177e4SLinus Torvalds 	struct sk_buff *skb;
12811da177e4SLinus Torvalds 	int n, er, qbit;
12821da177e4SLinus Torvalds 
12831da177e4SLinus Torvalds 	/*
12841da177e4SLinus Torvalds 	 * This works for seqpacket too. The receiver has ordered the queue for
12851da177e4SLinus Torvalds 	 * us! We do one quick check first though
12861da177e4SLinus Torvalds 	 */
12871da177e4SLinus Torvalds 	if (sk->sk_state != TCP_ESTABLISHED)
12881da177e4SLinus Torvalds 		return -ENOTCONN;
12891da177e4SLinus Torvalds 
12901da177e4SLinus Torvalds 	/* Now we can treat all alike */
1291f4b41f06SOliver Hartkopp 	skb = skb_recv_datagram(sk, flags, &er);
1292f4b41f06SOliver Hartkopp 	if (!skb)
12931da177e4SLinus Torvalds 		return er;
12941da177e4SLinus Torvalds 
12951da177e4SLinus Torvalds 	qbit = (skb->data[0] & ROSE_Q_BIT) == ROSE_Q_BIT;
12961da177e4SLinus Torvalds 
12971da177e4SLinus Torvalds 	skb_pull(skb, ROSE_MIN_LEN);
12981da177e4SLinus Torvalds 
12991da177e4SLinus Torvalds 	if (rose->qbitincl) {
13001da177e4SLinus Torvalds 		asmptr  = skb_push(skb, 1);
13011da177e4SLinus Torvalds 		*asmptr = qbit;
13021da177e4SLinus Torvalds 	}
13031da177e4SLinus Torvalds 
1304badff6d0SArnaldo Carvalho de Melo 	skb_reset_transport_header(skb);
13051da177e4SLinus Torvalds 	copied     = skb->len;
13061da177e4SLinus Torvalds 
13071da177e4SLinus Torvalds 	if (copied > size) {
13081da177e4SLinus Torvalds 		copied = size;
13091da177e4SLinus Torvalds 		msg->msg_flags |= MSG_TRUNC;
13101da177e4SLinus Torvalds 	}
13111da177e4SLinus Torvalds 
131251f3d02bSDavid S. Miller 	skb_copy_datagram_msg(skb, 0, msg, copied);
13131da177e4SLinus Torvalds 
1314f3d33426SHannes Frederic Sowa 	if (msg->msg_name) {
1315f3d33426SHannes Frederic Sowa 		struct sockaddr_rose *srose;
1316342dfc30SSteffen Hurrle 		DECLARE_SOCKADDR(struct full_sockaddr_rose *, full_srose,
1317342dfc30SSteffen Hurrle 				 msg->msg_name);
1318f3d33426SHannes Frederic Sowa 
1319f3d33426SHannes Frederic Sowa 		memset(msg->msg_name, 0, sizeof(struct full_sockaddr_rose));
1320f3d33426SHannes Frederic Sowa 		srose = msg->msg_name;
13211da177e4SLinus Torvalds 		srose->srose_family = AF_ROSE;
13221da177e4SLinus Torvalds 		srose->srose_addr   = rose->dest_addr;
13231da177e4SLinus Torvalds 		srose->srose_call   = rose->dest_call;
13241da177e4SLinus Torvalds 		srose->srose_ndigis = rose->dest_ndigis;
13251da177e4SLinus Torvalds 		for (n = 0 ; n < rose->dest_ndigis ; n++)
13261da177e4SLinus Torvalds 			full_srose->srose_digis[n] = rose->dest_digis[n];
13271da177e4SLinus Torvalds 		msg->msg_namelen = sizeof(struct full_sockaddr_rose);
13281da177e4SLinus Torvalds 	}
13291da177e4SLinus Torvalds 
13301da177e4SLinus Torvalds 	skb_free_datagram(sk, skb);
13311da177e4SLinus Torvalds 
13321da177e4SLinus Torvalds 	return copied;
13331da177e4SLinus Torvalds }
13341da177e4SLinus Torvalds 
13351da177e4SLinus Torvalds 
rose_ioctl(struct socket * sock,unsigned int cmd,unsigned long arg)13361da177e4SLinus Torvalds static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
13371da177e4SLinus Torvalds {
13381da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
13391da177e4SLinus Torvalds 	struct rose_sock *rose = rose_sk(sk);
13401da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
13411da177e4SLinus Torvalds 
13421da177e4SLinus Torvalds 	switch (cmd) {
13431da177e4SLinus Torvalds 	case TIOCOUTQ: {
13441da177e4SLinus Torvalds 		long amount;
134531e6d363SEric Dumazet 
134631e6d363SEric Dumazet 		amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
13471da177e4SLinus Torvalds 		if (amount < 0)
13481da177e4SLinus Torvalds 			amount = 0;
13491da177e4SLinus Torvalds 		return put_user(amount, (unsigned int __user *) argp);
13501da177e4SLinus Torvalds 	}
13511da177e4SLinus Torvalds 
13521da177e4SLinus Torvalds 	case TIOCINQ: {
13531da177e4SLinus Torvalds 		struct sk_buff *skb;
13541da177e4SLinus Torvalds 		long amount = 0L;
135563caa518SHyunwoo Kim 
135663caa518SHyunwoo Kim 		spin_lock_irq(&sk->sk_receive_queue.lock);
13571da177e4SLinus Torvalds 		if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
13581da177e4SLinus Torvalds 			amount = skb->len;
135963caa518SHyunwoo Kim 		spin_unlock_irq(&sk->sk_receive_queue.lock);
13601da177e4SLinus Torvalds 		return put_user(amount, (unsigned int __user *) argp);
13611da177e4SLinus Torvalds 	}
13621da177e4SLinus Torvalds 
13631da177e4SLinus Torvalds 	case SIOCGIFADDR:
13641da177e4SLinus Torvalds 	case SIOCSIFADDR:
13651da177e4SLinus Torvalds 	case SIOCGIFDSTADDR:
13661da177e4SLinus Torvalds 	case SIOCSIFDSTADDR:
13671da177e4SLinus Torvalds 	case SIOCGIFBRDADDR:
13681da177e4SLinus Torvalds 	case SIOCSIFBRDADDR:
13691da177e4SLinus Torvalds 	case SIOCGIFNETMASK:
13701da177e4SLinus Torvalds 	case SIOCSIFNETMASK:
13711da177e4SLinus Torvalds 	case SIOCGIFMETRIC:
13721da177e4SLinus Torvalds 	case SIOCSIFMETRIC:
13731da177e4SLinus Torvalds 		return -EINVAL;
13741da177e4SLinus Torvalds 
13751da177e4SLinus Torvalds 	case SIOCADDRT:
13761da177e4SLinus Torvalds 	case SIOCDELRT:
13771da177e4SLinus Torvalds 	case SIOCRSCLRRT:
13781da177e4SLinus Torvalds 		if (!capable(CAP_NET_ADMIN))
13791da177e4SLinus Torvalds 			return -EPERM;
13801da177e4SLinus Torvalds 		return rose_rt_ioctl(cmd, argp);
13811da177e4SLinus Torvalds 
13821da177e4SLinus Torvalds 	case SIOCRSGCAUSE: {
13831da177e4SLinus Torvalds 		struct rose_cause_struct rose_cause;
13841da177e4SLinus Torvalds 		rose_cause.cause      = rose->cause;
13851da177e4SLinus Torvalds 		rose_cause.diagnostic = rose->diagnostic;
13861da177e4SLinus Torvalds 		return copy_to_user(argp, &rose_cause, sizeof(struct rose_cause_struct)) ? -EFAULT : 0;
13871da177e4SLinus Torvalds 	}
13881da177e4SLinus Torvalds 
13891da177e4SLinus Torvalds 	case SIOCRSSCAUSE: {
13901da177e4SLinus Torvalds 		struct rose_cause_struct rose_cause;
13911da177e4SLinus Torvalds 		if (copy_from_user(&rose_cause, argp, sizeof(struct rose_cause_struct)))
13921da177e4SLinus Torvalds 			return -EFAULT;
13931da177e4SLinus Torvalds 		rose->cause      = rose_cause.cause;
13941da177e4SLinus Torvalds 		rose->diagnostic = rose_cause.diagnostic;
13951da177e4SLinus Torvalds 		return 0;
13961da177e4SLinus Torvalds 	}
13971da177e4SLinus Torvalds 
13981da177e4SLinus Torvalds 	case SIOCRSSL2CALL:
13991da177e4SLinus Torvalds 		if (!capable(CAP_NET_ADMIN)) return -EPERM;
14001da177e4SLinus Torvalds 		if (ax25cmp(&rose_callsign, &null_ax25_address) != 0)
14011da177e4SLinus Torvalds 			ax25_listen_release(&rose_callsign, NULL);
14021da177e4SLinus Torvalds 		if (copy_from_user(&rose_callsign, argp, sizeof(ax25_address)))
14031da177e4SLinus Torvalds 			return -EFAULT;
14041da177e4SLinus Torvalds 		if (ax25cmp(&rose_callsign, &null_ax25_address) != 0)
140581dcd169SRalf Baechle 			return ax25_listen_register(&rose_callsign, NULL);
140681dcd169SRalf Baechle 
14071da177e4SLinus Torvalds 		return 0;
14081da177e4SLinus Torvalds 
14091da177e4SLinus Torvalds 	case SIOCRSGL2CALL:
14101da177e4SLinus Torvalds 		return copy_to_user(argp, &rose_callsign, sizeof(ax25_address)) ? -EFAULT : 0;
14111da177e4SLinus Torvalds 
14121da177e4SLinus Torvalds 	case SIOCRSACCEPT:
14131da177e4SLinus Torvalds 		if (rose->state == ROSE_STATE_5) {
14141da177e4SLinus Torvalds 			rose_write_internal(sk, ROSE_CALL_ACCEPTED);
14151da177e4SLinus Torvalds 			rose_start_idletimer(sk);
14161da177e4SLinus Torvalds 			rose->condition = 0x00;
14171da177e4SLinus Torvalds 			rose->vs        = 0;
14181da177e4SLinus Torvalds 			rose->va        = 0;
14191da177e4SLinus Torvalds 			rose->vr        = 0;
14201da177e4SLinus Torvalds 			rose->vl        = 0;
14211da177e4SLinus Torvalds 			rose->state     = ROSE_STATE_3;
14221da177e4SLinus Torvalds 		}
14231da177e4SLinus Torvalds 		return 0;
14241da177e4SLinus Torvalds 
14251da177e4SLinus Torvalds 	default:
1426b5e5fa5eSChristoph Hellwig 		return -ENOIOCTLCMD;
14271da177e4SLinus Torvalds 	}
14281da177e4SLinus Torvalds 
14291da177e4SLinus Torvalds 	return 0;
14301da177e4SLinus Torvalds }
14311da177e4SLinus Torvalds 
14321da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
rose_info_start(struct seq_file * seq,loff_t * pos)14331da177e4SLinus Torvalds static void *rose_info_start(struct seq_file *seq, loff_t *pos)
143495b7d924SEric Dumazet 	__acquires(rose_list_lock)
14351da177e4SLinus Torvalds {
14361da177e4SLinus Torvalds 	spin_lock_bh(&rose_list_lock);
1437b999748aSLi Zefan 	return seq_hlist_start_head(&rose_list, *pos);
14381da177e4SLinus Torvalds }
14391da177e4SLinus Torvalds 
rose_info_next(struct seq_file * seq,void * v,loff_t * pos)14401da177e4SLinus Torvalds static void *rose_info_next(struct seq_file *seq, void *v, loff_t *pos)
14411da177e4SLinus Torvalds {
1442b999748aSLi Zefan 	return seq_hlist_next(v, &rose_list, pos);
14431da177e4SLinus Torvalds }
14441da177e4SLinus Torvalds 
rose_info_stop(struct seq_file * seq,void * v)14451da177e4SLinus Torvalds static void rose_info_stop(struct seq_file *seq, void *v)
144695b7d924SEric Dumazet 	__releases(rose_list_lock)
14471da177e4SLinus Torvalds {
14481da177e4SLinus Torvalds 	spin_unlock_bh(&rose_list_lock);
14491da177e4SLinus Torvalds }
14501da177e4SLinus Torvalds 
rose_info_show(struct seq_file * seq,void * v)14511da177e4SLinus Torvalds static int rose_info_show(struct seq_file *seq, void *v)
14521da177e4SLinus Torvalds {
1453dcf777f6SRalf Baechle 	char buf[11], rsbuf[11];
1454f75268cdSRalf Baechle 
14551da177e4SLinus Torvalds 	if (v == SEQ_START_TOKEN)
14561da177e4SLinus Torvalds 		seq_puts(seq,
14571da177e4SLinus Torvalds 			 "dest_addr  dest_call src_addr   src_call  dev   lci neigh st vs vr va   t  t1  t2  t3  hb    idle Snd-Q Rcv-Q inode\n");
14581da177e4SLinus Torvalds 
14591da177e4SLinus Torvalds 	else {
1460b999748aSLi Zefan 		struct sock *s = sk_entry(v);
14611da177e4SLinus Torvalds 		struct rose_sock *rose = rose_sk(s);
14621da177e4SLinus Torvalds 		const char *devname, *callsign;
14631da177e4SLinus Torvalds 		const struct net_device *dev = rose->device;
14641da177e4SLinus Torvalds 
14651da177e4SLinus Torvalds 		if (!dev)
14661da177e4SLinus Torvalds 			devname = "???";
14671da177e4SLinus Torvalds 		else
14681da177e4SLinus Torvalds 			devname = dev->name;
14691da177e4SLinus Torvalds 
14701da177e4SLinus Torvalds 		seq_printf(seq, "%-10s %-9s ",
1471dcf777f6SRalf Baechle 			   rose2asc(rsbuf, &rose->dest_addr),
1472f75268cdSRalf Baechle 			   ax2asc(buf, &rose->dest_call));
14731da177e4SLinus Torvalds 
14741da177e4SLinus Torvalds 		if (ax25cmp(&rose->source_call, &null_ax25_address) == 0)
14751da177e4SLinus Torvalds 			callsign = "??????-?";
14761da177e4SLinus Torvalds 		else
1477f75268cdSRalf Baechle 			callsign = ax2asc(buf, &rose->source_call);
14781da177e4SLinus Torvalds 
14791da177e4SLinus Torvalds 		seq_printf(seq,
14801da177e4SLinus Torvalds 			   "%-10s %-9s %-5s %3.3X %05d  %d  %d  %d  %d %3lu %3lu %3lu %3lu %3lu %3lu/%03lu %5d %5d %ld\n",
1481dcf777f6SRalf Baechle 			rose2asc(rsbuf, &rose->source_addr),
14821da177e4SLinus Torvalds 			callsign,
14831da177e4SLinus Torvalds 			devname,
14841da177e4SLinus Torvalds 			rose->lci & 0x0FFF,
14851da177e4SLinus Torvalds 			(rose->neighbour) ? rose->neighbour->number : 0,
14861da177e4SLinus Torvalds 			rose->state,
14871da177e4SLinus Torvalds 			rose->vs,
14881da177e4SLinus Torvalds 			rose->vr,
14891da177e4SLinus Torvalds 			rose->va,
14901da177e4SLinus Torvalds 			ax25_display_timer(&rose->timer) / HZ,
14911da177e4SLinus Torvalds 			rose->t1 / HZ,
14921da177e4SLinus Torvalds 			rose->t2 / HZ,
14931da177e4SLinus Torvalds 			rose->t3 / HZ,
14941da177e4SLinus Torvalds 			rose->hb / HZ,
14951da177e4SLinus Torvalds 			ax25_display_timer(&rose->idletimer) / (60 * HZ),
14961da177e4SLinus Torvalds 			rose->idle / (60 * HZ),
149731e6d363SEric Dumazet 			sk_wmem_alloc_get(s),
149831e6d363SEric Dumazet 			sk_rmem_alloc_get(s),
14991da177e4SLinus Torvalds 			s->sk_socket ? SOCK_INODE(s->sk_socket)->i_ino : 0L);
15001da177e4SLinus Torvalds 	}
15011da177e4SLinus Torvalds 
15021da177e4SLinus Torvalds 	return 0;
15031da177e4SLinus Torvalds }
15041da177e4SLinus Torvalds 
150556b3d975SPhilippe De Muyter static const struct seq_operations rose_info_seqops = {
15061da177e4SLinus Torvalds 	.start = rose_info_start,
15071da177e4SLinus Torvalds 	.next = rose_info_next,
15081da177e4SLinus Torvalds 	.stop = rose_info_stop,
15091da177e4SLinus Torvalds 	.show = rose_info_show,
15101da177e4SLinus Torvalds };
15111da177e4SLinus Torvalds #endif	/* CONFIG_PROC_FS */
15121da177e4SLinus Torvalds 
1513ec1b4cf7SStephen Hemminger static const struct net_proto_family rose_family_ops = {
15141da177e4SLinus Torvalds 	.family		=	PF_ROSE,
15151da177e4SLinus Torvalds 	.create		=	rose_create,
15161da177e4SLinus Torvalds 	.owner		=	THIS_MODULE,
15171da177e4SLinus Torvalds };
15181da177e4SLinus Torvalds 
15195708e868SAlexey Dobriyan static const struct proto_ops rose_proto_ops = {
15201da177e4SLinus Torvalds 	.family		=	PF_ROSE,
15211da177e4SLinus Torvalds 	.owner		=	THIS_MODULE,
15221da177e4SLinus Torvalds 	.release	=	rose_release,
15231da177e4SLinus Torvalds 	.bind		=	rose_bind,
15241da177e4SLinus Torvalds 	.connect	=	rose_connect,
15251da177e4SLinus Torvalds 	.socketpair	=	sock_no_socketpair,
15261da177e4SLinus Torvalds 	.accept		=	rose_accept,
15271da177e4SLinus Torvalds 	.getname	=	rose_getname,
1528a11e1d43SLinus Torvalds 	.poll		=	datagram_poll,
15291da177e4SLinus Torvalds 	.ioctl		=	rose_ioctl,
1530c7cbdbf2SArnd Bergmann 	.gettstamp	=	sock_gettstamp,
15311da177e4SLinus Torvalds 	.listen		=	rose_listen,
15321da177e4SLinus Torvalds 	.shutdown	=	sock_no_shutdown,
15331da177e4SLinus Torvalds 	.setsockopt	=	rose_setsockopt,
15341da177e4SLinus Torvalds 	.getsockopt	=	rose_getsockopt,
15351da177e4SLinus Torvalds 	.sendmsg	=	rose_sendmsg,
15361da177e4SLinus Torvalds 	.recvmsg	=	rose_recvmsg,
15371da177e4SLinus Torvalds 	.mmap		=	sock_no_mmap,
15381da177e4SLinus Torvalds };
15391da177e4SLinus Torvalds 
15401da177e4SLinus Torvalds static struct notifier_block rose_dev_notifier = {
15411da177e4SLinus Torvalds 	.notifier_call	=	rose_device_event,
15421da177e4SLinus Torvalds };
15431da177e4SLinus Torvalds 
15441da177e4SLinus Torvalds static struct net_device **dev_rose;
15451da177e4SLinus Torvalds 
15468d5cf596SRalf Baechle static struct ax25_protocol rose_pid = {
15478d5cf596SRalf Baechle 	.pid	= AX25_P_ROSE,
15488d5cf596SRalf Baechle 	.func	= rose_route_frame
15498d5cf596SRalf Baechle };
15508d5cf596SRalf Baechle 
1551a4282717SRalf Baechle static struct ax25_linkfail rose_linkfail_notifier = {
1552a4282717SRalf Baechle 	.func	= rose_link_failed
1553a4282717SRalf Baechle };
1554a4282717SRalf Baechle 
rose_proto_init(void)15551da177e4SLinus Torvalds static int __init rose_proto_init(void)
15561da177e4SLinus Torvalds {
15571da177e4SLinus Torvalds 	int i;
1558a83cd2ccSAlexey Dobriyan 	int rc;
15591da177e4SLinus Torvalds 
1560a83cd2ccSAlexey Dobriyan 	if (rose_ndevs > 0x7FFFFFFF/sizeof(struct net_device *)) {
15614d299f18SColin Ian King 		printk(KERN_ERR "ROSE: rose_proto_init - rose_ndevs parameter too large\n");
1562a83cd2ccSAlexey Dobriyan 		rc = -EINVAL;
1563a83cd2ccSAlexey Dobriyan 		goto out;
1564a83cd2ccSAlexey Dobriyan 	}
1565a83cd2ccSAlexey Dobriyan 
1566a83cd2ccSAlexey Dobriyan 	rc = proto_register(&rose_proto, 0);
15671da177e4SLinus Torvalds 	if (rc != 0)
15681da177e4SLinus Torvalds 		goto out;
15691da177e4SLinus Torvalds 
15701da177e4SLinus Torvalds 	rose_callsign = null_ax25_address;
15711da177e4SLinus Torvalds 
15726396bb22SKees Cook 	dev_rose = kcalloc(rose_ndevs, sizeof(struct net_device *),
15736396bb22SKees Cook 			   GFP_KERNEL);
15741da177e4SLinus Torvalds 	if (dev_rose == NULL) {
15751da177e4SLinus Torvalds 		printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate device structure\n");
1576a83cd2ccSAlexey Dobriyan 		rc = -ENOMEM;
1577a83cd2ccSAlexey Dobriyan 		goto out_proto_unregister;
15781da177e4SLinus Torvalds 	}
15791da177e4SLinus Torvalds 
15801da177e4SLinus Torvalds 	for (i = 0; i < rose_ndevs; i++) {
15811da177e4SLinus Torvalds 		struct net_device *dev;
15821da177e4SLinus Torvalds 		char name[IFNAMSIZ];
15831da177e4SLinus Torvalds 
15841da177e4SLinus Torvalds 		sprintf(name, "rose%d", i);
1585c835a677STom Gundersen 		dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, rose_setup);
15861da177e4SLinus Torvalds 		if (!dev) {
15871da177e4SLinus Torvalds 			printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate memory\n");
158870ff3b66SAlexey Dobriyan 			rc = -ENOMEM;
15891da177e4SLinus Torvalds 			goto fail;
15901da177e4SLinus Torvalds 		}
159170ff3b66SAlexey Dobriyan 		rc = register_netdev(dev);
159270ff3b66SAlexey Dobriyan 		if (rc) {
1593520d1b83SAlexey Dobriyan 			printk(KERN_ERR "ROSE: netdevice registration failed\n");
15941da177e4SLinus Torvalds 			free_netdev(dev);
15951da177e4SLinus Torvalds 			goto fail;
15961da177e4SLinus Torvalds 		}
15971a33e10eSCong Wang 		rose_set_lockdep_key(dev);
15981da177e4SLinus Torvalds 		dev_rose[i] = dev;
15991da177e4SLinus Torvalds 	}
16001da177e4SLinus Torvalds 
16011da177e4SLinus Torvalds 	sock_register(&rose_family_ops);
16021da177e4SLinus Torvalds 	register_netdevice_notifier(&rose_dev_notifier);
16031da177e4SLinus Torvalds 
16048d5cf596SRalf Baechle 	ax25_register_pid(&rose_pid);
1605a4282717SRalf Baechle 	ax25_linkfail_register(&rose_linkfail_notifier);
16061da177e4SLinus Torvalds 
16071da177e4SLinus Torvalds #ifdef CONFIG_SYSCTL
16081da177e4SLinus Torvalds 	rose_register_sysctl();
16091da177e4SLinus Torvalds #endif
16101da177e4SLinus Torvalds 	rose_loopback_init();
16111da177e4SLinus Torvalds 
16121da177e4SLinus Torvalds 	rose_add_loopback_neigh();
16131da177e4SLinus Torvalds 
1614fddda2b7SChristoph Hellwig 	proc_create_seq("rose", 0444, init_net.proc_net, &rose_info_seqops);
1615fddda2b7SChristoph Hellwig 	proc_create_seq("rose_neigh", 0444, init_net.proc_net,
1616fddda2b7SChristoph Hellwig 		    &rose_neigh_seqops);
1617fddda2b7SChristoph Hellwig 	proc_create_seq("rose_nodes", 0444, init_net.proc_net,
1618fddda2b7SChristoph Hellwig 		    &rose_node_seqops);
1619fddda2b7SChristoph Hellwig 	proc_create_seq("rose_routes", 0444, init_net.proc_net,
1620fddda2b7SChristoph Hellwig 		    &rose_route_seqops);
16211da177e4SLinus Torvalds out:
16221da177e4SLinus Torvalds 	return rc;
16231da177e4SLinus Torvalds fail:
16241da177e4SLinus Torvalds 	while (--i >= 0) {
16251da177e4SLinus Torvalds 		unregister_netdev(dev_rose[i]);
16261da177e4SLinus Torvalds 		free_netdev(dev_rose[i]);
16271da177e4SLinus Torvalds 	}
16281da177e4SLinus Torvalds 	kfree(dev_rose);
1629a83cd2ccSAlexey Dobriyan out_proto_unregister:
16301da177e4SLinus Torvalds 	proto_unregister(&rose_proto);
163170ff3b66SAlexey Dobriyan 	goto out;
16321da177e4SLinus Torvalds }
16331da177e4SLinus Torvalds module_init(rose_proto_init);
16341da177e4SLinus Torvalds 
16351da177e4SLinus Torvalds module_param(rose_ndevs, int, 0);
16361da177e4SLinus Torvalds MODULE_PARM_DESC(rose_ndevs, "number of ROSE devices");
16371da177e4SLinus Torvalds 
16381da177e4SLinus Torvalds MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>");
16391da177e4SLinus Torvalds MODULE_DESCRIPTION("The amateur radio ROSE network layer protocol");
16401da177e4SLinus Torvalds MODULE_LICENSE("GPL");
16411da177e4SLinus Torvalds MODULE_ALIAS_NETPROTO(PF_ROSE);
16421da177e4SLinus Torvalds 
rose_exit(void)16431da177e4SLinus Torvalds static void __exit rose_exit(void)
16441da177e4SLinus Torvalds {
16451da177e4SLinus Torvalds 	int i;
16461da177e4SLinus Torvalds 
1647ece31ffdSGao feng 	remove_proc_entry("rose", init_net.proc_net);
1648ece31ffdSGao feng 	remove_proc_entry("rose_neigh", init_net.proc_net);
1649ece31ffdSGao feng 	remove_proc_entry("rose_nodes", init_net.proc_net);
1650ece31ffdSGao feng 	remove_proc_entry("rose_routes", init_net.proc_net);
16511da177e4SLinus Torvalds 	rose_loopback_clear();
16521da177e4SLinus Torvalds 
16531da177e4SLinus Torvalds 	rose_rt_free();
16541da177e4SLinus Torvalds 
16551da177e4SLinus Torvalds 	ax25_protocol_release(AX25_P_ROSE);
1656a4282717SRalf Baechle 	ax25_linkfail_release(&rose_linkfail_notifier);
16571da177e4SLinus Torvalds 
16581da177e4SLinus Torvalds 	if (ax25cmp(&rose_callsign, &null_ax25_address) != 0)
16591da177e4SLinus Torvalds 		ax25_listen_release(&rose_callsign, NULL);
16601da177e4SLinus Torvalds 
16611da177e4SLinus Torvalds #ifdef CONFIG_SYSCTL
16621da177e4SLinus Torvalds 	rose_unregister_sysctl();
16631da177e4SLinus Torvalds #endif
16641da177e4SLinus Torvalds 	unregister_netdevice_notifier(&rose_dev_notifier);
16651da177e4SLinus Torvalds 
16661da177e4SLinus Torvalds 	sock_unregister(PF_ROSE);
16671da177e4SLinus Torvalds 
16681da177e4SLinus Torvalds 	for (i = 0; i < rose_ndevs; i++) {
16691da177e4SLinus Torvalds 		struct net_device *dev = dev_rose[i];
16701da177e4SLinus Torvalds 
16711da177e4SLinus Torvalds 		if (dev) {
16721da177e4SLinus Torvalds 			unregister_netdev(dev);
16731da177e4SLinus Torvalds 			free_netdev(dev);
16741da177e4SLinus Torvalds 		}
16751da177e4SLinus Torvalds 	}
16761da177e4SLinus Torvalds 
16771da177e4SLinus Torvalds 	kfree(dev_rose);
16781da177e4SLinus Torvalds 	proto_unregister(&rose_proto);
16791da177e4SLinus Torvalds }
16801da177e4SLinus Torvalds 
16811da177e4SLinus Torvalds module_exit(rose_exit);
1682