diff options
author | Ron Yorston <rmy@pobox.com> | 2021-09-10 14:47:27 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-09-10 14:47:27 +0100 |
commit | 3eb1d088e09db204f456ad7b76eced21e429f001 (patch) | |
tree | a81b5bb422db5ee97475a8f1a4b5236442ed6f14 /networking | |
parent | 12bc40da28f85cbe97673671f315f847f1dbbabf (diff) | |
parent | 40f2dd7dd2e50c9d81dda4d72bf9c85c4c479a89 (diff) | |
download | busybox-w32-3eb1d088e09db204f456ad7b76eced21e429f001.tar.gz busybox-w32-3eb1d088e09db204f456ad7b76eced21e429f001.tar.bz2 busybox-w32-3eb1d088e09db204f456ad7b76eced21e429f001.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'networking')
-rw-r--r-- | networking/ftpgetput.c | 3 | ||||
-rw-r--r-- | networking/httpd.c | 13 | ||||
-rw-r--r-- | networking/nc.c | 2 | ||||
-rw-r--r-- | networking/nc_bloaty.c | 7 | ||||
-rw-r--r-- | networking/telnetd.c | 10 | ||||
-rw-r--r-- | networking/udhcp/common.h | 31 | ||||
-rw-r--r-- | networking/udhcp/dhcpd.c | 35 | ||||
-rw-r--r-- | networking/udhcp/dhcprelay.c | 63 |
8 files changed, 112 insertions, 52 deletions
diff --git a/networking/ftpgetput.c b/networking/ftpgetput.c index f1d5ca571..ef0973a84 100644 --- a/networking/ftpgetput.c +++ b/networking/ftpgetput.c | |||
@@ -296,8 +296,7 @@ static const char ftpgetput_longopts[] ALIGN1 = | |||
296 | int ftpgetput_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 296 | int ftpgetput_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
297 | int ftpgetput_main(int argc UNUSED_PARAM, char **argv) | 297 | int ftpgetput_main(int argc UNUSED_PARAM, char **argv) |
298 | { | 298 | { |
299 | const char *port = "ftp"; | 299 | const char *port = NULL; |
300 | /* socket to ftp server */ | ||
301 | 300 | ||
302 | #if ENABLE_FTPPUT && !ENABLE_FTPGET | 301 | #if ENABLE_FTPPUT && !ENABLE_FTPGET |
303 | # define ftp_action ftp_send | 302 | # define ftp_action ftp_send |
diff --git a/networking/httpd.c b/networking/httpd.c index fcd1627b1..71e3a723f 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -102,6 +102,12 @@ | |||
102 | //config: help | 102 | //config: help |
103 | //config: HTTP server. | 103 | //config: HTTP server. |
104 | //config: | 104 | //config: |
105 | //config:config FEATURE_HTTPD_PORT_DEFAULT | ||
106 | //config: int "Default port" | ||
107 | //config: default 80 | ||
108 | //config: range 1 65535 | ||
109 | //config: depends on HTTPD | ||
110 | //config: | ||
105 | //config:config FEATURE_HTTPD_RANGES | 111 | //config:config FEATURE_HTTPD_RANGES |
106 | //config: bool "Support 'Ranges:' header" | 112 | //config: bool "Support 'Ranges:' header" |
107 | //config: default y | 113 | //config: default y |
@@ -277,7 +283,7 @@ | |||
277 | //usage: ) | 283 | //usage: ) |
278 | //usage: "\n -f Don't daemonize" | 284 | //usage: "\n -f Don't daemonize" |
279 | //usage: "\n -v[v] Verbose" | 285 | //usage: "\n -v[v] Verbose" |
280 | //usage: "\n -p [IP:]PORT Bind to IP:PORT (default *:80)" | 286 | //usage: "\n -p [IP:]PORT Bind to IP:PORT (default *:"STR(CONFIG_FEATURE_HTTPD_PORT_DEFAULT)")" |
281 | //usage: IF_FEATURE_HTTPD_SETUID( | 287 | //usage: IF_FEATURE_HTTPD_SETUID( |
282 | //usage: "\n -u USER[:GRP] Set uid/gid after binding to port") | 288 | //usage: "\n -u USER[:GRP] Set uid/gid after binding to port") |
283 | //usage: IF_FEATURE_HTTPD_BASIC_AUTH( | 289 | //usage: IF_FEATURE_HTTPD_BASIC_AUTH( |
@@ -325,6 +331,9 @@ | |||
325 | 331 | ||
326 | static void send_REQUEST_TIMEOUT_and_exit(int sig) NORETURN; | 332 | static void send_REQUEST_TIMEOUT_and_exit(int sig) NORETURN; |
327 | 333 | ||
334 | #define STR1(s) #s | ||
335 | #define STR(s) STR1(s) | ||
336 | |||
328 | static const char DEFAULT_PATH_HTTPD_CONF[] ALIGN1 = "/etc"; | 337 | static const char DEFAULT_PATH_HTTPD_CONF[] ALIGN1 = "/etc"; |
329 | static const char HTTPD_CONF[] ALIGN1 = "httpd.conf"; | 338 | static const char HTTPD_CONF[] ALIGN1 = "httpd.conf"; |
330 | static const char HTTP_200[] ALIGN1 = "HTTP/1.1 200 OK\r\n"; | 339 | static const char HTTP_200[] ALIGN1 = "HTTP/1.1 200 OK\r\n"; |
@@ -551,7 +560,7 @@ enum { | |||
551 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | 560 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
552 | IF_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \ | 561 | IF_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \ |
553 | IF_FEATURE_HTTPD_RANGES(range_start = -1;) \ | 562 | IF_FEATURE_HTTPD_RANGES(range_start = -1;) \ |
554 | bind_addr_or_port = "80"; \ | 563 | bind_addr_or_port = STR(CONFIG_FEATURE_HTTPD_PORT_DEFAULT); \ |
555 | index_page = index_html; \ | 564 | index_page = index_html; \ |
556 | file_size = -1; \ | 565 | file_size = -1; \ |
557 | } while (0) | 566 | } while (0) |
diff --git a/networking/nc.c b/networking/nc.c index 3483edb01..5525e41f9 100644 --- a/networking/nc.c +++ b/networking/nc.c | |||
@@ -226,7 +226,7 @@ int nc_main(int argc, char **argv) | |||
226 | close(sfd); | 226 | close(sfd); |
227 | } else { | 227 | } else { |
228 | cfd = create_and_connect_stream_or_die(argv[0], | 228 | cfd = create_and_connect_stream_or_die(argv[0], |
229 | argv[1] ? bb_lookup_port(argv[1], "tcp", 0) : 0); | 229 | bb_lookup_port(argv[1], "tcp", 0)); |
230 | } | 230 | } |
231 | } | 231 | } |
232 | 232 | ||
diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c index 25b95246f..cfa133eae 100644 --- a/networking/nc_bloaty.c +++ b/networking/nc_bloaty.c | |||
@@ -813,8 +813,6 @@ int nc_main(int argc UNUSED_PARAM, char **argv) | |||
813 | //if (option_mask32 & OPT_o) /* hexdump log */ | 813 | //if (option_mask32 & OPT_o) /* hexdump log */ |
814 | if (option_mask32 & OPT_p) { /* local source port */ | 814 | if (option_mask32 & OPT_p) { /* local source port */ |
815 | o_lport = bb_lookup_port(str_p, o_udpmode ? "udp" : "tcp", 0); | 815 | o_lport = bb_lookup_port(str_p, o_udpmode ? "udp" : "tcp", 0); |
816 | if (!o_lport) | ||
817 | bb_error_msg_and_die("bad local port '%s'", str_p); | ||
818 | } | 816 | } |
819 | //if (option_mask32 & OPT_r) /* randomize various things */ | 817 | //if (option_mask32 & OPT_r) /* randomize various things */ |
820 | //if (option_mask32 & OPT_u) /* use UDP */ | 818 | //if (option_mask32 & OPT_u) /* use UDP */ |
@@ -827,9 +825,8 @@ int nc_main(int argc UNUSED_PARAM, char **argv) | |||
827 | 825 | ||
828 | if (argv[0]) { | 826 | if (argv[0]) { |
829 | themaddr = xhost2sockaddr(argv[0], | 827 | themaddr = xhost2sockaddr(argv[0], |
830 | argv[1] | 828 | bb_lookup_port(argv[1], o_udpmode ? "udp" : "tcp", 0) |
831 | ? bb_lookup_port(argv[1], o_udpmode ? "udp" : "tcp", 0) | 829 | ); |
832 | : 0); | ||
833 | } | 830 | } |
834 | 831 | ||
835 | /* create & bind network socket */ | 832 | /* create & bind network socket */ |
diff --git a/networking/telnetd.c b/networking/telnetd.c index de4d733f9..581da1924 100644 --- a/networking/telnetd.c +++ b/networking/telnetd.c | |||
@@ -68,6 +68,12 @@ | |||
68 | //config: help | 68 | //config: help |
69 | //config: Selecting this will make telnetd able to run standalone. | 69 | //config: Selecting this will make telnetd able to run standalone. |
70 | //config: | 70 | //config: |
71 | //config:config FEATURE_TELNETD_PORT_DEFAULT | ||
72 | //config: int "Default port" | ||
73 | //config: default 23 | ||
74 | //config: range 1 65535 | ||
75 | //config: depends on FEATURE_TELNETD_STANDALONE | ||
76 | //config: | ||
71 | //config:config FEATURE_TELNETD_INETD_WAIT | 77 | //config:config FEATURE_TELNETD_INETD_WAIT |
72 | //config: bool "Support -w SEC option (inetd wait mode)" | 78 | //config: bool "Support -w SEC option (inetd wait mode)" |
73 | //config: default y | 79 | //config: default y |
@@ -103,7 +109,7 @@ | |||
103 | //usage: "\n -K Close connection as soon as login exits" | 109 | //usage: "\n -K Close connection as soon as login exits" |
104 | //usage: "\n (normally wait until all programs close slave pty)" | 110 | //usage: "\n (normally wait until all programs close slave pty)" |
105 | //usage: IF_FEATURE_TELNETD_STANDALONE( | 111 | //usage: IF_FEATURE_TELNETD_STANDALONE( |
106 | //usage: "\n -p PORT Port to listen on" | 112 | //usage: "\n -p PORT Port to listen on. Default "STR(CONFIG_FEATURE_TELNETD_PORT_DEFAULT) |
107 | //usage: "\n -b ADDR[:PORT] Address to bind to" | 113 | //usage: "\n -b ADDR[:PORT] Address to bind to" |
108 | //usage: "\n -F Run in foreground" | 114 | //usage: "\n -F Run in foreground" |
109 | //usage: "\n -i Inetd mode" | 115 | //usage: "\n -i Inetd mode" |
@@ -708,7 +714,7 @@ int telnetd_main(int argc UNUSED_PARAM, char **argv) | |||
708 | } else { | 714 | } else { |
709 | master_fd = 0; | 715 | master_fd = 0; |
710 | if (!(opt & OPT_WAIT)) { | 716 | if (!(opt & OPT_WAIT)) { |
711 | unsigned portnbr = 23; | 717 | unsigned portnbr = CONFIG_FEATURE_TELNETD_PORT_DEFAULT; |
712 | if (opt & OPT_PORT) | 718 | if (opt & OPT_PORT) |
713 | portnbr = xatou16(opt_portnbr); | 719 | portnbr = xatou16(opt_portnbr); |
714 | master_fd = create_and_bind_stream_or_die(opt_bindaddr, portnbr); | 720 | master_fd = create_and_bind_stream_or_die(opt_bindaddr, portnbr); |
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index ca778dab8..e374771cb 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h | |||
@@ -38,13 +38,27 @@ struct dhcp_packet { | |||
38 | #define BROADCAST_FLAG 0x8000 /* "I need broadcast replies" */ | 38 | #define BROADCAST_FLAG 0x8000 /* "I need broadcast replies" */ |
39 | uint32_t ciaddr; /* client IP (if client is in BOUND, RENEW or REBINDING state) */ | 39 | uint32_t ciaddr; /* client IP (if client is in BOUND, RENEW or REBINDING state) */ |
40 | uint32_t yiaddr; /* 'your' (client) IP address */ | 40 | uint32_t yiaddr; /* 'your' (client) IP address */ |
41 | /* IP address of next server to use in bootstrap, returned in DHCPOFFER, DHCPACK by server */ | 41 | /* IP address of "next server" (usually meant to be an TFTP server) |
42 | * to use in bootstrap, returned in DHCPOFFER, DHCPACK by server: */ | ||
42 | uint32_t siaddr_nip; | 43 | uint32_t siaddr_nip; |
43 | uint32_t gateway_nip; /* aka 'giaddr': relay agent IP address */ | 44 | /* RFC 951 (BOOTP): "place my (server) IP address in the 'siaddr' field" |
45 | * (IOW: unconditionally, not just if we are also a TFTP server). | ||
46 | * DHCP servers don't have to do this, they add SERVER_ID option | ||
47 | * to their reply packets to let client identify lease-giving server. | ||
48 | */ | ||
49 | uint32_t gateway_nip; /* aka 'giaddr': relay agent IP address, else 0 */ | ||
44 | uint8_t chaddr[16]; /* link-layer client hardware address (MAC) */ | 50 | uint8_t chaddr[16]; /* link-layer client hardware address (MAC) */ |
45 | uint8_t sname[64]; /* server host name (ASCIZ) */ | 51 | uint8_t sname[64]; /* server host name (ASCIZ) */ |
52 | /* RFC 951 (BOOTP): "If the client wishes to restrict booting | ||
53 | * to a particular server name, it may place [it] in 'sname'" | ||
54 | */ | ||
46 | uint8_t file[128]; /* boot file name (ASCIZ) */ | 55 | uint8_t file[128]; /* boot file name (ASCIZ) */ |
47 | uint32_t cookie; /* fixed first four option bytes (99,130,83,99 dec) */ | 56 | /* RFC 951 (BOOTP): in client requests, "...can be a 'generic' name |
57 | * such as 'unix' or 'gateway'; this means 'boot the named program | ||
58 | * configured for my machine'" | ||
59 | */ | ||
60 | /* BOOTP fields end here, BOOTP says optional uint8_t vend[64] follows */ | ||
61 | uint32_t cookie; /* DHCP magic bytes: 99,130,83,99 decimal */ | ||
48 | uint8_t options[DHCP_OPTIONS_BUFSIZE + CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS]; | 62 | uint8_t options[DHCP_OPTIONS_BUFSIZE + CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS]; |
49 | }; | 63 | }; |
50 | #define DHCP_PKT_SNAME_LEN 64 | 64 | #define DHCP_PKT_SNAME_LEN 64 |
@@ -142,18 +156,21 @@ struct dhcp_scan_state { | |||
142 | //#define DHCP_NTP_SERVER 0x2a | 156 | //#define DHCP_NTP_SERVER 0x2a |
143 | //#define DHCP_WINS_SERVER 0x2c | 157 | //#define DHCP_WINS_SERVER 0x2c |
144 | #define DHCP_REQUESTED_IP 0x32 /* 50: sent by client if specific IP is wanted */ | 158 | #define DHCP_REQUESTED_IP 0x32 /* 50: sent by client if specific IP is wanted */ |
145 | #define DHCP_LEASE_TIME 0x33 /* 51: */ | 159 | #define DHCP_LEASE_TIME 0x33 /* 51: 32bit big-endian */ |
146 | #define DHCP_OPTION_OVERLOAD 0x34 /* 52: */ | 160 | #define DHCP_OPTION_OVERLOAD 0x34 /* 52: 1 byte */ |
147 | #define DHCP_MESSAGE_TYPE 0x35 /* 53: */ | 161 | #define DHCP_MESSAGE_TYPE 0x35 /* 53: 1 byte */ |
148 | #define DHCP_SERVER_ID 0x36 /* 54: server's IP */ | 162 | #define DHCP_SERVER_ID 0x36 /* 54: server's IP */ |
149 | #define DHCP_PARAM_REQ 0x37 /* 55: list of options client wants */ | 163 | #define DHCP_PARAM_REQ 0x37 /* 55: list of options client wants */ |
150 | //#define DHCP_ERR_MESSAGE 0x38 /* 56: error message when sending NAK etc */ | 164 | //#define DHCP_ERR_MESSAGE 0x38 /* 56: error message when sending NAK etc */ |
151 | #define DHCP_MAX_SIZE 0x39 /* 57: */ | 165 | #define DHCP_MAX_SIZE 0x39 /* 57: 16bit big-endian */ |
166 | // 0x3a /* 58: from server: renew time, 32bit big-endian */ | ||
167 | // 0x3b /* 59: from server: rebind time, 32bit big-endian */ | ||
152 | #define DHCP_VENDOR 0x3c /* 60: client's vendor (a string) */ | 168 | #define DHCP_VENDOR 0x3c /* 60: client's vendor (a string) */ |
153 | #define DHCP_CLIENT_ID 0x3d /* 61: by default client's MAC addr, but may be arbitrarily long */ | 169 | #define DHCP_CLIENT_ID 0x3d /* 61: by default client's MAC addr, but may be arbitrarily long */ |
154 | //#define DHCP_TFTP_SERVER_NAME 0x42 /* 66: same as 'sname' field */ | 170 | //#define DHCP_TFTP_SERVER_NAME 0x42 /* 66: same as 'sname' field */ |
155 | //#define DHCP_BOOT_FILE 0x43 /* 67: same as 'file' field */ | 171 | //#define DHCP_BOOT_FILE 0x43 /* 67: same as 'file' field */ |
156 | //#define DHCP_USER_CLASS 0x4d /* 77: RFC 3004. set of LASCII strings. "I am a printer" etc */ | 172 | //#define DHCP_USER_CLASS 0x4d /* 77: RFC 3004. set of LASCII strings. "I am a printer" etc */ |
173 | // 0x50 /* 80: rapid commit ("I'm ok with getting immediate ACK, not just OFFER"), 0 bytes */ | ||
157 | #define DHCP_FQDN 0x51 /* 81: client asks to update DNS to map its FQDN to its new IP */ | 174 | #define DHCP_FQDN 0x51 /* 81: client asks to update DNS to map its FQDN to its new IP */ |
158 | //#define DHCP_PCODE 0x64 /* 100: RFC 4833. IEEE 1003.1 TZ string */ | 175 | //#define DHCP_PCODE 0x64 /* 100: RFC 4833. IEEE 1003.1 TZ string */ |
159 | //#define DHCP_TCODE 0x65 /* 101: RFC 4833. Reference to the TZ database string */ | 176 | //#define DHCP_TCODE 0x65 /* 101: RFC 4833. Reference to the TZ database string */ |
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 91f70970a..0f5edb75c 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
@@ -27,7 +27,7 @@ | |||
27 | //kbuild:lib-$(CONFIG_FEATURE_UDHCP_RFC3397) += domain_codec.o | 27 | //kbuild:lib-$(CONFIG_FEATURE_UDHCP_RFC3397) += domain_codec.o |
28 | 28 | ||
29 | //usage:#define udhcpd_trivial_usage | 29 | //usage:#define udhcpd_trivial_usage |
30 | //usage: "[-fS] [-I ADDR]" IF_FEATURE_UDHCP_PORT(" [-P PORT]") " [CONFFILE]" | 30 | //usage: "[-fS] [-I ADDR] [-a MSEC]" IF_FEATURE_UDHCP_PORT(" [-P PORT]") " [CONFFILE]" |
31 | //usage:#define udhcpd_full_usage "\n\n" | 31 | //usage:#define udhcpd_full_usage "\n\n" |
32 | //usage: "DHCP server\n" | 32 | //usage: "DHCP server\n" |
33 | //usage: "\n -f Run in foreground" | 33 | //usage: "\n -f Run in foreground" |
@@ -451,6 +451,8 @@ static NOINLINE void read_config(const char *file) | |||
451 | 451 | ||
452 | server_data.start_ip = ntohl(server_data.start_ip); | 452 | server_data.start_ip = ntohl(server_data.start_ip); |
453 | server_data.end_ip = ntohl(server_data.end_ip); | 453 | server_data.end_ip = ntohl(server_data.end_ip); |
454 | if (server_data.start_ip > server_data.end_ip) | ||
455 | bb_error_msg_and_die("bad start/end IP range in %s", file); | ||
454 | } | 456 | } |
455 | 457 | ||
456 | static void write_leases(void) | 458 | static void write_leases(void) |
@@ -612,6 +614,10 @@ static void send_packet_to_relay(struct dhcp_packet *dhcp_pkt) | |||
612 | udhcp_send_kernel_packet(dhcp_pkt, | 614 | udhcp_send_kernel_packet(dhcp_pkt, |
613 | server_data.server_nip, SERVER_PORT, | 615 | server_data.server_nip, SERVER_PORT, |
614 | dhcp_pkt->gateway_nip, SERVER_PORT, | 616 | dhcp_pkt->gateway_nip, SERVER_PORT, |
617 | /* Yes, relay agents receive (and send) all their packets on SERVER_PORT, | ||
618 | * even those which are clients' requests and would normally | ||
619 | * (i.e. without relay) use CLIENT_PORT. See RFC 1542. | ||
620 | */ | ||
615 | server_data.interface); | 621 | server_data.interface); |
616 | } | 622 | } |
617 | 623 | ||
@@ -858,7 +864,6 @@ int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |||
858 | int udhcpd_main(int argc UNUSED_PARAM, char **argv) | 864 | int udhcpd_main(int argc UNUSED_PARAM, char **argv) |
859 | { | 865 | { |
860 | int server_socket = -1, retval; | 866 | int server_socket = -1, retval; |
861 | uint8_t *state; | ||
862 | unsigned timeout_end; | 867 | unsigned timeout_end; |
863 | unsigned num_ips; | 868 | unsigned num_ips; |
864 | unsigned opt; | 869 | unsigned opt; |
@@ -877,6 +882,12 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
877 | /* Setup the signal pipe on fds 3,4 - must be before openlog() */ | 882 | /* Setup the signal pipe on fds 3,4 - must be before openlog() */ |
878 | udhcp_sp_setup(); | 883 | udhcp_sp_setup(); |
879 | 884 | ||
885 | #define OPT_f (1 << 0) | ||
886 | #define OPT_S (1 << 1) | ||
887 | #define OPT_I (1 << 2) | ||
888 | #define OPT_v (1 << 3) | ||
889 | #define OPT_a (1 << 4) | ||
890 | #define OPT_P (1 << 5) | ||
880 | opt = getopt32(argv, "^" | 891 | opt = getopt32(argv, "^" |
881 | "fSI:va:"IF_FEATURE_UDHCP_PORT("P:") | 892 | "fSI:va:"IF_FEATURE_UDHCP_PORT("P:") |
882 | "\0" | 893 | "\0" |
@@ -887,24 +898,24 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
887 | , &str_a | 898 | , &str_a |
888 | IF_FEATURE_UDHCP_PORT(, &str_P) | 899 | IF_FEATURE_UDHCP_PORT(, &str_P) |
889 | IF_UDHCP_VERBOSE(, &dhcp_verbose) | 900 | IF_UDHCP_VERBOSE(, &dhcp_verbose) |
890 | ); | 901 | ); |
891 | if (!(opt & 1)) { /* no -f */ | 902 | if (!(opt & OPT_f)) { /* no -f */ |
892 | bb_daemonize_or_rexec(0, argv); | 903 | bb_daemonize_or_rexec(0, argv); |
893 | logmode = LOGMODE_NONE; | 904 | logmode = LOGMODE_NONE; |
894 | } | 905 | } |
895 | /* update argv after the possible vfork+exec in daemonize */ | 906 | /* update argv after the possible vfork+exec in daemonize */ |
896 | argv += optind; | 907 | argv += optind; |
897 | if (opt & 2) { /* -S */ | 908 | if (opt & OPT_S) { |
898 | openlog(applet_name, LOG_PID, LOG_DAEMON); | 909 | openlog(applet_name, LOG_PID, LOG_DAEMON); |
899 | logmode |= LOGMODE_SYSLOG; | 910 | logmode |= LOGMODE_SYSLOG; |
900 | } | 911 | } |
901 | if (opt & 4) { /* -I */ | 912 | if (opt & OPT_I) { |
902 | len_and_sockaddr *lsa = xhost_and_af2sockaddr(str_I, 0, AF_INET); | 913 | len_and_sockaddr *lsa = xhost_and_af2sockaddr(str_I, 0, AF_INET); |
903 | server_data.server_nip = lsa->u.sin.sin_addr.s_addr; | 914 | server_data.server_nip = lsa->u.sin.sin_addr.s_addr; |
904 | free(lsa); | 915 | free(lsa); |
905 | } | 916 | } |
906 | #if ENABLE_FEATURE_UDHCP_PORT | 917 | #if ENABLE_FEATURE_UDHCP_PORT |
907 | if (opt & 32) { /* -P */ | 918 | if (opt & OPT_P) { |
908 | SERVER_PORT = xatou16(str_P); | 919 | SERVER_PORT = xatou16(str_P); |
909 | CLIENT_PORT = SERVER_PORT + 1; | 920 | CLIENT_PORT = SERVER_PORT + 1; |
910 | } | 921 | } |
@@ -960,6 +971,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
960 | struct dhcp_packet packet; | 971 | struct dhcp_packet packet; |
961 | int bytes; | 972 | int bytes; |
962 | int tv; | 973 | int tv; |
974 | uint8_t *msg_type; | ||
963 | uint8_t *server_id_opt; | 975 | uint8_t *server_id_opt; |
964 | uint8_t *requested_ip_opt; | 976 | uint8_t *requested_ip_opt; |
965 | uint32_t requested_nip; | 977 | uint32_t requested_nip; |
@@ -1017,6 +1029,9 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
1017 | * socket read inside this call is restarted on caught signals. | 1029 | * socket read inside this call is restarted on caught signals. |
1018 | */ | 1030 | */ |
1019 | bytes = udhcp_recv_kernel_packet(&packet, server_socket); | 1031 | bytes = udhcp_recv_kernel_packet(&packet, server_socket); |
1032 | //NB: we do not check source port here. Should we? | ||
1033 | //It should be CLIENT_PORT for clients, | ||
1034 | //or SERVER_PORT for relay agents (in which case giaddr must be != 0.0.0.0) | ||
1020 | if (bytes < 0) { | 1035 | if (bytes < 0) { |
1021 | /* bytes can also be -2 ("bad packet data") */ | 1036 | /* bytes can also be -2 ("bad packet data") */ |
1022 | if (bytes == -1 && errno != EINTR) { | 1037 | if (bytes == -1 && errno != EINTR) { |
@@ -1034,8 +1049,8 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
1034 | bb_info_msg("not a REQUEST%s", ", ignoring packet"); | 1049 | bb_info_msg("not a REQUEST%s", ", ignoring packet"); |
1035 | continue; | 1050 | continue; |
1036 | } | 1051 | } |
1037 | state = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE); | 1052 | msg_type = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE); |
1038 | if (state == NULL || state[0] < DHCP_MINTYPE || state[0] > DHCP_MAXTYPE) { | 1053 | if (!msg_type || msg_type[0] < DHCP_MINTYPE || msg_type[0] > DHCP_MAXTYPE) { |
1039 | bb_info_msg("no or bad message type option%s", ", ignoring packet"); | 1054 | bb_info_msg("no or bad message type option%s", ", ignoring packet"); |
1040 | continue; | 1055 | continue; |
1041 | } | 1056 | } |
@@ -1071,7 +1086,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
1071 | move_from_unaligned32(requested_nip, requested_ip_opt); | 1086 | move_from_unaligned32(requested_nip, requested_ip_opt); |
1072 | } | 1087 | } |
1073 | 1088 | ||
1074 | switch (state[0]) { | 1089 | switch (msg_type[0]) { |
1075 | 1090 | ||
1076 | case DHCPDISCOVER: | 1091 | case DHCPDISCOVER: |
1077 | log1("received %s", "DISCOVER"); | 1092 | log1("received %s", "DISCOVER"); |
diff --git a/networking/udhcp/dhcprelay.c b/networking/udhcp/dhcprelay.c index ef9447b4b..2352c34a2 100644 --- a/networking/udhcp/dhcprelay.c +++ b/networking/udhcp/dhcprelay.c | |||
@@ -17,7 +17,8 @@ | |||
17 | //usage:#define dhcprelay_trivial_usage | 17 | //usage:#define dhcprelay_trivial_usage |
18 | //usage: "CLIENT_IFACE[,CLIENT_IFACE2]... SERVER_IFACE [SERVER_IP]" | 18 | //usage: "CLIENT_IFACE[,CLIENT_IFACE2]... SERVER_IFACE [SERVER_IP]" |
19 | //usage:#define dhcprelay_full_usage "\n\n" | 19 | //usage:#define dhcprelay_full_usage "\n\n" |
20 | //usage: "Relay DHCP requests between clients and server" | 20 | //usage: "Relay DHCP requests between clients and server.\n" |
21 | //usage: "Without SERVER_IP, requests are broadcast on SERVER_IFACE." | ||
21 | 22 | ||
22 | #include "common.h" | 23 | #include "common.h" |
23 | 24 | ||
@@ -31,7 +32,7 @@ | |||
31 | /* This list holds information about clients. The xid_* functions manipulate this list. */ | 32 | /* This list holds information about clients. The xid_* functions manipulate this list. */ |
32 | struct xid_item { | 33 | struct xid_item { |
33 | unsigned timestamp; | 34 | unsigned timestamp; |
34 | int client; | 35 | unsigned iface_no; |
35 | uint32_t xid; | 36 | uint32_t xid; |
36 | struct sockaddr_in ip; | 37 | struct sockaddr_in ip; |
37 | struct xid_item *next; | 38 | struct xid_item *next; |
@@ -40,7 +41,7 @@ struct xid_item { | |||
40 | #define dhcprelay_xid_list (*(struct xid_item*)bb_common_bufsiz1) | 41 | #define dhcprelay_xid_list (*(struct xid_item*)bb_common_bufsiz1) |
41 | #define INIT_G() do { setup_common_bufsiz(); } while (0) | 42 | #define INIT_G() do { setup_common_bufsiz(); } while (0) |
42 | 43 | ||
43 | static struct xid_item *xid_add(uint32_t xid, struct sockaddr_in *ip, int client) | 44 | static struct xid_item *xid_add(uint32_t xid, struct sockaddr_in *ip, unsigned iface_no) |
44 | { | 45 | { |
45 | struct xid_item *item; | 46 | struct xid_item *item; |
46 | 47 | ||
@@ -50,7 +51,7 @@ static struct xid_item *xid_add(uint32_t xid, struct sockaddr_in *ip, int client | |||
50 | /* add xid entry */ | 51 | /* add xid entry */ |
51 | item->ip = *ip; | 52 | item->ip = *ip; |
52 | item->xid = xid; | 53 | item->xid = xid; |
53 | item->client = client; | 54 | item->iface_no = iface_no; |
54 | item->timestamp = monotonic_sec(); | 55 | item->timestamp = monotonic_sec(); |
55 | item->next = dhcprelay_xid_list.next; | 56 | item->next = dhcprelay_xid_list.next; |
56 | dhcprelay_xid_list.next = item; | 57 | dhcprelay_xid_list.next = item; |
@@ -127,10 +128,10 @@ static int get_dhcp_packet_type(struct dhcp_packet *p) | |||
127 | * make_iface_list - parses client/server interface names | 128 | * make_iface_list - parses client/server interface names |
128 | * returns array | 129 | * returns array |
129 | */ | 130 | */ |
130 | static char **make_iface_list(char **client_and_server_ifaces, int *client_number) | 131 | static char **make_iface_list(char **client_and_server_ifaces, unsigned *client_number) |
131 | { | 132 | { |
132 | char *s, **iface_list; | 133 | char *s, **iface_list; |
133 | int i, cn; | 134 | unsigned i, cn; |
134 | 135 | ||
135 | /* get number of items */ | 136 | /* get number of items */ |
136 | cn = 2; /* 1 server iface + at least 1 client one */ | 137 | cn = 2; /* 1 server iface + at least 1 client one */ |
@@ -165,9 +166,9 @@ static char **make_iface_list(char **client_and_server_ifaces, int *client_numbe | |||
165 | /* Creates listen sockets (in fds) bound to client and server ifaces, | 166 | /* Creates listen sockets (in fds) bound to client and server ifaces, |
166 | * and returns numerically max fd. | 167 | * and returns numerically max fd. |
167 | */ | 168 | */ |
168 | static int init_sockets(char **iface_list, int num_clients, int *fds) | 169 | static unsigned init_sockets(char **iface_list, unsigned num_clients, int *fds) |
169 | { | 170 | { |
170 | int i, n; | 171 | unsigned i, n; |
171 | 172 | ||
172 | n = 0; | 173 | n = 0; |
173 | for (i = 0; i < num_clients; i++) { | 174 | for (i = 0; i < num_clients; i++) { |
@@ -195,13 +196,14 @@ static int sendto_ip4(int sock, const void *msg, int msg_len, struct sockaddr_in | |||
195 | * p - packet to send | 196 | * p - packet to send |
196 | * client - number of the client | 197 | * client - number of the client |
197 | */ | 198 | */ |
198 | static void pass_to_server(struct dhcp_packet *p, int packet_len, int client, int *fds, | 199 | static void pass_to_server(struct dhcp_packet *p, int packet_len, unsigned from_iface_no, int *fds, |
199 | struct sockaddr_in *client_addr, struct sockaddr_in *server_addr) | 200 | struct sockaddr_in *client_addr, struct sockaddr_in *server_addr) |
200 | { | 201 | { |
201 | int type; | 202 | int type; |
202 | 203 | ||
203 | /* check packet_type */ | 204 | /* check packet_type */ |
204 | type = get_dhcp_packet_type(p); | 205 | type = get_dhcp_packet_type(p); |
206 | //FIXME: the above does not consider packet_len! | ||
205 | if (type != DHCPDISCOVER && type != DHCPREQUEST | 207 | if (type != DHCPDISCOVER && type != DHCPREQUEST |
206 | && type != DHCPDECLINE && type != DHCPRELEASE | 208 | && type != DHCPDECLINE && type != DHCPRELEASE |
207 | && type != DHCPINFORM | 209 | && type != DHCPINFORM |
@@ -210,7 +212,10 @@ static void pass_to_server(struct dhcp_packet *p, int packet_len, int client, in | |||
210 | } | 212 | } |
211 | 213 | ||
212 | /* create new xid entry */ | 214 | /* create new xid entry */ |
213 | xid_add(p->xid, client_addr, client); | 215 | xid_add(p->xid, client_addr, from_iface_no); |
216 | //TODO: since we key request/reply pairs on xid values, shouldn't we drop new requests | ||
217 | //with xid accidentally matching a xid of one of requests we currently hold | ||
218 | //waiting for their replies? | ||
214 | 219 | ||
215 | /* forward request to server */ | 220 | /* forward request to server */ |
216 | /* note that we send from fds[0] which is bound to SERVER_PORT (67). | 221 | /* note that we send from fds[0] which is bound to SERVER_PORT (67). |
@@ -229,25 +234,30 @@ static void pass_to_client(struct dhcp_packet *p, int packet_len, int *fds) | |||
229 | int type; | 234 | int type; |
230 | struct xid_item *item; | 235 | struct xid_item *item; |
231 | 236 | ||
232 | /* check xid */ | ||
233 | item = xid_find(p->xid); | ||
234 | if (!item) { | ||
235 | return; | ||
236 | } | ||
237 | |||
238 | /* check packet type */ | 237 | /* check packet type */ |
239 | type = get_dhcp_packet_type(p); | 238 | type = get_dhcp_packet_type(p); |
239 | //FIXME: the above does not consider packet_len! | ||
240 | if (type != DHCPOFFER && type != DHCPACK && type != DHCPNAK) { | 240 | if (type != DHCPOFFER && type != DHCPACK && type != DHCPNAK) { |
241 | return; | 241 | return; |
242 | } | 242 | } |
243 | 243 | ||
244 | /* check xid */ | ||
245 | item = xid_find(p->xid); | ||
246 | if (!item) { | ||
247 | return; | ||
248 | } | ||
249 | //NB: RFC 1542 section 4.1 seems to envision the logic that | ||
250 | //relay agents use giaddr (dhcp_msg.gateway_nip in our code) | ||
251 | //to find out on which interface to reply. | ||
252 | //(server is meant to copy giaddr from our request packet to its reply). | ||
253 | //Above, we don't use that logic, instead we use xid as a key. | ||
254 | |||
244 | //TODO: also do it if (p->flags & htons(BROADCAST_FLAG)) is set! | 255 | //TODO: also do it if (p->flags & htons(BROADCAST_FLAG)) is set! |
245 | if (item->ip.sin_addr.s_addr == htonl(INADDR_ANY)) | 256 | if (item->ip.sin_addr.s_addr == htonl(INADDR_ANY)) |
246 | item->ip.sin_addr.s_addr = htonl(INADDR_BROADCAST); | 257 | item->ip.sin_addr.s_addr = htonl(INADDR_BROADCAST); |
247 | 258 | ||
248 | if (sendto_ip4(fds[item->client], p, packet_len, &item->ip) != 0) { | 259 | sendto_ip4(fds[item->iface_no], p, packet_len, &item->ip); |
249 | return; /* send error occurred */ | 260 | /* ^^^ if send error occurred, we can't do much, hence no check */ |
250 | } | ||
251 | 261 | ||
252 | /* remove xid entry */ | 262 | /* remove xid entry */ |
253 | xid_del(p->xid); | 263 | xid_del(p->xid); |
@@ -259,7 +269,7 @@ int dhcprelay_main(int argc UNUSED_PARAM, char **argv) | |||
259 | struct sockaddr_in server_addr; | 269 | struct sockaddr_in server_addr; |
260 | char **iface_list; | 270 | char **iface_list; |
261 | int *fds; | 271 | int *fds; |
262 | int num_sockets, max_socket; | 272 | unsigned num_sockets, max_socket; |
263 | uint32_t our_nip; | 273 | uint32_t our_nip; |
264 | 274 | ||
265 | INIT_G(); | 275 | INIT_G(); |
@@ -293,7 +303,7 @@ int dhcprelay_main(int argc UNUSED_PARAM, char **argv) | |||
293 | // every N minutes? | 303 | // every N minutes? |
294 | fd_set rfds; | 304 | fd_set rfds; |
295 | struct timeval tv; | 305 | struct timeval tv; |
296 | int i; | 306 | unsigned i; |
297 | 307 | ||
298 | FD_ZERO(&rfds); | 308 | FD_ZERO(&rfds); |
299 | for (i = 0; i < num_sockets; i++) | 309 | for (i = 0; i < num_sockets; i++) |
@@ -304,15 +314,17 @@ int dhcprelay_main(int argc UNUSED_PARAM, char **argv) | |||
304 | int packlen; | 314 | int packlen; |
305 | struct dhcp_packet dhcp_msg; | 315 | struct dhcp_packet dhcp_msg; |
306 | 316 | ||
307 | /* server */ | 317 | /* from server */ |
308 | if (FD_ISSET(fds[0], &rfds)) { | 318 | if (FD_ISSET(fds[0], &rfds)) { |
309 | packlen = udhcp_recv_kernel_packet(&dhcp_msg, fds[0]); | 319 | packlen = udhcp_recv_kernel_packet(&dhcp_msg, fds[0]); |
320 | //NB: we do not check source port here. Should we? | ||
321 | //It should be SERVER_PORT. | ||
310 | if (packlen > 0) { | 322 | if (packlen > 0) { |
311 | pass_to_client(&dhcp_msg, packlen, fds); | 323 | pass_to_client(&dhcp_msg, packlen, fds); |
312 | } | 324 | } |
313 | } | 325 | } |
314 | 326 | ||
315 | /* clients */ | 327 | /* from clients */ |
316 | for (i = 1; i < num_sockets; i++) { | 328 | for (i = 1; i < num_sockets; i++) { |
317 | struct sockaddr_in client_addr; | 329 | struct sockaddr_in client_addr; |
318 | socklen_t addr_size; | 330 | socklen_t addr_size; |
@@ -325,6 +337,11 @@ int dhcprelay_main(int argc UNUSED_PARAM, char **argv) | |||
325 | (struct sockaddr *)(&client_addr), &addr_size); | 337 | (struct sockaddr *)(&client_addr), &addr_size); |
326 | if (packlen <= 0) | 338 | if (packlen <= 0) |
327 | continue; | 339 | continue; |
340 | //NB: we do not check source port here. Should we? | ||
341 | //It should be CLIENT_PORT for clients. | ||
342 | //It can be SERVER_PORT for relay agents (in which case giaddr must be != 0.0.0.0), | ||
343 | //but is it even supported to chain relay agents like this? | ||
344 | //(we still copy client_addr.port and use it to reply to the port we got request from) | ||
328 | 345 | ||
329 | /* Get our IP on corresponding client_iface */ | 346 | /* Get our IP on corresponding client_iface */ |
330 | // RFC 1542 | 347 | // RFC 1542 |