Mercurial > vim
comparison src/channel.c @ 20003:e373843e2980 v8.2.0557
patch 8.2.0557: no IPv6 support for channels
Commit: https://github.com/vim/vim/commit/bfe13ccc58ccb96f243a58309800410db1ccb52c
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Apr 12 17:53:12 2020 +0200
patch 8.2.0557: no IPv6 support for channels
Problem: No IPv6 support for channels.
Solution: Add IPv6 support. (Ozaki Kiichi, closes https://github.com/vim/vim/issues/5893)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 12 Apr 2020 18:00:07 +0200 |
parents | 435726a03481 |
children | aadd1cae2ff5 |
comparison
equal
deleted
inserted
replaced
20002:2bf41f30475c | 20003:e373843e2980 |
---|---|
7 */ | 7 */ |
8 | 8 |
9 /* | 9 /* |
10 * Implements communication through a socket or any file handle. | 10 * Implements communication through a socket or any file handle. |
11 */ | 11 */ |
12 | |
13 #ifdef WIN32 | |
14 // Must include winsock2.h before windows.h since it conflicts with winsock.h | |
15 // (included in windows.h). | |
16 # include <winsock2.h> | |
17 # include <ws2tcpip.h> | |
18 #endif | |
12 | 19 |
13 #include "vim.h" | 20 #include "vim.h" |
14 | 21 |
15 #if defined(FEAT_JOB_CHANNEL) || defined(PROTO) | 22 #if defined(FEAT_JOB_CHANNEL) || defined(PROTO) |
16 | 23 |
38 # define sock_read(sd, buf, len) recv((SOCKET)sd, buf, len, 0) | 45 # define sock_read(sd, buf, len) recv((SOCKET)sd, buf, len, 0) |
39 # define sock_close(sd) closesocket((SOCKET)sd) | 46 # define sock_close(sd) closesocket((SOCKET)sd) |
40 #else | 47 #else |
41 # include <netdb.h> | 48 # include <netdb.h> |
42 # include <netinet/in.h> | 49 # include <netinet/in.h> |
43 | 50 # include <arpa/inet.h> |
44 # include <sys/socket.h> | 51 # include <sys/socket.h> |
45 # ifdef HAVE_LIBGEN_H | 52 # ifdef HAVE_LIBGEN_H |
46 # include <libgen.h> | 53 # include <libgen.h> |
47 # endif | 54 # endif |
48 # define SOCK_ERRNO | 55 # define SOCK_ERRNO |
709 #endif // FEAT_GUI | 716 #endif // FEAT_GUI |
710 | 717 |
711 static char *e_cannot_connect = N_("E902: Cannot connect to port"); | 718 static char *e_cannot_connect = N_("E902: Cannot connect to port"); |
712 | 719 |
713 /* | 720 /* |
714 * Open a socket channel to "hostname":"port". | 721 * For Unix we need to call connect() again after connect() failed. |
715 * "waittime" is the time in msec to wait for the connection. | 722 * On Win32 one time is sufficient. |
716 * When negative wait forever. | 723 */ |
717 * Returns the channel for success. | 724 static int |
718 * Returns NULL for failure. | 725 channel_connect( |
719 */ | 726 channel_T *channel, |
720 channel_T * | 727 const struct sockaddr *server_addr, |
721 channel_open( | 728 int server_addrlen, |
722 char *hostname, | 729 int *waittime) |
723 int port_in, | 730 { |
724 int waittime, | 731 int sd = -1; |
725 void (*nb_close_cb)(void)) | |
726 { | |
727 int sd = -1; | |
728 struct sockaddr_in server; | |
729 struct hostent *host; | |
730 #ifdef MSWIN | 732 #ifdef MSWIN |
731 u_short port = port_in; | 733 u_long val = 1; |
732 u_long val = 1; | |
733 #else | |
734 int port = port_in; | |
735 #endif | 734 #endif |
736 channel_T *channel; | 735 |
737 int ret; | |
738 | |
739 #ifdef MSWIN | |
740 channel_init_winsock(); | |
741 #endif | |
742 | |
743 channel = add_channel(); | |
744 if (channel == NULL) | |
745 { | |
746 ch_error(NULL, "Cannot allocate channel."); | |
747 return NULL; | |
748 } | |
749 | |
750 // Get the server internet address and put into addr structure | |
751 // fill in the socket address structure and connect to server | |
752 vim_memset((char *)&server, 0, sizeof(server)); | |
753 server.sin_family = AF_INET; | |
754 server.sin_port = htons(port); | |
755 if ((host = gethostbyname(hostname)) == NULL) | |
756 { | |
757 ch_error(channel, "in gethostbyname() in channel_open()"); | |
758 PERROR(_("E901: gethostbyname() in channel_open()")); | |
759 channel_free(channel); | |
760 return NULL; | |
761 } | |
762 { | |
763 char *p; | |
764 | |
765 // When using host->h_addr_list[0] directly ubsan warns for it to not | |
766 // be aligned. First copy the pointer to avoid that. | |
767 memcpy(&p, &host->h_addr_list[0], sizeof(p)); | |
768 memcpy((char *)&server.sin_addr, p, host->h_length); | |
769 } | |
770 | |
771 // On Mac and Solaris a zero timeout almost never works. At least wait | |
772 // one millisecond. Let's do it for all systems, because we don't know why | |
773 // this is needed. | |
774 if (waittime == 0) | |
775 waittime = 1; | |
776 | |
777 /* | |
778 * For Unix we need to call connect() again after connect() failed. | |
779 * On Win32 one time is sufficient. | |
780 */ | |
781 while (TRUE) | 736 while (TRUE) |
782 { | 737 { |
783 long elapsed_msec = 0; | 738 long elapsed_msec = 0; |
784 int waitnow; | 739 int waitnow; |
740 int ret; | |
785 | 741 |
786 if (sd >= 0) | 742 if (sd >= 0) |
787 sock_close(sd); | 743 sock_close(sd); |
788 sd = socket(AF_INET, SOCK_STREAM, 0); | 744 sd = socket(server_addr->sa_family, SOCK_STREAM, 0); |
789 if (sd == -1) | 745 if (sd == -1) |
790 { | 746 { |
791 ch_error(channel, "in socket() in channel_open()."); | 747 ch_error(channel, "in socket() in channel_connect()."); |
792 PERROR(_("E898: socket() in channel_open()")); | 748 PERROR(_("E898: socket() in channel_connect()")); |
793 channel_free(channel); | 749 return -1; |
794 return NULL; | 750 } |
795 } | 751 |
796 | 752 if (*waittime >= 0) |
797 if (waittime >= 0) | |
798 { | 753 { |
799 // Make connect() non-blocking. | 754 // Make connect() non-blocking. |
800 if ( | 755 if ( |
801 #ifdef MSWIN | 756 #ifdef MSWIN |
802 ioctlsocket(sd, FIONBIO, &val) < 0 | 757 ioctlsocket(sd, FIONBIO, &val) < 0 |
805 #endif | 760 #endif |
806 ) | 761 ) |
807 { | 762 { |
808 SOCK_ERRNO; | 763 SOCK_ERRNO; |
809 ch_error(channel, | 764 ch_error(channel, |
810 "channel_open: Connect failed with errno %d", errno); | 765 "channel_connect: Connect failed with errno %d", errno); |
811 sock_close(sd); | 766 sock_close(sd); |
812 channel_free(channel); | 767 return -1; |
813 return NULL; | |
814 } | 768 } |
815 } | 769 } |
816 | 770 |
817 // Try connecting to the server. | 771 // Try connecting to the server. |
818 ch_log(channel, "Connecting to %s port %d", hostname, port); | 772 ch_log(channel, "Connecting..."); |
819 ret = connect(sd, (struct sockaddr *)&server, sizeof(server)); | 773 |
820 | 774 ret = connect(sd, server_addr, server_addrlen); |
821 if (ret == 0) | 775 if (ret == 0) |
822 // The connection could be established. | 776 // The connection could be established. |
823 break; | 777 break; |
824 | 778 |
825 SOCK_ERRNO; | 779 SOCK_ERRNO; |
826 if (waittime < 0 || (errno != EWOULDBLOCK | 780 if (*waittime < 0 || (errno != EWOULDBLOCK |
827 && errno != ECONNREFUSED | 781 && errno != ECONNREFUSED |
828 #ifdef EINPROGRESS | 782 #ifdef EINPROGRESS |
829 && errno != EINPROGRESS | 783 && errno != EINPROGRESS |
830 #endif | 784 #endif |
831 )) | 785 )) |
832 { | 786 { |
833 ch_error(channel, | 787 ch_error(channel, |
834 "channel_open: Connect failed with errno %d", errno); | 788 "channel_connect: Connect failed with errno %d", errno); |
835 PERROR(_(e_cannot_connect)); | 789 PERROR(_(e_cannot_connect)); |
836 sock_close(sd); | 790 sock_close(sd); |
837 channel_free(channel); | 791 return -1; |
838 return NULL; | 792 } |
793 else if (errno == ECONNREFUSED) | |
794 { | |
795 ch_error(channel, "channel_connect: Connection refused"); | |
796 sock_close(sd); | |
797 return -1; | |
839 } | 798 } |
840 | 799 |
841 // Limit the waittime to 50 msec. If it doesn't work within this | 800 // Limit the waittime to 50 msec. If it doesn't work within this |
842 // time we close the socket and try creating it again. | 801 // time we close the socket and try creating it again. |
843 waitnow = waittime > 50 ? 50 : waittime; | 802 waitnow = *waittime > 50 ? 50 : *waittime; |
844 | 803 |
845 // If connect() didn't finish then try using select() to wait for the | 804 // If connect() didn't finish then try using select() to wait for the |
846 // connection to be made. For Win32 always use select() to wait. | 805 // connection to be made. For Win32 always use select() to wait. |
847 #ifndef MSWIN | |
848 if (errno != ECONNREFUSED) | |
849 #endif | |
850 { | 806 { |
851 struct timeval tv; | 807 struct timeval tv; |
852 fd_set rfds; | 808 fd_set rfds; |
853 fd_set wfds; | 809 fd_set wfds; |
854 #ifndef MSWIN | 810 #ifndef MSWIN |
866 tv.tv_usec = (waitnow % 1000) * 1000; | 822 tv.tv_usec = (waitnow % 1000) * 1000; |
867 #ifndef MSWIN | 823 #ifndef MSWIN |
868 gettimeofday(&start_tv, NULL); | 824 gettimeofday(&start_tv, NULL); |
869 #endif | 825 #endif |
870 ch_log(channel, | 826 ch_log(channel, |
871 "Waiting for connection (waiting %d msec)...", waitnow); | 827 "Waiting for connection (waiting %d msec)...", waitnow); |
828 | |
872 ret = select((int)sd + 1, &rfds, &wfds, NULL, &tv); | 829 ret = select((int)sd + 1, &rfds, &wfds, NULL, &tv); |
873 | |
874 if (ret < 0) | 830 if (ret < 0) |
875 { | 831 { |
876 SOCK_ERRNO; | 832 SOCK_ERRNO; |
877 ch_error(channel, | 833 ch_error(channel, |
878 "channel_open: Connect failed with errno %d", errno); | 834 "channel_connect: Connect failed with errno %d", errno); |
879 PERROR(_(e_cannot_connect)); | 835 PERROR(_(e_cannot_connect)); |
880 sock_close(sd); | 836 sock_close(sd); |
881 channel_free(channel); | 837 return -1; |
882 return NULL; | |
883 } | 838 } |
884 | 839 |
885 #ifdef MSWIN | 840 #ifdef MSWIN |
886 // On Win32: select() is expected to work and wait for up to | 841 // On Win32: select() is expected to work and wait for up to |
887 // "waitnow" msec for the socket to be open. | 842 // "waitnow" msec for the socket to be open. |
888 if (FD_ISSET(sd, &wfds)) | 843 if (FD_ISSET(sd, &wfds)) |
889 break; | 844 break; |
890 elapsed_msec = waitnow; | 845 elapsed_msec = waitnow; |
891 if (waittime > 1 && elapsed_msec < waittime) | 846 if (*waittime > 1 && elapsed_msec < *waittime) |
892 { | 847 { |
893 waittime -= elapsed_msec; | 848 *waittime -= elapsed_msec; |
894 continue; | 849 continue; |
895 } | 850 } |
896 #else | 851 #else |
897 // On Linux-like systems: See socket(7) for the behavior | 852 // On Linux-like systems: See socket(7) for the behavior |
898 // After putting the socket in non-blocking mode, connect() will | 853 // After putting the socket in non-blocking mode, connect() will |
912 && so_error != EINPROGRESS | 867 && so_error != EINPROGRESS |
913 # endif | 868 # endif |
914 )) | 869 )) |
915 { | 870 { |
916 ch_error(channel, | 871 ch_error(channel, |
917 "channel_open: Connect failed with errno %d", | 872 "channel_connect: Connect failed with errno %d", |
918 so_error); | 873 so_error); |
919 PERROR(_(e_cannot_connect)); | 874 PERROR(_(e_cannot_connect)); |
920 sock_close(sd); | 875 sock_close(sd); |
921 channel_free(channel); | 876 return -1; |
922 return NULL; | 877 } |
878 else if (errno == ECONNREFUSED) | |
879 { | |
880 ch_error(channel, "channel_connect: Connection refused"); | |
881 sock_close(sd); | |
882 return -1; | |
923 } | 883 } |
924 } | 884 } |
925 | 885 |
926 if (FD_ISSET(sd, &wfds) && so_error == 0) | 886 if (FD_ISSET(sd, &wfds) && so_error == 0) |
927 // Did not detect an error, connection is established. | 887 // Did not detect an error, connection is established. |
928 break; | 888 break; |
929 | 889 |
930 gettimeofday(&end_tv, NULL); | 890 gettimeofday(&end_tv, NULL); |
931 elapsed_msec = (end_tv.tv_sec - start_tv.tv_sec) * 1000 | 891 elapsed_msec = (end_tv.tv_sec - start_tv.tv_sec) * 1000 |
932 + (end_tv.tv_usec - start_tv.tv_usec) / 1000; | 892 + (end_tv.tv_usec - start_tv.tv_usec) / 1000; |
933 #endif | 893 #endif |
934 } | 894 } |
935 | 895 |
936 #ifndef MSWIN | 896 #ifndef MSWIN |
937 if (waittime > 1 && elapsed_msec < waittime) | 897 if (*waittime > 1 && elapsed_msec < *waittime) |
938 { | 898 { |
939 // The port isn't ready but we also didn't get an error. | 899 // The port isn't ready but we also didn't get an error. |
940 // This happens when the server didn't open the socket | 900 // This happens when the server didn't open the socket |
941 // yet. Select() may return early, wait until the remaining | 901 // yet. Select() may return early, wait until the remaining |
942 // "waitnow" and try again. | 902 // "waitnow" and try again. |
943 waitnow -= elapsed_msec; | 903 waitnow -= elapsed_msec; |
944 waittime -= elapsed_msec; | 904 *waittime -= elapsed_msec; |
945 if (waitnow > 0) | 905 if (waitnow > 0) |
946 { | 906 { |
947 mch_delay((long)waitnow, TRUE); | 907 mch_delay((long)waitnow, TRUE); |
948 ui_breakcheck(); | 908 ui_breakcheck(); |
949 waittime -= waitnow; | 909 *waittime -= waitnow; |
950 } | 910 } |
951 if (!got_int) | 911 if (!got_int) |
952 { | 912 { |
953 if (waittime <= 0) | 913 if (*waittime <= 0) |
954 // give it one more try | 914 // give it one more try |
955 waittime = 1; | 915 *waittime = 1; |
956 continue; | 916 continue; |
957 } | 917 } |
958 // we were interrupted, behave as if timed out | 918 // we were interrupted, behave as if timed out |
959 } | 919 } |
960 #endif | 920 #endif |
961 | 921 |
962 // We timed out. | 922 // We timed out. |
963 ch_error(channel, "Connection timed out"); | 923 ch_error(channel, "Connection timed out"); |
964 sock_close(sd); | 924 sock_close(sd); |
965 channel_free(channel); | 925 return -1; |
966 return NULL; | 926 } |
967 } | 927 |
968 | 928 if (*waittime >= 0) |
969 ch_log(channel, "Connection made"); | |
970 | |
971 if (waittime >= 0) | |
972 { | 929 { |
973 #ifdef MSWIN | 930 #ifdef MSWIN |
974 val = 0; | 931 val = 0; |
975 ioctlsocket(sd, FIONBIO, &val); | 932 ioctlsocket(sd, FIONBIO, &val); |
976 #else | 933 #else |
977 (void)fcntl(sd, F_SETFL, 0); | 934 (void)fcntl(sd, F_SETFL, 0); |
978 #endif | 935 #endif |
979 } | 936 } |
980 | 937 |
938 return sd; | |
939 } | |
940 | |
941 /* | |
942 * Open a socket channel to "hostname":"port". | |
943 * "waittime" is the time in msec to wait for the connection. | |
944 * When negative wait forever. | |
945 * Returns the channel for success. | |
946 * Returns NULL for failure. | |
947 */ | |
948 channel_T * | |
949 channel_open( | |
950 const char *hostname, | |
951 int port, | |
952 int waittime, | |
953 void (*nb_close_cb)(void)) | |
954 { | |
955 int sd = -1; | |
956 channel_T *channel = NULL; | |
957 #ifdef FEAT_IPV6 | |
958 struct addrinfo hints; | |
959 struct addrinfo *res = NULL; | |
960 struct addrinfo *addr = NULL; | |
961 #else | |
962 struct sockaddr_in server; | |
963 struct hostent *host = NULL; | |
964 #endif | |
965 | |
966 #ifdef MSWIN | |
967 channel_init_winsock(); | |
968 #endif | |
969 | |
970 channel = add_channel(); | |
971 if (channel == NULL) | |
972 { | |
973 ch_error(NULL, "Cannot allocate channel."); | |
974 return NULL; | |
975 } | |
976 | |
977 // Get the server internet address and put into addr structure fill in the | |
978 // socket address structure and connect to server. | |
979 #ifdef FEAT_IPV6 | |
980 vim_memset(&hints, 0, sizeof(hints)); | |
981 hints.ai_family = AF_UNSPEC; | |
982 hints.ai_socktype = SOCK_STREAM; | |
983 # ifdef AI_ADDRCONFIG | |
984 hints.ai_flags = AI_ADDRCONFIG; | |
985 # endif | |
986 // Set port number manually in order to prevent name resolution services | |
987 // from being invoked in the environment where AI_NUMERICSERV is not | |
988 // defined. | |
989 if (getaddrinfo(hostname, NULL, &hints, &res) != 0) | |
990 { | |
991 ch_error(channel, "in getaddrinfo() in channel_open()"); | |
992 PERROR(_("E901: getaddrinfo() in channel_open()")); | |
993 channel_free(channel); | |
994 return NULL; | |
995 } | |
996 | |
997 for (addr = res; addr != NULL; addr = addr->ai_next) | |
998 { | |
999 const char *dst = hostname; | |
1000 const void *src = NULL; | |
1001 char buf[NUMBUFLEN]; | |
1002 | |
1003 if (addr->ai_family == AF_INET6) | |
1004 { | |
1005 struct sockaddr_in6 *sai = (struct sockaddr_in6 *)addr->ai_addr; | |
1006 | |
1007 sai->sin6_port = htons(port); | |
1008 src = &sai->sin6_addr; | |
1009 } | |
1010 else if (addr->ai_family == AF_INET) | |
1011 { | |
1012 struct sockaddr_in *sai = (struct sockaddr_in *)addr->ai_addr; | |
1013 | |
1014 sai->sin_port = htons(port); | |
1015 src = &sai->sin_addr; | |
1016 } | |
1017 if (src != NULL) | |
1018 { | |
1019 dst = inet_ntop(addr->ai_family, src, buf, sizeof(buf)); | |
1020 if (dst != NULL && STRCMP(hostname, dst) != 0) | |
1021 ch_log(channel, "Resolved %s to %s", hostname, dst); | |
1022 } | |
1023 | |
1024 ch_log(channel, "Trying to connect to %s port %d", dst, port); | |
1025 | |
1026 // On Mac and Solaris a zero timeout almost never works. At least wait | |
1027 // one millisecond. Let's do it for all systems, because we don't know | |
1028 // why this is needed. | |
1029 if (waittime == 0) | |
1030 waittime = 1; | |
1031 | |
1032 sd = channel_connect(channel, addr->ai_addr, addr->ai_addrlen, | |
1033 &waittime); | |
1034 if (sd >= 0) | |
1035 break; | |
1036 } | |
1037 | |
1038 freeaddrinfo(res); | |
1039 #else | |
1040 vim_memset((char *)&server, 0, sizeof(server)); | |
1041 server.sin_family = AF_INET; | |
1042 server.sin_port = htons(port); | |
1043 if ((host = gethostbyname(hostname)) == NULL) | |
1044 { | |
1045 ch_error(channel, "in gethostbyname() in channel_open()"); | |
1046 PERROR(_("E901: gethostbyname() in channel_open()")); | |
1047 channel_free(channel); | |
1048 return NULL; | |
1049 } | |
1050 { | |
1051 char *p; | |
1052 | |
1053 // When using host->h_addr_list[0] directly ubsan warns for it to not | |
1054 // be aligned. First copy the pointer to avoid that. | |
1055 memcpy(&p, &host->h_addr_list[0], sizeof(p)); | |
1056 memcpy((char *)&server.sin_addr, p, host->h_length); | |
1057 } | |
1058 | |
1059 ch_log(channel, "Trying to connect to %s port %d", hostname, port); | |
1060 | |
1061 // On Mac and Solaris a zero timeout almost never works. At least wait one | |
1062 // millisecond. Let's do it for all systems, because we don't know why | |
1063 // this is needed. | |
1064 if (waittime == 0) | |
1065 waittime = 1; | |
1066 | |
1067 sd = channel_connect(channel, (struct sockaddr *)&server, sizeof(server), | |
1068 &waittime); | |
1069 #endif | |
1070 | |
1071 if (sd < 0) | |
1072 { | |
1073 channel_free(channel); | |
1074 return NULL; | |
1075 } | |
1076 | |
1077 ch_log(channel, "Connection made"); | |
1078 | |
981 channel->CH_SOCK_FD = (sock_T)sd; | 1079 channel->CH_SOCK_FD = (sock_T)sd; |
982 channel->ch_nb_close_cb = nb_close_cb; | 1080 channel->ch_nb_close_cb = nb_close_cb; |
983 channel->ch_hostname = (char *)vim_strsave((char_u *)hostname); | 1081 channel->ch_hostname = (char *)vim_strsave((char_u *)hostname); |
984 channel->ch_port = port_in; | 1082 channel->ch_port = port; |
985 channel->ch_to_be_closed |= (1U << PART_SOCK); | 1083 channel->ch_to_be_closed |= (1U << PART_SOCK); |
986 | 1084 |
987 #ifdef FEAT_GUI | 1085 #ifdef FEAT_GUI |
988 channel_gui_register_one(channel, PART_SOCK); | 1086 channel_gui_register_one(channel, PART_SOCK); |
989 #endif | 1087 #endif |
1220 { | 1318 { |
1221 char_u *address; | 1319 char_u *address; |
1222 char_u *p; | 1320 char_u *p; |
1223 char *rest; | 1321 char *rest; |
1224 int port; | 1322 int port; |
1323 int is_ipv6 = FALSE; | |
1225 jobopt_T opt; | 1324 jobopt_T opt; |
1226 channel_T *channel = NULL; | 1325 channel_T *channel = NULL; |
1227 | 1326 |
1228 address = tv_get_string(&argvars[0]); | 1327 address = tv_get_string(&argvars[0]); |
1229 if (argvars[1].v_type != VAR_UNKNOWN | 1328 if (argvars[1].v_type != VAR_UNKNOWN |
1232 emsg(_(e_invarg)); | 1331 emsg(_(e_invarg)); |
1233 return NULL; | 1332 return NULL; |
1234 } | 1333 } |
1235 | 1334 |
1236 // parse address | 1335 // parse address |
1237 p = vim_strchr(address, ':'); | 1336 if (*address == '[') |
1238 if (p == NULL) | 1337 { |
1338 // ipv6 address | |
1339 is_ipv6 = TRUE; | |
1340 p = vim_strchr(address + 1, ']'); | |
1341 if (p == NULL || *++p != ':') | |
1342 { | |
1343 semsg(_(e_invarg2), address); | |
1344 return NULL; | |
1345 } | |
1346 } | |
1347 else | |
1348 { | |
1349 p = vim_strchr(address, ':'); | |
1350 if (p == NULL) | |
1351 { | |
1352 semsg(_(e_invarg2), address); | |
1353 return NULL; | |
1354 } | |
1355 } | |
1356 port = strtol((char *)(p + 1), &rest, 10); | |
1357 if (*address == NUL || port <= 0 || port >= 65536 || *rest != NUL) | |
1239 { | 1358 { |
1240 semsg(_(e_invarg2), address); | 1359 semsg(_(e_invarg2), address); |
1241 return NULL; | 1360 return NULL; |
1242 } | 1361 } |
1243 *p++ = NUL; | 1362 if (is_ipv6) |
1244 port = strtol((char *)p, &rest, 10); | 1363 { |
1245 if (*address == NUL || port <= 0 || *rest != NUL) | 1364 // strip '[' and ']' |
1246 { | 1365 ++address; |
1247 p[-1] = ':'; | 1366 *(p - 1) = NUL; |
1248 semsg(_(e_invarg2), address); | 1367 } |
1249 return NULL; | 1368 else |
1250 } | 1369 *p = NUL; |
1251 | 1370 |
1252 // parse options | 1371 // parse options |
1253 clear_job_options(&opt); | 1372 clear_job_options(&opt); |
1254 opt.jo_mode = MODE_JSON; | 1373 opt.jo_mode = MODE_JSON; |
1255 opt.jo_timeout = 2000; | 1374 opt.jo_timeout = 2000; |