~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to net/tipc/socket.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 * net/tipc/socket.c: TIPC socket API
3
3
 *
4
4
 * Copyright (c) 2001-2007, Ericsson AB
5
 
 * Copyright (c) 2004-2008, Wind River Systems
 
5
 * Copyright (c) 2004-2008, 2010-2011, Wind River Systems
6
6
 * All rights reserved.
7
7
 *
8
8
 * Redistribution and use in source and binary forms, with or without
58
58
#define tipc_sk(sk) ((struct tipc_sock *)(sk))
59
59
#define tipc_sk_port(sk) ((struct tipc_port *)(tipc_sk(sk)->p))
60
60
 
 
61
#define tipc_rx_ready(sock) (!skb_queue_empty(&sock->sk->sk_receive_queue) || \
 
62
                        (sock->state == SS_DISCONNECTING))
 
63
 
61
64
static int backlog_rcv(struct sock *sk, struct sk_buff *skb);
62
65
static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf);
63
66
static void wakeupdispatch(struct tipc_port *tport);
241
244
                        tipc_set_portunreliable(tp_ptr->ref, 1);
242
245
        }
243
246
 
244
 
        atomic_inc(&tipc_user_count);
245
247
        return 0;
246
248
}
247
249
 
290
292
                if (buf == NULL)
291
293
                        break;
292
294
                atomic_dec(&tipc_queue_size);
293
 
                if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf)))
 
295
                if (TIPC_SKB_CB(buf)->handle != 0)
294
296
                        buf_discard(buf);
295
297
                else {
296
298
                        if ((sock->state == SS_CONNECTING) ||
321
323
        sock_put(sk);
322
324
        sock->sk = NULL;
323
325
 
324
 
        atomic_dec(&tipc_user_count);
325
326
        return res;
326
327
}
327
328
 
495
496
        if (likely(dest->addr.name.name.type != TIPC_CFG_SRV))
496
497
                return -EACCES;
497
498
 
 
499
        if (!m->msg_iovlen || (m->msg_iov[0].iov_len < sizeof(hdr)))
 
500
                return -EMSGSIZE;
498
501
        if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr)))
499
502
                return -EFAULT;
500
503
        if ((ntohs(hdr.tcm_type) & 0xC000) && (!capable(CAP_NET_ADMIN)))
532
535
        if (unlikely((m->msg_namelen < sizeof(*dest)) ||
533
536
                     (dest->family != AF_TIPC)))
534
537
                return -EINVAL;
 
538
        if ((total_len > TIPC_MAX_USER_MSG_SIZE) ||
 
539
            (m->msg_iovlen > (unsigned)INT_MAX))
 
540
                return -EMSGSIZE;
535
541
 
536
542
        if (iocb)
537
543
                lock_sock(sk);
570
576
                                             &dest->addr.name.name,
571
577
                                             dest->addr.name.domain,
572
578
                                             m->msg_iovlen,
573
 
                                             m->msg_iov);
 
579
                                             m->msg_iov,
 
580
                                             total_len);
574
581
                } else if (dest->addrtype == TIPC_ADDR_ID) {
575
582
                        res = tipc_send2port(tport->ref,
576
583
                                             &dest->addr.id,
577
584
                                             m->msg_iovlen,
578
 
                                             m->msg_iov);
 
585
                                             m->msg_iov,
 
586
                                             total_len);
579
587
                } else if (dest->addrtype == TIPC_ADDR_MCAST) {
580
588
                        if (needs_conn) {
581
589
                                res = -EOPNOTSUPP;
587
595
                        res = tipc_multicast(tport->ref,
588
596
                                             &dest->addr.nameseq,
589
597
                                             m->msg_iovlen,
590
 
                                             m->msg_iov);
 
598
                                             m->msg_iov,
 
599
                                             total_len);
591
600
                }
592
601
                if (likely(res != -ELINKCONG)) {
593
602
                        if (needs_conn && (res >= 0))
637
646
        if (unlikely(dest))
638
647
                return send_msg(iocb, sock, m, total_len);
639
648
 
 
649
        if ((total_len > TIPC_MAX_USER_MSG_SIZE) ||
 
650
            (m->msg_iovlen > (unsigned)INT_MAX))
 
651
                return -EMSGSIZE;
 
652
 
640
653
        if (iocb)
641
654
                lock_sock(sk);
642
655
 
649
662
                        break;
650
663
                }
