aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-13 03:33:46 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-13 03:33:46 +0000
commite8a796828eee4b898be2141ecbe34bad594bfbbb (patch)
tree7f71934e445346fcc153ce63ffbac733b07f665d
parent1f63229a8e5384bcc2ea99c9063383d3960fe275 (diff)
downloadbusybox-w32-e8a796828eee4b898be2141ecbe34bad594bfbbb.tar.gz
busybox-w32-e8a796828eee4b898be2141ecbe34bad594bfbbb.tar.bz2
busybox-w32-e8a796828eee4b898be2141ecbe34bad594bfbbb.zip
dhcprelay: fix usage text. Simplify and make code more readable.
Add TODOs.
-rw-r--r--include/usage.h5
-rw-r--r--networking/udhcp/dhcprelay.c135
2 files changed, 75 insertions, 65 deletions
diff --git a/include/usage.h b/include/usage.h
index cbbd7516a..c36a3bbd7 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -802,10 +802,9 @@
802 "/dev/sda3 17381728 17107080 274648 98% /\n" 802 "/dev/sda3 17381728 17107080 274648 98% /\n"
803 803
804#define dhcprelay_trivial_usage \ 804#define dhcprelay_trivial_usage \
805 "[client1,client2,...] [server_device]" 805 "CLIENT_IFACE[,CLIENT_IFACE2...] SERVER_IFACE [SERVER_IP]"
806#define dhcprelay_full_usage "\n\n" \ 806#define dhcprelay_full_usage "\n\n" \
807 "Relay dhcp requests from client devices to server device.\n" \ 807 "Relay DHCP requests between clients and server" \
808 "Pass clients as CSV"
809 808
810#define diff_trivial_usage \ 809#define diff_trivial_usage \
811 "[-abdiNqrTstw] [-L LABEL] [-S FILE] [-U LINES] FILE1 FILE2" 810 "[-abdiNqrTstw] [-L LABEL] [-S FILE] [-U LINES] FILE1 FILE2"
diff --git a/networking/udhcp/dhcprelay.c b/networking/udhcp/dhcprelay.c
index f3b2855d8..53540d1ab 100644
--- a/networking/udhcp/dhcprelay.c
+++ b/networking/udhcp/dhcprelay.c
@@ -13,7 +13,6 @@
13#include "common.h" 13#include "common.h"
14#include "options.h" 14#include "options.h"
15 15
16/* constants */
17#define SERVER_PORT 67 16#define SERVER_PORT 67
18#define SELECT_TIMEOUT 5 /* select timeout in sec. */ 17#define SELECT_TIMEOUT 5 /* select timeout in sec. */
19#define MAX_LIFETIME 2*60 /* lifetime of an xid entry in sec. */ 18#define MAX_LIFETIME 2*60 /* lifetime of an xid entry in sec. */
@@ -149,19 +148,21 @@ static char **get_client_devices(char *dev_list, int *client_number)
149} 148}
150 149
151 150
152/* Creates listen sockets (in fds) and returns numerically max fd. */ 151/* Creates listen sockets (in fds) bound to client and server ifaces,
153static int init_sockets(char **client, int num_clients, 152 * and returns numerically max fd.
154 char *server, int *fds) 153 */
154static int init_sockets(char **client_ifaces, int num_clients,
155 char *server_iface, int *fds)
155{ 156{
156 int i, n; 157 int i, n;
157 158
158 /* talk to real server on bootps */ 159 /* talk to real server on bootps */
159 fds[0] = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT, server); 160 fds[0] = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT, server_iface);
160 n = fds[0]; 161 n = fds[0];
161 162
162 for (i = 1; i < num_clients; i++) { 163 for (i = 1; i < num_clients; i++) {
163 /* listen for clients on bootps */ 164 /* listen for clients on bootps */
164 fds[i] = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT, client[i-1]); 165 fds[i] = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT, client_ifaces[i-1]);
165 if (fds[i] > n) 166 if (fds[i] > n)
166 n = fds[i]; 167 n = fds[i];
167 } 168 }
@@ -170,11 +171,11 @@ static int init_sockets(char **client, int num_clients,
170 171
171 172
172/** 173/**
173 * pass_on() - forwards dhcp packets from client to server 174 * pass_to_server() - forwards dhcp packets from client to server
174 * p - packet to send 175 * p - packet to send
175 * client - number of the client 176 * client - number of the client
176 */ 177 */
177static void pass_on(struct dhcpMessage *p, int packet_len, int client, int *fds, 178static void pass_to_server(struct dhcpMessage *p, int packet_len, int client, int *fds,
178 struct sockaddr_in *client_addr, struct sockaddr_in *server_addr) 179 struct sockaddr_in *client_addr, struct sockaddr_in *server_addr)
179{ 180{
180 int res, type; 181 int res, type;
@@ -193,19 +194,19 @@ static void pass_on(struct dhcpMessage *p, int packet_len, int client, int *fds,
193 item = xid_add(p->xid, client_addr, client); 194 item = xid_add(p->xid, client_addr, client);
194 195
195 /* forward request to LAN (server) */ 196 /* forward request to LAN (server) */
197 errno = 0;
196 res = sendto(fds[0], p, packet_len, 0, (struct sockaddr*)server_addr, 198 res = sendto(fds[0], p, packet_len, 0, (struct sockaddr*)server_addr,
197 sizeof(struct sockaddr_in)); 199 sizeof(struct sockaddr_in));
198 if (res != packet_len) { 200 if (res != packet_len) {
199 bb_perror_msg("pass_on"); 201 bb_perror_msg("sendto");
200 return;
201 } 202 }
202} 203}
203 204
204/** 205/**
205 * pass_back() - forwards dhcp packets from server to client 206 * pass_to_client() - forwards dhcp packets from server to client
206 * p - packet to send 207 * p - packet to send
207 */ 208 */
208static void pass_back(struct dhcpMessage *p, int packet_len, int *fds) 209static void pass_to_client(struct dhcpMessage *p, int packet_len, int *fds)
209{ 210{
210 int res, type; 211 int res, type;
211 struct xid_item *item; 212 struct xid_item *item;
@@ -224,10 +225,11 @@ static void pass_back(struct dhcpMessage *p, int packet_len, int *fds)
224 225
225 if (item->ip.sin_addr.s_addr == htonl(INADDR_ANY)) 226 if (item->ip.sin_addr.s_addr == htonl(INADDR_ANY))
226 item->ip.sin_addr.s_addr = htonl(INADDR_BROADCAST); 227 item->ip.sin_addr.s_addr = htonl(INADDR_BROADCAST);
227 res = sendto(fds[item->client], p, packet_len, 0, (struct sockaddr*)(&item->ip), 228 errno = 0;
228 sizeof(item->ip)); 229 res = sendto(fds[item->client], p, packet_len, 0, (struct sockaddr*) &(item->ip),
230 sizeof(item->ip));
229 if (res != packet_len) { 231 if (res != packet_len) {
230 bb_perror_msg("pass_back"); 232 bb_perror_msg("sendto");
231 return; 233 return;
232 } 234 }
233 235
@@ -235,20 +237,53 @@ static void pass_back(struct dhcpMessage *p, int packet_len, int *fds)
235 xid_del(p->xid); 237 xid_del(p->xid);
236} 238}
237 239
238static void dhcprelay_loop(int *fds, int num_sockets, int max_socket, char **clients, 240int dhcprelay_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
239 struct sockaddr_in *server_addr, uint32_t gw_ip) NORETURN; 241int dhcprelay_main(int argc, char **argv)
240static void dhcprelay_loop(int *fds, int num_sockets, int max_socket, char **clients,
241 struct sockaddr_in *server_addr, uint32_t gw_ip)
242{ 242{
243 struct dhcpMessage dhcp_msg; 243 struct dhcpMessage dhcp_msg;
244 fd_set rfds; 244 struct sockaddr_in server_addr;
245 size_t packlen;
246 socklen_t addr_size;
247 struct sockaddr_in client_addr; 245 struct sockaddr_in client_addr;
248 struct timeval tv; 246 fd_set rfds;
249 int i; 247 char **client_ifaces;
248 int *fds;
249 int num_sockets, max_socket;
250 uint32_t our_ip;
251
252 server_addr.sin_family = AF_INET;
253 server_addr.sin_port = htons(SERVER_PORT);
254
255 /* dhcprelay client_iface1,client_iface2,... server_iface [server_IP] */
256 if (argc == 4) {
257 if (!inet_aton(argv[3], &server_addr.sin_addr))
258 bb_perror_msg_and_die("bad server IP");
259 } else if (argc == 3) {
260 server_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
261 } else {
262 bb_show_usage();
263 }
264
265 /* Produce list of client ifaces */
266 client_ifaces = get_client_devices(argv[1], &num_sockets);
267
268 num_sockets++; /* for server socket at fds[0] */
269 fds = xmalloc(num_sockets * sizeof(fds[0]));
270
271 /* Create sockets and bind one to every iface */
272 max_socket = init_sockets(client_ifaces, num_sockets, argv[2], fds);
273
274 /* Get our IP on server_iface */
275 if (udhcp_read_interface(argv[2], NULL, &our_ip, NULL))
276 return 1;
250 277
278 /* Main loop */
251 while (1) { 279 while (1) {
280//reinit stuff from time to time? go back to get_client_devices
281//every N minutes?
282 struct timeval tv;
283 size_t packlen;
284 socklen_t addr_size;
285 int i;
286
252 FD_ZERO(&rfds); 287 FD_ZERO(&rfds);
253 for (i = 0; i < num_sockets; i++) 288 for (i = 0; i < num_sockets; i++)
254 FD_SET(fds[i], &rfds); 289 FD_SET(fds[i], &rfds);
@@ -259,56 +294,32 @@ static void dhcprelay_loop(int *fds, int num_sockets, int max_socket, char **cli
259 if (FD_ISSET(fds[0], &rfds)) { 294 if (FD_ISSET(fds[0], &rfds)) {
260 packlen = udhcp_recv_kernel_packet(&dhcp_msg, fds[0]); 295 packlen = udhcp_recv_kernel_packet(&dhcp_msg, fds[0]);
261 if (packlen > 0) { 296 if (packlen > 0) {
262 pass_back(&dhcp_msg, packlen, fds); 297 pass_to_client(&dhcp_msg, packlen, fds);
263 } 298 }
264 } 299 }
300 /* clients */
265 for (i = 1; i < num_sockets; i++) { 301 for (i = 1; i < num_sockets; i++) {
266 /* clients */
267 if (!FD_ISSET(fds[i], &rfds)) 302 if (!FD_ISSET(fds[i], &rfds))
268 continue; 303 continue;
269 addr_size = sizeof(struct sockaddr_in); 304 addr_size = sizeof(struct sockaddr_in);
270 packlen = recvfrom(fds[i], &dhcp_msg, sizeof(dhcp_msg), 0, 305 packlen = recvfrom(fds[i], &dhcp_msg, sizeof(dhcp_msg), 0,
271 (struct sockaddr *)(&client_addr), &addr_size); 306 (struct sockaddr *)(&client_addr), &addr_size);
272 if (packlen <= 0) 307 if (packlen <= 0)
273 continue; 308 continue;
274 if (udhcp_read_interface(clients[i-1], NULL, &dhcp_msg.giaddr, NULL)) 309
275 dhcp_msg.giaddr = gw_ip; 310 /* Get our IP on corresponding client_iface */
276 pass_on(&dhcp_msg, packlen, i, fds, &client_addr, server_addr); 311//why? what if server can't route such IP?
312 if (udhcp_read_interface(client_ifaces[i-1], NULL, &dhcp_msg.giaddr, NULL)) {
313 /* Fall back to our server_iface's IP */
314//this makes more sense!
315 dhcp_msg.giaddr = our_ip;
316 }
317//maybe set dhcp_msg.flags |= BROADCAST_FLAG too?
318 pass_to_server(&dhcp_msg, packlen, i, fds, &client_addr, &server_addr);
277 } 319 }
278 } 320 }
279 xid_expire(); 321 xid_expire();
280 } 322 } /* while (1) */
281}
282
283int dhcprelay_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
284int dhcprelay_main(int argc, char **argv)
285{
286 int num_sockets, max_socket;
287 int *fds;
288 uint32_t gw_ip;
289 char **clients;
290 struct sockaddr_in server_addr;
291
292 server_addr.sin_family = AF_INET;
293 server_addr.sin_port = htons(SERVER_PORT);
294 if (argc == 4) {
295 if (!inet_aton(argv[3], &server_addr.sin_addr))
296 bb_perror_msg_and_die("didn't grok server");
297 } else if (argc == 3) {
298 server_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
299 } else {
300 bb_show_usage();
301 }
302
303 clients = get_client_devices(argv[1], &num_sockets);
304 num_sockets++; /* for server socket at fds[0] */
305 fds = xmalloc(num_sockets * sizeof(fds[0]));
306 max_socket = init_sockets(clients, num_sockets, argv[2], fds);
307
308 if (udhcp_read_interface(argv[2], NULL, &gw_ip, NULL))
309 return 1;
310 323
311 /* doesn't return */
312 dhcprelay_loop(fds, num_sockets, max_socket, clients, &server_addr, gw_ip);
313 /* return 0; - not reached */ 324 /* return 0; - not reached */
314} 325}