aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2021-09-02 16:23:24 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2021-09-02 16:24:52 +0200
commit3f2d969db9023e273a327418b32ebd4ed88893c4 (patch)
tree8796e8dc29994a8b6de62f23d6fef89e4a8abf0c
parent62d0c8e02872d444ba20b4bdf638ac26c509a3dd (diff)
downloadbusybox-w32-3f2d969db9023e273a327418b32ebd4ed88893c4.tar.gz
busybox-w32-3f2d969db9023e273a327418b32ebd4ed88893c4.tar.bz2
busybox-w32-3f2d969db9023e273a327418b32ebd4ed88893c4.zip
udhcp: clarify aspects of relay operation, add TODOs and FIXMEs, tweak --help
function old new delta packed_usage 33891 33920 +29 dhcprelay_main 943 926 -17 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 29/-17) Total: 12 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/udhcp/dhcpd.c7
-rw-r--r--networking/udhcp/dhcprelay.c61
2 files changed, 46 insertions, 22 deletions
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index b67dfc3bc..0f5edb75c 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -614,6 +614,10 @@ static void send_packet_to_relay(struct dhcp_packet *dhcp_pkt)
614 udhcp_send_kernel_packet(dhcp_pkt, 614 udhcp_send_kernel_packet(dhcp_pkt,
615 server_data.server_nip, SERVER_PORT, 615 server_data.server_nip, SERVER_PORT,
616 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 */
617 server_data.interface); 621 server_data.interface);
618} 622}
619 623
@@ -1025,6 +1029,9 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
1025 * socket read inside this call is restarted on caught signals. 1029 * socket read inside this call is restarted on caught signals.
1026 */ 1030 */
1027 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)
1028 if (bytes < 0) { 1035 if (bytes < 0) {
1029 /* bytes can also be -2 ("bad packet data") */ 1036 /* bytes can also be -2 ("bad packet data") */
1030 if (bytes == -1 && errno != EINTR) { 1037 if (bytes == -1 && errno != EINTR) {
diff --git a/networking/udhcp/dhcprelay.c b/networking/udhcp/dhcprelay.c
index ef9447b4b..de3e4b0e1 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,7 +128,7 @@ 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 int i, cn;
@@ -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