comparison src/core/ngx_inet.c @ 7478:4f9b72a229c1

Multiple addresses in "listen". Previously only one address was used by the listen directive handler even if host name resolved to multiple addresses. Now a separate listening socket is created for each address.
author Roman Arutyunyan <arut@nginx.com>
date Fri, 15 Mar 2019 15:45:56 +0300
parents 935b1902a7dd
children 8be88b22fe81
comparison
equal deleted inserted replaced
7477:c74904a17021 7478:4f9b72a229c1
10 10
11 11
12 static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u); 12 static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u);
13 static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u); 13 static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u);
14 static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u); 14 static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u);
15 static ngx_int_t ngx_inet_add_addr(ngx_pool_t *pool, ngx_url_t *u,
16 struct sockaddr *sockaddr, socklen_t socklen, ngx_uint_t total);
15 17
16 18
17 in_addr_t 19 in_addr_t
18 ngx_inet_addr(u_char *text, size_t len) 20 ngx_inet_addr(u_char *text, size_t len)
19 { 21 {
778 780
779 781
780 static ngx_int_t 782 static ngx_int_t
781 ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u) 783 ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
782 { 784 {
783 u_char *p, *host, *port, *last, *uri, *args; 785 u_char *host, *port, *last, *uri, *args;
784 size_t len; 786 size_t len;
785 ngx_int_t n; 787 ngx_int_t n;
786 struct sockaddr_in *sin; 788 struct sockaddr_in *sin;
787 #if (NGX_HAVE_INET6)
788 struct sockaddr_in6 *sin6;
789 #endif
790 789
791 u->socklen = sizeof(struct sockaddr_in); 790 u->socklen = sizeof(struct sockaddr_in);
792 sin = (struct sockaddr_in *) &u->sockaddr; 791 sin = (struct sockaddr_in *) &u->sockaddr;
793 sin->sin_family = AF_INET; 792 sin->sin_family = AF_INET;
794 793
862 return NGX_ERROR; 861 return NGX_ERROR;
863 } 862 }
864 863
865 u->port = (in_port_t) n; 864 u->port = (in_port_t) n;
866 sin->sin_port = htons((in_port_t) n); 865 sin->sin_port = htons((in_port_t) n);
866 sin->sin_addr.s_addr = INADDR_ANY;
867 867
868 u->port_text.len = last - host; 868 u->port_text.len = last - host;
869 u->port_text.data = host; 869 u->port_text.data = host;
870 870
871 u->wildcard = 1; 871 u->wildcard = 1;
872 872
873 return NGX_OK; 873 return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr,
874 u->socklen, 1);
874 } 875 }
875 } 876 }
876 } 877 }
877 878
878 u->no_port = 1; 879 u->no_port = 1;
891 u->host.data = host; 892 u->host.data = host;
892 893
893 if (u->listen && len == 1 && *host == '*') { 894 if (u->listen && len == 1 && *host == '*') {
894 sin->sin_addr.s_addr = INADDR_ANY; 895 sin->sin_addr.s_addr = INADDR_ANY;
895 u->wildcard = 1; 896 u->wildcard = 1;
896 return NGX_OK; 897 return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1);
897 } 898 }
898 899
899 sin->sin_addr.s_addr = ngx_inet_addr(host, len); 900 sin->sin_addr.s_addr = ngx_inet_addr(host, len);
900 901
901 if (sin->sin_addr.s_addr != INADDR_NONE) { 902 if (sin->sin_addr.s_addr != INADDR_NONE) {
902 903
903 if (sin->sin_addr.s_addr == INADDR_ANY) { 904 if (sin->sin_addr.s_addr == INADDR_ANY) {
904 u->wildcard = 1; 905 u->wildcard = 1;
905 } 906 }
906 907
907 u->naddrs = 1; 908 return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1);
908
909 u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
910 if (u->addrs == NULL) {
911 return NGX_ERROR;
912 }
913
914 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
915 if (sin == NULL) {
916 return NGX_ERROR;
917 }
918
919 ngx_memcpy(sin, &u->sockaddr, sizeof(struct sockaddr_in));
920
921 u->addrs[0].sockaddr = (struct sockaddr *) sin;
922 u->addrs[0].socklen = sizeof(struct sockaddr_in);
923
924 p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
925 if (p == NULL) {
926 return NGX_ERROR;
927 }
928
929 u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
930 &u->host, u->port) - p;
931 u->addrs[0].name.data = p;
932
933 return NGX_OK;
934 } 909 }
935 910
936 if (u->no_resolve) { 911 if (u->no_resolve) {
937 return NGX_OK; 912 return NGX_OK;
938 } 913 }
942 } 917 }
943 918
944 u->family = u->addrs[0].sockaddr->sa_family; 919 u->family = u->addrs[0].sockaddr->sa_family;
945 u->socklen = u->addrs[0].socklen; 920 u->socklen = u->addrs[0].socklen;
946 ngx_memcpy(&u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen); 921 ngx_memcpy(&u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen);
947 922 u->wildcard = ngx_inet_wildcard(&u->sockaddr.sockaddr);
948 switch (u->family) {
949
950 #if (NGX_HAVE_INET6)
951 case AF_INET6:
952 sin6 = (struct sockaddr_in6 *) &u->sockaddr;
953
954 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
955 u->wildcard = 1;
956 }
957
958 break;
959 #endif
960
961 default: /* AF_INET */
962 sin = (struct sockaddr_in *) &u->sockaddr;
963
964 if (sin->sin_addr.s_addr == INADDR_ANY) {
965 u->wildcard = 1;
966 }
967
968 break;
969 }
970 923
971 return NGX_OK; 924 return NGX_OK;
972 } 925 }
973 926
974 927
1059 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 1012 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1060 u->wildcard = 1; 1013 u->wildcard = 1;
1061 } 1014 }
1062 1015
1063 u->family = AF_INET6; 1016 u->family = AF_INET6;
1064 u->naddrs = 1; 1017
1065 1018 return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1);
1066 u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
1067 if (u->addrs == NULL) {
1068 return NGX_ERROR;
1069 }
1070
1071 sin6 = ngx_pcalloc(pool, sizeof(struct sockaddr_in6));
1072 if (sin6 == NULL) {
1073 return NGX_ERROR;
1074 }
1075
1076 ngx_memcpy(sin6, &u->sockaddr, sizeof(struct sockaddr_in6));
1077
1078 u->addrs[0].sockaddr = (struct sockaddr *) sin6;
1079 u->addrs[0].socklen = sizeof(struct sockaddr_in6);
1080
1081 p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
1082 if (p == NULL) {
1083 return NGX_ERROR;
1084 }
1085
1086 u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
1087 &u->host, u->port) - p;
1088 u->addrs[0].name.data = p;
1089
1090 return NGX_OK;
1091 1019
1092 #else 1020 #else
1093 1021
1094 u->err = "the INET6 sockets are not supported on this platform"; 1022 u->err = "the INET6 sockets are not supported on this platform";
1095 1023
1102 #if (NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6) 1030 #if (NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6)
1103 1031
1104 ngx_int_t 1032 ngx_int_t
1105 ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u) 1033 ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
1106 { 1034 {
1107 u_char *p, *host; 1035 u_char *host;
1108 size_t len; 1036 ngx_uint_t n;
1109 in_port_t port; 1037 struct addrinfo hints, *res, *rp;
1110 ngx_uint_t i;
1111 struct addrinfo hints, *res, *rp;
1112 struct sockaddr_in *sin;
1113 struct sockaddr_in6 *sin6;
1114
1115 port = htons(u->port);
1116 1038
1117 host = ngx_alloc(u->host.len + 1, pool->log); 1039 host = ngx_alloc(u->host.len + 1, pool->log);
1118 if (host == NULL) { 1040 if (host == NULL) {
1119 return NGX_ERROR; 1041 return NGX_ERROR;
1120 } 1042 }
1134 return NGX_ERROR; 1056 return NGX_ERROR;
1135 } 1057 }
1136 1058
1137 ngx_free(host); 1059 ngx_free(host);
1138 1060
1139 for (i = 0, rp = res; rp != NULL; rp = rp->ai_next) { 1061 for (n = 0, rp = res; rp != NULL; rp = rp->ai_next) {
1140 1062
1141 switch (rp->ai_family) { 1063 switch (rp->ai_family) {
1142 1064
1143 case AF_INET: 1065 case AF_INET:
1144 case AF_INET6: 1066 case AF_INET6:
1146 1068
1147 default: 1069 default:
1148 continue; 1070 continue;
1149 } 1071 }
1150 1072
1151 i++; 1073 n++;
1152 } 1074 }
1153 1075
1154 if (i == 0) { 1076 if (n == 0) {
1155 u->err = "host not found"; 1077 u->err = "host not found";
1156 goto failed; 1078 goto failed;
1157 } 1079 }
1158 1080
1159 /* MP: ngx_shared_palloc() */ 1081 /* MP: ngx_shared_palloc() */
1160 1082
1161 u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
1162 if (u->addrs == NULL) {
1163 goto failed;
1164 }
1165
1166 u->naddrs = i;
1167
1168 i = 0;
1169
1170 /* AF_INET addresses first */ 1083 /* AF_INET addresses first */
1171 1084
1172 for (rp = res; rp != NULL; rp = rp->ai_next) { 1085 for (rp = res; rp != NULL; rp = rp->ai_next) {
1173 1086
1174 if (rp->ai_family != AF_INET) { 1087 if (rp->ai_family != AF_INET) {
1175 continue; 1088 continue;
1176 } 1089 }
1177 1090
1178 sin = ngx_pcalloc(pool, rp->ai_addrlen); 1091 if (ngx_inet_add_addr(pool, u, rp->ai_addr, rp->ai_addrlen, n)
1179 if (sin == NULL) { 1092 != NGX_OK)
1093 {
1180 goto failed; 1094 goto failed;
1181 } 1095 }
1182
1183 ngx_memcpy(sin, rp->ai_addr, rp->ai_addrlen);
1184
1185 sin->sin_port = port;
1186
1187 u->addrs[i].sockaddr = (struct sockaddr *) sin;
1188 u->addrs[i].socklen = rp->ai_addrlen;
1189
1190 len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
1191
1192 p = ngx_pnalloc(pool, len);
1193 if (p == NULL) {
1194 goto failed;
1195 }
1196
1197 len = ngx_sock_ntop((struct sockaddr *) sin, rp->ai_addrlen, p, len, 1);
1198
1199 u->addrs[i].name.len = len;
1200 u->addrs[i].name.data = p;
1201
1202 i++;
1203 } 1096 }
1204 1097
1205 for (rp = res; rp != NULL; rp = rp->ai_next) { 1098 for (rp = res; rp != NULL; rp = rp->ai_next) {
1206 1099
1207 if (rp->ai_family != AF_INET6) { 1100 if (rp->ai_family != AF_INET6) {
1208 continue; 1101 continue;
1209 } 1102 }
1210 1103
1211 sin6 = ngx_pcalloc(pool, rp->ai_addrlen); 1104 if (ngx_inet_add_addr(pool, u, rp->ai_addr, rp->ai_addrlen, n)
1212 if (sin6 == NULL) { 1105 != NGX_OK)
1106 {
1213 goto failed; 1107 goto failed;
1214 } 1108 }
1215
1216 ngx_memcpy(sin6, rp->ai_addr, rp->ai_addrlen);
1217
1218 sin6->sin6_port = port;
1219
1220 u->addrs[i].sockaddr = (struct sockaddr *) sin6;
1221 u->addrs[i].socklen = rp->ai_addrlen;
1222
1223 len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1;
1224
1225 p = ngx_pnalloc(pool, len);
1226 if (p == NULL) {
1227 goto failed;
1228 }
1229
1230 len = ngx_sock_ntop((struct sockaddr *) sin6, rp->ai_addrlen, p,
1231 len, 1);
1232
1233 u->addrs[i].name.len = len;
1234 u->addrs[i].name.data = p;
1235
1236 i++;
1237 } 1109 }
1238 1110
1239 freeaddrinfo(res); 1111 freeaddrinfo(res);
1240 return NGX_OK; 1112 return NGX_OK;
1241 1113
1248 #else /* !NGX_HAVE_GETADDRINFO || !NGX_HAVE_INET6 */ 1120 #else /* !NGX_HAVE_GETADDRINFO || !NGX_HAVE_INET6 */
1249 1121
1250 ngx_int_t 1122 ngx_int_t
1251 ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u) 1123 ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
1252 { 1124 {
1253 u_char *p, *host; 1125 u_char *host;
1254 size_t len; 1126 ngx_uint_t i, n;
1255 in_port_t port;
1256 in_addr_t in_addr;
1257 ngx_uint_t i;
1258 struct hostent *h; 1127 struct hostent *h;
1259 struct sockaddr_in *sin; 1128 struct sockaddr_in sin;
1260 1129
1261 /* AF_INET only */ 1130 /* AF_INET only */
1262 1131
1263 port = htons(u->port); 1132 ngx_memzero(&sin, sizeof(struct sockaddr_in));
1264 1133
1265 in_addr = ngx_inet_addr(u->host.data, u->host.len); 1134 sin.sin_family = AF_INET;
1266 1135 sin.sin_addr.s_addr = ngx_inet_addr(u->host.data, u->host.len);
1267 if (in_addr == INADDR_NONE) { 1136
1137 if (sin.sin_addr.s_addr == INADDR_NONE) {
1268 host = ngx_alloc(u->host.len + 1, pool->log); 1138 host = ngx_alloc(u->host.len + 1, pool->log);
1269 if (host == NULL) { 1139 if (host == NULL) {
1270 return NGX_ERROR; 1140 return NGX_ERROR;
1271 } 1141 }
1272 1142
1279 if (h == NULL || h->h_addr_list[0] == NULL) { 1149 if (h == NULL || h->h_addr_list[0] == NULL) {
1280 u->err = "host not found"; 1150 u->err = "host not found";
1281 return NGX_ERROR; 1151 return NGX_ERROR;
1282 } 1152 }
1283 1153
1284 for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ } 1154 for (n = 0; h->h_addr_list[n] != NULL; n++) { /* void */ }
1285 1155
1286 /* MP: ngx_shared_palloc() */ 1156 /* MP: ngx_shared_palloc() */
1287 1157
1288 u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t)); 1158 for (i = 0; i < n; i++) {
1159 sin.sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
1160
1161 if (ngx_inet_add_addr(pool, u, (struct sockaddr *) &sin,
1162 sizeof(struct sockaddr_in), n)
1163 != NGX_OK)
1164 {
1165 return NGX_ERROR;
1166 }
1167 }
1168
1169 } else {
1170
1171 /* MP: ngx_shared_palloc() */
1172
1173 if (ngx_inet_add_addr(pool, u, (struct sockaddr *) &sin,
1174 sizeof(struct sockaddr_in), 1)
1175 != NGX_OK)
1176 {
1177 return NGX_ERROR;
1178 }
1179 }
1180
1181 return NGX_OK;
1182 }
1183
1184 #endif /* NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6 */
1185
1186
1187 static ngx_int_t
1188 ngx_inet_add_addr(ngx_pool_t *pool, ngx_url_t *u, struct sockaddr *sockaddr,
1189 socklen_t socklen, ngx_uint_t total)
1190 {
1191 u_char *p;
1192 size_t len;
1193 ngx_addr_t *addr;
1194 struct sockaddr *sa;
1195
1196 if (u->addrs == NULL) {
1197 u->addrs = ngx_palloc(pool, total * sizeof(ngx_addr_t));
1289 if (u->addrs == NULL) { 1198 if (u->addrs == NULL) {
1290 return NGX_ERROR; 1199 return NGX_ERROR;
1291 } 1200 }
1292 1201 }
1293 u->naddrs = i; 1202
1294 1203 sa = ngx_pcalloc(pool, socklen);
1295 for (i = 0; i < u->naddrs; i++) { 1204 if (sa == NULL) {
1296 1205 return NGX_ERROR;
1297 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in)); 1206 }
1298 if (sin == NULL) { 1207
1299 return NGX_ERROR; 1208 ngx_memcpy(sa, sockaddr, socklen);
1300 } 1209
1301 1210 ngx_inet_set_port(sa, u->port);
1302 sin->sin_family = AF_INET; 1211
1303 sin->sin_port = port; 1212 switch (sa->sa_family) {
1304 sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]); 1213
1305 1214 #if (NGX_HAVE_INET6)
1306 u->addrs[i].sockaddr = (struct sockaddr *) sin; 1215 case AF_INET6:
1307 u->addrs[i].socklen = sizeof(struct sockaddr_in); 1216 len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65536") - 1;
1308 1217 break;
1309 len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; 1218 #endif
1310 1219
1311 p = ngx_pnalloc(pool, len); 1220 default: /* AF_INET */
1312 if (p == NULL) { 1221 len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
1313 return NGX_ERROR; 1222 }
1314 } 1223
1315 1224 p = ngx_pnalloc(pool, len);
1316 len = ngx_sock_ntop((struct sockaddr *) sin, 1225 if (p == NULL) {
1317 sizeof(struct sockaddr_in), p, len, 1); 1226 return NGX_ERROR;
1318 1227 }
1319 u->addrs[i].name.len = len; 1228
1320 u->addrs[i].name.data = p; 1229 len = ngx_sock_ntop(sa, socklen, p, len, 1);
1321 } 1230
1322 1231 addr = &u->addrs[u->naddrs++];
1323 } else { 1232
1324 1233 addr->sockaddr = sa;
1325 /* MP: ngx_shared_palloc() */ 1234 addr->socklen = socklen;
1326 1235
1327 u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t)); 1236 addr->name.len = len;
1328 if (u->addrs == NULL) { 1237 addr->name.data = p;
1329 return NGX_ERROR;
1330 }
1331
1332 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
1333 if (sin == NULL) {
1334 return NGX_ERROR;
1335 }
1336
1337 u->naddrs = 1;
1338
1339 sin->sin_family = AF_INET;
1340 sin->sin_port = port;
1341 sin->sin_addr.s_addr = in_addr;
1342
1343 u->addrs[0].sockaddr = (struct sockaddr *) sin;
1344 u->addrs[0].socklen = sizeof(struct sockaddr_in);
1345
1346 p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
1347 if (p == NULL) {
1348 return NGX_ERROR;
1349 }
1350
1351 u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
1352 &u->host, ntohs(port)) - p;
1353 u->addrs[0].name.data = p;
1354 }
1355 1238
1356 return NGX_OK; 1239 return NGX_OK;
1357 } 1240 }
1358
1359 #endif /* NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6 */
1360 1241
1361 1242
1362 ngx_int_t 1243 ngx_int_t
1363 ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1, 1244 ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1,
1364 struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port) 1245 struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port)
1493 sin = (struct sockaddr_in *) sa; 1374 sin = (struct sockaddr_in *) sa;
1494 sin->sin_port = htons(port); 1375 sin->sin_port = htons(port);
1495 break; 1376 break;
1496 } 1377 }
1497 } 1378 }
1379
1380
1381 ngx_uint_t
1382 ngx_inet_wildcard(struct sockaddr *sa)
1383 {
1384 struct sockaddr_in *sin;
1385 #if (NGX_HAVE_INET6)
1386 struct sockaddr_in6 *sin6;
1387 #endif
1388
1389 switch (sa->sa_family) {
1390
1391 case AF_INET:
1392 sin = (struct sockaddr_in *) sa;
1393
1394 if (sin->sin_addr.s_addr == INADDR_ANY) {
1395 return 1;
1396 }
1397
1398 break;
1399
1400 #if (NGX_HAVE_INET6)
1401
1402 case AF_INET6:
1403 sin6 = (struct sockaddr_in6 *) sa;
1404
1405 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1406 return 1;
1407 }
1408
1409 break;
1410
1411 #endif
1412 }
1413
1414 return 0;
1415 }