Listen port ranges.
A range is specified with a dash. For each port in a range a separate listen
socket is created.
Examples:
listen 8080-9000;
listen example.com:80-88;
Roman Arutyunyan
3 years ago
781 | 781 | static ngx_int_t |
782 | 782 | ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u) |
783 | 783 | { |
784 | u_char *host, *port, *last, *uri, *args; | |
784 | u_char *host, *port, *last, *uri, *args, *dash; | |
785 | 785 | size_t len; |
786 | 786 | ngx_int_t n; |
787 | 787 | struct sockaddr_in *sin; |
829 | 829 | |
830 | 830 | len = last - port; |
831 | 831 | |
832 | if (u->listen) { | |
833 | dash = ngx_strlchr(port, last, '-'); | |
834 | ||
835 | if (dash) { | |
836 | dash++; | |
837 | ||
838 | n = ngx_atoi(dash, last - dash); | |
839 | ||
840 | if (n < 1 || n > 65535) { | |
841 | u->err = "invalid port"; | |
842 | return NGX_ERROR; | |
843 | } | |
844 | ||
845 | u->last_port = (in_port_t) n; | |
846 | ||
847 | len = dash - port - 1; | |
848 | } | |
849 | } | |
850 | ||
832 | 851 | n = ngx_atoi(port, len); |
833 | 852 | |
834 | 853 | if (n < 1 || n > 65535) { |
836 | 855 | return NGX_ERROR; |
837 | 856 | } |
838 | 857 | |
858 | if (u->last_port && n > u->last_port) { | |
859 | u->err = "invalid port range"; | |
860 | return NGX_ERROR; | |
861 | } | |
862 | ||
839 | 863 | u->port = (in_port_t) n; |
840 | 864 | sin->sin_port = htons((in_port_t) n); |
841 | 865 | |
842 | u->port_text.len = len; | |
866 | u->port_text.len = last - port; | |
843 | 867 | u->port_text.data = port; |
844 | 868 | |
845 | 869 | last = port - 1; |
851 | 875 | |
852 | 876 | /* test value as port only */ |
853 | 877 | |
854 | n = ngx_atoi(host, last - host); | |
878 | len = last - host; | |
879 | ||
880 | dash = ngx_strlchr(host, last, '-'); | |
881 | ||
882 | if (dash) { | |
883 | dash++; | |
884 | ||
885 | n = ngx_atoi(dash, last - dash); | |
886 | ||
887 | if (n == NGX_ERROR) { | |
888 | goto no_port; | |
889 | } | |
890 | ||
891 | if (n < 1 || n > 65535) { | |
892 | u->err = "invalid port"; | |
893 | ||
894 | } else { | |
895 | u->last_port = (in_port_t) n; | |
896 | } | |
897 | ||
898 | len = dash - host - 1; | |
899 | } | |
900 | ||
901 | n = ngx_atoi(host, len); | |
855 | 902 | |
856 | 903 | if (n != NGX_ERROR) { |
904 | ||
905 | if (u->err) { | |
906 | return NGX_ERROR; | |
907 | } | |
857 | 908 | |
858 | 909 | if (n < 1 || n > 65535) { |
859 | 910 | u->err = "invalid port"; |
860 | 911 | return NGX_ERROR; |
861 | 912 | } |
862 | 913 | |
914 | if (u->last_port && n > u->last_port) { | |
915 | u->err = "invalid port range"; | |
916 | return NGX_ERROR; | |
917 | } | |
918 | ||
863 | 919 | u->port = (in_port_t) n; |
864 | 920 | sin->sin_port = htons((in_port_t) n); |
865 | 921 | sin->sin_addr.s_addr = INADDR_ANY; |
875 | 931 | } |
876 | 932 | } |
877 | 933 | |
934 | no_port: | |
935 | ||
936 | u->err = NULL; | |
878 | 937 | u->no_port = 1; |
879 | 938 | u->port = u->default_port; |
880 | 939 | sin->sin_port = htons(u->default_port); |
940 | u->last_port = 0; | |
881 | 941 | } |
882 | 942 | |
883 | 943 | len = last - host; |
928 | 988 | ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u) |
929 | 989 | { |
930 | 990 | #if (NGX_HAVE_INET6) |
931 | u_char *p, *host, *port, *last, *uri; | |
991 | u_char *p, *host, *port, *last, *uri, *dash; | |
932 | 992 | size_t len; |
933 | 993 | ngx_int_t n; |
934 | 994 | struct sockaddr_in6 *sin6; |
974 | 1034 | |
975 | 1035 | len = last - port; |
976 | 1036 | |
1037 | if (u->listen) { | |
1038 | dash = ngx_strlchr(port, last, '-'); | |
1039 | ||
1040 | if (dash) { | |
1041 | dash++; | |
1042 | ||
1043 | n = ngx_atoi(dash, last - dash); | |
1044 | ||
1045 | if (n < 1 || n > 65535) { | |
1046 | u->err = "invalid port"; | |
1047 | return NGX_ERROR; | |
1048 | } | |
1049 | ||
1050 | u->last_port = (in_port_t) n; | |
1051 | ||
1052 | len = dash - port - 1; | |
1053 | } | |
1054 | } | |
1055 | ||
977 | 1056 | n = ngx_atoi(port, len); |
978 | 1057 | |
979 | 1058 | if (n < 1 || n > 65535) { |
981 | 1060 | return NGX_ERROR; |
982 | 1061 | } |
983 | 1062 | |
1063 | if (u->last_port && n > u->last_port) { | |
1064 | u->err = "invalid port range"; | |
1065 | return NGX_ERROR; | |
1066 | } | |
1067 | ||
984 | 1068 | u->port = (in_port_t) n; |
985 | 1069 | sin6->sin6_port = htons((in_port_t) n); |
986 | 1070 | |
987 | u->port_text.len = len; | |
1071 | u->port_text.len = last - port; | |
988 | 1072 | u->port_text.data = port; |
989 | 1073 | |
990 | 1074 | } else { |
1180 | 1264 | { |
1181 | 1265 | u_char *p; |
1182 | 1266 | size_t len; |
1267 | ngx_uint_t i, nports; | |
1183 | 1268 | ngx_addr_t *addr; |
1184 | 1269 | struct sockaddr *sa; |
1185 | 1270 | |
1271 | nports = u->last_port ? u->last_port - u->port + 1 : 1; | |
1272 | ||
1186 | 1273 | if (u->addrs == NULL) { |
1187 | u->addrs = ngx_palloc(pool, total * sizeof(ngx_addr_t)); | |
1274 | u->addrs = ngx_palloc(pool, total * nports * sizeof(ngx_addr_t)); | |
1188 | 1275 | if (u->addrs == NULL) { |
1189 | 1276 | return NGX_ERROR; |
1190 | 1277 | } |
1191 | 1278 | } |
1192 | 1279 | |
1193 | sa = ngx_pcalloc(pool, socklen); | |
1194 | if (sa == NULL) { | |
1195 | return NGX_ERROR; | |
1196 | } | |
1197 | ||
1198 | ngx_memcpy(sa, sockaddr, socklen); | |
1199 | ||
1200 | ngx_inet_set_port(sa, u->port); | |
1201 | ||
1202 | switch (sa->sa_family) { | |
1203 | ||
1204 | #if (NGX_HAVE_INET6) | |
1205 | case AF_INET6: | |
1206 | len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65536") - 1; | |
1207 | break; | |
1208 | #endif | |
1209 | ||
1210 | default: /* AF_INET */ | |
1211 | len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; | |
1212 | } | |
1213 | ||
1214 | p = ngx_pnalloc(pool, len); | |
1215 | if (p == NULL) { | |
1216 | return NGX_ERROR; | |
1217 | } | |
1218 | ||
1219 | len = ngx_sock_ntop(sa, socklen, p, len, 1); | |
1220 | ||
1221 | addr = &u->addrs[u->naddrs++]; | |
1222 | ||
1223 | addr->sockaddr = sa; | |
1224 | addr->socklen = socklen; | |
1225 | ||
1226 | addr->name.len = len; | |
1227 | addr->name.data = p; | |
1280 | for (i = 0; i < nports; i++) { | |
1281 | sa = ngx_pcalloc(pool, socklen); | |
1282 | if (sa == NULL) { | |
1283 | return NGX_ERROR; | |
1284 | } | |
1285 | ||
1286 | ngx_memcpy(sa, sockaddr, socklen); | |
1287 | ||
1288 | ngx_inet_set_port(sa, u->port + i); | |
1289 | ||
1290 | switch (sa->sa_family) { | |
1291 | ||
1292 | #if (NGX_HAVE_INET6) | |
1293 | case AF_INET6: | |
1294 | len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65536") - 1; | |
1295 | break; | |
1296 | #endif | |
1297 | ||
1298 | default: /* AF_INET */ | |
1299 | len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; | |
1300 | } | |
1301 | ||
1302 | p = ngx_pnalloc(pool, len); | |
1303 | if (p == NULL) { | |
1304 | return NGX_ERROR; | |
1305 | } | |
1306 | ||
1307 | len = ngx_sock_ntop(sa, socklen, p, len, 1); | |
1308 | ||
1309 | addr = &u->addrs[u->naddrs++]; | |
1310 | ||
1311 | addr->sockaddr = sa; | |
1312 | addr->socklen = socklen; | |
1313 | ||
1314 | addr->name.len = len; | |
1315 | addr->name.data = p; | |
1316 | } | |
1228 | 1317 | |
1229 | 1318 | return NGX_OK; |
1230 | 1319 | } |