651
664
 
652
 
                res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov);
 
665
                res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov,
 
666
                                total_len);
653
667
                if (likely(res != -ELINKCONG))
654
668
                        break;
655
669
                if (m->msg_flags & MSG_DONTWAIT) {
720
734
                goto exit;
721
735
        }
722
736
 
 
737
        if ((total_len > (unsigned)INT_MAX) ||
 
738
            (m->msg_iovlen > (unsigned)INT_MAX)) {
 
739
                res = -EMSGSIZE;
 
740
                goto exit;
 
741
        }
 
742
 
723
743
        /*
724
744
         * Send each iovec entry using one or more messages
725
745
         *
750
770
                                bytes_to_send = curr_left;
751
771
                        my_iov.iov_base = curr_start;
752
772
                        my_iov.iov_len = bytes_to_send;
753
 
                        res = send_packet(NULL, sock, &my_msg, 0);
 
773
                        res = send_packet(NULL, sock, &my_msg, bytes_to_send);
754
774
                        if (res < 0) {
755
775
                                if (bytes_sent)
756
776
                                        res = bytes_sent;
911
931
        struct tipc_port *tport = tipc_sk_port(sk);
912
932
        struct sk_buff *buf;
913
933
        struct tipc_msg *msg;
 
934
        long timeout;
914
935
        unsigned int sz;
915
936
        u32 err;
916
937
        int res;
917
938
 
918
939
        /* Catch invalid receive requests */
919
940
 
920
 
        if (m->msg_iovlen != 1)
921
 
                return -EOPNOTSUPP;   /* Don't do multiple iovec entries yet */
922
 
 
923
941
        if (unlikely(!buf_len))
924
942
                return -EINVAL;
925
943
 
930
948
                goto exit;
931
949
        }
932
950
 
 
951
        timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
933
952
restart:
934
953
 
935
954
        /* Look for a message in receive queue; wait if necessary */
939
958
                        res = -ENOTCONN;
940
959
                        goto exit;
941
960
                }
942
 
                if (flags & MSG_DONTWAIT) {
943
 
                        res = -EWOULDBLOCK;
 
961
                if (timeout <= 0L) {
 
962
                        res = timeout ? timeout : -EWOULDBLOCK;
944
963
                        goto exit;
945
964
                }
946
965
                release_sock(sk);
947
 
                res = wait_event_interruptible(*sk_sleep(sk),
948
 
                        (!skb_queue_empty(&sk->sk_receive_queue) ||
949
 
                         (sock->state == SS_DISCONNECTING)));
 
966
                timeout = wait_event_interruptible_timeout(*sk_sleep(sk),
 
967
                                                           tipc_rx_ready(sock),
 
968
                                                           timeout);
950
969
                lock_sock(sk);
951
 
                if (res)
952
 
                        goto exit;
953
970
        }
954
971
 
955
972
        /* Look at first message in receive queue */
991
1008
                        sz = buf_len;
992
1009
                        m->msg_flags |= MSG_TRUNC;
993
1010
                }
994
 
                if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg),
995
 
                                          sz))) {
996
 
                        res = -EFAULT;
 
1011
                res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg),
 
1012
                                              m->msg_iov, sz);
 
1013
                if (res)
997
1014
                        goto exit;
998
 
                }
999
1015
                res = sz;
