aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/udhcp/clientsocket.c55
-rw-r--r--networking/udhcp/common.h7
-rw-r--r--networking/udhcp/dhcpc.c3
-rw-r--r--networking/udhcp/dhcprelay.c6
-rw-r--r--networking/udhcp/options.h3
5 files changed, 64 insertions, 10 deletions
diff --git a/networking/udhcp/clientsocket.c b/networking/udhcp/clientsocket.c
index 541f883b5..954db5319 100644
--- a/networking/udhcp/clientsocket.c
+++ b/networking/udhcp/clientsocket.c
@@ -30,22 +30,75 @@
30#include <linux/if_packet.h> 30#include <linux/if_packet.h>
31#include <linux/if_ether.h> 31#include <linux/if_ether.h>
32#endif 32#endif
33#include <linux/filter.h>
33 34
34#include "common.h" 35#include "common.h"
35 36
37#define SERVER_AND_CLIENT_PORTS ((SERVER_PORT << 16) + CLIENT_PORT)
36 38
37int raw_socket(int ifindex) 39int raw_socket(int ifindex)
38{ 40{
39 int fd; 41 int fd;
40 struct sockaddr_ll sock; 42 struct sockaddr_ll sock;
41 43
42 DEBUG("Opening raw socket on ifindex %d", ifindex); 44 /*
45 * Comment:
46 *
47 * I've selected not to see LL header, so BPF doesn't see it, too.
48 * The filter may also pass non-IP and non-ARP packets, but we do
49 * a more complete check when receiving the message in userspace.
50 *
51 * and filter shamelessly stolen from:
52 *
53 * http://www.flamewarmaster.de/software/dhcpclient/
54 *
55 * There are a few other interesting ideas on that page (look under
56 * "Motivation"). Use of netlink events is most interesting. Think
57 * of various network servers listening for events and reconfiguring.
58 * That would obsolete sending HUP signals and/or make use of restarts.
59 *
60 * Copyright: 2006, 2007 Stefan Rompf <sux@loplof.de>.
61 * License: GPL v2.
62 *
63 * TODO: make conditional?
64 */
65 static const struct sock_filter filter_instr[] = {
66 /* check for udp */
67 BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 9),
68 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, IPPROTO_UDP, 2, 0), /* L5, L1, is UDP? */
69 /* ugly check for arp on ethernet-like and IPv4 */
70 BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 2), /* L1: */
71 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x08000604, 3, 4), /* L3, L4 */
72 /* skip IP header */
73 BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0), /* L5: */
74 /* check udp source and destination ports */
75 BPF_STMT(BPF_LD|BPF_W|BPF_IND, 0),
76 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, SERVER_AND_CLIENT_PORTS, 0, 1), /* L3, L4 */
77 /* returns */
78 BPF_STMT(BPF_RET|BPF_K, ~0UL), /* L3: pass */
79 BPF_STMT(BPF_RET|BPF_K, 0), /* L4: reject */
80 };
81 static const struct sock_fprog filter_prog = {
82 .len = sizeof(filter_instr) / sizeof(filter_instr[0]),
83 /* casting const away: */
84 .filter = (struct sock_filter *) filter_instr,
85 };
86
87 DEBUG("opening raw socket on ifindex %d", ifindex);
88
43 fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); 89 fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
90 DEBUG("got raw socket fd %d", fd);
91
92 /* Ignoring error (kernel may lack support for this) */
93 if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog,
94 sizeof(filter_prog)) >= 0)
95 DEBUG("attached filter to raw socket fd %d", fd);
44 96
45 sock.sll_family = AF_PACKET; 97 sock.sll_family = AF_PACKET;
46 sock.sll_protocol = htons(ETH_P_IP); 98 sock.sll_protocol = htons(ETH_P_IP);
47 sock.sll_ifindex = ifindex; 99 sock.sll_ifindex = ifindex;
48 xbind(fd, (struct sockaddr *) &sock, sizeof(sock)); 100 xbind(fd, (struct sockaddr *) &sock, sizeof(sock));
101 DEBUG("bound to raw socket fd %d", fd);
49 102
50 return fd; 103 return fd;
51} 104}
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
index 38ede0124..b1d629b18 100644
--- a/networking/udhcp/common.h
+++ b/networking/udhcp/common.h
@@ -14,6 +14,9 @@
14 14
15#define DEFAULT_SCRIPT "/usr/share/udhcpc/default.script" 15#define DEFAULT_SCRIPT "/usr/share/udhcpc/default.script"
16 16
17#define SERVER_PORT 67
18#define CLIENT_PORT 68
19
17extern const uint8_t MAC_BCAST_ADDR[6]; /* six all-ones */ 20extern const uint8_t MAC_BCAST_ADDR[6]; /* six all-ones */
18 21
19/*** packet.h ***/ 22/*** packet.h ***/
@@ -21,7 +24,7 @@ extern const uint8_t MAC_BCAST_ADDR[6]; /* six all-ones */
21#include <netinet/udp.h> 24#include <netinet/udp.h>
22#include <netinet/ip.h> 25#include <netinet/ip.h>
23 26
24#define DHCP_OPTIONS_BUFSIZE 308 27#define DHCP_OPTIONS_BUFSIZE 308
25 28
26struct dhcpMessage { 29struct dhcpMessage {
27 uint8_t op; 30 uint8_t op;
@@ -93,7 +96,7 @@ int listen_socket(/*uint32_t ip,*/ int port, const char *inf);
93int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *interface); 96int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *interface);
94 97
95#if ENABLE_FEATURE_UDHCP_DEBUG 98#if ENABLE_FEATURE_UDHCP_DEBUG
96# define DEBUG(str, args...) bb_info_msg(str, ## args) 99# define DEBUG(str, args...) bb_info_msg("### " str, ## args)
97#else 100#else
98# define DEBUG(str, args...) do {;} while (0) 101# define DEBUG(str, args...) do {;} while (0)
99#endif 102#endif
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index e9b728ab5..f54bc08f1 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -452,7 +452,8 @@ int udhcpc_main(int argc, char **argv)
452 452
453 if (listen_mode == LISTEN_KERNEL) 453 if (listen_mode == LISTEN_KERNEL)
454 len = udhcp_recv_packet(&packet, sockfd); 454 len = udhcp_recv_packet(&packet, sockfd);
455 else len = get_raw_packet(&packet, sockfd); 455 else
456 len = get_raw_packet(&packet, sockfd);
456 457
457 if (len == -1) { /* error is severe, reopen socket */ 458 if (len == -1) { /* error is severe, reopen socket */
458 DEBUG("error on read, %s, reopening socket", strerror(errno)); 459 DEBUG("error on read, %s, reopening socket", strerror(errno));
diff --git a/networking/udhcp/dhcprelay.c b/networking/udhcp/dhcprelay.c
index a6483fc1f..c243cc16c 100644
--- a/networking/udhcp/dhcprelay.c
+++ b/networking/udhcp/dhcprelay.c
@@ -155,12 +155,12 @@ static int init_sockets(char **client, int num_clients,
155 int i, n; 155 int i, n;
156 156
157 /* talk to real server on bootps */ 157 /* talk to real server on bootps */
158 fds[0] = listen_socket(/*INADDR_ANY,*/ 67, server); 158 fds[0] = listen_socket(/*INADDR_ANY,*/ SERVER_PORT, server);
159 n = fds[0]; 159 n = fds[0];
160 160
161 for (i = 1; i < num_clients; i++) { 161 for (i = 1; i < num_clients; i++) {
162 /* listen for clients on bootps */ 162 /* listen for clients on bootps */
163 fds[i] = listen_socket(/*INADDR_ANY,*/ 67, client[i-1]); 163 fds[i] = listen_socket(/*INADDR_ANY,*/ SERVER_PORT, client[i-1]);
164 if (fds[i] > n) 164 if (fds[i] > n)
165 n = fds[i]; 165 n = fds[i];
166 } 166 }
@@ -289,7 +289,7 @@ int dhcprelay_main(int argc, char **argv)
289 struct sockaddr_in server_addr; 289 struct sockaddr_in server_addr;
290 290
291 server_addr.sin_family = AF_INET; 291 server_addr.sin_family = AF_INET;
292 server_addr.sin_port = htons(67); 292 server_addr.sin_port = htons(SERVER_PORT);
293 if (argc == 4) { 293 if (argc == 4) {
294 if (!inet_aton(argv[3], &server_addr.sin_addr)) 294 if (!inet_aton(argv[3], &server_addr.sin_addr))
295 bb_perror_msg_and_die("didn't grok server"); 295 bb_perror_msg_and_die("didn't grok server");
diff --git a/networking/udhcp/options.h b/networking/udhcp/options.h
index c98aec48f..e9eeefb57 100644
--- a/networking/udhcp/options.h
+++ b/networking/udhcp/options.h
@@ -28,9 +28,6 @@ enum {
28/*****************************************************************/ 28/*****************************************************************/
29 29
30/* DHCP protocol -- see RFC 2131 */ 30/* DHCP protocol -- see RFC 2131 */
31#define SERVER_PORT 67
32#define CLIENT_PORT 68
33
34#define DHCP_MAGIC 0x63825363 31#define DHCP_MAGIC 0x63825363
35 32
36 33