Fossil SCM
Clean getaddrinfo() code in http_socket.c incorporating suggestions from Gé Weijers
Commit
c24e1c278580b243346486ce54050e11f2f1dd52
Parent
c30eaa88625c958…
2 files changed
+56
-3
+12
-10
+56
-3
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -1198,11 +1198,11 @@ | ||
| 1198 | 1198 | int v4mapped=0; |
| 1199 | 1199 | if( remoteName.ss_family == AF_INET6 && |
| 1200 | 1200 | IN6_IS_ADDR_V4MAPPED(&(((struct sockaddr_in6*)&remoteName)->sin6_addr)) ){ |
| 1201 | 1201 | v4mapped = 1; |
| 1202 | 1202 | } |
| 1203 | - if(!getnameinfo((struct sockaddr*)&remoteName, remoteName.ss_len, zLine, sizeof(zLine), | |
| 1203 | + if(!getnameinfo((struct sockaddr*)&remoteName, size, zLine, sizeof(zLine), | |
| 1204 | 1204 | NULL, 0, NI_NUMERICHOST)){ |
| 1205 | 1205 | zIpAddr = zLine; |
| 1206 | 1206 | } else { |
| 1207 | 1207 | zIpAddr = NULL; |
| 1208 | 1208 | } |
| @@ -1253,20 +1253,73 @@ | ||
| 1253 | 1253 | fd_set readfds; /* Set of file descriptors for select() */ |
| 1254 | 1254 | socklen_t lenaddr; /* Length of the inaddr structure */ |
| 1255 | 1255 | int child; /* PID of the child process */ |
| 1256 | 1256 | int nchildren = 0; /* Number of child processes */ |
| 1257 | 1257 | struct timeval delay; /* How long to wait inside select() */ |
| 1258 | +#ifdef HAVE_GETADDRINFO | |
| 1259 | + struct addrinfo hints; | |
| 1260 | + struct addrinfo* res; | |
| 1261 | + struct addrinfo* i; | |
| 1262 | + struct sockaddr_storage inaddr; /* The socket address */ | |
| 1263 | + char* sPort; | |
| 1264 | + int iRet; | |
| 1265 | +#else | |
| 1258 | 1266 | #ifdef WITH_IPV6 |
| 1259 | 1267 | struct sockaddr_in6 inaddr; /* The socket address */ |
| 1260 | 1268 | #else |
| 1261 | 1269 | struct sockaddr_in inaddr; /* The socket address */ |
| 1270 | +#endif | |
| 1262 | 1271 | #endif |
| 1263 | 1272 | int opt = 1; /* setsockopt flag */ |
| 1264 | 1273 | int iPort = mnPort; |
| 1265 | 1274 | |
| 1266 | 1275 | while( iPort<=mxPort ){ |
| 1276 | +#ifdef HAVE_GETADDRINFO | |
| 1277 | + memset(&hints, 0, sizeof(struct addrinfo)); | |
| 1278 | +#ifdef WITH_IPV6 | |
| 1279 | + hints.ai_family = PF_UNSPEC; | |
| 1280 | +#else | |
| 1281 | + hints.ai_family = PF_INET; | |
| 1282 | +#endif | |
| 1283 | + hints.ai_socktype = SOCK_STREAM; | |
| 1284 | + hints.ai_protocol = IPPROTO_TCP; | |
| 1285 | + if(!(flags & HTTP_SERVER_LOCALHOST)) hints.ai_flags |= AI_PASSIVE; | |
| 1286 | + | |
| 1287 | + sPort = mprintf("%d", iPort); | |
| 1288 | + | |
| 1289 | + if(iRet = getaddrinfo(NULL, sPort, &hints, &res)) { | |
| 1290 | + fossil_fatal("Unable to obtain address: %s", gai_strerror(iRet)); | |
| 1291 | + } | |
| 1292 | + | |
| 1293 | + for(i = res; i; i = i->ai_next) { | |
| 1294 | + listener = socket(i->ai_family, i->ai_socktype, i->ai_protocol); | |
| 1295 | + if(listener < 0) { | |
| 1296 | + fossil_fatal("Unable to create socket"); | |
| 1297 | + } | |
| 1298 | + opt=1; | |
| 1299 | + setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); | |
| 1300 | + if(i->ai_family == AF_INET6) { | |
| 1301 | + opt=0; | |
| 1302 | + setsockopt(listener, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)); | |
| 1303 | + } | |
| 1304 | + if( bind(listener, i->ai_addr, i->ai_addrlen)<0 ){ | |
| 1305 | + close(listener); | |
| 1306 | + listener = -1; | |
| 1307 | + } | |
| 1308 | + break; | |
| 1309 | + } | |
| 1310 | + | |
| 1311 | + free(sPort); | |
| 1312 | + freeaddrinfo(res); | |
| 1313 | + | |
| 1314 | + if(listener == -1) { | |
| 1315 | + iPort++; | |
| 1316 | + continue; | |
| 1317 | + } | |
| 1318 | +#else | |
| 1267 | 1319 | memset(&inaddr, 0, sizeof(inaddr)); |
| 1320 | + | |
| 1268 | 1321 | #ifdef WITH_IPV6 |
| 1269 | 1322 | inaddr.sin6_family = AF_INET6; |
| 1270 | 1323 | #else |
| 1271 | 1324 | inaddr.sin_family = AF_INET; |
| 1272 | 1325 | #endif |
| @@ -1289,12 +1342,11 @@ | ||
| 1289 | 1342 | #else |
| 1290 | 1343 | inaddr.sin_port = htons(iPort); |
| 1291 | 1344 | listener = socket(AF_INET, SOCK_STREAM, 0); |
| 1292 | 1345 | #endif |
| 1293 | 1346 | if( listener<0 ){ |
| 1294 | - iPort++; | |
| 1295 | - continue; | |
| 1347 | + fossil_fatal("Unable to create socket"); | |
| 1296 | 1348 | } |
| 1297 | 1349 | |
| 1298 | 1350 | /* if we can't terminate nicely, at least allow the socket to be reused */ |
| 1299 | 1351 | setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); |
| 1300 | 1352 | |
| @@ -1306,10 +1358,11 @@ | ||
| 1306 | 1358 | if( bind(listener, (struct sockaddr*)&inaddr, sizeof(inaddr))<0 ){ |
| 1307 | 1359 | close(listener); |
| 1308 | 1360 | iPort++; |
| 1309 | 1361 | continue; |
| 1310 | 1362 | } |
| 1363 | +#endif | |
| 1311 | 1364 | break; |
| 1312 | 1365 | } |
| 1313 | 1366 | if( iPort>mxPort ){ |
| 1314 | 1367 | if( mnPort==mxPort ){ |
| 1315 | 1368 | fossil_fatal("unable to open listening socket on ports %d", mnPort); |
| 1316 | 1369 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -1198,11 +1198,11 @@ | |
| 1198 | int v4mapped=0; |
| 1199 | if( remoteName.ss_family == AF_INET6 && |
| 1200 | IN6_IS_ADDR_V4MAPPED(&(((struct sockaddr_in6*)&remoteName)->sin6_addr)) ){ |
| 1201 | v4mapped = 1; |
| 1202 | } |
| 1203 | if(!getnameinfo((struct sockaddr*)&remoteName, remoteName.ss_len, zLine, sizeof(zLine), |
| 1204 | NULL, 0, NI_NUMERICHOST)){ |
| 1205 | zIpAddr = zLine; |
| 1206 | } else { |
| 1207 | zIpAddr = NULL; |
| 1208 | } |
| @@ -1253,20 +1253,73 @@ | |
| 1253 | fd_set readfds; /* Set of file descriptors for select() */ |
| 1254 | socklen_t lenaddr; /* Length of the inaddr structure */ |
| 1255 | int child; /* PID of the child process */ |
| 1256 | int nchildren = 0; /* Number of child processes */ |
| 1257 | struct timeval delay; /* How long to wait inside select() */ |
| 1258 | #ifdef WITH_IPV6 |
| 1259 | struct sockaddr_in6 inaddr; /* The socket address */ |
| 1260 | #else |
| 1261 | struct sockaddr_in inaddr; /* The socket address */ |
| 1262 | #endif |
| 1263 | int opt = 1; /* setsockopt flag */ |
| 1264 | int iPort = mnPort; |
| 1265 | |
| 1266 | while( iPort<=mxPort ){ |
| 1267 | memset(&inaddr, 0, sizeof(inaddr)); |
| 1268 | #ifdef WITH_IPV6 |
| 1269 | inaddr.sin6_family = AF_INET6; |
| 1270 | #else |
| 1271 | inaddr.sin_family = AF_INET; |
| 1272 | #endif |
| @@ -1289,12 +1342,11 @@ | |
| 1289 | #else |
| 1290 | inaddr.sin_port = htons(iPort); |
| 1291 | listener = socket(AF_INET, SOCK_STREAM, 0); |
| 1292 | #endif |
| 1293 | if( listener<0 ){ |
| 1294 | iPort++; |
| 1295 | continue; |
| 1296 | } |
| 1297 | |
| 1298 | /* if we can't terminate nicely, at least allow the socket to be reused */ |
| 1299 | setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); |
| 1300 | |
| @@ -1306,10 +1358,11 @@ | |
| 1306 | if( bind(listener, (struct sockaddr*)&inaddr, sizeof(inaddr))<0 ){ |
| 1307 | close(listener); |
| 1308 | iPort++; |
| 1309 | continue; |
| 1310 | } |
| 1311 | break; |
| 1312 | } |
| 1313 | if( iPort>mxPort ){ |
| 1314 | if( mnPort==mxPort ){ |
| 1315 | fossil_fatal("unable to open listening socket on ports %d", mnPort); |
| 1316 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -1198,11 +1198,11 @@ | |
| 1198 | int v4mapped=0; |
| 1199 | if( remoteName.ss_family == AF_INET6 && |
| 1200 | IN6_IS_ADDR_V4MAPPED(&(((struct sockaddr_in6*)&remoteName)->sin6_addr)) ){ |
| 1201 | v4mapped = 1; |
| 1202 | } |
| 1203 | if(!getnameinfo((struct sockaddr*)&remoteName, size, zLine, sizeof(zLine), |
| 1204 | NULL, 0, NI_NUMERICHOST)){ |
| 1205 | zIpAddr = zLine; |
| 1206 | } else { |
| 1207 | zIpAddr = NULL; |
| 1208 | } |
| @@ -1253,20 +1253,73 @@ | |
| 1253 | fd_set readfds; /* Set of file descriptors for select() */ |
| 1254 | socklen_t lenaddr; /* Length of the inaddr structure */ |
| 1255 | int child; /* PID of the child process */ |
| 1256 | int nchildren = 0; /* Number of child processes */ |
| 1257 | struct timeval delay; /* How long to wait inside select() */ |
| 1258 | #ifdef HAVE_GETADDRINFO |
| 1259 | struct addrinfo hints; |
| 1260 | struct addrinfo* res; |
| 1261 | struct addrinfo* i; |
| 1262 | struct sockaddr_storage inaddr; /* The socket address */ |
| 1263 | char* sPort; |
| 1264 | int iRet; |
| 1265 | #else |
| 1266 | #ifdef WITH_IPV6 |
| 1267 | struct sockaddr_in6 inaddr; /* The socket address */ |
| 1268 | #else |
| 1269 | struct sockaddr_in inaddr; /* The socket address */ |
| 1270 | #endif |
| 1271 | #endif |
| 1272 | int opt = 1; /* setsockopt flag */ |
| 1273 | int iPort = mnPort; |
| 1274 | |
| 1275 | while( iPort<=mxPort ){ |
| 1276 | #ifdef HAVE_GETADDRINFO |
| 1277 | memset(&hints, 0, sizeof(struct addrinfo)); |
| 1278 | #ifdef WITH_IPV6 |
| 1279 | hints.ai_family = PF_UNSPEC; |
| 1280 | #else |
| 1281 | hints.ai_family = PF_INET; |
| 1282 | #endif |
| 1283 | hints.ai_socktype = SOCK_STREAM; |
| 1284 | hints.ai_protocol = IPPROTO_TCP; |
| 1285 | if(!(flags & HTTP_SERVER_LOCALHOST)) hints.ai_flags |= AI_PASSIVE; |
| 1286 | |
| 1287 | sPort = mprintf("%d", iPort); |
| 1288 | |
| 1289 | if(iRet = getaddrinfo(NULL, sPort, &hints, &res)) { |
| 1290 | fossil_fatal("Unable to obtain address: %s", gai_strerror(iRet)); |
| 1291 | } |
| 1292 | |
| 1293 | for(i = res; i; i = i->ai_next) { |
| 1294 | listener = socket(i->ai_family, i->ai_socktype, i->ai_protocol); |
| 1295 | if(listener < 0) { |
| 1296 | fossil_fatal("Unable to create socket"); |
| 1297 | } |
| 1298 | opt=1; |
| 1299 | setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); |
| 1300 | if(i->ai_family == AF_INET6) { |
| 1301 | opt=0; |
| 1302 | setsockopt(listener, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)); |
| 1303 | } |
| 1304 | if( bind(listener, i->ai_addr, i->ai_addrlen)<0 ){ |
| 1305 | close(listener); |
| 1306 | listener = -1; |
| 1307 | } |
| 1308 | break; |
| 1309 | } |
| 1310 | |
| 1311 | free(sPort); |
| 1312 | freeaddrinfo(res); |
| 1313 | |
| 1314 | if(listener == -1) { |
| 1315 | iPort++; |
| 1316 | continue; |
| 1317 | } |
| 1318 | #else |
| 1319 | memset(&inaddr, 0, sizeof(inaddr)); |
| 1320 | |
| 1321 | #ifdef WITH_IPV6 |
| 1322 | inaddr.sin6_family = AF_INET6; |
| 1323 | #else |
| 1324 | inaddr.sin_family = AF_INET; |
| 1325 | #endif |
| @@ -1289,12 +1342,11 @@ | |
| 1342 | #else |
| 1343 | inaddr.sin_port = htons(iPort); |
| 1344 | listener = socket(AF_INET, SOCK_STREAM, 0); |
| 1345 | #endif |
| 1346 | if( listener<0 ){ |
| 1347 | fossil_fatal("Unable to create socket"); |
| 1348 | } |
| 1349 | |
| 1350 | /* if we can't terminate nicely, at least allow the socket to be reused */ |
| 1351 | setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); |
| 1352 | |
| @@ -1306,10 +1358,11 @@ | |
| 1358 | if( bind(listener, (struct sockaddr*)&inaddr, sizeof(inaddr))<0 ){ |
| 1359 | close(listener); |
| 1360 | iPort++; |
| 1361 | continue; |
| 1362 | } |
| 1363 | #endif |
| 1364 | break; |
| 1365 | } |
| 1366 | if( iPort>mxPort ){ |
| 1367 | if( mnPort==mxPort ){ |
| 1368 | fossil_fatal("unable to open listening socket on ports %d", mnPort); |
| 1369 |
+12
-10
| --- src/http_socket.c | ||
| +++ src/http_socket.c | ||
| @@ -142,10 +142,11 @@ | ||
| 142 | 142 | struct addrinfo hints; |
| 143 | 143 | struct addrinfo* res; |
| 144 | 144 | struct addrinfo* i; |
| 145 | 145 | char ip[INET6_ADDRSTRLEN]; |
| 146 | 146 | void* addr; |
| 147 | + char* sPort; | |
| 147 | 148 | |
| 148 | 149 | memset(&hints, 0, sizeof(struct addrinfo)); |
| 149 | 150 | hints.ai_flags = AI_ADDRCONFIG; |
| 150 | 151 | #ifdef WITH_IPV6 |
| 151 | 152 | hints.ai_family = PF_UNSPEC; |
| @@ -152,37 +153,38 @@ | ||
| 152 | 153 | #else |
| 153 | 154 | hints.ai_family = PF_INET; |
| 154 | 155 | #endif |
| 155 | 156 | hints.ai_socktype = SOCK_STREAM; |
| 156 | 157 | hints.ai_protocol = IPPROTO_TCP; |
| 157 | - if(getaddrinfo(g.urlName, NULL, &hints, &res)) { | |
| 158 | + | |
| 159 | + sPort = mprintf("%d", g.urlPort); | |
| 160 | + | |
| 161 | + if(getaddrinfo(g.urlName, sPort, &hints, &res)) { | |
| 158 | 162 | socket_set_errmsg("can't resolve host name: %s", g.urlName); |
| 163 | + free(sPort); | |
| 159 | 164 | return 1; |
| 160 | 165 | } |
| 161 | 166 | for(i = res; i; i = i->ai_next) { |
| 162 | 167 | iSocket = socket(i->ai_family, i->ai_socktype, i->ai_protocol); |
| 163 | 168 | if(iSocket < 0) { |
| 164 | 169 | continue; |
| 165 | 170 | } |
| 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 | 171 | if(connect(iSocket, i->ai_addr, i->ai_addrlen) < 0) { |
| 172 | 172 | close(iSocket); |
| 173 | 173 | iSocket = -1; |
| 174 | 174 | continue; |
| 175 | 175 | } |
| 176 | - if(!getnameinfo(i->ai_addr, i->ai_addrlen, ip, sizeof(ip), | |
| 177 | - NULL, 0, NI_NUMERICHOST)) | |
| 178 | - g.zIpAddr = mprintf("%s", ip); | |
| 176 | + if(!getnameinfo(i->ai_addr, i->ai_addrlen, ip, sizeof(ip), | |
| 177 | + NULL, 0, NI_NUMERICHOST)) | |
| 178 | + g.zIpAddr = mprintf("%s", ip); | |
| 179 | + break; | |
| 179 | 180 | } |
| 180 | 181 | if(iSocket == -1) { |
| 181 | - socket_set_errmsg("cannot connect to host %s:%d", g.urlName, g.urlPort); | |
| 182 | + socket_set_errmsg("cannot connect to host %s:%s", g.urlName, sPort); | |
| 182 | 183 | error = 1; |
| 183 | 184 | } |
| 185 | + free(sPort); | |
| 184 | 186 | freeaddrinfo(res); |
| 185 | 187 | #else |
| 186 | 188 | static struct sockaddr_in addr; /* The server address */ |
| 187 | 189 | static int addrIsInit = 0; /* True once addr is initialized */ |
| 188 | 190 | |
| 189 | 191 |
| --- src/http_socket.c | |
| +++ src/http_socket.c | |
| @@ -142,10 +142,11 @@ | |
| 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,37 +153,38 @@ | |
| 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 |
| --- src/http_socket.c | |
| +++ src/http_socket.c | |
| @@ -142,10 +142,11 @@ | |
| 142 | struct addrinfo hints; |
| 143 | struct addrinfo* res; |
| 144 | struct addrinfo* i; |
| 145 | char ip[INET6_ADDRSTRLEN]; |
| 146 | void* addr; |
| 147 | char* sPort; |
| 148 | |
| 149 | memset(&hints, 0, sizeof(struct addrinfo)); |
| 150 | hints.ai_flags = AI_ADDRCONFIG; |
| 151 | #ifdef WITH_IPV6 |
| 152 | hints.ai_family = PF_UNSPEC; |
| @@ -152,37 +153,38 @@ | |
| 153 | #else |
| 154 | hints.ai_family = PF_INET; |
| 155 | #endif |
| 156 | hints.ai_socktype = SOCK_STREAM; |
| 157 | hints.ai_protocol = IPPROTO_TCP; |
| 158 | |
| 159 | sPort = mprintf("%d", g.urlPort); |
| 160 | |
| 161 | if(getaddrinfo(g.urlName, sPort, &hints, &res)) { |
| 162 | socket_set_errmsg("can't resolve host name: %s", g.urlName); |
| 163 | free(sPort); |
| 164 | return 1; |
| 165 | } |
| 166 | for(i = res; i; i = i->ai_next) { |
| 167 | iSocket = socket(i->ai_family, i->ai_socktype, i->ai_protocol); |
| 168 | if(iSocket < 0) { |
| 169 | continue; |
| 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 | break; |
| 180 | } |
| 181 | if(iSocket == -1) { |
| 182 | socket_set_errmsg("cannot connect to host %s:%s", g.urlName, sPort); |
| 183 | error = 1; |
| 184 | } |
| 185 | free(sPort); |
| 186 | freeaddrinfo(res); |
| 187 | #else |
| 188 | static struct sockaddr_in addr; /* The server address */ |
| 189 | static int addrIsInit = 0; /* True once addr is initialized */ |
| 190 | |
| 191 |