Fossil SCM

Add initial IPv6 support code

ashish 2011-10-16 12:53 ashish-ipv6
Commit 92c59f1202ba5c442ed9087fefbbf2de2ddca831
+10
--- auto.def
+++ auto.def
@@ -8,10 +8,11 @@
88
with-zlib:path => {Look for zlib in the given path}
99
internal-sqlite=1 => {Don't use the internal sqlite, use the system one}
1010
static=0 => {Link a static executable}
1111
lineedit=1 => {Disable line editing}
1212
fossil-debug=0 => {Build with fossil debugging enabled}
13
+ ipv6=1 => {Disable IPv6 support}
1314
}
1415
1516
# sqlite wants these types if possible
1617
cc-with {-includes {stdint.h inttypes.h}} {
1718
cc-check-types uint32_t uint16_t int16_t uint8_t
@@ -66,10 +67,19 @@
6667
6768
if {[opt-bool static]} {
6869
# XXX: This will not work on all systems.
6970
define-append EXTRA_LDFLAGS -static
7071
}
72
+
73
+if {[opt-bool ipv6]} {
74
+ define-append EXTRA_CFLAGS -DWITH_IPV6
75
+ msg-result "IPv6 support enabled"
76
+ if {[cc-check-functions getaddrinfo]} {
77
+ define-append EXTRA_CFLAGS -DHAVE_GETADDRINFO
78
+ msg-result "getaddrinfo() enabled"
79
+ }
80
+}
7181
7282
7383
# Check for zlib, using the given location if specified
7484
set zlibpath [opt-val with-zlib]
7585
if {$zlibpath ne ""} {
7686
--- auto.def
+++ auto.def
@@ -8,10 +8,11 @@
8 with-zlib:path => {Look for zlib in the given path}
9 internal-sqlite=1 => {Don't use the internal sqlite, use the system one}
10 static=0 => {Link a static executable}
11 lineedit=1 => {Disable line editing}
12 fossil-debug=0 => {Build with fossil debugging enabled}
 
13 }
14
15 # sqlite wants these types if possible
16 cc-with {-includes {stdint.h inttypes.h}} {
17 cc-check-types uint32_t uint16_t int16_t uint8_t
@@ -66,10 +67,19 @@
66
67 if {[opt-bool static]} {
68 # XXX: This will not work on all systems.
69 define-append EXTRA_LDFLAGS -static
70 }
 
 
 
 
 
 
 
 
 
71
72
73 # Check for zlib, using the given location if specified
74 set zlibpath [opt-val with-zlib]
75 if {$zlibpath ne ""} {
76
--- auto.def
+++ auto.def
@@ -8,10 +8,11 @@
8 with-zlib:path => {Look for zlib in the given path}
9 internal-sqlite=1 => {Don't use the internal sqlite, use the system one}
10 static=0 => {Link a static executable}
11 lineedit=1 => {Disable line editing}
12 fossil-debug=0 => {Build with fossil debugging enabled}
13 ipv6=1 => {Disable IPv6 support}
14 }
15
16 # sqlite wants these types if possible
17 cc-with {-includes {stdint.h inttypes.h}} {
18 cc-check-types uint32_t uint16_t int16_t uint8_t
@@ -66,10 +67,19 @@
67
68 if {[opt-bool static]} {
69 # XXX: This will not work on all systems.
70 define-append EXTRA_LDFLAGS -static
71 }
72
73 if {[opt-bool ipv6]} {
74 define-append EXTRA_CFLAGS -DWITH_IPV6
75 msg-result "IPv6 support enabled"
76 if {[cc-check-functions getaddrinfo]} {
77 define-append EXTRA_CFLAGS -DHAVE_GETADDRINFO
78 msg-result "getaddrinfo() enabled"
79 }
80 }
81
82
83 # Check for zlib, using the given location if specified
84 set zlibpath [opt-val with-zlib]
85 if {$zlibpath ne ""} {
86
+64 -12
--- src/cgi.c
+++ src/cgi.c
@@ -34,10 +34,11 @@
3434
# include <arpa/inet.h>
3535
# include <sys/times.h>
3636
# include <sys/time.h>
3737
# include <sys/wait.h>
3838
# include <sys/select.h>
39
+# include <netdb.h> /* for NI_NUMERICHOST */
3940
#endif
4041
#ifdef __EMX__
4142
typedef int socklen_t;
4243
#endif
4344
#include <time.h>
@@ -992,12 +993,12 @@
992993
** and subsequent code handles the actual generation of the webpage.
993994
*/
994995
void cgi_handle_http_request(const char *zIpAddr){
995996
char *z, *zToken;
996997
int i;
997
- struct sockaddr_in remoteName;
998
- socklen_t size = sizeof(struct sockaddr_in);
998
+ struct sockaddr_storage remoteName;
999
+ socklen_t size = sizeof(remoteName);
9991000
char zLine[2000]; /* A single line of input. */
10001001
10011002
g.fullHttpReply = 1;
10021003
if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
10031004
malformed_request();
@@ -1019,20 +1020,10 @@
10191020
cgi_setenv("REQUEST_URI", zToken);
10201021
for(i=0; zToken[i] && zToken[i]!='?'; i++){}
10211022
if( zToken[i] ) zToken[i++] = 0;
10221023
cgi_setenv("PATH_INFO", zToken);
10231024
cgi_setenv("QUERY_STRING", &zToken[i]);
1024
- if( zIpAddr==0 &&
1025
- getpeername(fileno(g.httpIn), (struct sockaddr*)&remoteName,
1026
- &size)>=0
1027
- ){
1028
- zIpAddr = inet_ntoa(remoteName.sin_addr);
1029
- }
1030
- if( zIpAddr ){
1031
- cgi_setenv("REMOTE_ADDR", zIpAddr);
1032
- g.zIpAddr = mprintf("%s", zIpAddr);
1033
- }
10341025
10351026
/* Get all the optional fields that follow the first line.
10361027
*/
10371028
while( fgets(zLine,sizeof(zLine),g.httpIn) ){
10381029
char *zFieldName;
@@ -1059,19 +1050,54 @@
10591050
cgi_setenv("HTTP_HOST", zVal);
10601051
}else if( fossil_strcmp(zFieldName,"if-none-match:")==0 ){
10611052
cgi_setenv("HTTP_IF_NONE_MATCH", zVal);
10621053
}else if( fossil_strcmp(zFieldName,"if-modified-since:")==0 ){
10631054
cgi_setenv("HTTP_IF_MODIFIED_SINCE", zVal);
1055
+ }else if( fossil_strcmp(zFieldName,"x-forwarded-for:")==0 ){
1056
+ char* p = zVal;
1057
+ /*
1058
+ ** x-forwarded-for header is a list of comma-separated addresses,
1059
+ ** with leftmost address corresponding to the client
1060
+ */
1061
+ while(*p && *p != ',') p++;
1062
+ *p = '\0';
1063
+ zIpAddr = mprintf( "%s", zVal );
10641064
}
10651065
#if 0
10661066
else if( fossil_strcmp(zFieldName,"referer:")==0 ){
10671067
cgi_setenv("HTTP_REFERER", zVal);
10681068
}else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){
10691069
cgi_setenv("HTTP_USER_AGENT", zVal);
10701070
}
10711071
#endif
10721072
}
1073
+
1074
+ if( zIpAddr==0 &&
1075
+ getsockname(fileno(g.httpIn), (struct sockaddr*)&remoteName,
1076
+ &size)>=0
1077
+ ){
1078
+ sa_family_t family;
1079
+ int v4mapped=0;
1080
+ if( remoteName.ss_family == AF_INET6 &&
1081
+ IN6_IS_ADDR_V4MAPPED(&(((struct sockaddr_in6*)&remoteName)->sin6_addr)) ){
1082
+ v4mapped = 1;
1083
+ }
1084
+ if(!getnameinfo((struct sockaddr*)&remoteName, remoteName.ss_len, zLine, sizeof(zLine),
1085
+ NULL, 0, NI_NUMERICHOST)){
1086
+ zIpAddr = zLine;
1087
+ } else {
1088
+ zIpAddr = NULL;
1089
+ }
1090
+ if(zIpAddr && v4mapped) {
1091
+ /* ::ffff:172.16.0.2 */
1092
+ zIpAddr += 7;
1093
+ }
1094
+ }
1095
+ if( zIpAddr ){
1096
+ cgi_setenv("REMOTE_ADDR", zIpAddr);
1097
+ g.zIpAddr = mprintf("%s", zIpAddr);
1098
+ }
10731099
10741100
cgi_init();
10751101
}
10761102
10771103
#if INTERFACE
@@ -1108,31 +1134,57 @@
11081134
fd_set readfds; /* Set of file descriptors for select() */
11091135
socklen_t lenaddr; /* Length of the inaddr structure */
11101136
int child; /* PID of the child process */
11111137
int nchildren = 0; /* Number of child processes */
11121138
struct timeval delay; /* How long to wait inside select() */
1139
+#ifdef WITH_IPV6
1140
+ struct sockaddr_in6 inaddr; /* The socket address */
1141
+#else
11131142
struct sockaddr_in inaddr; /* The socket address */
1143
+#endif
11141144
int opt = 1; /* setsockopt flag */
11151145
int iPort = mnPort;
11161146
11171147
while( iPort<=mxPort ){
11181148
memset(&inaddr, 0, sizeof(inaddr));
1149
+#ifdef WITH_IPV6
1150
+ inaddr.sin6_family = AF_INET6;
1151
+#else
11191152
inaddr.sin_family = AF_INET;
1153
+#endif
11201154
if( flags & HTTP_SERVER_LOCALHOST ){
1155
+#ifdef WITH_IPV6
1156
+ memcpy(&inaddr.sin6_addr, &in6addr_loopback, sizeof(inaddr.sin6_addr));
1157
+#else
11211158
inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1159
+#endif
11221160
}else{
1161
+#ifdef WITH_IPV6
1162
+ memcpy(&inaddr.sin6_addr, &in6addr_any, sizeof(inaddr.sin6_addr));
1163
+#else
11231164
inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
1165
+#endif
11241166
}
1167
+#ifdef WITH_IPV6
1168
+ inaddr.sin6_port = htons(iPort);
1169
+ listener = socket(AF_INET6, SOCK_STREAM, 0);
1170
+#else
11251171
inaddr.sin_port = htons(iPort);
11261172
listener = socket(AF_INET, SOCK_STREAM, 0);
1173
+#endif
11271174
if( listener<0 ){
11281175
iPort++;
11291176
continue;
11301177
}
11311178
11321179
/* if we can't terminate nicely, at least allow the socket to be reused */
11331180
setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
1181
+
1182
+#ifdef WITH_IPV6
1183
+ opt=0;
1184
+ setsockopt(listener, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
1185
+#endif
11341186
11351187
if( bind(listener, (struct sockaddr*)&inaddr, sizeof(inaddr))<0 ){
11361188
close(listener);
11371189
iPort++;
11381190
continue;
11391191
--- src/cgi.c
+++ src/cgi.c
@@ -34,10 +34,11 @@
34 # include <arpa/inet.h>
35 # include <sys/times.h>
36 # include <sys/time.h>
37 # include <sys/wait.h>
38 # include <sys/select.h>
 
39 #endif
40 #ifdef __EMX__
41 typedef int socklen_t;
42 #endif
43 #include <time.h>
@@ -992,12 +993,12 @@
992 ** and subsequent code handles the actual generation of the webpage.
993 */
994 void cgi_handle_http_request(const char *zIpAddr){
995 char *z, *zToken;
996 int i;
997 struct sockaddr_in remoteName;
998 socklen_t size = sizeof(struct sockaddr_in);
999 char zLine[2000]; /* A single line of input. */
1000
1001 g.fullHttpReply = 1;
1002 if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1003 malformed_request();
@@ -1019,20 +1020,10 @@
1019 cgi_setenv("REQUEST_URI", zToken);
1020 for(i=0; zToken[i] && zToken[i]!='?'; i++){}
1021 if( zToken[i] ) zToken[i++] = 0;
1022 cgi_setenv("PATH_INFO", zToken);
1023 cgi_setenv("QUERY_STRING", &zToken[i]);
1024 if( zIpAddr==0 &&
1025 getpeername(fileno(g.httpIn), (struct sockaddr*)&remoteName,
1026 &size)>=0
1027 ){
1028 zIpAddr = inet_ntoa(remoteName.sin_addr);
1029 }
1030 if( zIpAddr ){
1031 cgi_setenv("REMOTE_ADDR", zIpAddr);
1032 g.zIpAddr = mprintf("%s", zIpAddr);
1033 }
1034
1035 /* Get all the optional fields that follow the first line.
1036 */
1037 while( fgets(zLine,sizeof(zLine),g.httpIn) ){
1038 char *zFieldName;
@@ -1059,19 +1050,54 @@
1059 cgi_setenv("HTTP_HOST", zVal);
1060 }else if( fossil_strcmp(zFieldName,"if-none-match:")==0 ){
1061 cgi_setenv("HTTP_IF_NONE_MATCH", zVal);
1062 }else if( fossil_strcmp(zFieldName,"if-modified-since:")==0 ){
1063 cgi_setenv("HTTP_IF_MODIFIED_SINCE", zVal);
 
 
 
 
 
 
 
 
 
1064 }
1065 #if 0
1066 else if( fossil_strcmp(zFieldName,"referer:")==0 ){
1067 cgi_setenv("HTTP_REFERER", zVal);
1068 }else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){
1069 cgi_setenv("HTTP_USER_AGENT", zVal);
1070 }
1071 #endif
1072 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1073
1074 cgi_init();
1075 }
1076
1077 #if INTERFACE
@@ -1108,31 +1134,57 @@
1108 fd_set readfds; /* Set of file descriptors for select() */
1109 socklen_t lenaddr; /* Length of the inaddr structure */
1110 int child; /* PID of the child process */
1111 int nchildren = 0; /* Number of child processes */
1112 struct timeval delay; /* How long to wait inside select() */
 
 
 
1113 struct sockaddr_in inaddr; /* The socket address */
 
1114 int opt = 1; /* setsockopt flag */
1115 int iPort = mnPort;
1116
1117 while( iPort<=mxPort ){
1118 memset(&inaddr, 0, sizeof(inaddr));
 
 
 
1119 inaddr.sin_family = AF_INET;
 
1120 if( flags & HTTP_SERVER_LOCALHOST ){
 
 
 
1121 inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
 
1122 }else{
 
 
 
1123 inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
 
1124 }
 
 
 
 
1125 inaddr.sin_port = htons(iPort);
1126 listener = socket(AF_INET, SOCK_STREAM, 0);
 
1127 if( listener<0 ){
1128 iPort++;
1129 continue;
1130 }
1131
1132 /* if we can't terminate nicely, at least allow the socket to be reused */
1133 setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
 
 
 
 
 
1134
1135 if( bind(listener, (struct sockaddr*)&inaddr, sizeof(inaddr))<0 ){
1136 close(listener);
1137 iPort++;
1138 continue;
1139
--- src/cgi.c
+++ src/cgi.c
@@ -34,10 +34,11 @@
34 # include <arpa/inet.h>
35 # include <sys/times.h>
36 # include <sys/time.h>
37 # include <sys/wait.h>
38 # include <sys/select.h>
39 # include <netdb.h> /* for NI_NUMERICHOST */
40 #endif
41 #ifdef __EMX__
42 typedef int socklen_t;
43 #endif
44 #include <time.h>
@@ -992,12 +993,12 @@
993 ** and subsequent code handles the actual generation of the webpage.
994 */
995 void cgi_handle_http_request(const char *zIpAddr){
996 char *z, *zToken;
997 int i;
998 struct sockaddr_storage remoteName;
999 socklen_t size = sizeof(remoteName);
1000 char zLine[2000]; /* A single line of input. */
1001
1002 g.fullHttpReply = 1;
1003 if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1004 malformed_request();
@@ -1019,20 +1020,10 @@
1020 cgi_setenv("REQUEST_URI", zToken);
1021 for(i=0; zToken[i] && zToken[i]!='?'; i++){}
1022 if( zToken[i] ) zToken[i++] = 0;
1023 cgi_setenv("PATH_INFO", zToken);
1024 cgi_setenv("QUERY_STRING", &zToken[i]);
 
 
 
 
 
 
 
 
 
 
1025
1026 /* Get all the optional fields that follow the first line.
1027 */
1028 while( fgets(zLine,sizeof(zLine),g.httpIn) ){
1029 char *zFieldName;
@@ -1059,19 +1050,54 @@
1050 cgi_setenv("HTTP_HOST", zVal);
1051 }else if( fossil_strcmp(zFieldName,"if-none-match:")==0 ){
1052 cgi_setenv("HTTP_IF_NONE_MATCH", zVal);
1053 }else if( fossil_strcmp(zFieldName,"if-modified-since:")==0 ){
1054 cgi_setenv("HTTP_IF_MODIFIED_SINCE", zVal);
1055 }else if( fossil_strcmp(zFieldName,"x-forwarded-for:")==0 ){
1056 char* p = zVal;
1057 /*
1058 ** x-forwarded-for header is a list of comma-separated addresses,
1059 ** with leftmost address corresponding to the client
1060 */
1061 while(*p && *p != ',') p++;
1062 *p = '\0';
1063 zIpAddr = mprintf( "%s", zVal );
1064 }
1065 #if 0
1066 else if( fossil_strcmp(zFieldName,"referer:")==0 ){
1067 cgi_setenv("HTTP_REFERER", zVal);
1068 }else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){
1069 cgi_setenv("HTTP_USER_AGENT", zVal);
1070 }
1071 #endif
1072 }
1073
1074 if( zIpAddr==0 &&
1075 getsockname(fileno(g.httpIn), (struct sockaddr*)&remoteName,
1076 &size)>=0
1077 ){
1078 sa_family_t family;
1079 int v4mapped=0;
1080 if( remoteName.ss_family == AF_INET6 &&
1081 IN6_IS_ADDR_V4MAPPED(&(((struct sockaddr_in6*)&remoteName)->sin6_addr)) ){
1082 v4mapped = 1;
1083 }
1084 if(!getnameinfo((struct sockaddr*)&remoteName, remoteName.ss_len, zLine, sizeof(zLine),
1085 NULL, 0, NI_NUMERICHOST)){
1086 zIpAddr = zLine;
1087 } else {
1088 zIpAddr = NULL;
1089 }
1090 if(zIpAddr && v4mapped) {
1091 /* ::ffff:172.16.0.2 */
1092 zIpAddr += 7;
1093 }
1094 }
1095 if( zIpAddr ){
1096 cgi_setenv("REMOTE_ADDR", zIpAddr);
1097 g.zIpAddr = mprintf("%s", zIpAddr);
1098 }
1099
1100 cgi_init();
1101 }
1102
1103 #if INTERFACE
@@ -1108,31 +1134,57 @@
1134 fd_set readfds; /* Set of file descriptors for select() */
1135 socklen_t lenaddr; /* Length of the inaddr structure */
1136 int child; /* PID of the child process */
1137 int nchildren = 0; /* Number of child processes */
1138 struct timeval delay; /* How long to wait inside select() */
1139 #ifdef WITH_IPV6
1140 struct sockaddr_in6 inaddr; /* The socket address */
1141 #else
1142 struct sockaddr_in inaddr; /* The socket address */
1143 #endif
1144 int opt = 1; /* setsockopt flag */
1145 int iPort = mnPort;
1146
1147 while( iPort<=mxPort ){
1148 memset(&inaddr, 0, sizeof(inaddr));
1149 #ifdef WITH_IPV6
1150 inaddr.sin6_family = AF_INET6;
1151 #else
1152 inaddr.sin_family = AF_INET;
1153 #endif
1154 if( flags & HTTP_SERVER_LOCALHOST ){
1155 #ifdef WITH_IPV6
1156 memcpy(&inaddr.sin6_addr, &in6addr_loopback, sizeof(inaddr.sin6_addr));
1157 #else
1158 inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1159 #endif
1160 }else{
1161 #ifdef WITH_IPV6
1162 memcpy(&inaddr.sin6_addr, &in6addr_any, sizeof(inaddr.sin6_addr));
1163 #else
1164 inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
1165 #endif
1166 }
1167 #ifdef WITH_IPV6
1168 inaddr.sin6_port = htons(iPort);
1169 listener = socket(AF_INET6, SOCK_STREAM, 0);
1170 #else
1171 inaddr.sin_port = htons(iPort);
1172 listener = socket(AF_INET, SOCK_STREAM, 0);
1173 #endif
1174 if( listener<0 ){
1175 iPort++;
1176 continue;
1177 }
1178
1179 /* if we can't terminate nicely, at least allow the socket to be reused */
1180 setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
1181
1182 #ifdef WITH_IPV6
1183 opt=0;
1184 setsockopt(listener, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
1185 #endif
1186
1187 if( bind(listener, (struct sockaddr*)&inaddr, sizeof(inaddr))<0 ){
1188 close(listener);
1189 iPort++;
1190 continue;
1191
--- src/http_socket.c
+++ src/http_socket.c
@@ -135,10 +135,56 @@
135135
** g.urlPort TCP/IP port to use. Ex: 80
136136
**
137137
** Return the number of errors.
138138
*/
139139
int socket_open(void){
140
+ int error = 0;
141
+#ifdef HAVE_GETADDRINFO
142
+ struct addrinfo hints;
143
+ struct addrinfo* res;
144
+ struct addrinfo* i;
145
+ char ip[INET6_ADDRSTRLEN];
146
+ void* addr;
147
+
148
+ memset(&hints, 0, sizeof(struct addrinfo));
149
+ hints.ai_flags = AI_ADDRCONFIG;
150
+#ifdef WITH_IPV6
151
+ hints.ai_family = PF_UNSPEC;
152
+#else
153
+ hints.ai_family = PF_INET;
154
+#endif
155
+ hints.ai_socktype = SOCK_STREAM;
156
+ hints.ai_protocol = IPPROTO_TCP;
157
+ if(getaddrinfo(g.urlName, NULL, &hints, &res)) {
158
+ socket_set_errmsg("can't resolve host name: %s", g.urlName);
159
+ return 1;
160
+ }
161
+ for(i = res; i; i = i->ai_next) {
162
+ iSocket = socket(i->ai_family, i->ai_socktype, i->ai_protocol);
163
+ if(iSocket < 0) {
164
+ continue;
165
+ }
166
+ if(i->ai_family == AF_INET) {
167
+ ((struct sockaddr_in*)i->ai_addr)->sin_port = htons(g.urlPort);
168
+ } else if(i->ai_family == AF_INET6) {
169
+ ((struct sockaddr_in6*)i->ai_addr)->sin6_port = htons(g.urlPort);
170
+ }
171
+ if(connect(iSocket, i->ai_addr, i->ai_addrlen) < 0) {
172
+ close(iSocket);
173
+ iSocket = -1;
174
+ continue;
175
+ }
176
+ if(!getnameinfo(i->ai_addr, i->ai_addrlen, ip, sizeof(ip),
177
+ NULL, 0, NI_NUMERICHOST))
178
+ g.zIpAddr = mprintf("%s", ip);
179
+ }
180
+ if(iSocket == -1) {
181
+ socket_set_errmsg("cannot connect to host %s:%d", g.urlName, g.urlPort);
182
+ error = 1;
183
+ }
184
+ freeaddrinfo(res);
185
+#else
140186
static struct sockaddr_in addr; /* The server address */
141187
static int addrIsInit = 0; /* True once addr is initialized */
142188
143189
socket_global_init();
144190
if( !addrIsInit ){
@@ -172,16 +218,18 @@
172218
return 1;
173219
}
174220
if( connect(iSocket,(struct sockaddr*)&addr,sizeof(addr))<0 ){
175221
socket_set_errmsg("cannot connect to host %s:%d", g.urlName, g.urlPort);
176222
socket_close();
177
- return 1;
223
+ error = 1;
178224
}
225
+#endif
179226
#if !defined(_WIN32)
180
- signal(SIGPIPE, SIG_IGN);
227
+ if(!error)
228
+ signal(SIGPIPE, SIG_IGN);
181229
#endif
182
- return 0;
230
+ return error;
183231
}
184232
185233
/*
186234
** Send content out over the open socket connection.
187235
*/
188236
--- src/http_socket.c
+++ src/http_socket.c
@@ -135,10 +135,56 @@
135 ** g.urlPort TCP/IP port to use. Ex: 80
136 **
137 ** Return the number of errors.
138 */
139 int socket_open(void){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140 static struct sockaddr_in addr; /* The server address */
141 static int addrIsInit = 0; /* True once addr is initialized */
142
143 socket_global_init();
144 if( !addrIsInit ){
@@ -172,16 +218,18 @@
172 return 1;
173 }
174 if( connect(iSocket,(struct sockaddr*)&addr,sizeof(addr))<0 ){
175 socket_set_errmsg("cannot connect to host %s:%d", g.urlName, g.urlPort);
176 socket_close();
177 return 1;
178 }
 
179 #if !defined(_WIN32)
180 signal(SIGPIPE, SIG_IGN);
 
181 #endif
182 return 0;
183 }
184
185 /*
186 ** Send content out over the open socket connection.
187 */
188
--- src/http_socket.c
+++ src/http_socket.c
@@ -135,10 +135,56 @@
135 ** g.urlPort TCP/IP port to use. Ex: 80
136 **
137 ** Return the number of errors.
138 */
139 int socket_open(void){
140 int error = 0;
141 #ifdef HAVE_GETADDRINFO
142 struct addrinfo hints;
143 struct addrinfo* res;
144 struct addrinfo* i;
145 char ip[INET6_ADDRSTRLEN];
146 void* addr;
147
148 memset(&hints, 0, sizeof(struct addrinfo));
149 hints.ai_flags = AI_ADDRCONFIG;
150 #ifdef WITH_IPV6
151 hints.ai_family = PF_UNSPEC;
152 #else
153 hints.ai_family = PF_INET;
154 #endif
155 hints.ai_socktype = SOCK_STREAM;
156 hints.ai_protocol = IPPROTO_TCP;
157 if(getaddrinfo(g.urlName, NULL, &hints, &res)) {
158 socket_set_errmsg("can't resolve host name: %s", g.urlName);
159 return 1;
160 }
161 for(i = res; i; i = i->ai_next) {
162 iSocket = socket(i->ai_family, i->ai_socktype, i->ai_protocol);
163 if(iSocket < 0) {
164 continue;
165 }
166 if(i->ai_family == AF_INET) {
167 ((struct sockaddr_in*)i->ai_addr)->sin_port = htons(g.urlPort);
168 } else if(i->ai_family == AF_INET6) {
169 ((struct sockaddr_in6*)i->ai_addr)->sin6_port = htons(g.urlPort);
170 }
171 if(connect(iSocket, i->ai_addr, i->ai_addrlen) < 0) {
172 close(iSocket);
173 iSocket = -1;
174 continue;
175 }
176 if(!getnameinfo(i->ai_addr, i->ai_addrlen, ip, sizeof(ip),
177 NULL, 0, NI_NUMERICHOST))
178 g.zIpAddr = mprintf("%s", ip);
179 }
180 if(iSocket == -1) {
181 socket_set_errmsg("cannot connect to host %s:%d", g.urlName, g.urlPort);
182 error = 1;
183 }
184 freeaddrinfo(res);
185 #else
186 static struct sockaddr_in addr; /* The server address */
187 static int addrIsInit = 0; /* True once addr is initialized */
188
189 socket_global_init();
190 if( !addrIsInit ){
@@ -172,16 +218,18 @@
218 return 1;
219 }
220 if( connect(iSocket,(struct sockaddr*)&addr,sizeof(addr))<0 ){
221 socket_set_errmsg("cannot connect to host %s:%d", g.urlName, g.urlPort);
222 socket_close();
223 error = 1;
224 }
225 #endif
226 #if !defined(_WIN32)
227 if(!error)
228 signal(SIGPIPE, SIG_IGN);
229 #endif
230 return error;
231 }
232
233 /*
234 ** Send content out over the open socket connection.
235 */
236
+3 -2
--- src/login.c
+++ src/login.c
@@ -597,11 +597,12 @@
597597
**
598598
** This feature allows the "fossil ui" command to give the user
599599
** full access rights without having to log in.
600600
*/
601601
zRemoteAddr = ipPrefix(zIpAddr = PD("REMOTE_ADDR","nil"));
602
- if( fossil_strcmp(zIpAddr, "127.0.0.1")==0
602
+ if( ( fossil_strcmp(zIpAddr, "127.0.0.1")==0 ||
603
+ fossil_strcmp(zIpAddr, "::1")==0 )
603604
&& g.useLocalauth
604605
&& db_get_int("localauth",0)==0
605606
&& P("HTTPS")==0
606607
){
607608
uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%%s%%'");
@@ -911,11 +912,11 @@
911912
db_exists("SELECT 1 FROM user"
912913
" WHERE login='anonymous'"
913914
" AND cap LIKE '%%h%%'") ){
914915
const char *zUrl = PD("REQUEST_URI", "index");
915916
@ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
916
- @ Use <a href="%s(g.zTop)/login?anon=1&amp;g=%T(zUrl)">anonymous login</a>
917
+ @ Use <a href="%s(g.zTop)/login?anon=1&amp;g=%T(g.zRoot)%T(zUrl)">anonymous login</a>
917918
@ to enable hyperlinks.</p>
918919
}
919920
}
920921
921922
/*
922923
--- src/login.c
+++ src/login.c
@@ -597,11 +597,12 @@
597 **
598 ** This feature allows the "fossil ui" command to give the user
599 ** full access rights without having to log in.
600 */
601 zRemoteAddr = ipPrefix(zIpAddr = PD("REMOTE_ADDR","nil"));
602 if( fossil_strcmp(zIpAddr, "127.0.0.1")==0
 
603 && g.useLocalauth
604 && db_get_int("localauth",0)==0
605 && P("HTTPS")==0
606 ){
607 uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%%s%%'");
@@ -911,11 +912,11 @@
911 db_exists("SELECT 1 FROM user"
912 " WHERE login='anonymous'"
913 " AND cap LIKE '%%h%%'") ){
914 const char *zUrl = PD("REQUEST_URI", "index");
915 @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
916 @ Use <a href="%s(g.zTop)/login?anon=1&amp;g=%T(zUrl)">anonymous login</a>
917 @ to enable hyperlinks.</p>
918 }
919 }
920
921 /*
922
--- src/login.c
+++ src/login.c
@@ -597,11 +597,12 @@
597 **
598 ** This feature allows the "fossil ui" command to give the user
599 ** full access rights without having to log in.
600 */
601 zRemoteAddr = ipPrefix(zIpAddr = PD("REMOTE_ADDR","nil"));
602 if( ( fossil_strcmp(zIpAddr, "127.0.0.1")==0 ||
603 fossil_strcmp(zIpAddr, "::1")==0 )
604 && g.useLocalauth
605 && db_get_int("localauth",0)==0
606 && P("HTTPS")==0
607 ){
608 uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%%s%%'");
@@ -911,11 +912,11 @@
912 db_exists("SELECT 1 FROM user"
913 " WHERE login='anonymous'"
914 " AND cap LIKE '%%h%%'") ){
915 const char *zUrl = PD("REQUEST_URI", "index");
916 @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
917 @ Use <a href="%s(g.zTop)/login?anon=1&amp;g=%T(g.zRoot)%T(zUrl)">anonymous login</a>
918 @ to enable hyperlinks.</p>
919 }
920 }
921
922 /*
923
+13 -5
--- src/main.c
+++ src/main.c
@@ -98,10 +98,12 @@
9898
int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */
9999
int fNoSync; /* Do not do an autosync even. --nosync */
100100
char *zPath; /* Name of webpage being served */
101101
char *zExtra; /* Extra path information past the webpage name */
102102
char *zBaseURL; /* Full text of the URL being served */
103
+ char *zRedirectBaseURL; /* Full text of the URL being served to be used in redirect */
104
+ char *zRoot; /* Repository web root */
103105
char *zTop; /* Parent directory of zPath */
104106
const char *zContentType; /* The content type of the input HTTP request */
105107
int iErrPriority; /* Priority of current error message */
106108
char *zErrMsg; /* Text of an error message */
107109
int sslNotAvailable; /* SSL is not available. Do not redirect to https: */
@@ -899,20 +901,21 @@
899901
const char *zHost;
900902
const char *zMode;
901903
const char *zCur;
902904
903905
if( g.zBaseURL!=0 ) return;
906
+ if( g.zRoot==0 ) g.zRoot="";
904907
zHost = PD("HTTP_HOST","");
905908
zMode = PD("HTTPS","off");
906909
zCur = PD("SCRIPT_NAME","/");
907910
i = strlen(zCur);
908911
while( i>0 && zCur[i-1]=='/' ) i--;
909912
if( fossil_stricmp(zMode,"on")==0 ){
910
- g.zBaseURL = mprintf("https://%s%.*s", zHost, i, zCur);
913
+ g.zBaseURL = mprintf("https://%s%s%.*s", zHost, g.zRoot, i, zCur);
911914
g.zTop = &g.zBaseURL[8+strlen(zHost)];
912915
}else{
913
- g.zBaseURL = mprintf("http://%s%.*s", zHost, i, zCur);
916
+ g.zBaseURL = mprintf("http://%s%s%.*s", zHost, g.zRoot, i, zCur);
914917
g.zTop = &g.zBaseURL[7+strlen(zHost)];
915918
}
916919
}
917920
918921
/*
@@ -1440,19 +1443,23 @@
14401443
14411444
/*
14421445
** COMMAND: server
14431446
** COMMAND: ui
14441447
**
1445
-** Usage: %fossil server ?-P|--port TCPPORT? ?REPOSITORY?
1446
-** Or: %fossil ui ?-P|--port TCPPORT? ?REPOSITORY?
1448
+** Usage: %fossil server ?-P|--port TCPPORT? -?-R|--root ROOT? ?REPOSITORY?
1449
+** Or: %fossil ui ?-P|--port TCPPORT? -?-R|--root ROOT? ?REPOSITORY?
14471450
**
14481451
** Open a socket and begin listening and responding to HTTP requests on
14491452
** TCP port 8080, or on any other TCP port defined by the -P or
14501453
** --port option. The optional argument is the name of the repository.
14511454
** The repository argument may be omitted if the working directory is
14521455
** within an open checkout.
14531456
**
1457
+** If HTTP requests are being reverse proxied to the fossil server,
1458
+** and in proxy server fossil is mapped at a virtual directory, then
1459
+** virtual directory can be specified using optional -R or --root option.
1460
+**
14541461
** The "ui" command automatically starts a web browser after initializing
14551462
** the web server. The "ui" command also binds to 127.0.0.1 and so will
14561463
** only process HTTP traffic from the local machine.
14571464
**
14581465
** In the "server" command, the REPOSITORY can be a directory (aka folder)
@@ -1480,10 +1487,11 @@
14801487
zStopperFile = find_option("stopper", 0, 1);
14811488
#endif
14821489
14831490
g.thTrace = find_option("th-trace", 0, 0)!=0;
14841491
g.useLocalauth = find_option("localauth", 0, 0)!=0;
1492
+ g.zRoot = find_option("root", "R", 1);
14851493
if( g.thTrace ){
14861494
blob_zero(&g.thLog);
14871495
}
14881496
zPort = find_option("port", "P", 1);
14891497
zNotFound = find_option("notfound", 0, 1);
@@ -1517,11 +1525,11 @@
15171525
}
15181526
}
15191527
#else
15201528
zBrowser = db_get("web-browser", "open");
15211529
#endif
1522
- zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
1530
+ zBrowserCmd = mprintf("%s http://localhost:%%d/%s &", zBrowser, (g.zRoot==0?"":g.zRoot));
15231531
}
15241532
db_close(1);
15251533
if( cgi_http_server(iPort, mxPort, zBrowserCmd, flags) ){
15261534
fossil_fatal("unable to listen on TCP socket %d", iPort);
15271535
}
15281536
--- src/main.c
+++ src/main.c
@@ -98,10 +98,12 @@
98 int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */
99 int fNoSync; /* Do not do an autosync even. --nosync */
100 char *zPath; /* Name of webpage being served */
101 char *zExtra; /* Extra path information past the webpage name */
102 char *zBaseURL; /* Full text of the URL being served */
 
 
103 char *zTop; /* Parent directory of zPath */
104 const char *zContentType; /* The content type of the input HTTP request */
105 int iErrPriority; /* Priority of current error message */
106 char *zErrMsg; /* Text of an error message */
107 int sslNotAvailable; /* SSL is not available. Do not redirect to https: */
@@ -899,20 +901,21 @@
899 const char *zHost;
900 const char *zMode;
901 const char *zCur;
902
903 if( g.zBaseURL!=0 ) return;
 
904 zHost = PD("HTTP_HOST","");
905 zMode = PD("HTTPS","off");
906 zCur = PD("SCRIPT_NAME","/");
907 i = strlen(zCur);
908 while( i>0 && zCur[i-1]=='/' ) i--;
909 if( fossil_stricmp(zMode,"on")==0 ){
910 g.zBaseURL = mprintf("https://%s%.*s", zHost, i, zCur);
911 g.zTop = &g.zBaseURL[8+strlen(zHost)];
912 }else{
913 g.zBaseURL = mprintf("http://%s%.*s", zHost, i, zCur);
914 g.zTop = &g.zBaseURL[7+strlen(zHost)];
915 }
916 }
917
918 /*
@@ -1440,19 +1443,23 @@
1440
1441 /*
1442 ** COMMAND: server
1443 ** COMMAND: ui
1444 **
1445 ** Usage: %fossil server ?-P|--port TCPPORT? ?REPOSITORY?
1446 ** Or: %fossil ui ?-P|--port TCPPORT? ?REPOSITORY?
1447 **
1448 ** Open a socket and begin listening and responding to HTTP requests on
1449 ** TCP port 8080, or on any other TCP port defined by the -P or
1450 ** --port option. The optional argument is the name of the repository.
1451 ** The repository argument may be omitted if the working directory is
1452 ** within an open checkout.
1453 **
 
 
 
 
1454 ** The "ui" command automatically starts a web browser after initializing
1455 ** the web server. The "ui" command also binds to 127.0.0.1 and so will
1456 ** only process HTTP traffic from the local machine.
1457 **
1458 ** In the "server" command, the REPOSITORY can be a directory (aka folder)
@@ -1480,10 +1487,11 @@
1480 zStopperFile = find_option("stopper", 0, 1);
1481 #endif
1482
1483 g.thTrace = find_option("th-trace", 0, 0)!=0;
1484 g.useLocalauth = find_option("localauth", 0, 0)!=0;
 
1485 if( g.thTrace ){
1486 blob_zero(&g.thLog);
1487 }
1488 zPort = find_option("port", "P", 1);
1489 zNotFound = find_option("notfound", 0, 1);
@@ -1517,11 +1525,11 @@
1517 }
1518 }
1519 #else
1520 zBrowser = db_get("web-browser", "open");
1521 #endif
1522 zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
1523 }
1524 db_close(1);
1525 if( cgi_http_server(iPort, mxPort, zBrowserCmd, flags) ){
1526 fossil_fatal("unable to listen on TCP socket %d", iPort);
1527 }
1528
--- src/main.c
+++ src/main.c
@@ -98,10 +98,12 @@
98 int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */
99 int fNoSync; /* Do not do an autosync even. --nosync */
100 char *zPath; /* Name of webpage being served */
101 char *zExtra; /* Extra path information past the webpage name */
102 char *zBaseURL; /* Full text of the URL being served */
103 char *zRedirectBaseURL; /* Full text of the URL being served to be used in redirect */
104 char *zRoot; /* Repository web root */
105 char *zTop; /* Parent directory of zPath */
106 const char *zContentType; /* The content type of the input HTTP request */
107 int iErrPriority; /* Priority of current error message */
108 char *zErrMsg; /* Text of an error message */
109 int sslNotAvailable; /* SSL is not available. Do not redirect to https: */
@@ -899,20 +901,21 @@
901 const char *zHost;
902 const char *zMode;
903 const char *zCur;
904
905 if( g.zBaseURL!=0 ) return;
906 if( g.zRoot==0 ) g.zRoot="";
907 zHost = PD("HTTP_HOST","");
908 zMode = PD("HTTPS","off");
909 zCur = PD("SCRIPT_NAME","/");
910 i = strlen(zCur);
911 while( i>0 && zCur[i-1]=='/' ) i--;
912 if( fossil_stricmp(zMode,"on")==0 ){
913 g.zBaseURL = mprintf("https://%s%s%.*s", zHost, g.zRoot, i, zCur);
914 g.zTop = &g.zBaseURL[8+strlen(zHost)];
915 }else{
916 g.zBaseURL = mprintf("http://%s%s%.*s", zHost, g.zRoot, i, zCur);
917 g.zTop = &g.zBaseURL[7+strlen(zHost)];
918 }
919 }
920
921 /*
@@ -1440,19 +1443,23 @@
1443
1444 /*
1445 ** COMMAND: server
1446 ** COMMAND: ui
1447 **
1448 ** Usage: %fossil server ?-P|--port TCPPORT? -?-R|--root ROOT? ?REPOSITORY?
1449 ** Or: %fossil ui ?-P|--port TCPPORT? -?-R|--root ROOT? ?REPOSITORY?
1450 **
1451 ** Open a socket and begin listening and responding to HTTP requests on
1452 ** TCP port 8080, or on any other TCP port defined by the -P or
1453 ** --port option. The optional argument is the name of the repository.
1454 ** The repository argument may be omitted if the working directory is
1455 ** within an open checkout.
1456 **
1457 ** If HTTP requests are being reverse proxied to the fossil server,
1458 ** and in proxy server fossil is mapped at a virtual directory, then
1459 ** virtual directory can be specified using optional -R or --root option.
1460 **
1461 ** The "ui" command automatically starts a web browser after initializing
1462 ** the web server. The "ui" command also binds to 127.0.0.1 and so will
1463 ** only process HTTP traffic from the local machine.
1464 **
1465 ** In the "server" command, the REPOSITORY can be a directory (aka folder)
@@ -1480,10 +1487,11 @@
1487 zStopperFile = find_option("stopper", 0, 1);
1488 #endif
1489
1490 g.thTrace = find_option("th-trace", 0, 0)!=0;
1491 g.useLocalauth = find_option("localauth", 0, 0)!=0;
1492 g.zRoot = find_option("root", "R", 1);
1493 if( g.thTrace ){
1494 blob_zero(&g.thLog);
1495 }
1496 zPort = find_option("port", "P", 1);
1497 zNotFound = find_option("notfound", 0, 1);
@@ -1517,11 +1525,11 @@
1525 }
1526 }
1527 #else
1528 zBrowser = db_get("web-browser", "open");
1529 #endif
1530 zBrowserCmd = mprintf("%s http://localhost:%%d/%s &", zBrowser, (g.zRoot==0?"":g.zRoot));
1531 }
1532 db_close(1);
1533 if( cgi_http_server(iPort, mxPort, zBrowserCmd, flags) ){
1534 fossil_fatal("unable to listen on TCP socket %d", iPort);
1535 }
1536

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button