diff options
author | Patrick McHardy <kaber@trash.net> | 2011-01-14 08:12:37 -0500 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2011-01-14 08:12:37 -0500 |
commit | 0134e89c7bcc9fde1da962c82a120691e185619f (patch) | |
tree | 3e03335cf001019a2687d161e956de4f73379984 /net/tipc/socket.c | |
parent | c7066f70d9610df0b9406cc635fc09e86136e714 (diff) | |
parent | 6faee60a4e82075853a437831768cc9e2e563e4e (diff) |
Merge branch 'master' of git://1984.lsi.us.es/net-next-2.6
Conflicts:
net/ipv4/route.c
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 156 |
1 files changed, 63 insertions, 93 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 33217fc3d697..2b02a3a80313 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -34,25 +34,13 @@ | |||
34 | * POSSIBILITY OF SUCH DAMAGE. | 34 | * POSSIBILITY OF SUCH DAMAGE. |
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include <linux/module.h> | ||
38 | #include <linux/types.h> | ||
39 | #include <linux/net.h> | ||
40 | #include <linux/socket.h> | ||
41 | #include <linux/errno.h> | ||
42 | #include <linux/mm.h> | ||
43 | #include <linux/poll.h> | ||
44 | #include <linux/fcntl.h> | ||
45 | #include <linux/gfp.h> | ||
46 | #include <asm/string.h> | ||
47 | #include <asm/atomic.h> | ||
48 | #include <net/sock.h> | 37 | #include <net/sock.h> |
49 | 38 | ||
50 | #include <linux/tipc.h> | 39 | #include <linux/tipc.h> |
51 | #include <linux/tipc_config.h> | 40 | #include <linux/tipc_config.h> |
52 | #include <net/tipc/tipc_msg.h> | ||
53 | #include <net/tipc/tipc_port.h> | ||
54 | 41 | ||
55 | #include "core.h" | 42 | #include "core.h" |
43 | #include "port.h" | ||
56 | 44 | ||
57 | #define SS_LISTENING -1 /* socket is listening */ | 45 | #define SS_LISTENING -1 /* socket is listening */ |
58 | #define SS_READY -2 /* socket is connectionless */ | 46 | #define SS_READY -2 /* socket is connectionless */ |
@@ -80,7 +68,7 @@ static const struct proto_ops msg_ops; | |||
80 | 68 | ||
81 | static struct proto tipc_proto; | 69 | static struct proto tipc_proto; |
82 | 70 | ||
83 | static int sockets_enabled = 0; | 71 | static int sockets_enabled; |
84 | 72 | ||
85 | static atomic_t tipc_queue_size = ATOMIC_INIT(0); | 73 | static atomic_t tipc_queue_size = ATOMIC_INIT(0); |
86 | 74 | ||
@@ -387,7 +375,7 @@ static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len) | |||
387 | * | 375 | * |
388 | * NOTE: This routine doesn't need to take the socket lock since it only | 376 | * NOTE: This routine doesn't need to take the socket lock since it only |
389 | * accesses socket information that is unchanging (or which changes in | 377 | * accesses socket information that is unchanging (or which changes in |
390 | * a completely predictable manner). | 378 | * a completely predictable manner). |
391 | */ | 379 | */ |
392 | 380 | ||
393 | static int get_name(struct socket *sock, struct sockaddr *uaddr, | 381 | static int get_name(struct socket *sock, struct sockaddr *uaddr, |
@@ -396,6 +384,7 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr, | |||
396 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; | 384 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; |
397 | struct tipc_sock *tsock = tipc_sk(sock->sk); | 385 | struct tipc_sock *tsock = tipc_sk(sock->sk); |
398 | 386 | ||
387 | memset(addr, 0, sizeof(*addr)); | ||
399 | if (peer) { | 388 | if (peer) { |
400 | if ((sock->state != SS_CONNECTED) && | 389 | if ((sock->state != SS_CONNECTED) && |
401 | ((peer != 2) || (sock->state != SS_DISCONNECTING))) | 390 | ((peer != 2) || (sock->state != SS_DISCONNECTING))) |
@@ -403,7 +392,8 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr, | |||
403 | addr->addr.id.ref = tsock->peer_name.ref; | 392 | addr->addr.id.ref = tsock->peer_name.ref; |
404 | addr->addr.id.node = tsock->peer_name.node; | 393 | addr->addr.id.node = tsock->peer_name.node; |
405 | } else { | 394 | } else { |
406 | tipc_ownidentity(tsock->p->ref, &addr->addr.id); | 395 | addr->addr.id.ref = tsock->p->ref; |
396 | addr->addr.id.node = tipc_own_addr; | ||
407 | } | 397 | } |
408 | 398 | ||
409 | *uaddr_len = sizeof(*addr); | 399 | *uaddr_len = sizeof(*addr); |
@@ -573,37 +563,35 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
573 | 563 | ||
574 | do { | 564 | do { |
575 | if (dest->addrtype == TIPC_ADDR_NAME) { | 565 | if (dest->addrtype == TIPC_ADDR_NAME) { |
576 | if ((res = dest_name_check(dest, m))) | 566 | res = dest_name_check(dest, m); |
567 | if (res) | ||
577 | break; | 568 | break; |
578 | res = tipc_send2name(tport->ref, | 569 | res = tipc_send2name(tport->ref, |
579 | &dest->addr.name.name, | 570 | &dest->addr.name.name, |
580 | dest->addr.name.domain, | 571 | dest->addr.name.domain, |
581 | m->msg_iovlen, | 572 | m->msg_iovlen, |
582 | m->msg_iov); | 573 | m->msg_iov); |
583 | } | 574 | } else if (dest->addrtype == TIPC_ADDR_ID) { |
584 | else if (dest->addrtype == TIPC_ADDR_ID) { | ||
585 | res = tipc_send2port(tport->ref, | 575 | res = tipc_send2port(tport->ref, |
586 | &dest->addr.id, | 576 | &dest->addr.id, |
587 | m->msg_iovlen, | 577 | m->msg_iovlen, |
588 | m->msg_iov); | 578 | m->msg_iov); |
589 | } | 579 | } else if (dest->addrtype == TIPC_ADDR_MCAST) { |
590 | else if (dest->addrtype == TIPC_ADDR_MCAST) { | ||
591 | if (needs_conn) { | 580 | if (needs_conn) { |
592 | res = -EOPNOTSUPP; | 581 | res = -EOPNOTSUPP; |
593 | break; | 582 | break; |
594 | } | 583 | } |
595 | if ((res = dest_name_check(dest, m))) | 584 | res = dest_name_check(dest, m); |
585 | if (res) | ||
596 | break; | 586 | break; |
597 | res = tipc_multicast(tport->ref, | 587 | res = tipc_multicast(tport->ref, |
598 | &dest->addr.nameseq, | 588 | &dest->addr.nameseq, |
599 | 0, | ||
600 | m->msg_iovlen, | 589 | m->msg_iovlen, |
601 | m->msg_iov); | 590 | m->msg_iov); |
602 | } | 591 | } |
603 | if (likely(res != -ELINKCONG)) { | 592 | if (likely(res != -ELINKCONG)) { |
604 | if (needs_conn && (res >= 0)) { | 593 | if (needs_conn && (res >= 0)) |
605 | sock->state = SS_CONNECTING; | 594 | sock->state = SS_CONNECTING; |
606 | } | ||
607 | break; | 595 | break; |
608 | } | 596 | } |
609 | if (m->msg_flags & MSG_DONTWAIT) { | 597 | if (m->msg_flags & MSG_DONTWAIT) { |
@@ -662,9 +650,8 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
662 | } | 650 | } |
663 | 651 | ||
664 | res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov); | 652 | res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov); |
665 | if (likely(res != -ELINKCONG)) { | 653 | if (likely(res != -ELINKCONG)) |
666 | break; | 654 | break; |
667 | } | ||
668 | if (m->msg_flags & MSG_DONTWAIT) { | 655 | if (m->msg_flags & MSG_DONTWAIT) { |
669 | res = -EWOULDBLOCK; | 656 | res = -EWOULDBLOCK; |
670 | break; | 657 | break; |
@@ -763,7 +750,8 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, | |||
763 | bytes_to_send = curr_left; | 750 | bytes_to_send = curr_left; |
764 | my_iov.iov_base = curr_start; | 751 | my_iov.iov_base = curr_start; |
765 | my_iov.iov_len = bytes_to_send; | 752 | my_iov.iov_len = bytes_to_send; |
766 | if ((res = send_packet(NULL, sock, &my_msg, 0)) < 0) { | 753 | res = send_packet(NULL, sock, &my_msg, 0); |
754 | if (res < 0) { | ||
767 | if (bytes_sent) | 755 | if (bytes_sent) |
768 | res = bytes_sent; | 756 | res = bytes_sent; |
769 | goto exit; | 757 | goto exit; |
@@ -823,8 +811,8 @@ static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg) | |||
823 | addr->addrtype = TIPC_ADDR_ID; | 811 | addr->addrtype = TIPC_ADDR_ID; |
824 | addr->addr.id.ref = msg_origport(msg); | 812 | addr->addr.id.ref = msg_origport(msg); |
825 | addr->addr.id.node = msg_orignode(msg); | 813 | addr->addr.id.node = msg_orignode(msg); |
826 | addr->addr.name.domain = 0; /* could leave uninitialized */ | 814 | addr->addr.name.domain = 0; /* could leave uninitialized */ |
827 | addr->scope = 0; /* could leave uninitialized */ | 815 | addr->scope = 0; /* could leave uninitialized */ |
828 | m->msg_namelen = sizeof(struct sockaddr_tipc); | 816 | m->msg_namelen = sizeof(struct sockaddr_tipc); |
829 | } | 817 | } |
830 | } | 818 | } |
@@ -858,12 +846,15 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, | |||
858 | if (unlikely(err)) { | 846 | if (unlikely(err)) { |
859 | anc_data[0] = err; | 847 | anc_data[0] = err; |
860 | anc_data[1] = msg_data_sz(msg); | 848 | anc_data[1] = msg_data_sz(msg); |
861 | if ((res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data))) | 849 | res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data); |
862 | return res; | 850 | if (res) |
863 | if (anc_data[1] && | ||
864 | (res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1], | ||
865 | msg_data(msg)))) | ||
866 | return res; | 851 | return res; |
852 | if (anc_data[1]) { | ||
853 | res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1], | ||
854 | msg_data(msg)); | ||
855 | if (res) | ||
856 | return res; | ||
857 | } | ||
867 | } | 858 | } |
868 | 859 | ||
869 | /* Optionally capture message destination object */ | 860 | /* Optionally capture message destination object */ |
@@ -891,9 +882,11 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, | |||
891 | default: | 882 | default: |
892 | has_name = 0; | 883 | has_name = 0; |
893 | } | 884 | } |
894 | if (has_name && | 885 | if (has_name) { |
895 | (res = put_cmsg(m, SOL_TIPC, TIPC_DESTNAME, 12, anc_data))) | 886 | res = put_cmsg(m, SOL_TIPC, TIPC_DESTNAME, 12, anc_data); |
896 | return res; | 887 | if (res) |
888 | return res; | ||
889 | } | ||
897 | 890 | ||
898 | return 0; | 891 | return 0; |
899 | } | 892 | } |
@@ -1226,42 +1219,25 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf) | |||
1226 | */ | 1219 | */ |
1227 | 1220 | ||
1228 | if (sock->state == SS_READY) { | 1221 | if (sock->state == SS_READY) { |
1229 | if (msg_connected(msg)) { | 1222 | if (msg_connected(msg)) |
1230 | msg_dbg(msg, "dispatch filter 1\n"); | ||
1231 | return TIPC_ERR_NO_PORT; | 1223 | return TIPC_ERR_NO_PORT; |
1232 | } | ||
1233 | } else { | 1224 | } else { |
1234 | if (msg_mcast(msg)) { | 1225 | if (msg_mcast(msg)) |
1235 | msg_dbg(msg, "dispatch filter 2\n"); | ||
1236 | return TIPC_ERR_NO_PORT; | 1226 | return TIPC_ERR_NO_PORT; |
1237 | } | ||
1238 | if (sock->state == SS_CONNECTED) { | 1227 | if (sock->state == SS_CONNECTED) { |
1239 | if (!msg_connected(msg)) { | 1228 | if (!msg_connected(msg)) |
1240 | msg_dbg(msg, "dispatch filter 3\n"); | ||
1241 | return TIPC_ERR_NO_PORT; | 1229 | return TIPC_ERR_NO_PORT; |
1242 | } | 1230 | } else if (sock->state == SS_CONNECTING) { |
1243 | } | 1231 | if (!msg_connected(msg) && (msg_errcode(msg) == 0)) |
1244 | else if (sock->state == SS_CONNECTING) { | ||
1245 | if (!msg_connected(msg) && (msg_errcode(msg) == 0)) { | ||
1246 | msg_dbg(msg, "dispatch filter 4\n"); | ||
1247 | return TIPC_ERR_NO_PORT; | 1232 | return TIPC_ERR_NO_PORT; |
1248 | } | 1233 | } else if (sock->state == SS_LISTENING) { |
1249 | } | 1234 | if (msg_connected(msg) || msg_errcode(msg)) |
1250 | else if (sock->state == SS_LISTENING) { | ||
1251 | if (msg_connected(msg) || msg_errcode(msg)) { | ||
1252 | msg_dbg(msg, "dispatch filter 5\n"); | ||
1253 | return TIPC_ERR_NO_PORT; | 1235 | return TIPC_ERR_NO_PORT; |
1254 | } | 1236 | } else if (sock->state == SS_DISCONNECTING) { |
1255 | } | ||
1256 | else if (sock->state == SS_DISCONNECTING) { | ||
1257 | msg_dbg(msg, "dispatch filter 6\n"); | ||
1258 | return TIPC_ERR_NO_PORT; | 1237 | return TIPC_ERR_NO_PORT; |
1259 | } | 1238 | } else /* (sock->state == SS_UNCONNECTED) */ { |
1260 | else /* (sock->state == SS_UNCONNECTED) */ { | 1239 | if (msg_connected(msg) || msg_errcode(msg)) |
1261 | if (msg_connected(msg) || msg_errcode(msg)) { | ||
1262 | msg_dbg(msg, "dispatch filter 7\n"); | ||
1263 | return TIPC_ERR_NO_PORT; | 1240 | return TIPC_ERR_NO_PORT; |
1264 | } | ||
1265 | } | 1241 | } |
1266 | } | 1242 | } |
1267 | 1243 | ||
@@ -1280,7 +1256,6 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf) | |||
1280 | 1256 | ||
1281 | /* Enqueue message (finally!) */ | 1257 | /* Enqueue message (finally!) */ |
1282 | 1258 | ||
1283 | msg_dbg(msg, "<DISP<: "); | ||
1284 | TIPC_SKB_CB(buf)->handle = msg_data(msg); | 1259 | TIPC_SKB_CB(buf)->handle = msg_data(msg); |
1285 | atomic_inc(&tipc_queue_size); | 1260 | atomic_inc(&tipc_queue_size); |
1286 | __skb_queue_tail(&sk->sk_receive_queue, buf); | 1261 | __skb_queue_tail(&sk->sk_receive_queue, buf); |
@@ -1441,9 +1416,8 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
1441 | m.msg_name = dest; | 1416 | m.msg_name = dest; |
1442 | m.msg_namelen = destlen; | 1417 | m.msg_namelen = destlen; |
1443 | res = send_msg(NULL, sock, &m, 0); | 1418 | res = send_msg(NULL, sock, &m, 0); |
1444 | if (res < 0) { | 1419 | if (res < 0) |
1445 | goto exit; | 1420 | goto exit; |
1446 | } | ||
1447 | 1421 | ||
1448 | /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */ | 1422 | /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */ |
1449 | 1423 | ||
@@ -1465,11 +1439,10 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
1465 | advance_rx_queue(sk); | 1439 | advance_rx_queue(sk); |
1466 | } | 1440 | } |
1467 | } else { | 1441 | } else { |
1468 | if (sock->state == SS_CONNECTED) { | 1442 | if (sock->state == SS_CONNECTED) |
1469 | res = -EISCONN; | 1443 | res = -EISCONN; |
1470 | } else { | 1444 | else |
1471 | res = -ECONNREFUSED; | 1445 | res = -ECONNREFUSED; |
1472 | } | ||
1473 | } | 1446 | } |
1474 | } else { | 1447 | } else { |
1475 | if (res == 0) | 1448 | if (res == 0) |
@@ -1588,7 +1561,6 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) | |||
1588 | * Respond to 'SYN+' by queuing it on new socket. | 1561 | * Respond to 'SYN+' by queuing it on new socket. |
1589 | */ | 1562 | */ |
1590 | 1563 | ||
1591 | msg_dbg(msg,"<ACC<: "); | ||
1592 | if (!msg_data_sz(msg)) { | 1564 | if (!msg_data_sz(msg)) { |
1593 | struct msghdr m = {NULL,}; | 1565 | struct msghdr m = {NULL,}; |
1594 | 1566 | ||
@@ -1696,7 +1668,8 @@ static int setsockopt(struct socket *sock, | |||
1696 | return -ENOPROTOOPT; | 1668 | return -ENOPROTOOPT; |
1697 | if (ol < sizeof(value)) | 1669 | if (ol < sizeof(value)) |
1698 | return -EINVAL; | 1670 | return -EINVAL; |
1699 | if ((res = get_user(value, (u32 __user *)ov))) | 1671 | res = get_user(value, (u32 __user *)ov); |
1672 | if (res) | ||
1700 | return res; | 1673 | return res; |
1701 | 1674 | ||
1702 | lock_sock(sk); | 1675 | lock_sock(sk); |
@@ -1754,7 +1727,8 @@ static int getsockopt(struct socket *sock, | |||
1754 | return put_user(0, ol); | 1727 | return put_user(0, ol); |
1755 | if (lvl != SOL_TIPC) | 1728 | if (lvl != SOL_TIPC) |
1756 | return -ENOPROTOOPT; | 1729 | return -ENOPROTOOPT; |
1757 | if ((res = get_user(len, ol))) | 1730 | res = get_user(len, ol); |
1731 | if (res) | ||
1758 | return res; | 1732 | return res; |
1759 | 1733 | ||
1760 | lock_sock(sk); | 1734 | lock_sock(sk); |
@@ -1773,10 +1747,10 @@ static int getsockopt(struct socket *sock, | |||
1773 | value = jiffies_to_msecs(tipc_sk(sk)->conn_timeout); | 1747 | value = jiffies_to_msecs(tipc_sk(sk)->conn_timeout); |
1774 | /* no need to set "res", since already 0 at this point */ | 1748 | /* no need to set "res", since already 0 at this point */ |
1775 | break; | 1749 | break; |
1776 | case TIPC_NODE_RECVQ_DEPTH: | 1750 | case TIPC_NODE_RECVQ_DEPTH: |
1777 | value = (u32)atomic_read(&tipc_queue_size); | 1751 | value = (u32)atomic_read(&tipc_queue_size); |
1778 | break; | 1752 | break; |
1779 | case TIPC_SOCK_RECVQ_DEPTH: | 1753 | case TIPC_SOCK_RECVQ_DEPTH: |
1780 | value = skb_queue_len(&sk->sk_receive_queue); | 1754 | value = skb_queue_len(&sk->sk_receive_queue); |
1781 | break; | 1755 | break; |
1782 | default: | 1756 | default: |
@@ -1785,20 +1759,16 @@ static int getsockopt(struct socket *sock, | |||
1785 | 1759 | ||
1786 | release_sock(sk); | 1760 | release_sock(sk); |
1787 | 1761 | ||
1788 | if (res) { | 1762 | if (res) |
1789 | /* "get" failed */ | 1763 | return res; /* "get" failed */ |
1790 | } | ||
1791 | else if (len < sizeof(value)) { | ||
1792 | res = -EINVAL; | ||
1793 | } | ||
1794 | else if (copy_to_user(ov, &value, sizeof(value))) { | ||
1795 | res = -EFAULT; | ||
1796 | } | ||
1797 | else { | ||
1798 | res = put_user(sizeof(value), ol); | ||
1799 | } | ||
1800 | 1764 | ||
1801 | return res; | 1765 | if (len < sizeof(value)) |
1766 | return -EINVAL; | ||
1767 | |||
1768 | if (copy_to_user(ov, &value, sizeof(value))) | ||
1769 | return -EFAULT; | ||
1770 | |||
1771 | return put_user(sizeof(value), ol); | ||
1802 | } | 1772 | } |
1803 | 1773 | ||
1804 | /** | 1774 | /** |
@@ -1806,7 +1776,7 @@ static int getsockopt(struct socket *sock, | |||
1806 | */ | 1776 | */ |
1807 | 1777 | ||
1808 | static const struct proto_ops msg_ops = { | 1778 | static const struct proto_ops msg_ops = { |
1809 | .owner = THIS_MODULE, | 1779 | .owner = THIS_MODULE, |
1810 | .family = AF_TIPC, | 1780 | .family = AF_TIPC, |
1811 | .release = release, | 1781 | .release = release, |
1812 | .bind = bind, | 1782 | .bind = bind, |
@@ -1827,7 +1797,7 @@ static const struct proto_ops msg_ops = { | |||
1827 | }; | 1797 | }; |
1828 | 1798 | ||
1829 | static const struct proto_ops packet_ops = { | 1799 | static const struct proto_ops packet_ops = { |
1830 | .owner = THIS_MODULE, | 1800 | .owner = THIS_MODULE, |
1831 | .family = AF_TIPC, | 1801 | .family = AF_TIPC, |
1832 | .release = release, | 1802 | .release = release, |
1833 | .bind = bind, | 1803 | .bind = bind, |
@@ -1848,7 +1818,7 @@ static const struct proto_ops packet_ops = { | |||
1848 | }; | 1818 | }; |
1849 | 1819 | ||
1850 | static const struct proto_ops stream_ops = { | 1820 | static const struct proto_ops stream_ops = { |
1851 | .owner = THIS_MODULE, | 1821 | .owner = THIS_MODULE, |
1852 | .family = AF_TIPC, | 1822 | .family = AF_TIPC, |
1853 | .release = release, | 1823 | .release = release, |
1854 | .bind = bind, | 1824 | .bind = bind, |
@@ -1869,7 +1839,7 @@ static const struct proto_ops stream_ops = { | |||
1869 | }; | 1839 | }; |
1870 | 1840 | ||
1871 | static const struct net_proto_family tipc_family_ops = { | 1841 | static const struct net_proto_family tipc_family_ops = { |
1872 | .owner = THIS_MODULE, | 1842 | .owner = THIS_MODULE, |
1873 | .family = AF_TIPC, | 1843 | .family = AF_TIPC, |
1874 | .create = tipc_create | 1844 | .create = tipc_create |
1875 | }; | 1845 | }; |