diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-23 23:44:19 -0500 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-23 23:44:19 -0500 |
| commit | 1ebbe2b20091d306453a5cf480a87e6cd28ae76f (patch) | |
| tree | f5cd7a0fa69b8b1938cb5a0faed2e7b0628072a5 /net/x25 | |
| parent | ac58c9059da8886b5e8cde012a80266b18ca146e (diff) | |
| parent | 674a396c6d2ba0341ebdd7c1c9950f32f018e2dd (diff) | |
Merge branch 'linus'
Diffstat (limited to 'net/x25')
| -rw-r--r-- | net/x25/af_x25.c | 173 | ||||
| -rw-r--r-- | net/x25/x25_facilities.c | 82 | ||||
| -rw-r--r-- | net/x25/x25_in.c | 3 | ||||
| -rw-r--r-- | net/x25/x25_subr.c | 6 |
4 files changed, 247 insertions, 17 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 72b6ff3299ba..282ce4e40d7b 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
| @@ -54,7 +54,10 @@ | |||
| 54 | #include <linux/termios.h> /* For TIOCINQ/OUTQ */ | 54 | #include <linux/termios.h> /* For TIOCINQ/OUTQ */ |
| 55 | #include <linux/notifier.h> | 55 | #include <linux/notifier.h> |
| 56 | #include <linux/init.h> | 56 | #include <linux/init.h> |
| 57 | #include <linux/compat.h> | ||
| 58 | |||
| 57 | #include <net/x25.h> | 59 | #include <net/x25.h> |
| 60 | #include <net/compat.h> | ||
| 58 | 61 | ||
| 59 | int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20; | 62 | int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20; |
| 60 | int sysctl_x25_call_request_timeout = X25_DEFAULT_T21; | 63 | int sysctl_x25_call_request_timeout = X25_DEFAULT_T21; |
| @@ -69,6 +72,14 @@ static const struct proto_ops x25_proto_ops; | |||
| 69 | 72 | ||
| 70 | static struct x25_address null_x25_address = {" "}; | 73 | static struct x25_address null_x25_address = {" "}; |
| 71 | 74 | ||
| 75 | #ifdef CONFIG_COMPAT | ||
| 76 | struct compat_x25_subscrip_struct { | ||
| 77 | char device[200-sizeof(compat_ulong_t)]; | ||
| 78 | compat_ulong_t global_facil_mask; | ||
| 79 | compat_uint_t extended; | ||
| 80 | }; | ||
| 81 | #endif | ||
| 82 | |||
| 72 | int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr, | 83 | int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr, |
| 73 | struct x25_address *calling_addr) | 84 | struct x25_address *calling_addr) |
| 74 | { | 85 | { |
| @@ -514,6 +525,13 @@ static int x25_create(struct socket *sock, int protocol) | |||
| 514 | x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; | 525 | x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; |
| 515 | x25->facilities.throughput = X25_DEFAULT_THROUGHPUT; | 526 | x25->facilities.throughput = X25_DEFAULT_THROUGHPUT; |
| 516 | x25->facilities.reverse = X25_DEFAULT_REVERSE; | 527 | x25->facilities.reverse = X25_DEFAULT_REVERSE; |
| 528 | x25->dte_facilities.calling_len = 0; | ||
| 529 | x25->dte_facilities.called_len = 0; | ||
| 530 | memset(x25->dte_facilities.called_ae, '\0', | ||
| 531 | sizeof(x25->dte_facilities.called_ae)); | ||
| 532 | memset(x25->dte_facilities.calling_ae, '\0', | ||
| 533 | sizeof(x25->dte_facilities.calling_ae)); | ||
| 534 | |||
| 517 | rc = 0; | 535 | rc = 0; |
| 518 | out: | 536 | out: |
| 519 | return rc; | 537 | return rc; |
| @@ -550,6 +568,7 @@ static struct sock *x25_make_new(struct sock *osk) | |||
| 550 | x25->t2 = ox25->t2; | 568 | x25->t2 = ox25->t2; |
| 551 | x25->facilities = ox25->facilities; | 569 | x25->facilities = ox25->facilities; |
| 552 | x25->qbitincl = ox25->qbitincl; | 570 | x25->qbitincl = ox25->qbitincl; |
| 571 | x25->dte_facilities = ox25->dte_facilities; | ||
| 553 | x25->cudmatchlength = ox25->cudmatchlength; | 572 | x25->cudmatchlength = ox25->cudmatchlength; |
| 554 | x25->accptapprv = ox25->accptapprv; | 573 | x25->accptapprv = ox25->accptapprv; |
| 555 | 574 | ||
| @@ -733,7 +752,7 @@ out: | |||
| 733 | return rc; | 752 | return rc; |
| 734 | } | 753 | } |
| 735 | 754 | ||
| 736 | static int x25_wait_for_data(struct sock *sk, int timeout) | 755 | static int x25_wait_for_data(struct sock *sk, long timeout) |
| 737 | { | 756 | { |
| 738 | DECLARE_WAITQUEUE(wait, current); | 757 | DECLARE_WAITQUEUE(wait, current); |
| 739 | int rc = 0; | 758 | int rc = 0; |
| @@ -829,6 +848,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
| 829 | struct x25_sock *makex25; | 848 | struct x25_sock *makex25; |
| 830 | struct x25_address source_addr, dest_addr; | 849 | struct x25_address source_addr, dest_addr; |
| 831 | struct x25_facilities facilities; | 850 | struct x25_facilities facilities; |
| 851 | struct x25_dte_facilities dte_facilities; | ||
| 832 | int len, rc; | 852 | int len, rc; |
| 833 | 853 | ||
| 834 | /* | 854 | /* |
| @@ -865,7 +885,8 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
| 865 | /* | 885 | /* |
| 866 | * Try to reach a compromise on the requested facilities. | 886 | * Try to reach a compromise on the requested facilities. |
| 867 | */ | 887 | */ |
| 868 | if ((len = x25_negotiate_facilities(skb, sk, &facilities)) == -1) | 888 | len = x25_negotiate_facilities(skb, sk, &facilities, &dte_facilities); |
| 889 | if (len == -1) | ||
| 869 | goto out_sock_put; | 890 | goto out_sock_put; |
| 870 | 891 | ||
| 871 | /* | 892 | /* |
| @@ -896,9 +917,12 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
| 896 | makex25->source_addr = source_addr; | 917 | makex25->source_addr = source_addr; |
| 897 | makex25->neighbour = nb; | 918 | makex25->neighbour = nb; |
| 898 | makex25->facilities = facilities; | 919 | makex25->facilities = facilities; |
| 920 | makex25->dte_facilities= dte_facilities; | ||
| 899 | makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask; | 921 | makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask; |
| 900 | /* ensure no reverse facil on accept */ | 922 | /* ensure no reverse facil on accept */ |
| 901 | makex25->vc_facil_mask &= ~X25_MASK_REVERSE; | 923 | makex25->vc_facil_mask &= ~X25_MASK_REVERSE; |
| 924 | /* ensure no calling address extension on accept */ | ||
| 925 | makex25->vc_facil_mask &= ~X25_MASK_CALLING_AE; | ||
| 902 | makex25->cudmatchlength = x25_sk(sk)->cudmatchlength; | 926 | makex25->cudmatchlength = x25_sk(sk)->cudmatchlength; |
| 903 | 927 | ||
| 904 | /* Normally all calls are accepted immediatly */ | 928 | /* Normally all calls are accepted immediatly */ |
| @@ -1305,6 +1329,36 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
| 1305 | break; | 1329 | break; |
| 1306 | } | 1330 | } |
| 1307 | 1331 | ||
| 1332 | case SIOCX25GDTEFACILITIES: { | ||
| 1333 | rc = copy_to_user(argp, &x25->dte_facilities, | ||
| 1334 | sizeof(x25->dte_facilities)); | ||
| 1335 | if (rc) | ||
| 1336 | rc = -EFAULT; | ||
| 1337 | break; | ||
| 1338 | } | ||
| 1339 | |||
| 1340 | case SIOCX25SDTEFACILITIES: { | ||
| 1341 | struct x25_dte_facilities dtefacs; | ||
| 1342 | rc = -EFAULT; | ||
| 1343 | if (copy_from_user(&dtefacs, argp, sizeof(dtefacs))) | ||
| 1344 | break; | ||
| 1345 | rc = -EINVAL; | ||
| 1346 | if (sk->sk_state != TCP_LISTEN && | ||
| 1347 | sk->sk_state != TCP_CLOSE) | ||
| 1348 | break; | ||
| 1349 | if (dtefacs.calling_len > X25_MAX_AE_LEN) | ||
| 1350 | break; | ||
| 1351 | if (dtefacs.calling_ae == NULL) | ||
| 1352 | break; | ||
| 1353 | if (dtefacs.called_len > X25_MAX_AE_LEN) | ||
| 1354 | break; | ||
| 1355 | if (dtefacs.called_ae == NULL) | ||
| 1356 | break; | ||
| 1357 | x25->dte_facilities = dtefacs; | ||
| 1358 | rc = 0; | ||
| 1359 | break; | ||
| 1360 | } | ||
| 1361 | |||
| 1308 | case SIOCX25GCALLUSERDATA: { | 1362 | case SIOCX25GCALLUSERDATA: { |
| 1309 | struct x25_calluserdata cud = x25->calluserdata; | 1363 | struct x25_calluserdata cud = x25->calluserdata; |
| 1310 | rc = copy_to_user(argp, &cud, | 1364 | rc = copy_to_user(argp, &cud, |
| @@ -1387,6 +1441,118 @@ static struct net_proto_family x25_family_ops = { | |||
| 1387 | .owner = THIS_MODULE, | 1441 | .owner = THIS_MODULE, |
| 1388 | }; | 1442 | }; |
| 1389 | 1443 | ||
| 1444 | #ifdef CONFIG_COMPAT | ||
| 1445 | static int compat_x25_subscr_ioctl(unsigned int cmd, | ||
| 1446 | struct compat_x25_subscrip_struct __user *x25_subscr32) | ||
| 1447 | { | ||
| 1448 | struct compat_x25_subscrip_struct x25_subscr; | ||
| 1449 | struct x25_neigh *nb; | ||
| 1450 | struct net_device *dev; | ||
| 1451 | int rc = -EINVAL; | ||
| 1452 | |||
| 1453 | rc = -EFAULT; | ||
| 1454 | if (copy_from_user(&x25_subscr, x25_subscr32, sizeof(*x25_subscr32))) | ||
| 1455 | goto out; | ||
| 1456 | |||
| 1457 | rc = -EINVAL; | ||
| 1458 | dev = x25_dev_get(x25_subscr.device); | ||
| 1459 | if (dev == NULL) | ||
| 1460 | goto out; | ||
| 1461 | |||
| 1462 | nb = x25_get_neigh(dev); | ||
| 1463 | if (nb == NULL) | ||
| 1464 | goto out_dev_put; | ||
| 1465 | |||
| 1466 | dev_put(dev); | ||
| 1467 | |||
| 1468 | if (cmd == SIOCX25GSUBSCRIP) { | ||
| 1469 | x25_subscr.extended = nb->extended; | ||
| 1470 | x25_subscr.global_facil_mask = nb->global_facil_mask; | ||
| 1471 | rc = copy_to_user(x25_subscr32, &x25_subscr, | ||
| 1472 | sizeof(*x25_subscr32)) ? -EFAULT : 0; | ||
| 1473 | } else { | ||
| 1474 | rc = -EINVAL; | ||
| 1475 | if (x25_subscr.extended == 0 || x25_subscr.extended == 1) { | ||
| 1476 | rc = 0; | ||
| 1477 | nb->extended = x25_subscr.extended; | ||
| 1478 | nb->global_facil_mask = x25_subscr.global_facil_mask; | ||
| 1479 | } | ||
| 1480 | } | ||
| 1481 | x25_neigh_put(nb); | ||
| 1482 | out: | ||
| 1483 | return rc; | ||
| 1484 | out_dev_put: | ||
| 1485 | dev_put(dev); | ||
| 1486 | goto out; | ||
| 1487 | } | ||
| 1488 | |||
| 1489 | static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, | ||
| 1490 | unsigned long arg) | ||
| 1491 | { | ||
| 1492 | void __user *argp = compat_ptr(arg); | ||
| 1493 | struct sock *sk = sock->sk; | ||
| 1494 | |||
| 1495 | int rc = -ENOIOCTLCMD; | ||
| 1496 | |||
| 1497 | switch(cmd) { | ||
| 1498 | case TIOCOUTQ: | ||
| 1499 | case TIOCINQ: | ||
| 1500 | rc = x25_ioctl(sock, cmd, (unsigned long)argp); | ||
| 1501 | break; | ||
| 1502 | case SIOCGSTAMP: | ||
| 1503 | rc = -EINVAL; | ||
| 1504 | if (sk) | ||
| 1505 | rc = compat_sock_get_timestamp(sk, | ||
| 1506 | (struct timeval __user*)argp); | ||
| 1507 | break; | ||
| 1508 | case SIOCGIFADDR: | ||
| 1509 | case SIOCSIFADDR: | ||
| 1510 | case SIOCGIFDSTADDR: | ||
| 1511 | case SIOCSIFDSTADDR: | ||
| 1512 | case SIOCGIFBRDADDR: | ||
| 1513 | case SIOCSIFBRDADDR: | ||
| 1514 | case SIOCGIFNETMASK: | ||
| 1515 | case SIOCSIFNETMASK: | ||
| 1516 | case SIOCGIFMETRIC: | ||
| 1517 | case SIOCSIFMETRIC: | ||
| 1518 | rc = -EINVAL; | ||
| 1519 | break; | ||
| 1520 | case SIOCADDRT: | ||
| 1521 | case SIOCDELRT: | ||
| 1522 | rc = -EPERM; | ||
| 1523 | if (!capable(CAP_NET_ADMIN)) | ||
| 1524 | break; | ||
| 1525 | rc = x25_route_ioctl(cmd, argp); | ||
| 1526 | break; | ||
| 1527 | case SIOCX25GSUBSCRIP: | ||
| 1528 | rc = compat_x25_subscr_ioctl(cmd, argp); | ||
| 1529 | break; | ||
| 1530 | case SIOCX25SSUBSCRIP: | ||
| 1531 | rc = -EPERM; | ||
| 1532 | if (!capable(CAP_NET_ADMIN)) | ||
| 1533 | break; | ||
| 1534 | rc = compat_x25_subscr_ioctl(cmd, argp); | ||
| 1535 | break; | ||
| 1536 | case SIOCX25GFACILITIES: | ||
| 1537 | case SIOCX25SFACILITIES: | ||
| 1538 | case SIOCX25GDTEFACILITIES: | ||
| 1539 | case SIOCX25SDTEFACILITIES: | ||
| 1540 | case SIOCX25GCALLUSERDATA: | ||
| 1541 | case SIOCX25SCALLUSERDATA: | ||
| 1542 | case SIOCX25GCAUSEDIAG: | ||
| 1543 | case SIOCX25SCUDMATCHLEN: | ||
| 1544 | case SIOCX25CALLACCPTAPPRV: | ||
| 1545 | case SIOCX25SENDCALLACCPT: | ||
| 1546 | rc = x25_ioctl(sock, cmd, (unsigned long)argp); | ||
| 1547 | break; | ||
| 1548 | default: | ||
| 1549 | rc = -ENOIOCTLCMD; | ||
| 1550 | break; | ||
| 1551 | } | ||
| 1552 | return rc; | ||
| 1553 | } | ||
| 1554 | #endif | ||
| 1555 | |||
| 1390 | static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { | 1556 | static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { |
| 1391 | .family = AF_X25, | 1557 | .family = AF_X25, |
| 1392 | .owner = THIS_MODULE, | 1558 | .owner = THIS_MODULE, |
| @@ -1398,6 +1564,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { | |||
| 1398 | .getname = x25_getname, | 1564 | .getname = x25_getname, |
| 1399 | .poll = datagram_poll, | 1565 | .poll = datagram_poll, |
| 1400 | .ioctl = x25_ioctl, | 1566 | .ioctl = x25_ioctl, |
| 1567 | #ifdef CONFIG_COMPAT | ||
| 1568 | .compat_ioctl = compat_x25_ioctl, | ||
| 1569 | #endif | ||
| 1401 | .listen = x25_listen, | 1570 | .listen = x25_listen, |
| 1402 | .shutdown = sock_no_shutdown, | 1571 | .shutdown = sock_no_shutdown, |
| 1403 | .setsockopt = x25_setsockopt, | 1572 | .setsockopt = x25_setsockopt, |
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index 54278b962f4c..9f42b9c9de37 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c | |||
| @@ -28,18 +28,28 @@ | |||
| 28 | #include <net/x25.h> | 28 | #include <net/x25.h> |
| 29 | 29 | ||
| 30 | /* | 30 | /* |
| 31 | * Parse a set of facilities into the facilities structure. Unrecognised | 31 | * Parse a set of facilities into the facilities structures. Unrecognised |
| 32 | * facilities are written to the debug log file. | 32 | * facilities are written to the debug log file. |
| 33 | */ | 33 | */ |
| 34 | int x25_parse_facilities(struct sk_buff *skb, | 34 | int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, |
| 35 | struct x25_facilities *facilities, | 35 | struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask) |
| 36 | unsigned long *vc_fac_mask) | ||
| 37 | { | 36 | { |
| 38 | unsigned char *p = skb->data; | 37 | unsigned char *p = skb->data; |
| 39 | unsigned int len = *p++; | 38 | unsigned int len = *p++; |
| 40 | 39 | ||
| 41 | *vc_fac_mask = 0; | 40 | *vc_fac_mask = 0; |
| 42 | 41 | ||
| 42 | /* | ||
| 43 | * The kernel knows which facilities were set on an incoming call but | ||
| 44 | * currently this information is not available to userspace. Here we | ||
| 45 | * give userspace who read incoming call facilities 0 length to indicate | ||
| 46 | * it wasn't set. | ||
| 47 | */ | ||
| 48 | dte_facs->calling_len = 0; | ||
| 49 | dte_facs->called_len = 0; | ||
| 50 | memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae)); | ||
| 51 | memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae)); | ||
| 52 | |||
| 43 | while (len > 0) { | 53 | while (len > 0) { |
| 44 | switch (*p & X25_FAC_CLASS_MASK) { | 54 | switch (*p & X25_FAC_CLASS_MASK) { |
| 45 | case X25_FAC_CLASS_A: | 55 | case X25_FAC_CLASS_A: |
| @@ -74,6 +84,8 @@ int x25_parse_facilities(struct sk_buff *skb, | |||
| 74 | facilities->throughput = p[1]; | 84 | facilities->throughput = p[1]; |
| 75 | *vc_fac_mask |= X25_MASK_THROUGHPUT; | 85 | *vc_fac_mask |= X25_MASK_THROUGHPUT; |
| 76 | break; | 86 | break; |
| 87 | case X25_MARKER: | ||
| 88 | break; | ||
| 77 | default: | 89 | default: |
| 78 | printk(KERN_DEBUG "X.25: unknown facility " | 90 | printk(KERN_DEBUG "X.25: unknown facility " |
| 79 | "%02X, value %02X\n", | 91 | "%02X, value %02X\n", |
| @@ -112,11 +124,30 @@ int x25_parse_facilities(struct sk_buff *skb, | |||
| 112 | len -= 4; | 124 | len -= 4; |
| 113 | break; | 125 | break; |
| 114 | case X25_FAC_CLASS_D: | 126 | case X25_FAC_CLASS_D: |
| 115 | printk(KERN_DEBUG "X.25: unknown facility %02X, " | 127 | switch (*p) { |
| 116 | "length %d, values %02X, %02X, %02X, %02X\n", | 128 | case X25_FAC_CALLING_AE: |
| 117 | p[0], p[1], p[2], p[3], p[4], p[5]); | 129 | if (p[1] > X25_MAX_DTE_FACIL_LEN) |
| 130 | break; | ||
| 131 | dte_facs->calling_len = p[2]; | ||
| 132 | memcpy(dte_facs->calling_ae, &p[3], p[1] - 1); | ||
| 133 | *vc_fac_mask |= X25_MASK_CALLING_AE; | ||
| 134 | break; | ||
| 135 | case X25_FAC_CALLED_AE: | ||
| 136 | if (p[1] > X25_MAX_DTE_FACIL_LEN) | ||
| 137 | break; | ||
| 138 | dte_facs->called_len = p[2]; | ||
| 139 | memcpy(dte_facs->called_ae, &p[3], p[1] - 1); | ||
| 140 | *vc_fac_mask |= X25_MASK_CALLED_AE; | ||
| 141 | break; | ||
| 142 | default: | ||
| 143 | printk(KERN_DEBUG "X.25: unknown facility %02X," | ||
| 144 | "length %d, values %02X, %02X, " | ||
| 145 | "%02X, %02X\n", | ||
| 146 | p[0], p[1], p[2], p[3], p[4], p[5]); | ||
| 147 | break; | ||
| 148 | } | ||
| 118 | len -= p[1] + 2; | 149 | len -= p[1] + 2; |
| 119 | p += p[1] + 2; | 150 | p += p[1] + 2; |
| 120 | break; | 151 | break; |
| 121 | } | 152 | } |
| 122 | } | 153 | } |
| @@ -128,8 +159,8 @@ int x25_parse_facilities(struct sk_buff *skb, | |||
| 128 | * Create a set of facilities. | 159 | * Create a set of facilities. |
| 129 | */ | 160 | */ |
| 130 | int x25_create_facilities(unsigned char *buffer, | 161 | int x25_create_facilities(unsigned char *buffer, |
| 131 | struct x25_facilities *facilities, | 162 | struct x25_facilities *facilities, |
| 132 | unsigned long facil_mask) | 163 | struct x25_dte_facilities *dte_facs, unsigned long facil_mask) |
| 133 | { | 164 | { |
| 134 | unsigned char *p = buffer + 1; | 165 | unsigned char *p = buffer + 1; |
| 135 | int len; | 166 | int len; |
| @@ -168,6 +199,33 @@ int x25_create_facilities(unsigned char *buffer, | |||
| 168 | *p++ = facilities->winsize_out ? : facilities->winsize_in; | 199 | *p++ = facilities->winsize_out ? : facilities->winsize_in; |
| 169 | } | 200 | } |
| 170 | 201 | ||
| 202 | if (facil_mask & (X25_MASK_CALLING_AE|X25_MASK_CALLED_AE)) { | ||
| 203 | *p++ = X25_MARKER; | ||
| 204 | *p++ = X25_DTE_SERVICES; | ||
| 205 | } | ||
| 206 | |||
| 207 | if (dte_facs->calling_len && (facil_mask & X25_MASK_CALLING_AE)) { | ||
| 208 | unsigned bytecount = (dte_facs->calling_len % 2) ? | ||
| 209 | dte_facs->calling_len / 2 + 1 : | ||
| 210 | dte_facs->calling_len / 2; | ||
| 211 | *p++ = X25_FAC_CALLING_AE; | ||
| 212 | *p++ = 1 + bytecount; | ||
| 213 | *p++ = dte_facs->calling_len; | ||
| 214 | memcpy(p, dte_facs->calling_ae, bytecount); | ||
| 215 | p += bytecount; | ||
| 216 | } | ||
| 217 | |||
| 218 | if (dte_facs->called_len && (facil_mask & X25_MASK_CALLED_AE)) { | ||
| 219 | unsigned bytecount = (dte_facs->called_len % 2) ? | ||
| 220 | dte_facs->called_len / 2 + 1 : | ||
| 221 | dte_facs->called_len / 2; | ||
| 222 | *p++ = X25_FAC_CALLED_AE; | ||
| 223 | *p++ = 1 + bytecount; | ||
| 224 | *p++ = dte_facs->called_len; | ||
| 225 | memcpy(p, dte_facs->called_ae, bytecount); | ||
| 226 | p+=bytecount; | ||
| 227 | } | ||
| 228 | |||
| 171 | len = p - buffer; | 229 | len = p - buffer; |
| 172 | buffer[0] = len - 1; | 230 | buffer[0] = len - 1; |
| 173 | 231 | ||
| @@ -180,7 +238,7 @@ int x25_create_facilities(unsigned char *buffer, | |||
| 180 | * The only real problem is with reverse charging. | 238 | * The only real problem is with reverse charging. |
| 181 | */ | 239 | */ |
| 182 | int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, | 240 | int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, |
| 183 | struct x25_facilities *new) | 241 | struct x25_facilities *new, struct x25_dte_facilities *dte) |
| 184 | { | 242 | { |
| 185 | struct x25_sock *x25 = x25_sk(sk); | 243 | struct x25_sock *x25 = x25_sk(sk); |
| 186 | struct x25_facilities *ours = &x25->facilities; | 244 | struct x25_facilities *ours = &x25->facilities; |
| @@ -190,7 +248,7 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, | |||
| 190 | memset(&theirs, 0, sizeof(theirs)); | 248 | memset(&theirs, 0, sizeof(theirs)); |
| 191 | memcpy(new, ours, sizeof(*new)); | 249 | memcpy(new, ours, sizeof(*new)); |
| 192 | 250 | ||
| 193 | len = x25_parse_facilities(skb, &theirs, &x25->vc_facil_mask); | 251 | len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask); |
| 194 | 252 | ||
| 195 | /* | 253 | /* |
| 196 | * They want reverse charging, we won't accept it. | 254 | * They want reverse charging, we won't accept it. |
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index 26146874b839..eed50e10f09b 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c | |||
| @@ -106,7 +106,8 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
| 106 | skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr)); | 106 | skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr)); |
| 107 | skb_pull(skb, | 107 | skb_pull(skb, |
| 108 | x25_parse_facilities(skb, &x25->facilities, | 108 | x25_parse_facilities(skb, &x25->facilities, |
| 109 | &x25->vc_facil_mask)); | 109 | &x25->dte_facilities, |
| 110 | &x25->vc_facil_mask)); | ||
| 110 | /* | 111 | /* |
| 111 | * Copy any Call User Data. | 112 | * Copy any Call User Data. |
| 112 | */ | 113 | */ |
diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c index 8be9b8fbc24d..8d6220aa5d0f 100644 --- a/net/x25/x25_subr.c +++ b/net/x25/x25_subr.c | |||
| @@ -190,8 +190,9 @@ void x25_write_internal(struct sock *sk, int frametype) | |||
| 190 | dptr = skb_put(skb, len); | 190 | dptr = skb_put(skb, len); |
| 191 | memcpy(dptr, addresses, len); | 191 | memcpy(dptr, addresses, len); |
| 192 | len = x25_create_facilities(facilities, | 192 | len = x25_create_facilities(facilities, |
| 193 | &x25->facilities, | 193 | &x25->facilities, |
| 194 | x25->neighbour->global_facil_mask); | 194 | &x25->dte_facilities, |
| 195 | x25->neighbour->global_facil_mask); | ||
| 195 | dptr = skb_put(skb, len); | 196 | dptr = skb_put(skb, len); |
| 196 | memcpy(dptr, facilities, len); | 197 | memcpy(dptr, facilities, len); |
| 197 | dptr = skb_put(skb, x25->calluserdata.cudlength); | 198 | dptr = skb_put(skb, x25->calluserdata.cudlength); |
| @@ -206,6 +207,7 @@ void x25_write_internal(struct sock *sk, int frametype) | |||
| 206 | *dptr++ = 0x00; /* Address lengths */ | 207 | *dptr++ = 0x00; /* Address lengths */ |
| 207 | len = x25_create_facilities(facilities, | 208 | len = x25_create_facilities(facilities, |
| 208 | &x25->facilities, | 209 | &x25->facilities, |
| 210 | &x25->dte_facilities, | ||
| 209 | x25->vc_facil_mask); | 211 | x25->vc_facil_mask); |
| 210 | dptr = skb_put(skb, len); | 212 | dptr = skb_put(skb, len); |
| 211 | memcpy(dptr, facilities, len); | 213 | memcpy(dptr, facilities, len); |
