// SPDX-License-Identifier: GPL-2.0-or-later /* * X.25 Packet Layer release 002 * * This is ALPHA test software. This code may break your machine, * randomly fail to work with new releases, misbehave and/or generally * screw up. It might even work. * * This code REQUIRES 2.1.15 or higher * * History * X.25 001 Split from x25_subr.c * mar/20/00 Daniela Squassoni Disabling/enabling of facilities * negotiation. * apr/14/05 Shaun Pereira - Allow fast select with no restriction * on response.
*/
/** * x25_parse_facilities - Parse facilities from skb into the facilities structs * * @skb: sk_buff to parse * @facilities: Regular facilities, updated as facilities are found * @dte_facs: ITU DTE facilities, updated as DTE facilities are found * @vc_fac_mask: mask is updated with all facilities found * * Return codes: * -1 - Parsing error, caller should drop call and clean up * 0 - Parse OK, this skb has no facilities * >0 - Parse OK, returns the length of the facilities header *
*/ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, struct x25_dte_facilities *dte_facs, unsignedlong *vc_fac_mask)
{ unsignedchar *p; unsignedint len;
*vc_fac_mask = 0;
/* * The kernel knows which facilities were set on an incoming call but * currently this information is not available to userspace. Here we * give userspace who read incoming call facilities 0 length to indicate * it wasn't set.
*/
dte_facs->calling_len = 0;
dte_facs->called_len = 0;
memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae));
memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae));
if (!pskb_may_pull(skb, 1)) return 0;
len = skb->data[0];
if (!pskb_may_pull(skb, 1 + len)) return -1;
p = skb->data + 1;
while (len > 0) { switch (*p & X25_FAC_CLASS_MASK) { case X25_FAC_CLASS_A: if (len < 2) return -1; switch (*p) { case X25_FAC_REVERSE: if((p[1] & 0x81) == 0x81) {
facilities->reverse = p[1] & 0x81;
*vc_fac_mask |= X25_MASK_REVERSE; break;
}
if(p[1] == 0x00) {
facilities->reverse
= X25_DEFAULT_REVERSE;
*vc_fac_mask |= X25_MASK_REVERSE; break;
}
fallthrough; case X25_FAC_THROUGHPUT:
facilities->throughput = p[1];
*vc_fac_mask |= X25_MASK_THROUGHPUT; break; case X25_MARKER: break; default:
pr_debug("unknown facility " "%02X, value %02X\n",
p[0], p[1]); break;
}
p += 2;
len -= 2; break; case X25_FAC_CLASS_B: if (len < 3) return -1; switch (*p) { case X25_FAC_PACKET_SIZE:
facilities->pacsize_in = p[1];
facilities->pacsize_out = p[2];
*vc_fac_mask |= X25_MASK_PACKET_SIZE; break; case X25_FAC_WINDOW_SIZE:
facilities->winsize_in = p[1];
facilities->winsize_out = p[2];
*vc_fac_mask |= X25_MASK_WINDOW_SIZE; break; default:
pr_debug("unknown facility " "%02X, values %02X, %02X\n",
p[0], p[1], p[2]); break;
}
p += 3;
len -= 3; break; case X25_FAC_CLASS_C: if (len < 4) return -1;
pr_debug("unknown facility %02X, " "values %02X, %02X, %02X\n",
p[0], p[1], p[2], p[3]);
p += 4;
len -= 4; break; case X25_FAC_CLASS_D: if (len < p[1] + 2) return -1; switch (*p) { case X25_FAC_CALLING_AE: if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] <= 1) return -1; if (p[2] > X25_MAX_AE_LEN) return -1;
dte_facs->calling_len = p[2];
memcpy(dte_facs->calling_ae, &p[3], p[1] - 1);
*vc_fac_mask |= X25_MASK_CALLING_AE; break; case X25_FAC_CALLED_AE: if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] <= 1) return -1; if (p[2] > X25_MAX_AE_LEN) return -1;
dte_facs->called_len = p[2];
memcpy(dte_facs->called_ae, &p[3], p[1] - 1);
*vc_fac_mask |= X25_MASK_CALLED_AE; break; default:
pr_debug("unknown facility %02X," "length %d\n", p[0], p[1]); break;
}
len -= p[1] + 2;
p += p[1] + 2; break;
}
}
return p - skb->data;
}
/* * Create a set of facilities.
*/ int x25_create_facilities(unsignedchar *buffer, struct x25_facilities *facilities, struct x25_dte_facilities *dte_facs, unsignedlong facil_mask)
{ unsignedchar *p = buffer + 1; int len;
if (!facil_mask) { /* * Length of the facilities field in call_req or * call_accept packets
*/
buffer[0] = 0;
len = 1; /* 1 byte for the length field */ return len;
}
/* * Try to reach a compromise on a set of facilities. * * The only real problem is with reverse charging.
*/ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, struct x25_facilities *new, struct x25_dte_facilities *dte)
{ struct x25_sock *x25 = x25_sk(sk); struct x25_facilities *ours = &x25->facilities; struct x25_facilities theirs; int len;
/* * Limit values of certain facilities according to the capability of the * currently attached x25 link.
*/ void x25_limit_facilities(struct x25_facilities *facilities, struct x25_neigh *nb)
{
if (!nb->extended) { if (facilities->winsize_in > 7) {
pr_debug("incoming winsize limited to 7\n");
facilities->winsize_in = 7;
} if (facilities->winsize_out > 7) {
facilities->winsize_out = 7;
pr_debug("outgoing winsize limited to 7\n");
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.