~james-page/ubuntu/saucy/openvswitch/1.12-snapshot

« back to all changes in this revision

Viewing changes to lib/socket-util.c

  • Committer: James Page
  • Date: 2013-08-21 10:16:57 UTC
  • mfrom: (1.1.20)
  • Revision ID: james.page@canonical.com-20130821101657-3o0z0qeiv5zkwlzi
New upstream snapshot

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
 
2
 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
3
3
 *
4
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
5
 * you may not use this file except in compliance with the License.
72
72
        if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != -1) {
73
73
            return 0;
74
74
        } else {
75
 
            VLOG_ERR("fcntl(F_SETFL) failed: %s", strerror(errno));
 
75
            VLOG_ERR("fcntl(F_SETFL) failed: %s", ovs_strerror(errno));
76
76
            return errno;
77
77
        }
78
78
    } else {
79
 
        VLOG_ERR("fcntl(F_GETFL) failed: %s", strerror(errno));
 
79
        VLOG_ERR("fcntl(F_GETFL) failed: %s", ovs_strerror(errno));
80
80
        return errno;
81
81
    }
82
82
}
132
132
int
133
133
get_max_fds(void)
134
134
{
135
 
    static int max_fds = -1;
136
 
    if (max_fds < 0) {
 
135
    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
 
136
    static int max_fds;
 
137
 
 
138
    if (ovsthread_once_start(&once)) {
137
139
        struct rlimit r;
138
140
        if (!getrlimit(RLIMIT_NOFILE, &r) && rlim_is_finite(r.rlim_cur)) {
139
141
            max_fds = r.rlim_cur;
141
143
            VLOG_WARN("failed to obtain fd limit, defaulting to 1024");
142
144
            max_fds = 1024;
143
145
        }
 
146
        ovsthread_once_done(&once);
144
147
    }
 
148
 
145
149
    return max_fds;
146
150
}
147
151
 
178
182
 * successful, otherwise a positive errno value.
179
183
 *
180
184
 * Most Open vSwitch code should not use this because it causes deadlocks:
181
 
 * gethostbyname() sends out a DNS request but that starts a new flow for which
 
185
 * getaddrinfo() sends out a DNS request but that starts a new flow for which
182
186
 * OVS must set up a flow, but it can't because it's waiting for a DNS reply.
183
187
 * The synchronous lookup also delays other activity.  (Of course we can solve
184
188
 * this but it doesn't seem worthwhile quite yet.)  */
185
189
int
186
190
lookup_hostname(const char *host_name, struct in_addr *addr)
187
191
{
188
 
    struct hostent *h;
 
192
    struct addrinfo *result;
 
193
    struct addrinfo hints;
189
194
 
190
195
    if (inet_aton(host_name, addr)) {
191
196
        return 0;
192
197
    }
193
198
 
194
 
    h = gethostbyname(host_name);
195
 
    if (h) {
196
 
        *addr = *(struct in_addr *) h->h_addr;
 
199
    memset(&hints, 0, sizeof hints);
 
200
    hints.ai_family = AF_INET;
 
201
 
 
202
    switch (getaddrinfo(host_name, NULL, &hints, &result)) {
 
203
    case 0:
 
204
        *addr = ALIGNED_CAST(struct sockaddr_in *,
 
205
                             result->ai_addr)->sin_addr;
 
206
        freeaddrinfo(result);
197
207
        return 0;
 
208
 
 
209
#ifdef EAI_ADDRFAMILY
 
210
    case EAI_ADDRFAMILY:
 
211
#endif
 
212
    case EAI_NONAME:
 
213
    case EAI_SERVICE:
 
214
        return ENOENT;
 
215
 
 
216
    case EAI_AGAIN:
 
217
        return EAGAIN;
 
218
 
 
219
    case EAI_BADFLAGS:
 
220
    case EAI_FAMILY:
 
221
    case EAI_SOCKTYPE:
 
222
        return EINVAL;
 
223
 
 
224
    case EAI_FAIL:
 
225
        return EIO;
 
226
 
 
227
    case EAI_MEMORY:
 
228
        return ENOMEM;
 
229
 
 
230
#ifdef EAI_NODATA
 
231
    case EAI_NODATA:
 
232
        return ENXIO;
 
233
#endif
 
234
 
 
235
    case EAI_SYSTEM:
 
236
        return errno;
 
237
 
 
238
    default:
 
239
        return EPROTO;
198
240
    }
199
 
 
200
 
    return (h_errno == HOST_NOT_FOUND ? ENOENT
201
 
            : h_errno == TRY_AGAIN ? EAGAIN
202
 
            : h_errno == NO_RECOVERY ? EIO
203
 
            : h_errno == NO_ADDRESS ? ENXIO
204
 
            : EINVAL);
205
241
}
206
242
 
207
243
int
228
264
        }
229
265
        return 0;
230
266
    } else if (retval < 0) {
231
 
        VLOG_ERR_RL(&rl, "poll: %s", strerror(errno));
 
267
        VLOG_ERR_RL(&rl, "poll: %s", ovs_strerror(errno));
232
268
        return errno;
233
269
    } else {
234
270
        return EAGAIN;
421
457
        int dirfd;
422
458
 
423
459
        if (unlink(bind_path) && errno != ENOENT) {
424
 
            VLOG_WARN("unlinking \"%s\": %s\n", bind_path, strerror(errno));
 
460
            VLOG_WARN("unlinking \"%s\": %s\n",
 
461
                      bind_path, ovs_strerror(errno));
425
462
        }
426
463
        fatal_signal_add_file_to_unlink(bind_path);
427
464
 
571
608
    /* Create non-blocking socket. */
572
609
    fd = socket(AF_INET, style, 0);
573
610
    if (fd < 0) {
574
 
        VLOG_ERR("%s: socket: %s", target, strerror(errno));
 
611
        VLOG_ERR("%s: socket: %s", target, ovs_strerror(errno));
575
612
        error = errno;
576
613
        goto exit;
577
614
    }
585
622
     * connect(), the handshake SYN frames will be sent with a TOS of 0. */
586
623
    error = set_dscp(fd, dscp);
587
624
    if (error) {
588
 
        VLOG_ERR("%s: socket: %s", target, strerror(error));
 
625
        VLOG_ERR("%s: socket: %s", target, ovs_strerror(error));
589
626
        goto exit;
590
627
    }
591
628
 
684
721
inet_open_passive(int style, const char *target, int default_port,
685
722
                  struct sockaddr_in *sinp, uint8_t dscp)
686
723
{
 
724
    bool kernel_chooses_port;
687
725
    struct sockaddr_in sin;
688
726
    int fd = 0, error;
689
727
    unsigned int yes = 1;
696
734
    fd = socket(AF_INET, style, 0);
697
735
    if (fd < 0) {
698
736
        error = errno;
699
 
        VLOG_ERR("%s: socket: %s", target, strerror(error));
 
737
        VLOG_ERR("%s: socket: %s", target, ovs_strerror(error));
700
738
        return -error;
701
739
    }
702
740
    error = set_nonblocking(fd);
706
744
    if (style == SOCK_STREAM
707
745
        && setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) < 0) {
708
746
        error = errno;
709
 
        VLOG_ERR("%s: setsockopt(SO_REUSEADDR): %s", target, strerror(error));
 
747
        VLOG_ERR("%s: setsockopt(SO_REUSEADDR): %s",
 
748
                 target, ovs_strerror(error));
710
749
        goto error;
711
750
    }
712
751
 
713
752
    /* Bind. */
714
753
    if (bind(fd, (struct sockaddr *) &sin, sizeof sin) < 0) {
715
754
        error = errno;
716
 
        VLOG_ERR("%s: bind: %s", target, strerror(error));
 
755
        VLOG_ERR("%s: bind: %s", target, ovs_strerror(error));
717
756
        goto error;
718
757
    }
719
758
 
722
761
     * connect(), the handshake SYN frames will be sent with a TOS of 0. */
723
762
    error = set_dscp(fd, dscp);
724
763
    if (error) {
725
 
        VLOG_ERR("%s: socket: %s", target, strerror(error));
 
764
        VLOG_ERR("%s: socket: %s", target, ovs_strerror(error));
726
765
        goto error;
727
766
    }
728
767
 
729
768
    /* Listen. */
730
769
    if (style == SOCK_STREAM && listen(fd, 10) < 0) {
731
770
        error = errno;
732
 
        VLOG_ERR("%s: listen: %s", target, strerror(error));
 
771
        VLOG_ERR("%s: listen: %s", target, ovs_strerror(error));
733
772
        goto error;
734
773
    }
735
774
 
736
 
    if (sinp) {
 
775
    kernel_chooses_port = sin.sin_port == htons(0);
 
776
    if (sinp || kernel_chooses_port) {
737
777
        socklen_t sin_len = sizeof sin;
738
 
        if (getsockname(fd, (struct sockaddr *) &sin, &sin_len) < 0){
 
778
        if (getsockname(fd, (struct sockaddr *) &sin, &sin_len) < 0) {
739
779
            error = errno;
740
 
            VLOG_ERR("%s: getsockname: %s", target, strerror(error));
 
780
            VLOG_ERR("%s: getsockname: %s", target, ovs_strerror(error));
741
781
            goto error;
742
782
        }
743
783
        if (sin.sin_family != AF_INET || sin_len != sizeof sin) {
745
785
            VLOG_ERR("%s: getsockname: invalid socket name", target);
746
786
            goto error;
747
787
        }
748
 
        *sinp = sin;
 
788
        if (sinp) {
 
789
            *sinp = sin;
 
790
        }
 
791
        if (kernel_chooses_port) {
 
792
            VLOG_INFO("%s: listening on port %"PRIu16,
 
793
                      target, ntohs(sin.sin_port));
 
794
        }
749
795
    }
750
796
 
751
797
    return fd;
761
807
int
762
808
get_null_fd(void)
763
809
{
764
 
    static int null_fd = -1;
765
 
    if (null_fd < 0) {
 
810
    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
 
811
    static int null_fd;
 
812
 
 
813
    if (ovsthread_once_start(&once)) {
766
814
        null_fd = open("/dev/null", O_RDWR);
767
815
        if (null_fd < 0) {
768
816
            int error = errno;
769
 
            VLOG_ERR("could not open /dev/null: %s", strerror(error));
770
 
            return -error;
 
817
            VLOG_ERR("could not open /dev/null: %s", ovs_strerror(error));
 
818
            null_fd = -error;
771
819
        }
 
820
        ovsthread_once_done(&once);
772
821
    }
 
822
 
773
823
    return null_fd;
774
824
}
775
825
 
834
884
                 * really an error. */
835
885
            } else {
836
886
                error = errno;
837
 
                VLOG_ERR("%s: fsync failed (%s)", dir, strerror(error));
 
887
                VLOG_ERR("%s: fsync failed (%s)", dir, ovs_strerror(error));
838
888
            }
839
889
        }
840
890
        close(fd);
841
891
    } else {
842
892
        error = errno;
843
 
        VLOG_ERR("%s: open failed (%s)", dir, strerror(error));
 
893
        VLOG_ERR("%s: open failed (%s)", dir, ovs_strerror(error));
844
894
    }
845
895
    free(dir);
846
896
 
878
928
xpipe(int fds[2])
879
929
{
880
930
    if (pipe(fds)) {
881
 
        VLOG_FATAL("failed to create pipe (%s)", strerror(errno));
 
931
        VLOG_FATAL("failed to create pipe (%s)", ovs_strerror(errno));
882
932
    }
883
933
}
884
934
 
894
944
xsocketpair(int domain, int type, int protocol, int fds[2])
895
945
{
896
946
    if (socketpair(domain, type, protocol, fds)) {
897
 
        VLOG_FATAL("failed to create socketpair (%s)", strerror(errno));
 
947
        VLOG_FATAL("failed to create socketpair (%s)", ovs_strerror(errno));
898
948
    }
899
949
}
900
950
 
909
959
    len = sizeof value;
910
960
    if (getsockopt(fd, level, option, &value, &len)) {
911
961
        error = errno;
912
 
        VLOG_ERR_RL(&rl, "getsockopt(%s): %s", optname, strerror(error));
 
962
        VLOG_ERR_RL(&rl, "getsockopt(%s): %s", optname, ovs_strerror(error));
913
963
    } else if (len != sizeof value) {
914
964
        error = EINVAL;
915
965
        VLOG_ERR_RL(&rl, "getsockopt(%s): value is %u bytes (expected %zu)",
1037
1087
 
1038
1088
    ds_init(&string);
1039
1089
    if (fstat(fd, &s)) {
1040
 
        ds_put_format(&string, "fstat failed (%s)", strerror(errno));
 
1090
        ds_put_format(&string, "fstat failed (%s)", ovs_strerror(errno));
1041
1091
    } else if (S_ISSOCK(s.st_mode)) {
1042
1092
        describe_sockaddr(&string, fd, getsockname);
1043
1093
        ds_put_cstr(&string, "<->");
1277
1327
            goto error;
1278
1328
        } else {
1279
1329
            size_t n_fds = (p->cmsg_len - CMSG_LEN(0)) / sizeof *fds;
1280
 
            const int *fds_data = (const int *) CMSG_DATA(p);
 
1330
            const int *fds_data = ALIGNED_CAST(const int *, CMSG_DATA(p));
1281
1331
 
1282
1332
            ovs_assert(n_fds > 0);
1283
1333
            if (n_fds > SOUTIL_MAX_FDS) {