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.
Roman Arutyunyan
3 years ago
11 | 11 | static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u); |
12 | 12 | static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u); |
13 | 13 | static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u); |
14 | static ngx_int_t ngx_inet_add_addr(ngx_pool_t *pool, ngx_url_t *u, | |
15 | struct sockaddr *sockaddr, socklen_t socklen, ngx_uint_t total); | |
14 | 16 | |
15 | 17 | |
16 | 18 | in_addr_t |
779 | 781 | static ngx_int_t |
780 | 782 | ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u) |
781 | 783 | { |
782 | u_char *p, *host, *port, *last, *uri, *args; | |
783 | size_t len; | |
784 | ngx_int_t n; | |
785 | struct sockaddr_in *sin; | |
786 | #if (NGX_HAVE_INET6) | |
787 | struct sockaddr_in6 *sin6; | |
788 | #endif | |
784 | u_char *host, *port, *last, *uri, *args; | |
785 | size_t len; | |
786 | ngx_int_t n; | |
787 | struct sockaddr_in *sin; | |
789 | 788 | |
790 | 789 | u->socklen = sizeof(struct sockaddr_in); |
791 | 790 | sin = (struct sockaddr_in *) &u->sockaddr; |
863 | 862 | |
864 | 863 | u->port = (in_port_t) n; |
865 | 864 | sin->sin_port = htons((in_port_t) n); |
865 | sin->sin_addr.s_addr = INADDR_ANY; | |
866 | 866 | |
867 | 867 | u->port_text.len = last - host; |
868 | 868 | u->port_text.data = host; |
869 | 869 | |
870 | 870 | u->wildcard = 1; |
871 | 871 | |
872 | return NGX_OK; | |
872 | return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, | |
873 | u->socklen, 1); | |
873 | 874 | } |
874 | 875 | } |
875 | 876 | } |
892 | 893 | if (u->listen && len == 1 && *host == '*') { |
893 | 894 | sin->sin_addr.s_addr = INADDR_ANY; |
894 | 895 | u->wildcard = 1; |
895 | return NGX_OK; | |
896 | return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1); | |
896 | 897 | } |
897 | 898 | |
898 | 899 | sin->sin_addr.s_addr = ngx_inet_addr(host, len); |
903 | 904 | u->wildcard = 1; |
904 | 905 | } |
905 | 906 | |
906 | u->naddrs = 1; | |
907 | ||
908 | u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t)); | |
909 | if (u->addrs == NULL) { | |
910 | return NGX_ERROR; | |
911 | } | |
912 | ||
913 | sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in)); | |
914 | if (sin == NULL) { | |
915 | return NGX_ERROR; | |
916 | } | |
917 | ||
918 | ngx_memcpy(sin, &u->sockaddr, sizeof(struct sockaddr_in)); | |
919 | ||
920 | u->addrs[0].sockaddr = (struct sockaddr *) sin; | |
921 | u->addrs[0].socklen = sizeof(struct sockaddr_in); | |
922 | ||
923 | p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1); | |
924 | if (p == NULL) { | |
925 | return NGX_ERROR; | |
926 | } | |
927 | ||
928 | u->addrs[0].name.len = ngx_sprintf(p, "%V:%d", | |
929 | &u->host, u->port) - p; | |
930 | u->addrs[0].name.data = p; | |
931 | ||
932 | return NGX_OK; | |
907 | return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1); | |
933 | 908 | } |
934 | 909 | |
935 | 910 | if (u->no_resolve) { |
943 | 918 | u->family = u->addrs[0].sockaddr->sa_family; |
944 | 919 | u->socklen = u->addrs[0].socklen; |
945 | 920 | ngx_memcpy(&u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen); |
946 | ||
947 | switch (u->family) { | |
948 | ||
949 | #if (NGX_HAVE_INET6) | |
950 | case AF_INET6: | |
951 | sin6 = (struct sockaddr_in6 *) &u->sockaddr; | |
952 | ||
953 | if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { | |
954 | u->wildcard = 1; | |
955 | } | |
956 | ||
957 | break; | |
958 | #endif | |
959 | ||
960 | default: /* AF_INET */ | |
961 | sin = (struct sockaddr_in *) &u->sockaddr; | |
962 | ||
963 | if (sin->sin_addr.s_addr == INADDR_ANY) { | |
964 | u->wildcard = 1; | |
965 | } | |
966 | ||
967 | break; | |
968 | } | |
921 | u->wildcard = ngx_inet_wildcard(&u->sockaddr.sockaddr); | |
969 | 922 | |
970 | 923 | return NGX_OK; |
971 | 924 | } |
1060 | 1013 | } |
1061 | 1014 | |
1062 | 1015 | u->family = AF_INET6; |
1063 | u->naddrs = 1; | |
1064 | ||
1065 | u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t)); | |
1066 | if (u->addrs == NULL) { | |
1067 | return NGX_ERROR; | |
1068 | } | |
1069 | ||
1070 | sin6 = ngx_pcalloc(pool, sizeof(struct sockaddr_in6)); | |
1071 | if (sin6 == NULL) { | |
1072 | return NGX_ERROR; | |
1073 | } | |
1074 | ||
1075 | ngx_memcpy(sin6, &u->sockaddr, sizeof(struct sockaddr_in6)); | |
1076 | ||
1077 | u->addrs[0].sockaddr = (struct sockaddr *) sin6; | |
1078 | u->addrs[0].socklen = sizeof(struct sockaddr_in6); | |
1079 | ||
1080 | p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1); | |
1081 | if (p == NULL) { | |
1082 | return NGX_ERROR; | |
1083 | } | |
1084 | ||
1085 | u->addrs[0].name.len = ngx_sprintf(p, "%V:%d", | |
1086 | &u->host, u->port) - p; | |
1087 | u->addrs[0].name.data = p; | |
1088 | ||
1089 | return NGX_OK; | |
1016 | ||
1017 | return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1); | |
1090 | 1018 | |
1091 | 1019 | #else |
1092 | 1020 | |
1103 | 1031 | ngx_int_t |
1104 | 1032 | ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u) |
1105 | 1033 | { |
1106 | u_char *p, *host; | |
1107 | size_t len; | |
1108 | in_port_t port; | |
1109 | ngx_uint_t i; | |
1110 | struct addrinfo hints, *res, *rp; | |
1111 | struct sockaddr_in *sin; | |
1112 | struct sockaddr_in6 *sin6; | |
1113 | ||
1114 | port = htons(u->port); | |
1034 | u_char *host; | |
1035 | ngx_uint_t n; | |
1036 | struct addrinfo hints, *res, *rp; | |
1115 | 1037 | |
1116 | 1038 | host = ngx_alloc(u->host.len + 1, pool->log); |
1117 | 1039 | if (host == NULL) { |
1135 | 1057 | |
1136 | 1058 | ngx_free(host); |
1137 | 1059 | |
1138 | for (i = 0, rp = res; rp != NULL; rp = rp->ai_next) { | |
1060 | for (n = 0, rp = res; rp != NULL; rp = rp->ai_next) { | |
1139 | 1061 | |
1140 | 1062 | switch (rp->ai_family) { |
1141 | 1063 | |
1147 | 1069 | continue; |
1148 | 1070 | } |
1149 | 1071 | |
1150 | i++; | |
1151 | } | |
1152 | ||
1153 | if (i == 0) { | |
1072 | n++; | |
1073 | } | |
1074 | ||
1075 | if (n == 0) { | |
1154 | 1076 | u->err = "host not found"; |
1155 | 1077 | goto failed; |
1156 | 1078 | } |
1157 | 1079 | |
1158 | 1080 | /* MP: ngx_shared_palloc() */ |
1159 | 1081 | |
1160 | u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t)); | |
1161 | if (u->addrs == NULL) { | |
1162 | goto failed; | |
1163 | } | |
1164 | ||
1165 | u->naddrs = i; | |
1166 | ||
1167 | i = 0; | |
1168 | ||
1169 | 1082 | /* AF_INET addresses first */ |
1170 | 1083 | |
1171 | 1084 | for (rp = res; rp != NULL; rp = rp->ai_next) { |
1174 | 1087 | continue; |
1175 | 1088 | } |
1176 | 1089 | |
1177 | sin = ngx_pcalloc(pool, rp->ai_addrlen); | |
1178 | if (sin == NULL) { | |
1090 | if (ngx_inet_add_addr(pool, u, rp->ai_addr, rp->ai_addrlen, n) | |
1091 | != NGX_OK) | |
1092 | { | |
1179 | 1093 | goto failed; |
1180 | 1094 | } |
1181 | ||
1182 | ngx_memcpy(sin, rp->ai_addr, rp->ai_addrlen); | |
1183 | ||
1184 | sin->sin_port = port; | |
1185 | ||
1186 | u->addrs[i].sockaddr = (struct sockaddr *) sin; | |
1187 | u->addrs[i].socklen = rp->ai_addrlen; | |
1188 | ||
1189 | len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; | |
1190 | ||
1191 | p = ngx_pnalloc(pool, len); | |
1192 | if (p == NULL) { | |
1193 | goto failed; | |
1194 | } | |
1195 | ||
1196 | len = ngx_sock_ntop((struct sockaddr *) sin, rp->ai_addrlen, p, len, 1); | |
1197 | ||
1198 | u->addrs[i].name.len = len; | |
1199 | u->addrs[i].name.data = p; | |
1200 | ||
1201 | i++; | |
1202 | 1095 | } |
1203 | 1096 | |
1204 | 1097 | for (rp = res; rp != NULL; rp = rp->ai_next) { |
1207 | 1100 | continue; |
1208 | 1101 | } |
1209 | 1102 | |
1210 | sin6 = ngx_pcalloc(pool, rp->ai_addrlen); | |
1211 | if (sin6 == NULL) { | |
1103 | if (ngx_inet_add_addr(pool, u, rp->ai_addr, rp->ai_addrlen, n) | |
1104 | != NGX_OK) | |
1105 | { | |
1212 | 1106 | goto failed; |
1213 | 1107 | } |
1214 | ||
1215 | ngx_memcpy(sin6, rp->ai_addr, rp->ai_addrlen); | |
1216 | ||
1217 | sin6->sin6_port = port; | |
1218 | ||
1219 | u->addrs[i].sockaddr = (struct sockaddr *) sin6; | |
1220 | u->addrs[i].socklen = rp->ai_addrlen; | |
1221 | ||
1222 | len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1; | |
1223 | ||
1224 | p = ngx_pnalloc(pool, len); | |
1225 | if (p == NULL) { | |
1226 | goto failed; | |
1227 | } | |
1228 | ||
1229 | len = ngx_sock_ntop((struct sockaddr *) sin6, rp->ai_addrlen, p, | |
1230 | len, 1); | |
1231 | ||
1232 | u->addrs[i].name.len = len; | |
1233 | u->addrs[i].name.data = p; | |
1234 | ||
1235 | i++; | |
1236 | 1108 | } |
1237 | 1109 | |
1238 | 1110 | freeaddrinfo(res); |
1249 | 1121 | ngx_int_t |
1250 | 1122 | ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u) |
1251 | 1123 | { |
1252 | u_char *p, *host; | |
1253 | size_t len; | |
1254 | in_port_t port; | |
1255 | in_addr_t in_addr; | |
1256 | ngx_uint_t i; | |
1124 | u_char *host; | |
1125 | ngx_uint_t i, n; | |
1257 | 1126 | struct hostent *h; |
1258 | struct sockaddr_in *sin; | |
1127 | struct sockaddr_in sin; | |
1259 | 1128 | |
1260 | 1129 | /* AF_INET only */ |
1261 | 1130 | |
1262 | port = htons(u->port); | |
1263 | ||
1264 | in_addr = ngx_inet_addr(u->host.data, u->host.len); | |
1265 | ||
1266 | if (in_addr == INADDR_NONE) { | |
1131 | ngx_memzero(&sin, sizeof(struct sockaddr_in)); | |
1132 | ||
1133 | sin.sin_family = AF_INET; | |
1134 | sin.sin_addr.s_addr = ngx_inet_addr(u->host.data, u->host.len); | |
1135 | ||
1136 | if (sin.sin_addr.s_addr == INADDR_NONE) { | |
1267 | 1137 | host = ngx_alloc(u->host.len + 1, pool->log); |
1268 | 1138 | if (host == NULL) { |
1269 | 1139 | return NGX_ERROR; |
1280 | 1150 | return NGX_ERROR; |
1281 | 1151 | } |
1282 | 1152 | |
1283 | for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ } | |
1153 | for (n = 0; h->h_addr_list[n] != NULL; n++) { /* void */ } | |
1284 | 1154 | |
1285 | 1155 | /* MP: ngx_shared_palloc() */ |
1286 | 1156 | |
1287 | u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t)); | |
1157 | for (i = 0; i < n; i++) { | |
1158 | sin.sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]); | |
1159 | ||
1160 | if (ngx_inet_add_addr(pool, u, (struct sockaddr *) &sin, | |
1161 | sizeof(struct sockaddr_in), n) | |
1162 | != NGX_OK) | |
1163 | { | |
1164 | return NGX_ERROR; | |
1165 | } | |
1166 | } | |
1167 | ||
1168 | } else { | |
1169 | ||
1170 | /* MP: ngx_shared_palloc() */ | |
1171 | ||
1172 | if (ngx_inet_add_addr(pool, u, (struct sockaddr *) &sin, | |
1173 | sizeof(struct sockaddr_in), 1) | |
1174 | != NGX_OK) | |
1175 | { | |
1176 | return NGX_ERROR; | |
1177 | } | |
1178 | } | |
1179 | ||
1180 | return NGX_OK; | |
1181 | } | |
1182 | ||
1183 | #endif /* NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6 */ | |
1184 | ||
1185 | ||
1186 | static ngx_int_t | |
1187 | ngx_inet_add_addr(ngx_pool_t *pool, ngx_url_t *u, struct sockaddr *sockaddr, | |
1188 | socklen_t socklen, ngx_uint_t total) | |
1189 | { | |
1190 | u_char *p; | |
1191 | size_t len; | |
1192 | ngx_addr_t *addr; | |
1193 | struct sockaddr *sa; | |
1194 | ||
1195 | if (u->addrs == NULL) { | |
1196 | u->addrs = ngx_palloc(pool, total * sizeof(ngx_addr_t)); | |
1288 | 1197 | if (u->addrs == NULL) { |
1289 | 1198 | return NGX_ERROR; |
1290 | 1199 | } |
1291 | ||
1292 | u->naddrs = i; | |
1293 | ||
1294 | for (i = 0; i < u->naddrs; i++) { | |
1295 | ||
1296 | sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in)); | |
1297 | if (sin == NULL) { | |
1298 | return NGX_ERROR; | |
1299 | } | |
1300 | ||
1301 | sin->sin_family = AF_INET; | |
1302 | sin->sin_port = port; | |
1303 | sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]); | |
1304 | ||
1305 | u->addrs[i].sockaddr = (struct sockaddr *) sin; | |
1306 | u->addrs[i].socklen = sizeof(struct sockaddr_in); | |
1307 | ||
1308 | len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; | |
1309 | ||
1310 | p = ngx_pnalloc(pool, len); | |
1311 | if (p == NULL) { | |
1312 | return NGX_ERROR; | |
1313 | } | |
1314 | ||
1315 | len = ngx_sock_ntop((struct sockaddr *) sin, | |
1316 | sizeof(struct sockaddr_in), p, len, 1); | |
1317 | ||
1318 | u->addrs[i].name.len = len; | |
1319 | u->addrs[i].name.data = p; | |
1320 | } | |
1321 | ||
1322 | } else { | |
1323 | ||
1324 | /* MP: ngx_shared_palloc() */ | |
1325 | ||
1326 | u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t)); | |
1327 | if (u->addrs == NULL) { | |
1328 | return NGX_ERROR; | |
1329 | } | |
1330 | ||
1331 | sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in)); | |
1332 | if (sin == NULL) { | |
1333 | return NGX_ERROR; | |
1334 | } | |
1335 | ||
1336 | u->naddrs = 1; | |
1337 | ||
1338 | sin->sin_family = AF_INET; | |
1339 | sin->sin_port = port; | |
1340 | sin->sin_addr.s_addr = in_addr; | |
1341 | ||
1342 | u->addrs[0].sockaddr = (struct sockaddr *) sin; | |
1343 | u->addrs[0].socklen = sizeof(struct sockaddr_in); | |
1344 | ||
1345 | p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1); | |
1346 | if (p == NULL) { | |
1347 | return NGX_ERROR; | |
1348 | } | |
1349 | ||
1350 | u->addrs[0].name.len = ngx_sprintf(p, "%V:%d", | |
1351 | &u->host, ntohs(port)) - p; | |
1352 | u->addrs[0].name.data = p; | |
1353 | } | |
1200 | } | |
1201 | ||
1202 | sa = ngx_pcalloc(pool, socklen); | |
1203 | if (sa == NULL) { | |
1204 | return NGX_ERROR; | |
1205 | } | |
1206 | ||
1207 | ngx_memcpy(sa, sockaddr, socklen); | |
1208 | ||
1209 | ngx_inet_set_port(sa, u->port); | |
1210 | ||
1211 | switch (sa->sa_family) { | |
1212 | ||
1213 | #if (NGX_HAVE_INET6) | |
1214 | case AF_INET6: | |
1215 | len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65536") - 1; | |
1216 | break; | |
1217 | #endif | |
1218 | ||
1219 | default: /* AF_INET */ | |
1220 | len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; | |
1221 | } | |
1222 | ||
1223 | p = ngx_pnalloc(pool, len); | |
1224 | if (p == NULL) { | |
1225 | return NGX_ERROR; | |
1226 | } | |
1227 | ||
1228 | len = ngx_sock_ntop(sa, socklen, p, len, 1); | |
1229 | ||
1230 | addr = &u->addrs[u->naddrs++]; | |
1231 | ||
1232 | addr->sockaddr = sa; | |
1233 | addr->socklen = socklen; | |
1234 | ||
1235 | addr->name.len = len; | |
1236 | addr->name.data = p; | |
1354 | 1237 | |
1355 | 1238 | return NGX_OK; |
1356 | 1239 | } |
1357 | ||
1358 | #endif /* NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6 */ | |
1359 | 1240 | |
1360 | 1241 | |
1361 | 1242 | ngx_int_t |
1494 | 1375 | break; |
1495 | 1376 | } |
1496 | 1377 | } |
1378 | ||
1379 | ||
1380 | ngx_uint_t | |
1381 | ngx_inet_wildcard(struct sockaddr *sa) | |
1382 | { | |
1383 | struct sockaddr_in *sin; | |
1384 | #if (NGX_HAVE_INET6) | |
1385 | struct sockaddr_in6 *sin6; | |
1386 | #endif | |
1387 | ||
1388 | switch (sa->sa_family) { | |
1389 | ||
1390 | case AF_INET: | |
1391 | sin = (struct sockaddr_in *) sa; | |
1392 | ||
1393 | if (sin->sin_addr.s_addr == INADDR_ANY) { | |
1394 | return 1; | |
1395 | } | |
1396 | ||
1397 | break; | |
1398 | ||
1399 | #if (NGX_HAVE_INET6) | |
1400 | ||
1401 | case AF_INET6: | |
1402 | sin6 = (struct sockaddr_in6 *) sa; | |
1403 | ||
1404 | if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { | |
1405 | return 1; | |
1406 | } | |
1407 | ||
1408 | break; | |
1409 | ||
1410 | #endif | |
1411 | } | |
1412 | ||
1413 | return 0; | |
1414 | } |
124 | 124 | struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port); |
125 | 125 | in_port_t ngx_inet_get_port(struct sockaddr *sa); |
126 | 126 | void ngx_inet_set_port(struct sockaddr *sa, in_port_t port); |
127 | ngx_uint_t ngx_inet_wildcard(struct sockaddr *sa); | |
127 | 128 | |
128 | 129 | |
129 | 130 | #endif /* _NGX_INET_H_INCLUDED_ */ |
1156 | 1156 | } |
1157 | 1157 | } |
1158 | 1158 | |
1159 | sa = &lsopt->sockaddr.sockaddr; | |
1159 | sa = lsopt->sockaddr; | |
1160 | 1160 | p = ngx_inet_get_port(sa); |
1161 | 1161 | |
1162 | 1162 | port = cmcf->ports->elts; |
1208 | 1208 | |
1209 | 1209 | for (i = 0; i < port->addrs.nelts; i++) { |
1210 | 1210 | |
1211 | if (ngx_cmp_sockaddr(&lsopt->sockaddr.sockaddr, lsopt->socklen, | |
1212 | &addr[i].opt.sockaddr.sockaddr, | |
1211 | if (ngx_cmp_sockaddr(lsopt->sockaddr, lsopt->socklen, | |
1212 | addr[i].opt.sockaddr, | |
1213 | 1213 | addr[i].opt.socklen, 0) |
1214 | 1214 | != NGX_OK) |
1215 | 1215 | { |
1238 | 1238 | |
1239 | 1239 | if (addr[i].opt.set) { |
1240 | 1240 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
1241 | "duplicate listen options for %s", addr[i].opt.addr); | |
1241 | "duplicate listen options for %V", | |
1242 | &addr[i].opt.addr_text); | |
1242 | 1243 | return NGX_ERROR; |
1243 | 1244 | } |
1244 | 1245 | |
1251 | 1252 | |
1252 | 1253 | if (default_server) { |
1253 | 1254 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
1254 | "a duplicate default server for %s", addr[i].opt.addr); | |
1255 | "a duplicate default server for %V", | |
1256 | &addr[i].opt.addr_text); | |
1255 | 1257 | return NGX_ERROR; |
1256 | 1258 | } |
1257 | 1259 | |
1304 | 1306 | if (lsopt->http2 && lsopt->ssl) { |
1305 | 1307 | ngx_conf_log_error(NGX_LOG_WARN, cf, 0, |
1306 | 1308 | "nginx was built with OpenSSL that lacks ALPN " |
1307 | "and NPN support, HTTP/2 is not enabled for %s", | |
1308 | lsopt->addr); | |
1309 | "and NPN support, HTTP/2 is not enabled for %V", | |
1310 | &lsopt->addr_text); | |
1309 | 1311 | } |
1310 | 1312 | |
1311 | 1313 | #endif |
1353 | 1355 | for (i = 0; i < addr->servers.nelts; i++) { |
1354 | 1356 | if (server[i] == cscf) { |
1355 | 1357 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
1356 | "a duplicate listen %s", addr->opt.addr); | |
1358 | "a duplicate listen %V", | |
1359 | &addr->opt.addr_text); | |
1357 | 1360 | return NGX_ERROR; |
1358 | 1361 | } |
1359 | 1362 | } |
1470 | 1473 | |
1471 | 1474 | if (rc == NGX_DECLINED) { |
1472 | 1475 | ngx_log_error(NGX_LOG_EMERG, cf->log, 0, |
1473 | "invalid server name or wildcard \"%V\" on %s", | |
1474 | &name[n].name, addr->opt.addr); | |
1476 | "invalid server name or wildcard \"%V\" on %V", | |
1477 | &name[n].name, &addr->opt.addr_text); | |
1475 | 1478 | return NGX_ERROR; |
1476 | 1479 | } |
1477 | 1480 | |
1478 | 1481 | if (rc == NGX_BUSY) { |
1479 | 1482 | ngx_log_error(NGX_LOG_WARN, cf->log, 0, |
1480 | "conflicting server name \"%V\" on %s, ignored", | |
1481 | &name[n].name, addr->opt.addr); | |
1483 | "conflicting server name \"%V\" on %V, ignored", | |
1484 | &name[n].name, &addr->opt.addr_text); | |
1482 | 1485 | } |
1483 | 1486 | } |
1484 | 1487 | } |
1699 | 1702 | ngx_http_core_loc_conf_t *clcf; |
1700 | 1703 | ngx_http_core_srv_conf_t *cscf; |
1701 | 1704 | |
1702 | ls = ngx_create_listening(cf, &addr->opt.sockaddr.sockaddr, | |
1703 | addr->opt.socklen); | |
1705 | ls = ngx_create_listening(cf, addr->opt.sockaddr, addr->opt.socklen); | |
1704 | 1706 | if (ls == NULL) { |
1705 | 1707 | return NULL; |
1706 | 1708 | } |
1790 | 1792 | |
1791 | 1793 | for (i = 0; i < hport->naddrs; i++) { |
1792 | 1794 | |
1793 | sin = &addr[i].opt.sockaddr.sockaddr_in; | |
1795 | sin = (struct sockaddr_in *) addr[i].opt.sockaddr; | |
1794 | 1796 | addrs[i].addr = sin->sin_addr.s_addr; |
1795 | 1797 | addrs[i].conf.default_server = addr[i].default_server; |
1796 | 1798 | #if (NGX_HTTP_SSL) |
1855 | 1857 | |
1856 | 1858 | for (i = 0; i < hport->naddrs; i++) { |
1857 | 1859 | |
1858 | sin6 = &addr[i].opt.sockaddr.sockaddr_in6; | |
1860 | sin6 = (struct sockaddr_in6 *) addr[i].opt.sockaddr; | |
1859 | 1861 | addrs6[i].addr6 = sin6->sin6_addr; |
1860 | 1862 | addrs6[i].conf.default_server = addr[i].default_server; |
1861 | 1863 | #if (NGX_HTTP_SSL) |
2714 | 2714 | { |
2715 | 2715 | char *rv; |
2716 | 2716 | void *mconf; |
2717 | size_t len; | |
2718 | u_char *p; | |
2717 | 2719 | ngx_uint_t i; |
2718 | 2720 | ngx_conf_t pcf; |
2719 | 2721 | ngx_http_module_t *module; |
2801 | 2803 | if (rv == NGX_CONF_OK && !cscf->listen) { |
2802 | 2804 | ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t)); |
2803 | 2805 | |
2804 | sin = &lsopt.sockaddr.sockaddr_in; | |
2806 | p = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in)); | |
2807 | if (p == NULL) { | |
2808 | return NGX_CONF_ERROR; | |
2809 | } | |
2810 | ||
2811 | lsopt.sockaddr = (struct sockaddr *) p; | |
2812 | ||
2813 | sin = (struct sockaddr_in *) p; | |
2805 | 2814 | |
2806 | 2815 | sin->sin_family = AF_INET; |
2807 | 2816 | #if (NGX_WIN32) |
2824 | 2833 | #endif |
2825 | 2834 | lsopt.wildcard = 1; |
2826 | 2835 | |
2827 | (void) ngx_sock_ntop(&lsopt.sockaddr.sockaddr, lsopt.socklen, | |
2828 | lsopt.addr, NGX_SOCKADDR_STRLEN, 1); | |
2836 | len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; | |
2837 | ||
2838 | p = ngx_pnalloc(cf->pool, len); | |
2839 | if (p == NULL) { | |
2840 | return NGX_CONF_ERROR; | |
2841 | } | |
2842 | ||
2843 | lsopt.addr_text.data = p; | |
2844 | lsopt.addr_text.len = ngx_sock_ntop(lsopt.sockaddr, lsopt.socklen, p, | |
2845 | len, 1); | |
2829 | 2846 | |
2830 | 2847 | if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) { |
2831 | 2848 | return NGX_CONF_ERROR; |
3778 | 3795 | |
3779 | 3796 | ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t)); |
3780 | 3797 | |
3781 | ngx_memcpy(&lsopt.sockaddr.sockaddr, &u.sockaddr, u.socklen); | |
3782 | ||
3783 | lsopt.socklen = u.socklen; | |
3784 | 3798 | lsopt.backlog = NGX_LISTEN_BACKLOG; |
3785 | 3799 | lsopt.rcvbuf = -1; |
3786 | 3800 | lsopt.sndbuf = -1; |
3790 | 3804 | #if (NGX_HAVE_TCP_FASTOPEN) |
3791 | 3805 | lsopt.fastopen = -1; |
3792 | 3806 | #endif |
3793 | lsopt.wildcard = u.wildcard; | |
3794 | 3807 | #if (NGX_HAVE_INET6) |
3795 | 3808 | lsopt.ipv6only = 1; |
3796 | 3809 | #endif |
3797 | ||
3798 | (void) ngx_sock_ntop(&lsopt.sockaddr.sockaddr, lsopt.socklen, lsopt.addr, | |
3799 | NGX_SOCKADDR_STRLEN, 1); | |
3800 | 3810 | |
3801 | 3811 | for (n = 2; n < cf->args->nelts; n++) { |
3802 | 3812 | |
3922 | 3932 | |
3923 | 3933 | if (ngx_strncmp(value[n].data, "ipv6only=o", 10) == 0) { |
3924 | 3934 | #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) |
3925 | struct sockaddr *sa; | |
3926 | ||
3927 | sa = &lsopt.sockaddr.sockaddr; | |
3928 | ||
3929 | if (sa->sa_family == AF_INET6) { | |
3930 | ||
3931 | if (ngx_strcmp(&value[n].data[10], "n") == 0) { | |
3932 | lsopt.ipv6only = 1; | |
3933 | ||
3934 | } else if (ngx_strcmp(&value[n].data[10], "ff") == 0) { | |
3935 | lsopt.ipv6only = 0; | |
3936 | ||
3937 | } else { | |
3938 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
3939 | "invalid ipv6only flags \"%s\"", | |
3940 | &value[n].data[9]); | |
3941 | return NGX_CONF_ERROR; | |
3942 | } | |
3943 | ||
3944 | lsopt.set = 1; | |
3945 | lsopt.bind = 1; | |
3935 | if (ngx_strcmp(&value[n].data[10], "n") == 0) { | |
3936 | lsopt.ipv6only = 1; | |
3937 | ||
3938 | } else if (ngx_strcmp(&value[n].data[10], "ff") == 0) { | |
3939 | lsopt.ipv6only = 0; | |
3946 | 3940 | |
3947 | 3941 | } else { |
3948 | 3942 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
3949 | "ipv6only is not supported " | |
3950 | "on addr \"%s\", ignored", lsopt.addr); | |
3943 | "invalid ipv6only flags \"%s\"", | |
3944 | &value[n].data[9]); | |
3945 | return NGX_CONF_ERROR; | |
3951 | 3946 | } |
3947 | ||
3948 | lsopt.set = 1; | |
3949 | lsopt.bind = 1; | |
3952 | 3950 | |
3953 | 3951 | continue; |
3954 | 3952 | #else |
4105 | 4103 | return NGX_CONF_ERROR; |
4106 | 4104 | } |
4107 | 4105 | |
4108 | if (ngx_http_add_listen(cf, cscf, &lsopt) == NGX_OK) { | |
4109 | return NGX_CONF_OK; | |
4110 | } | |
4111 | ||
4112 | return NGX_CONF_ERROR; | |
4106 | for (n = 0; n < u.naddrs; n++) { | |
4107 | lsopt.sockaddr = u.addrs[n].sockaddr; | |
4108 | lsopt.socklen = u.addrs[n].socklen; | |
4109 | lsopt.addr_text = u.addrs[n].name; | |
4110 | lsopt.wildcard = ngx_inet_wildcard(lsopt.sockaddr); | |
4111 | ||
4112 | if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) { | |
4113 | return NGX_CONF_ERROR; | |
4114 | } | |
4115 | } | |
4116 | ||
4117 | return NGX_CONF_OK; | |
4113 | 4118 | } |
4114 | 4119 | |
4115 | 4120 |
64 | 64 | |
65 | 65 | |
66 | 66 | typedef struct { |
67 | ngx_sockaddr_t sockaddr; | |
67 | struct sockaddr *sockaddr; | |
68 | 68 | socklen_t socklen; |
69 | ngx_str_t addr_text; | |
69 | 70 | |
70 | 71 | unsigned set:1; |
71 | 72 | unsigned default_server:1; |
99 | 100 | #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) |
100 | 101 | char *accept_filter; |
101 | 102 | #endif |
102 | ||
103 | u_char addr[NGX_SOCKADDR_STRLEN + 1]; | |
104 | 103 | } ngx_http_listen_opt_t; |
105 | 104 | |
106 | 105 |
230 | 230 | ngx_mail_conf_port_t *port; |
231 | 231 | ngx_mail_conf_addr_t *addr; |
232 | 232 | |
233 | sa = &listen->sockaddr.sockaddr; | |
233 | sa = listen->sockaddr; | |
234 | 234 | p = ngx_inet_get_port(sa); |
235 | 235 | |
236 | 236 | port = ports->elts; |
315 | 315 | continue; |
316 | 316 | } |
317 | 317 | |
318 | ls = ngx_create_listening(cf, &addr[i].opt.sockaddr.sockaddr, | |
318 | ls = ngx_create_listening(cf, addr[i].opt.sockaddr, | |
319 | 319 | addr[i].opt.socklen); |
320 | 320 | if (ls == NULL) { |
321 | 321 | return NGX_CONF_ERROR; |
383 | 383 | ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport, |
384 | 384 | ngx_mail_conf_addr_t *addr) |
385 | 385 | { |
386 | u_char *p; | |
387 | size_t len; | |
388 | 386 | ngx_uint_t i; |
389 | 387 | ngx_mail_in_addr_t *addrs; |
390 | 388 | struct sockaddr_in *sin; |
391 | u_char buf[NGX_SOCKADDR_STRLEN]; | |
392 | 389 | |
393 | 390 | mport->addrs = ngx_pcalloc(cf->pool, |
394 | 391 | mport->naddrs * sizeof(ngx_mail_in_addr_t)); |
400 | 397 | |
401 | 398 | for (i = 0; i < mport->naddrs; i++) { |
402 | 399 | |
403 | sin = &addr[i].opt.sockaddr.sockaddr_in; | |
400 | sin = (struct sockaddr_in *) addr[i].opt.sockaddr; | |
404 | 401 | addrs[i].addr = sin->sin_addr.s_addr; |
405 | 402 | |
406 | 403 | addrs[i].conf.ctx = addr[i].opt.ctx; |
407 | 404 | #if (NGX_MAIL_SSL) |
408 | 405 | addrs[i].conf.ssl = addr[i].opt.ssl; |
409 | 406 | #endif |
410 | ||
411 | len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, | |
412 | buf, NGX_SOCKADDR_STRLEN, 1); | |
413 | ||
414 | p = ngx_pnalloc(cf->pool, len); | |
415 | if (p == NULL) { | |
416 | return NGX_ERROR; | |
417 | } | |
418 | ||
419 | ngx_memcpy(p, buf, len); | |
420 | ||
421 | addrs[i].conf.addr_text.len = len; | |
422 | addrs[i].conf.addr_text.data = p; | |
407 | addrs[i].conf.addr_text = addr[i].opt.addr_text; | |
423 | 408 | } |
424 | 409 | |
425 | 410 | return NGX_OK; |
432 | 417 | ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport, |
433 | 418 | ngx_mail_conf_addr_t *addr) |
434 | 419 | { |
435 | u_char *p; | |
436 | size_t len; | |
437 | 420 | ngx_uint_t i; |
438 | 421 | ngx_mail_in6_addr_t *addrs6; |
439 | 422 | struct sockaddr_in6 *sin6; |
440 | u_char buf[NGX_SOCKADDR_STRLEN]; | |
441 | 423 | |
442 | 424 | mport->addrs = ngx_pcalloc(cf->pool, |
443 | 425 | mport->naddrs * sizeof(ngx_mail_in6_addr_t)); |
449 | 431 | |
450 | 432 | for (i = 0; i < mport->naddrs; i++) { |
451 | 433 | |
452 | sin6 = &addr[i].opt.sockaddr.sockaddr_in6; | |
434 | sin6 = (struct sockaddr_in6 *) addr[i].opt.sockaddr; | |
453 | 435 | addrs6[i].addr6 = sin6->sin6_addr; |
454 | 436 | |
455 | 437 | addrs6[i].conf.ctx = addr[i].opt.ctx; |
456 | 438 | #if (NGX_MAIL_SSL) |
457 | 439 | addrs6[i].conf.ssl = addr[i].opt.ssl; |
458 | 440 | #endif |
459 | ||
460 | len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, | |
461 | buf, NGX_SOCKADDR_STRLEN, 1); | |
462 | ||
463 | p = ngx_pnalloc(cf->pool, len); | |
464 | if (p == NULL) { | |
465 | return NGX_ERROR; | |
466 | } | |
467 | ||
468 | ngx_memcpy(p, buf, len); | |
469 | ||
470 | addrs6[i].conf.addr_text.len = len; | |
471 | addrs6[i].conf.addr_text.data = p; | |
441 | addrs6[i].conf.addr_text = addr[i].opt.addr_text; | |
472 | 442 | } |
473 | 443 | |
474 | 444 | return NGX_OK; |
26 | 26 | |
27 | 27 | |
28 | 28 | typedef struct { |
29 | ngx_sockaddr_t sockaddr; | |
29 | struct sockaddr *sockaddr; | |
30 | 30 | socklen_t socklen; |
31 | ngx_str_t addr_text; | |
31 | 32 | |
32 | 33 | /* server ctx */ |
33 | 34 | ngx_mail_conf_ctx_t *ctx; |
296 | 296 | |
297 | 297 | ngx_str_t *value, size; |
298 | 298 | ngx_url_t u; |
299 | ngx_uint_t i, m; | |
300 | ngx_mail_listen_t *ls; | |
299 | ngx_uint_t i, n, m; | |
300 | ngx_mail_listen_t *ls, *als; | |
301 | 301 | ngx_mail_module_t *module; |
302 | 302 | ngx_mail_core_main_conf_t *cmcf; |
303 | 303 | |
322 | 322 | |
323 | 323 | cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module); |
324 | 324 | |
325 | ls = cmcf->listen.elts; | |
326 | ||
327 | for (i = 0; i < cmcf->listen.nelts; i++) { | |
328 | ||
329 | if (ngx_cmp_sockaddr(&ls[i].sockaddr.sockaddr, ls[i].socklen, | |
330 | (struct sockaddr *) &u.sockaddr, u.socklen, 1) | |
331 | != NGX_OK) | |
332 | { | |
333 | continue; | |
334 | } | |
335 | ||
336 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
337 | "duplicate \"%V\" address and port pair", &u.url); | |
338 | return NGX_CONF_ERROR; | |
339 | } | |
340 | ||
341 | ls = ngx_array_push(&cmcf->listen); | |
325 | ls = ngx_array_push_n(&cmcf->listen, u.naddrs); | |
342 | 326 | if (ls == NULL) { |
343 | 327 | return NGX_CONF_ERROR; |
344 | 328 | } |
345 | 329 | |
346 | 330 | ngx_memzero(ls, sizeof(ngx_mail_listen_t)); |
347 | 331 | |
348 | ngx_memcpy(&ls->sockaddr.sockaddr, &u.sockaddr, u.socklen); | |
349 | ||
350 | ls->socklen = u.socklen; | |
351 | 332 | ls->backlog = NGX_LISTEN_BACKLOG; |
352 | 333 | ls->rcvbuf = -1; |
353 | 334 | ls->sndbuf = -1; |
354 | ls->wildcard = u.wildcard; | |
355 | 335 | ls->ctx = cf->ctx; |
356 | 336 | |
357 | 337 | #if (NGX_HAVE_INET6) |
433 | 413 | |
434 | 414 | if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { |
435 | 415 | #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) |
436 | size_t len; | |
437 | u_char buf[NGX_SOCKADDR_STRLEN]; | |
438 | ||
439 | if (ls->sockaddr.sockaddr.sa_family == AF_INET6) { | |
440 | ||
441 | if (ngx_strcmp(&value[i].data[10], "n") == 0) { | |
442 | ls->ipv6only = 1; | |
443 | ||
444 | } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { | |
445 | ls->ipv6only = 0; | |
446 | ||
447 | } else { | |
448 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
449 | "invalid ipv6only flags \"%s\"", | |
450 | &value[i].data[9]); | |
451 | return NGX_CONF_ERROR; | |
452 | } | |
453 | ||
454 | ls->bind = 1; | |
416 | if (ngx_strcmp(&value[i].data[10], "n") == 0) { | |
417 | ls->ipv6only = 1; | |
418 | ||
419 | } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { | |
420 | ls->ipv6only = 0; | |
455 | 421 | |
456 | 422 | } else { |
457 | len = ngx_sock_ntop(&ls->sockaddr.sockaddr, ls->socklen, buf, | |
458 | NGX_SOCKADDR_STRLEN, 1); | |
459 | ||
460 | 423 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
461 | "ipv6only is not supported " | |
462 | "on addr \"%*s\", ignored", len, buf); | |
463 | } | |
464 | ||
424 | "invalid ipv6only flags \"%s\"", | |
425 | &value[i].data[9]); | |
426 | return NGX_CONF_ERROR; | |
427 | } | |
428 | ||
429 | ls->bind = 1; | |
465 | 430 | continue; |
466 | 431 | #else |
467 | 432 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
587 | 552 | return NGX_CONF_ERROR; |
588 | 553 | } |
589 | 554 | |
555 | als = cmcf->listen.elts; | |
556 | ||
557 | for (n = 0; n < u.naddrs; n++) { | |
558 | ls[n] = ls[0]; | |
559 | ||
560 | ls[n].sockaddr = u.addrs[n].sockaddr; | |
561 | ls[n].socklen = u.addrs[n].socklen; | |
562 | ls[n].addr_text = u.addrs[n].name; | |
563 | ls[n].wildcard = ngx_inet_wildcard(ls[n].sockaddr); | |
564 | ||
565 | for (i = 0; i < cmcf->listen.nelts - u.naddrs + n; i++) { | |
566 | ||
567 | if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen, | |
568 | ls[n].sockaddr, ls[n].socklen, 1) | |
569 | != NGX_OK) | |
570 | { | |
571 | continue; | |
572 | } | |
573 | ||
574 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
575 | "duplicate \"%V\" address and port pair", | |
576 | &ls[n].addr_text); | |
577 | return NGX_CONF_ERROR; | |
578 | } | |
579 | } | |
580 | ||
590 | 581 | return NGX_CONF_OK; |
591 | 582 | } |
592 | 583 |
386 | 386 | ngx_stream_conf_port_t *port; |
387 | 387 | ngx_stream_conf_addr_t *addr; |
388 | 388 | |
389 | sa = &listen->sockaddr.sockaddr; | |
389 | sa = listen->sockaddr; | |
390 | 390 | p = ngx_inet_get_port(sa); |
391 | 391 | |
392 | 392 | port = ports->elts; |
475 | 475 | continue; |
476 | 476 | } |
477 | 477 | |
478 | ls = ngx_create_listening(cf, &addr[i].opt.sockaddr.sockaddr, | |
478 | ls = ngx_create_listening(cf, addr[i].opt.sockaddr, | |
479 | 479 | addr[i].opt.socklen); |
480 | 480 | if (ls == NULL) { |
481 | 481 | return NGX_CONF_ERROR; |
550 | 550 | ngx_stream_add_addrs(ngx_conf_t *cf, ngx_stream_port_t *stport, |
551 | 551 | ngx_stream_conf_addr_t *addr) |
552 | 552 | { |
553 | u_char *p; | |
554 | size_t len; | |
555 | 553 | ngx_uint_t i; |
556 | 554 | struct sockaddr_in *sin; |
557 | 555 | ngx_stream_in_addr_t *addrs; |
558 | u_char buf[NGX_SOCKADDR_STRLEN]; | |
559 | 556 | |
560 | 557 | stport->addrs = ngx_pcalloc(cf->pool, |
561 | 558 | stport->naddrs * sizeof(ngx_stream_in_addr_t)); |
567 | 564 | |
568 | 565 | for (i = 0; i < stport->naddrs; i++) { |
569 | 566 | |
570 | sin = &addr[i].opt.sockaddr.sockaddr_in; | |
567 | sin = (struct sockaddr_in *) addr[i].opt.sockaddr; | |
571 | 568 | addrs[i].addr = sin->sin_addr.s_addr; |
572 | 569 | |
573 | 570 | addrs[i].conf.ctx = addr[i].opt.ctx; |
575 | 572 | addrs[i].conf.ssl = addr[i].opt.ssl; |
576 | 573 | #endif |
577 | 574 | addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; |
578 | ||
579 | len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, | |
580 | buf, NGX_SOCKADDR_STRLEN, 1); | |
581 | ||
582 | p = ngx_pnalloc(cf->pool, len); | |
583 | if (p == NULL) { | |
584 | return NGX_ERROR; | |
585 | } | |
586 | ||
587 | ngx_memcpy(p, buf, len); | |
588 | ||
589 | addrs[i].conf.addr_text.len = len; | |
590 | addrs[i].conf.addr_text.data = p; | |
575 | addrs[i].conf.addr_text = addr[i].opt.addr_text; | |
591 | 576 | } |
592 | 577 | |
593 | 578 | return NGX_OK; |
600 | 585 | ngx_stream_add_addrs6(ngx_conf_t *cf, ngx_stream_port_t *stport, |
601 | 586 | ngx_stream_conf_addr_t *addr) |
602 | 587 | { |
603 | u_char *p; | |
604 | size_t len; | |
605 | 588 | ngx_uint_t i; |
606 | 589 | struct sockaddr_in6 *sin6; |
607 | 590 | ngx_stream_in6_addr_t *addrs6; |
608 | u_char buf[NGX_SOCKADDR_STRLEN]; | |
609 | 591 | |
610 | 592 | stport->addrs = ngx_pcalloc(cf->pool, |
611 | 593 | stport->naddrs * sizeof(ngx_stream_in6_addr_t)); |
617 | 599 | |
618 | 600 | for (i = 0; i < stport->naddrs; i++) { |
619 | 601 | |
620 | sin6 = &addr[i].opt.sockaddr.sockaddr_in6; | |
602 | sin6 = (struct sockaddr_in6 *) addr[i].opt.sockaddr; | |
621 | 603 | addrs6[i].addr6 = sin6->sin6_addr; |
622 | 604 | |
623 | 605 | addrs6[i].conf.ctx = addr[i].opt.ctx; |
625 | 607 | addrs6[i].conf.ssl = addr[i].opt.ssl; |
626 | 608 | #endif |
627 | 609 | addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; |
628 | ||
629 | len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, | |
630 | buf, NGX_SOCKADDR_STRLEN, 1); | |
631 | ||
632 | p = ngx_pnalloc(cf->pool, len); | |
633 | if (p == NULL) { | |
634 | return NGX_ERROR; | |
635 | } | |
636 | ||
637 | ngx_memcpy(p, buf, len); | |
638 | ||
639 | addrs6[i].conf.addr_text.len = len; | |
640 | addrs6[i].conf.addr_text.data = p; | |
610 | addrs6[i].conf.addr_text = addr[i].opt.addr_text; | |
641 | 611 | } |
642 | 612 | |
643 | 613 | return NGX_OK; |
40 | 40 | |
41 | 41 | |
42 | 42 | typedef struct { |
43 | ngx_sockaddr_t sockaddr; | |
43 | struct sockaddr *sockaddr; | |
44 | 44 | socklen_t socklen; |
45 | ngx_str_t addr_text; | |
45 | 46 | |
46 | 47 | /* server ctx */ |
47 | 48 | ngx_stream_conf_ctx_t *ctx; |
576 | 576 | |
577 | 577 | ngx_str_t *value, size; |
578 | 578 | ngx_url_t u; |
579 | ngx_uint_t i, backlog; | |
579 | ngx_uint_t i, n, backlog; | |
580 | 580 | ngx_stream_listen_t *ls, *als; |
581 | 581 | ngx_stream_core_main_conf_t *cmcf; |
582 | 582 | |
601 | 601 | |
602 | 602 | cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); |
603 | 603 | |
604 | ls = ngx_array_push(&cmcf->listen); | |
604 | ls = ngx_array_push_n(&cmcf->listen, u.naddrs); | |
605 | 605 | if (ls == NULL) { |
606 | 606 | return NGX_CONF_ERROR; |
607 | 607 | } |
608 | 608 | |
609 | 609 | ngx_memzero(ls, sizeof(ngx_stream_listen_t)); |
610 | 610 | |
611 | ngx_memcpy(&ls->sockaddr.sockaddr, &u.sockaddr, u.socklen); | |
612 | ||
613 | ls->socklen = u.socklen; | |
614 | 611 | ls->backlog = NGX_LISTEN_BACKLOG; |
615 | 612 | ls->rcvbuf = -1; |
616 | 613 | ls->sndbuf = -1; |
617 | 614 | ls->type = SOCK_STREAM; |
618 | ls->wildcard = u.wildcard; | |
619 | 615 | ls->ctx = cf->ctx; |
620 | 616 | |
621 | 617 | #if (NGX_HAVE_INET6) |
687 | 683 | |
688 | 684 | if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { |
689 | 685 | #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) |
690 | size_t len; | |
691 | u_char buf[NGX_SOCKADDR_STRLEN]; | |
692 | ||
693 | if (ls->sockaddr.sockaddr.sa_family == AF_INET6) { | |
694 | ||
695 | if (ngx_strcmp(&value[i].data[10], "n") == 0) { | |
696 | ls->ipv6only = 1; | |
697 | ||
698 | } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { | |
699 | ls->ipv6only = 0; | |
700 | ||
701 | } else { | |
702 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
703 | "invalid ipv6only flags \"%s\"", | |
704 | &value[i].data[9]); | |
705 | return NGX_CONF_ERROR; | |
706 | } | |
707 | ||
708 | ls->bind = 1; | |
686 | if (ngx_strcmp(&value[i].data[10], "n") == 0) { | |
687 | ls->ipv6only = 1; | |
688 | ||
689 | } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { | |
690 | ls->ipv6only = 0; | |
709 | 691 | |
710 | 692 | } else { |
711 | len = ngx_sock_ntop(&ls->sockaddr.sockaddr, ls->socklen, buf, | |
712 | NGX_SOCKADDR_STRLEN, 1); | |
713 | ||
714 | 693 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
715 | "ipv6only is not supported " | |
716 | "on addr \"%*s\", ignored", len, buf); | |
694 | "invalid ipv6only flags \"%s\"", | |
695 | &value[i].data[9]); | |
696 | return NGX_CONF_ERROR; | |
717 | 697 | } |
718 | 698 | |
699 | ls->bind = 1; | |
719 | 700 | continue; |
720 | 701 | #else |
721 | 702 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
881 | 862 | |
882 | 863 | als = cmcf->listen.elts; |
883 | 864 | |
884 | for (i = 0; i < cmcf->listen.nelts - 1; i++) { | |
885 | if (ls->type != als[i].type) { | |
886 | continue; | |
887 | } | |
888 | ||
889 | if (ngx_cmp_sockaddr(&als[i].sockaddr.sockaddr, als[i].socklen, | |
890 | &ls->sockaddr.sockaddr, ls->socklen, 1) | |
891 | != NGX_OK) | |
892 | { | |
893 | continue; | |
894 | } | |
895 | ||
896 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
897 | "duplicate \"%V\" address and port pair", &u.url); | |
898 | return NGX_CONF_ERROR; | |
865 | for (n = 0; n < u.naddrs; n++) { | |
866 | ls[n] = ls[0]; | |
867 | ||
868 | ls[n].sockaddr = u.addrs[n].sockaddr; | |
869 | ls[n].socklen = u.addrs[n].socklen; | |
870 | ls[n].addr_text = u.addrs[n].name; | |
871 | ls[n].wildcard = ngx_inet_wildcard(ls[n].sockaddr); | |
872 | ||
873 | for (i = 0; i < cmcf->listen.nelts - u.naddrs + n; i++) { | |
874 | if (ls[n].type != als[i].type) { | |
875 | continue; | |
876 | } | |
877 | ||
878 | if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen, | |
879 | ls[n].sockaddr, ls[n].socklen, 1) | |
880 | != NGX_OK) | |
881 | { | |
882 | continue; | |
883 | } | |
884 | ||
885 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
886 | "duplicate \"%V\" address and port pair", | |
887 | &ls[n].addr_text); | |
888 | return NGX_CONF_ERROR; | |
889 | } | |
899 | 890 | } |
900 | 891 | |
901 | 892 | return NGX_CONF_OK; |