Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }