diff options
Diffstat (limited to 'networking/udhcp/dhcpd.c')
-rw-r--r-- | networking/udhcp/dhcpd.c | 35 |
1 files changed, 25 insertions, 10 deletions
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"); |