1000
1016
        } else {
1001
1017
                if ((sock->state == SS_READY) ||
1038
1054
        struct tipc_port *tport = tipc_sk_port(sk);
1039
1055
        struct sk_buff *buf;
1040
1056
        struct tipc_msg *msg;
 
1057
        long timeout;
1041
1058
        unsigned int sz;
1042
1059
        int sz_to_copy, target, needed;
1043
1060
        int sz_copied = 0;
1044
 
        char __user *crs = m->msg_iov->iov_base;
1045
 
        unsigned char *buf_crs;
1046
1061
        u32 err;
1047
1062
        int res = 0;
1048
1063
 
1049
1064
        /* Catch invalid receive attempts */
1050
1065
 
1051
 
        if (m->msg_iovlen != 1)
1052
 
                return -EOPNOTSUPP;   /* Don't do multiple iovec entries yet */
1053
 
 
1054
1066
        if (unlikely(!buf_len))
1055
1067
                return -EINVAL;
1056
1068
 
1063
1075
        }
1064
1076
 
1065
1077
        target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
1066
 
 
 
1078
        timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
1067
1079
restart:
1068
1080
 
1069
1081
        /* Look for a message in receive queue; wait if necessary */
1073
1085
                        res = -ENOTCONN;
1074
1086
                        goto exit;
1075
1087
                }
1076
 
                if (flags & MSG_DONTWAIT) {
1077
 
                        res = -EWOULDBLOCK;
 
1088
                if (timeout <= 0L) {
 
1089
                        res = timeout ? timeout : -EWOULDBLOCK;
1078
1090
                        goto exit;
1079
1091
                }
1080
1092
                release_sock(sk);
1081
 
                res = wait_event_interruptible(*sk_sleep(sk),
1082
 
                        (!skb_queue_empty(&sk->sk_receive_queue) ||
1083
 
                         (sock->state == SS_DISCONNECTING)));
 
1093
                timeout = wait_event_interruptible_timeout(*sk_sleep(sk),
 
1094
                                                           tipc_rx_ready(sock),
 
1095
                                                           timeout);
1084
1096
                lock_sock(sk);
1085
 
                if (res)
1086
 
                        goto exit;
1087
1097
        }
1088
1098
 
1089
1099
        /* Look at first message in receive queue */
1112
1122
        /* Capture message data (if valid) & compute return value (always) */
1113
1123
 
1114
1124
        if (!err) {
1115
 
                buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle);
1116
 
                sz = (unsigned char *)msg + msg_size(msg) - buf_crs;
 
1125
                u32 offset = (u32)(unsigned long)(TIPC_SKB_CB(buf)->handle);
1117
1126
 
 
1127
                sz -= offset;
1118
1128
                needed = (buf_len - sz_copied);
1119
1129
                sz_to_copy = (sz <= needed) ? sz : needed;
1120
 
                if (unlikely(copy_to_user(crs, buf_crs, sz_to_copy))) {
1121
 
                        res = -EFAULT;
 
1130
 
 
1131
                res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg) + offset,
 
1132
                                              m->msg_iov, sz_to_copy);
 
1133
                if (res)
1122
1134
                        goto exit;
1123
 
                }
 
1135
 
1124
1136
                sz_copied += sz_to_copy;
1125
1137
 
1126
1138
                if (sz_to_copy < sz) {
1127
1139
                        if (!(flags & MSG_PEEK))
1128
 
                                TIPC_SKB_CB(buf)->handle = buf_crs + sz_to_copy;
 
1140
                                TIPC_SKB_CB(buf)->handle =
 
1141
                                (void *)(unsigned long)(offset + sz_to_copy);
1129
1142
                        goto exit;
1130
1143
                }
1131
 
 
1132
 
                crs += sz_to_copy;
1133
1144
        } else {
1134
1145
                if (sz_copied != 0)
1135
1146
                        goto exit; /* can't add error msg to valid data */
1256
1267
 
1257
1268
        /* Enqueue message (finally!) */
1258
1269
 
1259
 
        TIPC_SKB_CB(buf)->handle = msg_data(msg);
 
1270
        TIPC_SKB_CB(buf)->handle = 0;
1260
1271
        atomic_inc(&tipc_queue_size);
1261
1272
        __skb_queue_tail(&sk->sk_receive_queue, buf);
1262
1273
 
1608
1619
                buf = __skb_dequeue(&sk->sk_receive_queue);
1609
1620
                if (buf) {
1610
1621
                        atomic_dec(&tipc_queue_size);
1611
 
                        if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) {
 
1622
                        if (TIPC_SKB_CB(buf)->handle != 0) {
1612
1623
                                buf_discard(buf);
1613
1624
                                goto restart;
1614
1625
                        }