comparison src/core/ngx_inet.c @ 7480:d9c3917c7f90

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