^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * X.25 Packet Layer release 002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This is ALPHA test software. This code may break your machine,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * randomly fail to work with new releases, misbehave and/or generally
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * screw up. It might even work.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * This code REQUIRES 2.1.15 or higher
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * History
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * X.25 001 Jonathan Naylor Started coding.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * X.25 002 Jonathan Naylor Centralised disconnect handling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * New timer architecture.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * 2000-03-11 Henner Eisen MSG_EOR handling more POSIX compliant.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * 2000-03-22 Daniela Squassoni Allowed disabling/enabling of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * facilities negotiation and increased
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * the throughput upper limit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * 2000-08-27 Arnaldo C. Melo s/suser/capable/ + micro cleanups
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * 2000-09-04 Henner Eisen Set sock->state in x25_accept().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Fixed x25_output() related skb leakage.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * 2000-10-02 Henner Eisen Made x25_kick() single threaded per socket.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * 2000-10-27 Henner Eisen MSG_DONTWAIT for fragment allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * 2000-11-14 Henner Eisen Closing datalink from NETDEV_GOING_DOWN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * 2002-10-06 Arnaldo C. Melo Get rid of cli/sti, move proc stuff to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * x25_proc.c, using seq_file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * 2005-04-02 Shaun Pereira Selective sub address matching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * with call user data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * 2005-04-15 Shaun Pereira Fast select with no restriction on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define pr_fmt(fmt) "X25: " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/capability.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/net.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <net/tcp_states.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <linux/termios.h> /* For TIOCINQ/OUTQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <linux/notifier.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include <linux/compat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #include <net/x25.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #include <net/compat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) int sysctl_x25_call_request_timeout = X25_DEFAULT_T21;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int sysctl_x25_reset_request_timeout = X25_DEFAULT_T22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int sysctl_x25_clear_request_timeout = X25_DEFAULT_T23;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) int sysctl_x25_ack_holdback_timeout = X25_DEFAULT_T2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int sysctl_x25_forward = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) HLIST_HEAD(x25_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) DEFINE_RWLOCK(x25_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static const struct proto_ops x25_proto_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static const struct x25_address null_x25_address = {" "};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct compat_x25_subscrip_struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) char device[200-sizeof(compat_ulong_t)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) compat_ulong_t global_facil_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) compat_uint_t extended;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) int x25_parse_address_block(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct x25_address *called_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct x25_address *calling_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) unsigned char len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) int needed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (!pskb_may_pull(skb, 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* packet has no address block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) goto empty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) len = *skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) needed = 1 + ((len >> 4) + (len & 0x0f) + 1) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (!pskb_may_pull(skb, needed)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /* packet is too short to hold the addresses it claims
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) to hold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) rc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) goto empty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return x25_addr_ntoa(skb->data, called_addr, calling_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) empty:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) *called_addr->x25_addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) *calling_addr->x25_addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct x25_address *calling_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) unsigned int called_len, calling_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) char *called, *calling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) called_len = (*p >> 0) & 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) calling_len = (*p >> 4) & 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) called = called_addr->x25_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) calling = calling_addr->x25_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) p++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) for (i = 0; i < (called_len + calling_len); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (i < called_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (i % 2 != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) *called++ = ((*p >> 0) & 0x0F) + '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) p++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) *called++ = ((*p >> 4) & 0x0F) + '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (i % 2 != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) *calling++ = ((*p >> 0) & 0x0F) + '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) p++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) *calling++ = ((*p >> 4) & 0x0F) + '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) *called = *calling = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return 1 + (called_len + calling_len + 1) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) int x25_addr_aton(unsigned char *p, struct x25_address *called_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct x25_address *calling_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) unsigned int called_len, calling_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) char *called, *calling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) called = called_addr->x25_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) calling = calling_addr->x25_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) called_len = strlen(called);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) calling_len = strlen(calling);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) *p++ = (calling_len << 4) | (called_len << 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) for (i = 0; i < (called_len + calling_len); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (i < called_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (i % 2 != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) *p |= (*called++ - '0') << 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) p++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) *p = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) *p |= (*called++ - '0') << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (i % 2 != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) *p |= (*calling++ - '0') << 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) p++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) *p = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) *p |= (*calling++ - '0') << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return 1 + (called_len + calling_len + 1) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * Socket removal during an interrupt is now safe.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static void x25_remove_socket(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) write_lock_bh(&x25_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) sk_del_node_init(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) write_unlock_bh(&x25_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * Kill all bound sockets on a dropped device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static void x25_kill_by_device(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) struct sock *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) write_lock_bh(&x25_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) sk_for_each(s, &x25_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (x25_sk(s)->neighbour && x25_sk(s)->neighbour->dev == dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) x25_disconnect(s, ENETUNREACH, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) write_unlock_bh(&x25_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * Handle device status changes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static int x25_device_event(struct notifier_block *this, unsigned long event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) void *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct net_device *dev = netdev_notifier_info_to_dev(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct x25_neigh *nb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (!net_eq(dev_net(dev), &init_net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return NOTIFY_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (dev->type == ARPHRD_X25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) #if IS_ENABLED(CONFIG_LLC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) || dev->type == ARPHRD_ETHER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) case NETDEV_UP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) x25_link_device_up(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) case NETDEV_GOING_DOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) nb = x25_get_neigh(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (nb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) x25_terminate_link(nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) x25_neigh_put(nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) case NETDEV_DOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) x25_kill_by_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) x25_route_device_down(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) x25_link_device_down(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return NOTIFY_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * Add a socket to the bound sockets list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static void x25_insert_socket(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) write_lock_bh(&x25_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) sk_add_node(sk, &x25_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) write_unlock_bh(&x25_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * Find a socket that wants to accept the Call Request we just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * received. Check the full list for an address/cud match.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * If no cuds match return the next_best thing, an address match.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * Note: if a listening socket has cud set it must only get calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * with matching cud.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static struct sock *x25_find_listener(struct x25_address *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct sock *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) struct sock *next_best;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) read_lock_bh(&x25_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) next_best = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) sk_for_each(s, &x25_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if ((!strcmp(addr->x25_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) x25_sk(s)->source_addr.x25_addr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) !strcmp(x25_sk(s)->source_addr.x25_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) null_x25_address.x25_addr)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) s->sk_state == TCP_LISTEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * Found a listening socket, now check the incoming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * call user data vs this sockets call user data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (x25_sk(s)->cudmatchlength > 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) skb->len >= x25_sk(s)->cudmatchlength) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if((memcmp(x25_sk(s)->calluserdata.cuddata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) skb->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) x25_sk(s)->cudmatchlength)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) sock_hold(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) next_best = s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (next_best) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) s = next_best;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) sock_hold(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) s = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) read_unlock_bh(&x25_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * Find a connected X.25 socket given my LCI and neighbour.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) static struct sock *__x25_find_socket(unsigned int lci, struct x25_neigh *nb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct sock *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) sk_for_each(s, &x25_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (x25_sk(s)->lci == lci && x25_sk(s)->neighbour == nb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) sock_hold(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) s = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) struct sock *x25_find_socket(unsigned int lci, struct x25_neigh *nb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) struct sock *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) read_lock_bh(&x25_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) s = __x25_find_socket(lci, nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) read_unlock_bh(&x25_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * Find a unique LCI for a given device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) static unsigned int x25_new_lci(struct x25_neigh *nb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) unsigned int lci = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) struct sock *sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) while ((sk = x25_find_socket(lci, nb)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) sock_put(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (++lci == 4096) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) lci = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return lci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * Deferred destroy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static void __x25_destroy_socket(struct sock *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * handler for deferred kills.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static void x25_destroy_timer(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct sock *sk = from_timer(sk, t, sk_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) x25_destroy_socket_from_timer(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * This is called from user mode and the timers. Thus it protects itself
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * against interrupt users but doesn't worry about being called during
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * work. Once it is removed from the queue no interrupt or bottom half
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * will touch it and we are (fairly 8-) ) safe.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * Not static as it's used by the timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static void __x25_destroy_socket(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) x25_stop_heartbeat(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) x25_stop_timer(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) x25_remove_socket(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) x25_clear_queues(sk); /* Flush the queues */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (skb->sk != sk) { /* A pending connection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * Queue the unaccepted socket for death
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) skb->sk->sk_state = TCP_LISTEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) sock_set_flag(skb->sk, SOCK_DEAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) x25_start_heartbeat(skb->sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) x25_sk(skb->sk)->state = X25_STATE_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (sk_has_allocations(sk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) /* Defer: outstanding buffers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) sk->sk_timer.expires = jiffies + 10 * HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) sk->sk_timer.function = x25_destroy_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) add_timer(&sk->sk_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) /* drop last reference so sock_put will free */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) __sock_put(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) void x25_destroy_socket_from_timer(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) sock_hold(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) bh_lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) __x25_destroy_socket(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) bh_unlock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) sock_put(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * Handling for system calls applied via the various interfaces to a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * X.25 socket object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) static int x25_setsockopt(struct socket *sock, int level, int optname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) sockptr_t optval, unsigned int optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) int opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) int rc = -ENOPROTOOPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (level != SOL_X25 || optname != X25_QBITINCL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (optlen < sizeof(int))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (copy_from_sockptr(&opt, optval, sizeof(int)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) set_bit(X25_Q_BIT_FLAG, &x25_sk(sk)->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) clear_bit(X25_Q_BIT_FLAG, &x25_sk(sk)->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static int x25_getsockopt(struct socket *sock, int level, int optname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) char __user *optval, int __user *optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) int val, len, rc = -ENOPROTOOPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (level != SOL_X25 || optname != X25_QBITINCL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (get_user(len, optlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) len = min_t(unsigned int, len, sizeof(int));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (put_user(len, optlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) val = test_bit(X25_Q_BIT_FLAG, &x25_sk(sk)->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) rc = copy_to_user(optval, &val, len) ? -EFAULT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) static int x25_listen(struct socket *sock, int backlog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) int rc = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (sk->sk_state != TCP_LISTEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) sk->sk_max_ack_backlog = backlog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) sk->sk_state = TCP_LISTEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static struct proto x25_proto = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) .name = "X25",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) .obj_size = sizeof(struct x25_sock),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static struct sock *x25_alloc_socket(struct net *net, int kern)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) struct x25_sock *x25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) struct sock *sk = sk_alloc(net, AF_X25, GFP_ATOMIC, &x25_proto, kern);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (!sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) sock_init_data(NULL, sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) x25 = x25_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) skb_queue_head_init(&x25->ack_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) skb_queue_head_init(&x25->fragment_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) skb_queue_head_init(&x25->interrupt_in_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) skb_queue_head_init(&x25->interrupt_out_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) static int x25_create(struct net *net, struct socket *sock, int protocol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) int kern)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) struct sock *sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) struct x25_sock *x25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int rc = -EAFNOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (!net_eq(net, &init_net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) rc = -ESOCKTNOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (sock->type != SOCK_SEQPACKET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (protocol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if ((sk = x25_alloc_socket(net, kern)) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) x25 = x25_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) sock_init_data(sock, sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) x25_init_timers(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) sock->ops = &x25_proto_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) sk->sk_protocol = protocol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) sk->sk_backlog_rcv = x25_backlog_rcv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) x25->t21 = sysctl_x25_call_request_timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) x25->t22 = sysctl_x25_reset_request_timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) x25->t23 = sysctl_x25_clear_request_timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) x25->t2 = sysctl_x25_ack_holdback_timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) x25->state = X25_STATE_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) x25->cudmatchlength = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) set_bit(X25_ACCPT_APPRV_FLAG, &x25->flags); /* normally no cud */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) /* on call accept */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) x25->facilities.winsize_in = X25_DEFAULT_WINDOW_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) x25->facilities.pacsize_in = X25_DEFAULT_PACKET_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) x25->facilities.throughput = 0; /* by default don't negotiate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) throughput */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) x25->facilities.reverse = X25_DEFAULT_REVERSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) x25->dte_facilities.calling_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) x25->dte_facilities.called_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) memset(x25->dte_facilities.called_ae, '\0',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) sizeof(x25->dte_facilities.called_ae));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) memset(x25->dte_facilities.calling_ae, '\0',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) sizeof(x25->dte_facilities.calling_ae));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) static struct sock *x25_make_new(struct sock *osk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) struct sock *sk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) struct x25_sock *x25, *ox25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (osk->sk_type != SOCK_SEQPACKET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if ((sk = x25_alloc_socket(sock_net(osk), 0)) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) x25 = x25_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) sk->sk_type = osk->sk_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) sk->sk_priority = osk->sk_priority;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) sk->sk_protocol = osk->sk_protocol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) sk->sk_rcvbuf = osk->sk_rcvbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) sk->sk_sndbuf = osk->sk_sndbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) sk->sk_state = TCP_ESTABLISHED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) sk->sk_backlog_rcv = osk->sk_backlog_rcv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) sock_copy_flags(sk, osk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) ox25 = x25_sk(osk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) x25->t21 = ox25->t21;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) x25->t22 = ox25->t22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) x25->t23 = ox25->t23;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) x25->t2 = ox25->t2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) x25->flags = ox25->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) x25->facilities = ox25->facilities;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) x25->dte_facilities = ox25->dte_facilities;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) x25->cudmatchlength = ox25->cudmatchlength;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) clear_bit(X25_INTERRUPT_FLAG, &x25->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) x25_init_timers(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) static int x25_release(struct socket *sock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) struct x25_sock *x25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (!sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) x25 = x25_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) sock_hold(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) switch (x25->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) case X25_STATE_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) case X25_STATE_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) x25_disconnect(sk, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) __x25_destroy_socket(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) case X25_STATE_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) case X25_STATE_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) case X25_STATE_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) x25_clear_queues(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) x25_write_internal(sk, X25_CLEAR_REQUEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) x25_start_t23timer(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) x25->state = X25_STATE_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) sk->sk_state = TCP_CLOSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) sk->sk_shutdown |= SEND_SHUTDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) sk->sk_state_change(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) sock_set_flag(sk, SOCK_DEAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) sock_set_flag(sk, SOCK_DESTROY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) case X25_STATE_5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) x25_write_internal(sk, X25_CLEAR_REQUEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) x25_disconnect(sk, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) __x25_destroy_socket(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) sock_orphan(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) sock_put(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) int len, i, rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (addr_len != sizeof(struct sockaddr_x25) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) addr->sx25_family != AF_X25 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) strnlen(addr->sx25_addr.x25_addr, X25_ADDR_LEN) == X25_ADDR_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) /* check for the null_x25_address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (strcmp(addr->sx25_addr.x25_addr, null_x25_address.x25_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) len = strlen(addr->sx25_addr.x25_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (!isdigit(addr->sx25_addr.x25_addr[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (sock_flag(sk, SOCK_ZAPPED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) x25_sk(sk)->source_addr = addr->sx25_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) x25_insert_socket(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) sock_reset_flag(sk, SOCK_ZAPPED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) SOCK_DEBUG(sk, "x25_bind: socket is bound\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) static int x25_wait_for_connection_establishment(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) DECLARE_WAITQUEUE(wait, current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) add_wait_queue_exclusive(sk_sleep(sk), &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) __set_current_state(TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) rc = -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (signal_pending(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) rc = sock_error(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) sk->sk_socket->state = SS_UNCONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (sk->sk_state != TCP_ESTABLISHED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) __set_current_state(TASK_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) remove_wait_queue(sk_sleep(sk), &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) static int x25_connect(struct socket *sock, struct sockaddr *uaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) int addr_len, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) struct x25_sock *x25 = x25_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) struct x25_route *rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) sock->state = SS_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) goto out; /* Connect completed during a ERESTARTSYS event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) rc = -ECONNREFUSED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) sock->state = SS_UNCONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) rc = -EISCONN; /* No reconnect on a seqpacket socket */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if (sk->sk_state == TCP_ESTABLISHED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) rc = -EALREADY; /* Do nothing if call is already in progress */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (sk->sk_state == TCP_SYN_SENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) sk->sk_state = TCP_CLOSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) sock->state = SS_UNCONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) if (addr_len != sizeof(struct sockaddr_x25) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) addr->sx25_family != AF_X25 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) strnlen(addr->sx25_addr.x25_addr, X25_ADDR_LEN) == X25_ADDR_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) rc = -ENETUNREACH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) rt = x25_get_route(&addr->sx25_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (!rt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) x25->neighbour = x25_get_neigh(rt->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (!x25->neighbour)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) goto out_put_route;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) x25_limit_facilities(&x25->facilities, x25->neighbour);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) x25->lci = x25_new_lci(x25->neighbour);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (!x25->lci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) goto out_put_neigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (sock_flag(sk, SOCK_ZAPPED)) /* Must bind first - autobinding does not work */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) goto out_put_neigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (!strcmp(x25->source_addr.x25_addr, null_x25_address.x25_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) memset(&x25->source_addr, '\0', X25_ADDR_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) x25->dest_addr = addr->sx25_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) /* Move to connecting socket, start sending Connect Requests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) sock->state = SS_CONNECTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) sk->sk_state = TCP_SYN_SENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) x25->state = X25_STATE_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) x25_write_internal(sk, X25_CALL_REQUEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) x25_start_heartbeat(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) x25_start_t21timer(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) /* Now the loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) rc = -EINPROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) rc = x25_wait_for_connection_establishment(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) goto out_put_neigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) sock->state = SS_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) out_put_neigh:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (rc && x25->neighbour) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) read_lock_bh(&x25_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) x25_neigh_put(x25->neighbour);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) x25->neighbour = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) read_unlock_bh(&x25_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) x25->state = X25_STATE_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) out_put_route:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) x25_route_put(rt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) static int x25_wait_for_data(struct sock *sk, long timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) DECLARE_WAITQUEUE(wait, current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) add_wait_queue_exclusive(sk_sleep(sk), &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) __set_current_state(TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (sk->sk_shutdown & RCV_SHUTDOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) rc = -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) if (signal_pending(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) rc = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (!timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (skb_queue_empty(&sk->sk_receive_queue)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) timeout = schedule_timeout(timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) __set_current_state(TASK_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) remove_wait_queue(sk_sleep(sk), &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) static int x25_accept(struct socket *sock, struct socket *newsock, int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) bool kern)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) struct sock *newsk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) int rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) if (!sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) rc = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (sk->sk_type != SOCK_SEQPACKET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) if (sk->sk_state != TCP_LISTEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) goto out2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) rc = x25_wait_for_data(sk, sk->sk_rcvtimeo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) goto out2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) skb = skb_dequeue(&sk->sk_receive_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (!skb->sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) goto out2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) newsk = skb->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) sock_graft(newsk, newsock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) /* Now attach up the new socket */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) skb->sk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) sk_acceptq_removed(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) newsock->state = SS_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) out2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) static int x25_getname(struct socket *sock, struct sockaddr *uaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) int peer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)uaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) struct x25_sock *x25 = x25_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) if (peer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (sk->sk_state != TCP_ESTABLISHED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) rc = -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) sx25->sx25_addr = x25->dest_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) sx25->sx25_addr = x25->source_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) sx25->sx25_family = AF_X25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) rc = sizeof(*sx25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) unsigned int lci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct sock *sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct sock *make;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) struct x25_sock *makex25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) struct x25_address source_addr, dest_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) struct x25_facilities facilities;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) struct x25_dte_facilities dte_facilities;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) int len, addr_len, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) * Remove the LCI and frame type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) skb_pull(skb, X25_STD_MIN_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) * Extract the X.25 addresses and convert them to ASCII strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) * and remove them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) * Address block is mandatory in call request packets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) addr_len = x25_parse_address_block(skb, &source_addr, &dest_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) if (addr_len <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) goto out_clear_request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) skb_pull(skb, addr_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) * Get the length of the facilities, skip past them for the moment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) * get the call user data because this is needed to determine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) * the correct listener
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) * Facilities length is mandatory in call request packets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) if (!pskb_may_pull(skb, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) goto out_clear_request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) len = skb->data[0] + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) if (!pskb_may_pull(skb, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) goto out_clear_request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) skb_pull(skb,len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) * Ensure that the amount of call user data is valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (skb->len > X25_MAX_CUD_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) goto out_clear_request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) * Get all the call user data so it can be used in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) * x25_find_listener and skb_copy_from_linear_data up ahead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) if (!pskb_may_pull(skb, skb->len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) goto out_clear_request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) * Find a listener for the particular address/cud pair.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) sk = x25_find_listener(&source_addr,skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) skb_push(skb,len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (sk != NULL && sk_acceptq_is_full(sk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) goto out_sock_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) * We dont have any listeners for this incoming call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) * Try forwarding it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if (sk == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) skb_push(skb, addr_len + X25_STD_MIN_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (sysctl_x25_forward &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) x25_forward_call(&dest_addr, nb, skb, lci) > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) /* Call was forwarded, dont process it any more */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) /* No listeners, can't forward, clear the call */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) goto out_clear_request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) * Try to reach a compromise on the requested facilities.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) len = x25_negotiate_facilities(skb, sk, &facilities, &dte_facilities);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (len == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) goto out_sock_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) * current neighbour/link might impose additional limits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) * on certain facilties
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) x25_limit_facilities(&facilities, nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) * Try to create a new socket.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) make = x25_make_new(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (!make)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) goto out_sock_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) * Remove the facilities
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) skb_pull(skb, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) skb->sk = make;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) make->sk_state = TCP_ESTABLISHED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) makex25 = x25_sk(make);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) makex25->lci = lci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) makex25->dest_addr = dest_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) makex25->source_addr = source_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) x25_neigh_hold(nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) makex25->neighbour = nb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) makex25->facilities = facilities;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) makex25->dte_facilities= dte_facilities;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) /* ensure no reverse facil on accept */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) makex25->vc_facil_mask &= ~X25_MASK_REVERSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) /* ensure no calling address extension on accept */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) makex25->vc_facil_mask &= ~X25_MASK_CALLING_AE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) makex25->cudmatchlength = x25_sk(sk)->cudmatchlength;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) /* Normally all calls are accepted immediately */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (test_bit(X25_ACCPT_APPRV_FLAG, &makex25->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) x25_write_internal(make, X25_CALL_ACCEPTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) makex25->state = X25_STATE_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) makex25->state = X25_STATE_5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) * Incoming Call User Data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) skb_copy_from_linear_data(skb, makex25->calluserdata.cuddata, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) makex25->calluserdata.cudlength = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) sk_acceptq_added(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) x25_insert_socket(make);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) skb_queue_head(&sk->sk_receive_queue, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) x25_start_heartbeat(make);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (!sock_flag(sk, SOCK_DEAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) sk->sk_data_ready(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) sock_put(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) out_sock_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) sock_put(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) out_clear_request:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) x25_transmit_clear_request(nb, lci, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) static int x25_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) struct x25_sock *x25 = x25_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) DECLARE_SOCKADDR(struct sockaddr_x25 *, usx25, msg->msg_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) struct sockaddr_x25 sx25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) unsigned char *asmptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) int noblock = msg->msg_flags & MSG_DONTWAIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) int qbit = 0, rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) /* we currently don't support segmented records at the user interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if (!(msg->msg_flags & (MSG_EOR|MSG_OOB)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) rc = -EADDRNOTAVAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) if (sock_flag(sk, SOCK_ZAPPED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) rc = -EPIPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) if (sk->sk_shutdown & SEND_SHUTDOWN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) send_sig(SIGPIPE, current, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) rc = -ENETUNREACH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) if (!x25->neighbour)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) if (usx25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) if (msg->msg_namelen < sizeof(sx25))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) memcpy(&sx25, usx25, sizeof(sx25));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) rc = -EISCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) if (strcmp(x25->dest_addr.x25_addr, sx25.sx25_addr.x25_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) if (sx25.sx25_family != AF_X25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) * FIXME 1003.1g - if the socket is like this because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) * it has become closed (not started closed) we ought
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) * to SIGPIPE, EPIPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) rc = -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) if (sk->sk_state != TCP_ESTABLISHED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) sx25.sx25_family = AF_X25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) sx25.sx25_addr = x25->dest_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) /* Sanity check the packet size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) if (len > 65535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) rc = -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) SOCK_DEBUG(sk, "x25_sendmsg: sendto: Addresses built.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) /* Build a packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) SOCK_DEBUG(sk, "x25_sendmsg: sendto: building packet.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) if ((msg->msg_flags & MSG_OOB) && len > 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) len = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) size = len + X25_MAX_L2_LEN + X25_EXT_MIN_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) skb = sock_alloc_send_skb(sk, size, noblock, &rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) X25_SKB_CB(skb)->flags = msg->msg_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) skb_reserve(skb, X25_MAX_L2_LEN + X25_EXT_MIN_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) * Put the data on the end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) SOCK_DEBUG(sk, "x25_sendmsg: Copying user data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) skb_reset_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) skb_put(skb, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) rc = memcpy_from_msg(skb_transport_header(skb), msg, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) goto out_kfree_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) * If the Q BIT Include socket option is in force, the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) * byte of the user data is the logical value of the Q Bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) if (!pskb_may_pull(skb, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) goto out_kfree_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) qbit = skb->data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) skb_pull(skb, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) * Push down the X.25 header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) SOCK_DEBUG(sk, "x25_sendmsg: Building X.25 Header.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) if (msg->msg_flags & MSG_OOB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) if (x25->neighbour->extended) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) asmptr = skb_push(skb, X25_STD_MIN_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) *asmptr++ = ((x25->lci >> 8) & 0x0F) | X25_GFI_EXTSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) *asmptr++ = (x25->lci >> 0) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) *asmptr++ = X25_INTERRUPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) asmptr = skb_push(skb, X25_STD_MIN_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) *asmptr++ = ((x25->lci >> 8) & 0x0F) | X25_GFI_STDSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) *asmptr++ = (x25->lci >> 0) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) *asmptr++ = X25_INTERRUPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) if (x25->neighbour->extended) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) /* Build an Extended X.25 header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) asmptr = skb_push(skb, X25_EXT_MIN_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) *asmptr++ = ((x25->lci >> 8) & 0x0F) | X25_GFI_EXTSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) *asmptr++ = (x25->lci >> 0) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) *asmptr++ = X25_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) *asmptr++ = X25_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) /* Build an Standard X.25 header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) asmptr = skb_push(skb, X25_STD_MIN_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) *asmptr++ = ((x25->lci >> 8) & 0x0F) | X25_GFI_STDSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) *asmptr++ = (x25->lci >> 0) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) *asmptr++ = X25_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) if (qbit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) skb->data[0] |= X25_Q_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) SOCK_DEBUG(sk, "x25_sendmsg: Built header.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) SOCK_DEBUG(sk, "x25_sendmsg: Transmitting buffer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) rc = -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) if (sk->sk_state != TCP_ESTABLISHED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) goto out_kfree_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) if (msg->msg_flags & MSG_OOB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) skb_queue_tail(&x25->interrupt_out_queue, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) rc = x25_output(sk, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) len = rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) else if (test_bit(X25_Q_BIT_FLAG, &x25->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) len++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) x25_kick(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) rc = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) out_kfree_skb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) static int x25_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) struct x25_sock *x25 = x25_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) DECLARE_SOCKADDR(struct sockaddr_x25 *, sx25, msg->msg_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) size_t copied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) int qbit, header_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) unsigned char *asmptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) int rc = -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) if (x25->neighbour == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) header_len = x25->neighbour->extended ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) X25_EXT_MIN_LEN : X25_STD_MIN_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) * This works for seqpacket too. The receiver has ordered the queue for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) * us! We do one quick check first though
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) if (sk->sk_state != TCP_ESTABLISHED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) if (flags & MSG_OOB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) if (sock_flag(sk, SOCK_URGINLINE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) !skb_peek(&x25->interrupt_in_queue))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) skb = skb_dequeue(&x25->interrupt_in_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) if (!pskb_may_pull(skb, X25_STD_MIN_LEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) goto out_free_dgram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) skb_pull(skb, X25_STD_MIN_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) * No Q bit information on Interrupt data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) asmptr = skb_push(skb, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) *asmptr = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) msg->msg_flags |= MSG_OOB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) /* Now we can treat all alike */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) flags & MSG_DONTWAIT, &rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) if (!pskb_may_pull(skb, header_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) goto out_free_dgram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) qbit = (skb->data[0] & X25_Q_BIT) == X25_Q_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) skb_pull(skb, header_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) asmptr = skb_push(skb, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) *asmptr = qbit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) skb_reset_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) copied = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) if (copied > size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) copied = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) msg->msg_flags |= MSG_TRUNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) /* Currently, each datagram always contains a complete record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) msg->msg_flags |= MSG_EOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) rc = skb_copy_datagram_msg(skb, 0, msg, copied);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) goto out_free_dgram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) if (sx25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) sx25->sx25_family = AF_X25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) sx25->sx25_addr = x25->dest_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) msg->msg_namelen = sizeof(*sx25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) x25_check_rbuf(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) rc = copied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) out_free_dgram:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) skb_free_datagram(sk, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) struct x25_sock *x25 = x25_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) void __user *argp = (void __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) case TIOCOUTQ: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) int amount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) if (amount < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) amount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) rc = put_user(amount, (unsigned int __user *)argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) case TIOCINQ: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) int amount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) * These two are safe on a single CPU system as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) * only user tasks fiddle here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) amount = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) rc = put_user(amount, (unsigned int __user *)argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) case SIOCGIFADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) case SIOCSIFADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) case SIOCGIFDSTADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) case SIOCSIFDSTADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) case SIOCGIFBRDADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) case SIOCSIFBRDADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) case SIOCGIFNETMASK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) case SIOCSIFNETMASK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) case SIOCGIFMETRIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) case SIOCSIFMETRIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) case SIOCADDRT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) case SIOCDELRT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) rc = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) if (!capable(CAP_NET_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) rc = x25_route_ioctl(cmd, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) case SIOCX25GSUBSCRIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) rc = x25_subscr_ioctl(cmd, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) case SIOCX25SSUBSCRIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) rc = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) if (!capable(CAP_NET_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) rc = x25_subscr_ioctl(cmd, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) case SIOCX25GFACILITIES: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) rc = copy_to_user(argp, &x25->facilities,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) sizeof(x25->facilities))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) ? -EFAULT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) case SIOCX25SFACILITIES: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) struct x25_facilities facilities;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) if (copy_from_user(&facilities, argp, sizeof(facilities)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) if (sk->sk_state != TCP_LISTEN &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) sk->sk_state != TCP_CLOSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) goto out_fac_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) if (facilities.pacsize_in < X25_PS16 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) facilities.pacsize_in > X25_PS4096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) goto out_fac_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) if (facilities.pacsize_out < X25_PS16 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) facilities.pacsize_out > X25_PS4096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) goto out_fac_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) if (facilities.winsize_in < 1 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) facilities.winsize_in > 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) goto out_fac_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) if (facilities.throughput) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) int out = facilities.throughput & 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) int in = facilities.throughput & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) if (!out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) facilities.throughput |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) X25_DEFAULT_THROUGHPUT << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) else if (out < 0x30 || out > 0xD0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) goto out_fac_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) if (!in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) facilities.throughput |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) X25_DEFAULT_THROUGHPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) else if (in < 0x03 || in > 0x0D)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) goto out_fac_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) if (facilities.reverse &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) (facilities.reverse & 0x81) != 0x81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) goto out_fac_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) x25->facilities = facilities;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) out_fac_release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) case SIOCX25GDTEFACILITIES: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) rc = copy_to_user(argp, &x25->dte_facilities,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) sizeof(x25->dte_facilities));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) case SIOCX25SDTEFACILITIES: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) struct x25_dte_facilities dtefacs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) if (copy_from_user(&dtefacs, argp, sizeof(dtefacs)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) if (sk->sk_state != TCP_LISTEN &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) sk->sk_state != TCP_CLOSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) goto out_dtefac_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) if (dtefacs.calling_len > X25_MAX_AE_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) goto out_dtefac_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) if (dtefacs.called_len > X25_MAX_AE_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) goto out_dtefac_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) x25->dte_facilities = dtefacs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) out_dtefac_release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) case SIOCX25GCALLUSERDATA: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) rc = copy_to_user(argp, &x25->calluserdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) sizeof(x25->calluserdata))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) ? -EFAULT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) case SIOCX25SCALLUSERDATA: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) struct x25_calluserdata calluserdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) if (copy_from_user(&calluserdata, argp, sizeof(calluserdata)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) if (calluserdata.cudlength > X25_MAX_CUD_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) x25->calluserdata = calluserdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) case SIOCX25GCAUSEDIAG: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) rc = copy_to_user(argp, &x25->causediag, sizeof(x25->causediag))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) ? -EFAULT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) case SIOCX25SCAUSEDIAG: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) struct x25_causediag causediag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) if (copy_from_user(&causediag, argp, sizeof(causediag)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) x25->causediag = causediag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) case SIOCX25SCUDMATCHLEN: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) struct x25_subaddr sub_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) if(sk->sk_state != TCP_CLOSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) goto out_cud_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) if (copy_from_user(&sub_addr, argp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) sizeof(sub_addr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) goto out_cud_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) if (sub_addr.cudmatchlength > X25_MAX_CUD_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) goto out_cud_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) x25->cudmatchlength = sub_addr.cudmatchlength;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) out_cud_release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) case SIOCX25CALLACCPTAPPRV: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) if (sk->sk_state == TCP_CLOSE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) case SIOCX25SENDCALLACCPT: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) if (sk->sk_state != TCP_ESTABLISHED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) goto out_sendcallaccpt_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) /* must call accptapprv above */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) if (test_bit(X25_ACCPT_APPRV_FLAG, &x25->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) goto out_sendcallaccpt_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) x25_write_internal(sk, X25_CALL_ACCEPTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) x25->state = X25_STATE_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) out_sendcallaccpt_release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) rc = -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) static const struct net_proto_family x25_family_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) .family = AF_X25,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) .create = x25_create,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) static int compat_x25_subscr_ioctl(unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) struct compat_x25_subscrip_struct __user *x25_subscr32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) struct compat_x25_subscrip_struct x25_subscr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) struct x25_neigh *nb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) int rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) if (copy_from_user(&x25_subscr, x25_subscr32, sizeof(*x25_subscr32)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) dev = x25_dev_get(x25_subscr.device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) if (dev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) nb = x25_get_neigh(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) if (nb == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) goto out_dev_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) if (cmd == SIOCX25GSUBSCRIP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) read_lock_bh(&x25_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) x25_subscr.extended = nb->extended;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) x25_subscr.global_facil_mask = nb->global_facil_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) read_unlock_bh(&x25_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) rc = copy_to_user(x25_subscr32, &x25_subscr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) sizeof(*x25_subscr32)) ? -EFAULT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) if (x25_subscr.extended == 0 || x25_subscr.extended == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) write_lock_bh(&x25_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) nb->extended = x25_subscr.extended;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) nb->global_facil_mask = x25_subscr.global_facil_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) write_unlock_bh(&x25_neigh_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) x25_neigh_put(nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) out_dev_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) void __user *argp = compat_ptr(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) int rc = -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) switch(cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) case TIOCOUTQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) case TIOCINQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) rc = x25_ioctl(sock, cmd, (unsigned long)argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) case SIOCGIFADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) case SIOCSIFADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) case SIOCGIFDSTADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) case SIOCSIFDSTADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) case SIOCGIFBRDADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) case SIOCSIFBRDADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) case SIOCGIFNETMASK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) case SIOCSIFNETMASK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) case SIOCGIFMETRIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) case SIOCSIFMETRIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) case SIOCADDRT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) case SIOCDELRT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) rc = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) if (!capable(CAP_NET_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) rc = x25_route_ioctl(cmd, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) case SIOCX25GSUBSCRIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) rc = compat_x25_subscr_ioctl(cmd, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) case SIOCX25SSUBSCRIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) rc = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) if (!capable(CAP_NET_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) rc = compat_x25_subscr_ioctl(cmd, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) case SIOCX25GFACILITIES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) case SIOCX25SFACILITIES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) case SIOCX25GDTEFACILITIES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) case SIOCX25SDTEFACILITIES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) case SIOCX25GCALLUSERDATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) case SIOCX25SCALLUSERDATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) case SIOCX25GCAUSEDIAG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) case SIOCX25SCAUSEDIAG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) case SIOCX25SCUDMATCHLEN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) case SIOCX25CALLACCPTAPPRV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) case SIOCX25SENDCALLACCPT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) rc = x25_ioctl(sock, cmd, (unsigned long)argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) rc = -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) static const struct proto_ops x25_proto_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) .family = AF_X25,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) .release = x25_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) .bind = x25_bind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) .connect = x25_connect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) .socketpair = sock_no_socketpair,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) .accept = x25_accept,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) .getname = x25_getname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) .poll = datagram_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) .ioctl = x25_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) .compat_ioctl = compat_x25_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) .gettstamp = sock_gettstamp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) .listen = x25_listen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) .shutdown = sock_no_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) .setsockopt = x25_setsockopt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) .getsockopt = x25_getsockopt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) .sendmsg = x25_sendmsg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) .recvmsg = x25_recvmsg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) .mmap = sock_no_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) .sendpage = sock_no_sendpage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) static struct packet_type x25_packet_type __read_mostly = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) .type = cpu_to_be16(ETH_P_X25),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) .func = x25_lapb_receive_frame,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) static struct notifier_block x25_dev_notifier = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) .notifier_call = x25_device_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) void x25_kill_by_neigh(struct x25_neigh *nb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) struct sock *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) write_lock_bh(&x25_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) sk_for_each(s, &x25_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) if (x25_sk(s)->neighbour == nb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) write_unlock_bh(&x25_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) lock_sock(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) x25_disconnect(s, ENETUNREACH, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) release_sock(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) write_lock_bh(&x25_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) write_unlock_bh(&x25_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) /* Remove any related forwards */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) x25_clear_forward_by_dev(nb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) static int __init x25_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) rc = proto_register(&x25_proto, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) rc = sock_register(&x25_family_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) goto out_proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) dev_add_pack(&x25_packet_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) rc = register_netdevice_notifier(&x25_dev_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) goto out_sock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) rc = x25_register_sysctl();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) goto out_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) rc = x25_proc_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) goto out_sysctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) pr_info("Linux Version 0.2\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) out_sysctl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) x25_unregister_sysctl();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) out_dev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) unregister_netdevice_notifier(&x25_dev_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) out_sock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) dev_remove_pack(&x25_packet_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) sock_unregister(AF_X25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) out_proto:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) proto_unregister(&x25_proto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) module_init(x25_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) static void __exit x25_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) x25_proc_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) x25_link_free();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) x25_route_free();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) x25_unregister_sysctl();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) unregister_netdevice_notifier(&x25_dev_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) dev_remove_pack(&x25_packet_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) sock_unregister(AF_X25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) proto_unregister(&x25_proto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) module_exit(x25_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) MODULE_DESCRIPTION("The X.25 Packet Layer network layer protocol");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) MODULE_ALIAS_NETPROTO(PF_X25);