diff options
| author | Shaun Pereira <spereira@tusc.com.au> | 2005-06-23 01:16:17 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2005-06-23 01:16:17 -0400 |
| commit | ebc3f64b864fc16a594c2e63bf55a55c7d42084b (patch) | |
| tree | 95040f32ad5902051527b91966118e565d48865b | |
| parent | cb65d506c34c86df5bcef939ce5a8666a451bd8b (diff) | |
[X25]: Fast select with no restriction on response
This patch is a follow up to patch 1 regarding "Selective Sub Address
matching with call user data". It allows use of the Fast-Select-Acceptance
optional user facility for X.25.
This patch just implements fast select with no restriction on response
(NRR). What this means (according to ITU-T Recomendation 10/96 section
6.16) is that if in an incoming call packet, the relevant facility bits are
set for fast-select-NRR, then the called DTE can issue a direct response to
the incoming packet using a call-accepted packet that contains
call-user-data. This patch allows such a response.
The called DTE can also respond with a clear-request packet that contains
call-user-data. However, this feature is currently not implemented by the
patch.
How is Fast Select Acceptance used?
By default, the system does not allow fast select acceptance (as before).
To enable a response to fast select acceptance,
After a listen socket in created and bound as follows
socket(AF_X25, SOCK_SEQPACKET, 0);
bind(call_soc, (struct sockaddr *)&locl_addr, sizeof(locl_addr));
but before a listen system call is made, the following ioctl should be used.
ioctl(call_soc,SIOCX25CALLACCPTAPPRV);
Now the listen system call can be made
listen(call_soc, 4);
After this, an incoming-call packet will be accepted, but no call-accepted
packet will be sent back until the following system call is made on the socket
that accepts the call
ioctl(vc_soc,SIOCX25SENDCALLACCPT);
The network (or cisco xot router used for testing here) will allow the
application server's call-user-data in the call-accepted packet,
provided the call-request was made with Fast-select NRR.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | include/linux/x25.h | 2 | ||||
| -rw-r--r-- | include/net/x25.h | 6 | ||||
| -rw-r--r-- | net/x25/af_x25.c | 37 | ||||
| -rw-r--r-- | net/x25/x25_facilities.c | 34 | ||||
| -rw-r--r-- | net/x25/x25_subr.c | 23 |
5 files changed, 86 insertions, 16 deletions
diff --git a/include/linux/x25.h b/include/linux/x25.h index 6f43b3d20248..16d44931afa0 100644 --- a/include/linux/x25.h +++ b/include/linux/x25.h | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | #define SIOCX25SCALLUSERDATA (SIOCPROTOPRIVATE + 5) | 19 | #define SIOCX25SCALLUSERDATA (SIOCPROTOPRIVATE + 5) |
| 20 | #define SIOCX25GCAUSEDIAG (SIOCPROTOPRIVATE + 6) | 20 | #define SIOCX25GCAUSEDIAG (SIOCPROTOPRIVATE + 6) |
| 21 | #define SIOCX25SCUDMATCHLEN (SIOCPROTOPRIVATE + 7) | 21 | #define SIOCX25SCUDMATCHLEN (SIOCPROTOPRIVATE + 7) |
| 22 | #define SIOCX25CALLACCPTAPPRV (SIOCPROTOPRIVATE + 8) | ||
| 23 | #define SIOCX25SENDCALLACCPT (SIOCPROTOPRIVATE + 9) | ||
| 22 | 24 | ||
| 23 | /* | 25 | /* |
| 24 | * Values for {get,set}sockopt. | 26 | * Values for {get,set}sockopt. |
diff --git a/include/net/x25.h b/include/net/x25.h index 9dd70dd4a9b7..8b39b98876e8 100644 --- a/include/net/x25.h +++ b/include/net/x25.h | |||
| @@ -79,6 +79,8 @@ enum { | |||
| 79 | #define X25_DEFAULT_PACKET_SIZE X25_PS128 /* Default Packet Size */ | 79 | #define X25_DEFAULT_PACKET_SIZE X25_PS128 /* Default Packet Size */ |
| 80 | #define X25_DEFAULT_THROUGHPUT 0x0A /* Deafult Throughput */ | 80 | #define X25_DEFAULT_THROUGHPUT 0x0A /* Deafult Throughput */ |
| 81 | #define X25_DEFAULT_REVERSE 0x00 /* Default Reverse Charging */ | 81 | #define X25_DEFAULT_REVERSE 0x00 /* Default Reverse Charging */ |
| 82 | #define X25_DENY_ACCPT_APPRV 0x01 /* Default value */ | ||
| 83 | #define X25_ALLOW_ACCPT_APPRV 0x00 /* Control enabled */ | ||
| 82 | 84 | ||
| 83 | #define X25_SMODULUS 8 | 85 | #define X25_SMODULUS 8 |
| 84 | #define X25_EMODULUS 128 | 86 | #define X25_EMODULUS 128 |
| @@ -94,7 +96,7 @@ enum { | |||
| 94 | #define X25_FAC_CLASS_C 0x80 | 96 | #define X25_FAC_CLASS_C 0x80 |
| 95 | #define X25_FAC_CLASS_D 0xC0 | 97 | #define X25_FAC_CLASS_D 0xC0 |
| 96 | 98 | ||
| 97 | #define X25_FAC_REVERSE 0x01 | 99 | #define X25_FAC_REVERSE 0x01 /* also fast select */ |
| 98 | #define X25_FAC_THROUGHPUT 0x02 | 100 | #define X25_FAC_THROUGHPUT 0x02 |
| 99 | #define X25_FAC_PACKET_SIZE 0x42 | 101 | #define X25_FAC_PACKET_SIZE 0x42 |
| 100 | #define X25_FAC_WINDOW_SIZE 0x43 | 102 | #define X25_FAC_WINDOW_SIZE 0x43 |
| @@ -135,7 +137,7 @@ struct x25_sock { | |||
| 135 | struct x25_address source_addr, dest_addr; | 137 | struct x25_address source_addr, dest_addr; |
| 136 | struct x25_neigh *neighbour; | 138 | struct x25_neigh *neighbour; |
| 137 | unsigned int lci, cudmatchlength; | 139 | unsigned int lci, cudmatchlength; |
| 138 | unsigned char state, condition, qbitincl, intflag; | 140 | unsigned char state, condition, qbitincl, intflag, accptapprv; |
| 139 | unsigned short vs, vr, va, vl; | 141 | unsigned short vs, vr, va, vl; |
| 140 | unsigned long t2, t21, t22, t23; | 142 | unsigned long t2, t21, t22, t23; |
| 141 | unsigned short fraglen; | 143 | unsigned short fraglen; |
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index e17d84a55d5e..04bec047fa9a 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
| @@ -31,6 +31,8 @@ | |||
| 31 | * x25_proc.c, using seq_file | 31 | * x25_proc.c, using seq_file |
| 32 | * 2005-04-02 Shaun Pereira Selective sub address matching | 32 | * 2005-04-02 Shaun Pereira Selective sub address matching |
| 33 | * with call user data | 33 | * with call user data |
| 34 | * 2005-04-15 Shaun Pereira Fast select with no restriction on | ||
| 35 | * response | ||
| 34 | */ | 36 | */ |
| 35 | 37 | ||
| 36 | #include <linux/config.h> | 38 | #include <linux/config.h> |
| @@ -502,6 +504,8 @@ static int x25_create(struct socket *sock, int protocol) | |||
| 502 | x25->t2 = sysctl_x25_ack_holdback_timeout; | 504 | x25->t2 = sysctl_x25_ack_holdback_timeout; |
| 503 | x25->state = X25_STATE_0; | 505 | x25->state = X25_STATE_0; |
| 504 | x25->cudmatchlength = 0; | 506 | x25->cudmatchlength = 0; |
| 507 | x25->accptapprv = X25_DENY_ACCPT_APPRV; /* normally no cud */ | ||
| 508 | /* on call accept */ | ||
| 505 | 509 | ||
| 506 | x25->facilities.winsize_in = X25_DEFAULT_WINDOW_SIZE; | 510 | x25->facilities.winsize_in = X25_DEFAULT_WINDOW_SIZE; |
| 507 | x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE; | 511 | x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE; |
| @@ -551,6 +555,7 @@ static struct sock *x25_make_new(struct sock *osk) | |||
| 551 | x25->facilities = ox25->facilities; | 555 | x25->facilities = ox25->facilities; |
| 552 | x25->qbitincl = ox25->qbitincl; | 556 | x25->qbitincl = ox25->qbitincl; |
| 553 | x25->cudmatchlength = ox25->cudmatchlength; | 557 | x25->cudmatchlength = ox25->cudmatchlength; |
| 558 | x25->accptapprv = ox25->accptapprv; | ||
| 554 | 559 | ||
| 555 | x25_init_timers(sk); | 560 | x25_init_timers(sk); |
| 556 | out: | 561 | out: |
| @@ -900,9 +905,11 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
| 900 | makex25->vc_facil_mask &= ~X25_MASK_REVERSE; | 905 | makex25->vc_facil_mask &= ~X25_MASK_REVERSE; |
| 901 | makex25->cudmatchlength = x25_sk(sk)->cudmatchlength; | 906 | makex25->cudmatchlength = x25_sk(sk)->cudmatchlength; |
| 902 | 907 | ||
| 903 | x25_write_internal(make, X25_CALL_ACCEPTED); | 908 | /* Normally all calls are accepted immediatly */ |
| 904 | 909 | if(makex25->accptapprv & X25_DENY_ACCPT_APPRV) { | |
| 905 | makex25->state = X25_STATE_3; | 910 | x25_write_internal(make, X25_CALL_ACCEPTED); |
| 911 | makex25->state = X25_STATE_3; | ||
| 912 | } | ||
| 906 | 913 | ||
| 907 | /* | 914 | /* |
| 908 | * Incoming Call User Data. | 915 | * Incoming Call User Data. |
| @@ -1294,7 +1301,8 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
| 1294 | if (facilities.throughput < 0x03 || | 1301 | if (facilities.throughput < 0x03 || |
| 1295 | facilities.throughput > 0xDD) | 1302 | facilities.throughput > 0xDD) |
| 1296 | break; | 1303 | break; |
| 1297 | if (facilities.reverse && facilities.reverse != 1) | 1304 | if (facilities.reverse && |
| 1305 | (facilities.reverse | 0x81)!= 0x81) | ||
| 1298 | break; | 1306 | break; |
| 1299 | x25->facilities = facilities; | 1307 | x25->facilities = facilities; |
| 1300 | rc = 0; | 1308 | rc = 0; |
| @@ -1348,6 +1356,27 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
| 1348 | break; | 1356 | break; |
| 1349 | } | 1357 | } |
| 1350 | 1358 | ||
| 1359 | case SIOCX25CALLACCPTAPPRV: { | ||
| 1360 | rc = -EINVAL; | ||
| 1361 | if (sk->sk_state != TCP_CLOSE) | ||
| 1362 | break; | ||
| 1363 | x25->accptapprv = X25_ALLOW_ACCPT_APPRV; | ||
| 1364 | rc = 0; | ||
| 1365 | break; | ||
| 1366 | } | ||
| 1367 | |||
| 1368 | case SIOCX25SENDCALLACCPT: { | ||
| 1369 | rc = -EINVAL; | ||
| 1370 | if (sk->sk_state != TCP_ESTABLISHED) | ||
| 1371 | break; | ||
| 1372 | if (x25->accptapprv) /* must call accptapprv above */ | ||
| 1373 | break; | ||
| 1374 | x25_write_internal(sk, X25_CALL_ACCEPTED); | ||
| 1375 | x25->state = X25_STATE_3; | ||
| 1376 | rc = 0; | ||
| 1377 | break; | ||
| 1378 | } | ||
| 1379 | |||
| 1351 | default: | 1380 | default: |
| 1352 | rc = dev_ioctl(cmd, argp); | 1381 | rc = dev_ioctl(cmd, argp); |
| 1353 | break; | 1382 | break; |
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index a21bdb95f9a8..54278b962f4c 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c | |||
| @@ -17,6 +17,8 @@ | |||
| 17 | * X.25 001 Split from x25_subr.c | 17 | * X.25 001 Split from x25_subr.c |
| 18 | * mar/20/00 Daniela Squassoni Disabling/enabling of facilities | 18 | * mar/20/00 Daniela Squassoni Disabling/enabling of facilities |
| 19 | * negotiation. | 19 | * negotiation. |
| 20 | * apr/14/05 Shaun Pereira - Allow fast select with no restriction | ||
| 21 | * on response. | ||
| 20 | */ | 22 | */ |
| 21 | 23 | ||
| 22 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
| @@ -43,9 +45,31 @@ int x25_parse_facilities(struct sk_buff *skb, | |||
| 43 | case X25_FAC_CLASS_A: | 45 | case X25_FAC_CLASS_A: |
| 44 | switch (*p) { | 46 | switch (*p) { |
| 45 | case X25_FAC_REVERSE: | 47 | case X25_FAC_REVERSE: |
| 46 | facilities->reverse = p[1] & 0x01; | 48 | if((p[1] & 0x81) == 0x81) { |
| 47 | *vc_fac_mask |= X25_MASK_REVERSE; | 49 | facilities->reverse = p[1] & 0x81; |
| 48 | break; | 50 | *vc_fac_mask |= X25_MASK_REVERSE; |
| 51 | break; | ||
| 52 | } | ||
| 53 | |||
| 54 | if((p[1] & 0x01) == 0x01) { | ||
| 55 | facilities->reverse = p[1] & 0x01; | ||
| 56 | *vc_fac_mask |= X25_MASK_REVERSE; | ||
| 57 | break; | ||
| 58 | } | ||
| 59 | |||
| 60 | if((p[1] & 0x80) == 0x80) { | ||
| 61 | facilities->reverse = p[1] & 0x80; | ||
| 62 | *vc_fac_mask |= X25_MASK_REVERSE; | ||
| 63 | break; | ||
| 64 | } | ||
| 65 | |||
| 66 | if(p[1] == 0x00) { | ||
| 67 | facilities->reverse | ||
| 68 | = X25_DEFAULT_REVERSE; | ||
| 69 | *vc_fac_mask |= X25_MASK_REVERSE; | ||
| 70 | break; | ||
| 71 | } | ||
| 72 | |||
| 49 | case X25_FAC_THROUGHPUT: | 73 | case X25_FAC_THROUGHPUT: |
| 50 | facilities->throughput = p[1]; | 74 | facilities->throughput = p[1]; |
| 51 | *vc_fac_mask |= X25_MASK_THROUGHPUT; | 75 | *vc_fac_mask |= X25_MASK_THROUGHPUT; |
| @@ -122,7 +146,7 @@ int x25_create_facilities(unsigned char *buffer, | |||
| 122 | 146 | ||
| 123 | if (facilities->reverse && (facil_mask & X25_MASK_REVERSE)) { | 147 | if (facilities->reverse && (facil_mask & X25_MASK_REVERSE)) { |
| 124 | *p++ = X25_FAC_REVERSE; | 148 | *p++ = X25_FAC_REVERSE; |
| 125 | *p++ = !!facilities->reverse; | 149 | *p++ = facilities->reverse; |
| 126 | } | 150 | } |
| 127 | 151 | ||
| 128 | if (facilities->throughput && (facil_mask & X25_MASK_THROUGHPUT)) { | 152 | if (facilities->throughput && (facil_mask & X25_MASK_THROUGHPUT)) { |
| @@ -171,7 +195,7 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, | |||
| 171 | /* | 195 | /* |
| 172 | * They want reverse charging, we won't accept it. | 196 | * They want reverse charging, we won't accept it. |
| 173 | */ | 197 | */ |
| 174 | if (theirs.reverse && ours->reverse) { | 198 | if ((theirs.reverse & 0x01 ) && (ours->reverse & 0x01)) { |
| 175 | SOCK_DEBUG(sk, "X.25: rejecting reverse charging request"); | 199 | SOCK_DEBUG(sk, "X.25: rejecting reverse charging request"); |
| 176 | return -1; | 200 | return -1; |
| 177 | } | 201 | } |
diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c index c349bbd61684..7fd872ad0c20 100644 --- a/net/x25/x25_subr.c +++ b/net/x25/x25_subr.c | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | * mar/20/00 Daniela Squassoni Disabling/enabling of facilities | 19 | * mar/20/00 Daniela Squassoni Disabling/enabling of facilities |
| 20 | * negotiation. | 20 | * negotiation. |
| 21 | * jun/24/01 Arnaldo C. Melo use skb_queue_purge, cleanups | 21 | * jun/24/01 Arnaldo C. Melo use skb_queue_purge, cleanups |
| 22 | * apr/04/15 Shaun Pereira Fast select with no | ||
| 23 | * restriction on response. | ||
| 22 | */ | 24 | */ |
| 23 | 25 | ||
| 24 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
| @@ -127,8 +129,12 @@ void x25_write_internal(struct sock *sk, int frametype) | |||
| 127 | len += 1 + X25_ADDR_LEN + X25_MAX_FAC_LEN + | 129 | len += 1 + X25_ADDR_LEN + X25_MAX_FAC_LEN + |
| 128 | X25_MAX_CUD_LEN; | 130 | X25_MAX_CUD_LEN; |
| 129 | break; | 131 | break; |
| 130 | case X25_CALL_ACCEPTED: | 132 | case X25_CALL_ACCEPTED: /* fast sel with no restr on resp */ |
| 131 | len += 1 + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN; | 133 | if(x25->facilities.reverse & 0x80) { |
| 134 | len += 1 + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN; | ||
| 135 | } else { | ||
| 136 | len += 1 + X25_MAX_FAC_LEN; | ||
| 137 | } | ||
| 132 | break; | 138 | break; |
| 133 | case X25_CLEAR_REQUEST: | 139 | case X25_CLEAR_REQUEST: |
| 134 | case X25_RESET_REQUEST: | 140 | case X25_RESET_REQUEST: |
| @@ -203,9 +209,16 @@ void x25_write_internal(struct sock *sk, int frametype) | |||
| 203 | x25->vc_facil_mask); | 209 | x25->vc_facil_mask); |
| 204 | dptr = skb_put(skb, len); | 210 | dptr = skb_put(skb, len); |
| 205 | memcpy(dptr, facilities, len); | 211 | memcpy(dptr, facilities, len); |
| 206 | dptr = skb_put(skb, x25->calluserdata.cudlength); | 212 | |
| 207 | memcpy(dptr, x25->calluserdata.cuddata, | 213 | /* fast select with no restriction on response |
| 208 | x25->calluserdata.cudlength); | 214 | allows call user data. Userland must |
| 215 | ensure it is ours and not theirs */ | ||
| 216 | if(x25->facilities.reverse & 0x80) { | ||
| 217 | dptr = skb_put(skb, | ||
| 218 | x25->calluserdata.cudlength); | ||
| 219 | memcpy(dptr, x25->calluserdata.cuddata, | ||
| 220 | x25->calluserdata.cudlength); | ||
| 221 | } | ||
| 209 | x25->calluserdata.cudlength = 0; | 222 | x25->calluserdata.cudlength = 0; |
| 210 | break; | 223 | break; |
| 211 | 224 | ||
