aboutsummaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-09-10 14:47:27 +0100
committerRon Yorston <rmy@pobox.com>2021-09-10 14:47:27 +0100
commit3eb1d088e09db204f456ad7b76eced21e429f001 (patch)
treea81b5bb422db5ee97475a8f1a4b5236442ed6f14 /networking
parent12bc40da28f85cbe97673671f315f847f1dbbabf (diff)
parent40f2dd7dd2e50c9d81dda4d72bf9c85c4c479a89 (diff)
downloadbusybox-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.c3
-rw-r--r--networking/httpd.c13
-rw-r--r--networking/nc.c2
-rw-r--r--networking/nc_bloaty.c7
-rw-r--r--networking/telnetd.c10
-rw-r--r--networking/udhcp/common.h31
-rw-r--r--networking/udhcp/dhcpd.c35
-rw-r--r--networking/udhcp/dhcprelay.c63
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 =
296int ftpgetput_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 296int ftpgetput_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
297int ftpgetput_main(int argc UNUSED_PARAM, char **argv) 297int 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
326static void send_REQUEST_TIMEOUT_and_exit(int sig) NORETURN; 332static void send_REQUEST_TIMEOUT_and_exit(int sig) NORETURN;
327 333
334#define STR1(s) #s
335#define STR(s) STR1(s)
336
328static const char DEFAULT_PATH_HTTPD_CONF[] ALIGN1 = "/etc"; 337static const char DEFAULT_PATH_HTTPD_CONF[] ALIGN1 = "/etc";
329static const char HTTPD_CONF[] ALIGN1 = "httpd.conf"; 338static const char HTTPD_CONF[] ALIGN1 = "httpd.conf";
330static const char HTTP_200[] ALIGN1 = "HTTP/1.1 200 OK\r\n"; 339static 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
456static void write_leases(void) 458static 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;
858int udhcpd_main(int argc UNUSED_PARAM, char **argv) 864int 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. */
32struct xid_item { 33struct 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
43static struct xid_item *xid_add(uint32_t xid, struct sockaddr_in *ip, int client) 44static 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 */
130static char **make_iface_list(char **client_and_server_ifaces, int *client_number) 131static 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 */
168static int init_sockets(char **iface_list, int num_clients, int *fds) 169static 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 */
198static void pass_to_server(struct dhcp_packet *p, int packet_len, int client, int *fds, 199static 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