^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 Split from x25_subr.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * mar/20/00 Daniela Squassoni Disabling/enabling of facilities
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * negotiation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * apr/14/05 Shaun Pereira - Allow fast select with no restriction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * on response.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define pr_fmt(fmt) "X25: " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <net/x25.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * x25_parse_facilities - Parse facilities from skb into the facilities structs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * @skb: sk_buff to parse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * @facilities: Regular facilities, updated as facilities are found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * @dte_facs: ITU DTE facilities, updated as DTE facilities are found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * @vc_fac_mask: mask is updated with all facilities found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * Return codes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * -1 - Parsing error, caller should drop call and clean up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * 0 - Parse OK, this skb has no facilities
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * >0 - Parse OK, returns the length of the facilities header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) unsigned char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) *vc_fac_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * The kernel knows which facilities were set on an incoming call but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * currently this information is not available to userspace. Here we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * give userspace who read incoming call facilities 0 length to indicate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * it wasn't set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) dte_facs->calling_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) dte_facs->called_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (!pskb_may_pull(skb, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) len = skb->data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (!pskb_may_pull(skb, 1 + len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) p = skb->data + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) while (len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) switch (*p & X25_FAC_CLASS_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) case X25_FAC_CLASS_A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (len < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) switch (*p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) case X25_FAC_REVERSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if((p[1] & 0x81) == 0x81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) facilities->reverse = p[1] & 0x81;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) *vc_fac_mask |= X25_MASK_REVERSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) break;
^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) if((p[1] & 0x01) == 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) facilities->reverse = p[1] & 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) *vc_fac_mask |= X25_MASK_REVERSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if((p[1] & 0x80) == 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) facilities->reverse = p[1] & 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) *vc_fac_mask |= X25_MASK_REVERSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if(p[1] == 0x00) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) facilities->reverse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) = X25_DEFAULT_REVERSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) *vc_fac_mask |= X25_MASK_REVERSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) case X25_FAC_THROUGHPUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) facilities->throughput = p[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) *vc_fac_mask |= X25_MASK_THROUGHPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) case X25_MARKER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) pr_debug("unknown facility "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) "%02X, value %02X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) p[0], p[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) p += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) len -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) case X25_FAC_CLASS_B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (len < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) switch (*p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) case X25_FAC_PACKET_SIZE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) facilities->pacsize_in = p[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) facilities->pacsize_out = p[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) *vc_fac_mask |= X25_MASK_PACKET_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) case X25_FAC_WINDOW_SIZE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) facilities->winsize_in = p[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) facilities->winsize_out = p[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) *vc_fac_mask |= X25_MASK_WINDOW_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) pr_debug("unknown facility "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) "%02X, values %02X, %02X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) p[0], p[1], p[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) p += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) len -= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) case X25_FAC_CLASS_C:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (len < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) pr_debug("unknown facility %02X, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) "values %02X, %02X, %02X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) p[0], p[1], p[2], p[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) p += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) len -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) case X25_FAC_CLASS_D:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (len < p[1] + 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) switch (*p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) case X25_FAC_CALLING_AE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] <= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (p[2] > X25_MAX_AE_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) dte_facs->calling_len = p[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) memcpy(dte_facs->calling_ae, &p[3], p[1] - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) *vc_fac_mask |= X25_MASK_CALLING_AE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) case X25_FAC_CALLED_AE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] <= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (p[2] > X25_MAX_AE_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) dte_facs->called_len = p[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) memcpy(dte_facs->called_ae, &p[3], p[1] - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) *vc_fac_mask |= X25_MASK_CALLED_AE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) pr_debug("unknown facility %02X,"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) "length %d\n", p[0], p[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) len -= p[1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) p += p[1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return p - skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * Create a set of facilities.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) int x25_create_facilities(unsigned char *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct x25_facilities *facilities,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct x25_dte_facilities *dte_facs, unsigned long facil_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) unsigned char *p = buffer + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (!facil_mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * Length of the facilities field in call_req or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * call_accept packets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) buffer[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) len = 1; /* 1 byte for the length field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (facilities->reverse && (facil_mask & X25_MASK_REVERSE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) *p++ = X25_FAC_REVERSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) *p++ = facilities->reverse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (facilities->throughput && (facil_mask & X25_MASK_THROUGHPUT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) *p++ = X25_FAC_THROUGHPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) *p++ = facilities->throughput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if ((facilities->pacsize_in || facilities->pacsize_out) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) (facil_mask & X25_MASK_PACKET_SIZE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) *p++ = X25_FAC_PACKET_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) *p++ = facilities->pacsize_in ? : facilities->pacsize_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) *p++ = facilities->pacsize_out ? : facilities->pacsize_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if ((facilities->winsize_in || facilities->winsize_out) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) (facil_mask & X25_MASK_WINDOW_SIZE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) *p++ = X25_FAC_WINDOW_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) *p++ = facilities->winsize_in ? : facilities->winsize_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) *p++ = facilities->winsize_out ? : facilities->winsize_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (facil_mask & (X25_MASK_CALLING_AE|X25_MASK_CALLED_AE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) *p++ = X25_MARKER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) *p++ = X25_DTE_SERVICES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (dte_facs->calling_len && (facil_mask & X25_MASK_CALLING_AE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) unsigned int bytecount = (dte_facs->calling_len + 1) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) *p++ = X25_FAC_CALLING_AE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) *p++ = 1 + bytecount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) *p++ = dte_facs->calling_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) memcpy(p, dte_facs->calling_ae, bytecount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) p += bytecount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (dte_facs->called_len && (facil_mask & X25_MASK_CALLED_AE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) unsigned int bytecount = (dte_facs->called_len % 2) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) dte_facs->called_len / 2 + 1 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) dte_facs->called_len / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) *p++ = X25_FAC_CALLED_AE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) *p++ = 1 + bytecount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) *p++ = dte_facs->called_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) memcpy(p, dte_facs->called_ae, bytecount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) p+=bytecount;
^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) len = p - buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) buffer[0] = len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * Try to reach a compromise on a set of facilities.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * The only real problem is with reverse charging.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) struct x25_facilities *new, struct x25_dte_facilities *dte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct x25_sock *x25 = x25_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct x25_facilities *ours = &x25->facilities;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct x25_facilities theirs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) memset(&theirs, 0, sizeof(theirs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) memcpy(new, ours, sizeof(*new));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) memset(dte, 0, sizeof(*dte));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * They want reverse charging, we won't accept it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if ((theirs.reverse & 0x01 ) && (ours->reverse & 0x01)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) SOCK_DEBUG(sk, "X.25: rejecting reverse charging request\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) new->reverse = theirs.reverse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (theirs.throughput) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) int theirs_in = theirs.throughput & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) int theirs_out = theirs.throughput & 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) int ours_in = ours->throughput & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) int ours_out = ours->throughput & 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (!ours_in || theirs_in < ours_in) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) SOCK_DEBUG(sk, "X.25: inbound throughput negotiated\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) new->throughput = (new->throughput & 0xf0) | theirs_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (!ours_out || theirs_out < ours_out) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) SOCK_DEBUG(sk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) "X.25: outbound throughput negotiated\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) new->throughput = (new->throughput & 0x0f) | theirs_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (theirs.pacsize_in && theirs.pacsize_out) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (theirs.pacsize_in < ours->pacsize_in) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) SOCK_DEBUG(sk, "X.25: packet size inwards negotiated down\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) new->pacsize_in = theirs.pacsize_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (theirs.pacsize_out < ours->pacsize_out) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) SOCK_DEBUG(sk, "X.25: packet size outwards negotiated down\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) new->pacsize_out = theirs.pacsize_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (theirs.winsize_in && theirs.winsize_out) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (theirs.winsize_in < ours->winsize_in) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) SOCK_DEBUG(sk, "X.25: window size inwards negotiated down\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) new->winsize_in = theirs.winsize_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (theirs.winsize_out < ours->winsize_out) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) SOCK_DEBUG(sk, "X.25: window size outwards negotiated down\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) new->winsize_out = theirs.winsize_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return len;
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * Limit values of certain facilities according to the capability of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * currently attached x25 link.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) void x25_limit_facilities(struct x25_facilities *facilities,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) struct x25_neigh *nb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (!nb->extended) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (facilities->winsize_in > 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) pr_debug("incoming winsize limited to 7\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) facilities->winsize_in = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (facilities->winsize_out > 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) facilities->winsize_out = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) pr_debug("outgoing winsize limited to 7\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }