aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/ether-wake.c173
1 files changed, 86 insertions, 87 deletions
diff --git a/networking/ether-wake.c b/networking/ether-wake.c
index 59055a951..71c3abfc3 100644
--- a/networking/ether-wake.c
+++ b/networking/ether-wake.c
@@ -97,20 +97,93 @@ void bb_debug_dump_packet(unsigned char *outpack, int pktsize)
97 printf("\n\n"); 97 printf("\n\n");
98} 98}
99#else 99#else
100# define bb_debug_msg(fmt, args...) 100# define bb_debug_msg(fmt, args...) ((void)0)
101# define bb_debug_dump_packet(outpack, pktsize) 101# define bb_debug_dump_packet(outpack, pktsize) ((void)0)
102#endif 102#endif
103 103
104static inline void get_dest_addr(const char *arg, struct ether_addr *eaddr); 104/* Convert the host ID string to a MAC address.
105static inline int get_fill(unsigned char *pkt, struct ether_addr *eaddr, int broadcast); 105 * The string may be a:
106static inline int get_wol_pw(const char *ethoptarg, unsigned char *wol_passwd); 106 * Host name
107 * IP address string
108 * MAC address string
109*/
110static void get_dest_addr(const char *hostid, struct ether_addr *eaddr)
111{
112 struct ether_addr *eap;
113
114 eap = ether_aton(hostid);
115 if (eap) {
116 *eaddr = *eap;
117 bb_debug_msg("The target station address is %s\n\n", ether_ntoa(eaddr));
118#if !defined(__UCLIBC__)
119 } else if (ether_hostton(hostid, eaddr) == 0) {
120 bb_debug_msg("Station address for hostname %s is %s\n\n", hostid, ether_ntoa(eaddr));
121#endif
122 } else
123 bb_show_usage();
124}
125
126static int get_fill(unsigned char *pkt, struct ether_addr *eaddr, int broadcast)
127{
128 int i;
129 unsigned char *station_addr = eaddr->ether_addr_octet;
130
131 memset(pkt, 0xff, 6);
132 if (!broadcast)
133 memcpy(pkt, station_addr, 6);
134 pkt += 6;
135
136 memcpy(pkt, station_addr, 6); /* 6 */
137 pkt += 6;
138
139 *pkt++ = 0x08; /* 12 */ /* Or 0x0806 for ARP, 0x8035 for RARP */
140 *pkt++ = 0x42; /* 13 */
141
142 memset(pkt, 0xff, 6); /* 14 */
143
144 for (i = 0; i < 16; ++i) {
145 pkt += 6;
146 memcpy(pkt, station_addr, 6); /* 20,26,32,... */
147 }
148
149 return 20 + 16*6; /* length of packet */
150}
151
152static int get_wol_pw(const char *ethoptarg, unsigned char *wol_passwd)
153{
154 unsigned passwd[6];
155 int byte_cnt, i;
156
157 /* handle MAC format */
158 byte_cnt = sscanf(ethoptarg, "%2x:%2x:%2x:%2x:%2x:%2x",
159 &passwd[0], &passwd[1], &passwd[2],
160 &passwd[3], &passwd[4], &passwd[5]);
161 /* handle IP format */
162// FIXME: why < 4?? should it be < 6?
163 if (byte_cnt < 4)
164 byte_cnt = sscanf(ethoptarg, "%u.%u.%u.%u",
165 &passwd[0], &passwd[1], &passwd[2], &passwd[3]);
166 if (byte_cnt < 4) {
167 bb_error_msg("cannot read Wake-On-LAN pass");
168 return 0;
169 }
170// TODO: check invalid numbers >255??
171 for (i = 0; i < byte_cnt; ++i)
172 wol_passwd[i] = passwd[i];
173
174 bb_debug_msg("password: %2.2x %2.2x %2.2x %2.2x (%d)\n\n",
175 wol_passwd[0], wol_passwd[1], wol_passwd[2], wol_passwd[3],
176 byte_cnt);
177
178 return byte_cnt;
179}
107 180
108int ether_wake_main(int argc, char **argv); 181int ether_wake_main(int argc, char **argv);
109int ether_wake_main(int argc, char **argv) 182int ether_wake_main(int argc, char **argv)
110{ 183{
111 const char *ifname = "eth0"; 184 const char *ifname = "eth0";
112 char *pass = NULL; 185 char *pass = NULL;
113 unsigned long flags; 186 unsigned flags;
114 unsigned char wol_passwd[6]; 187 unsigned char wol_passwd[6];
115 int wol_passwd_sz = 0; 188 int wol_passwd_sz = 0;
116 189
@@ -138,7 +211,7 @@ int ether_wake_main(int argc, char **argv)
138 get_dest_addr(argv[optind], &eaddr); 211 get_dest_addr(argv[optind], &eaddr);
139 212
140 /* fill out the header of the packet */ 213 /* fill out the header of the packet */
141 pktsize = get_fill(outpack, &eaddr, flags /*& 1 [OPT_BROADCAST]*/); 214 pktsize = get_fill(outpack, &eaddr, flags & 1 /* OPT_BROADCAST */);
142 215
143 bb_debug_dump_packet(outpack, pktsize); 216 bb_debug_dump_packet(outpack, pktsize);
144 217
@@ -148,7 +221,7 @@ int ether_wake_main(int argc, char **argv)
148 struct ifreq if_hwaddr; 221 struct ifreq if_hwaddr;
149 222
150 strncpy(if_hwaddr.ifr_name, ifname, sizeof(if_hwaddr.ifr_name)); 223 strncpy(if_hwaddr.ifr_name, ifname, sizeof(if_hwaddr.ifr_name));
151 if (ioctl(s, SIOCGIFHWADDR, &if_hwaddr) < 0) 224 if (ioctl(s, SIOCGIFHWADDR, &if_hwaddr) != 0)
152 bb_perror_msg_and_die("SIOCGIFHWADDR on %s failed", ifname); 225 bb_perror_msg_and_die("SIOCGIFHWADDR on %s failed", ifname);
153 226
154 memcpy(outpack+6, if_hwaddr.ifr_hwaddr.sa_data, 6); 227 memcpy(outpack+6, if_hwaddr.ifr_hwaddr.sa_data, 6);
@@ -176,8 +249,8 @@ int ether_wake_main(int argc, char **argv)
176 bb_debug_dump_packet(outpack, pktsize); 249 bb_debug_dump_packet(outpack, pktsize);
177 250
178 /* This is necessary for broadcasts to work */ 251 /* This is necessary for broadcasts to work */
179 if (flags /*& 1 [OPT_BROADCAST]*/) { 252 if (flags & 1 /* OPT_BROADCAST */) {
180 if (setsockopt_broadcast(s) < 0) 253 if (setsockopt_broadcast(s) != 0)
181 bb_perror_msg("SO_BROADCAST"); 254 bb_perror_msg("SO_BROADCAST");
182 } 255 }
183 256
@@ -185,7 +258,7 @@ int ether_wake_main(int argc, char **argv)
185 { 258 {
186 struct ifreq ifr; 259 struct ifreq ifr;
187 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 260 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
188 if (ioctl(s, SIOCGIFINDEX, &ifr) == -1) 261 if (ioctl(s, SIOCGIFINDEX, &ifr) != 0)
189 bb_perror_msg_and_die("SIOCGIFINDEX"); 262 bb_perror_msg_and_die("SIOCGIFINDEX");
190 memset(&whereto, 0, sizeof(whereto)); 263 memset(&whereto, 0, sizeof(whereto));
191 whereto.sll_family = AF_PACKET; 264 whereto.sll_family = AF_PACKET;
@@ -200,81 +273,7 @@ int ether_wake_main(int argc, char **argv)
200 strcpy(whereto.sa_data, ifname); 273 strcpy(whereto.sa_data, ifname);
201#endif 274#endif
202 xsendto(s, outpack, pktsize, (struct sockaddr *)&whereto, sizeof(whereto)); 275 xsendto(s, outpack, pktsize, (struct sockaddr *)&whereto, sizeof(whereto));
203 close(s); 276 if (ENABLE_FEATURE_CLEAN_UP)
277 close(s);
204 return EXIT_SUCCESS; 278 return EXIT_SUCCESS;
205} 279}
206
207/* Convert the host ID string to a MAC address.
208 * The string may be a:
209 * Host name
210 * IP address string
211 * MAC address string
212*/
213static inline void get_dest_addr(const char *hostid, struct ether_addr *eaddr)
214{
215 struct ether_addr *eap;
216
217 eap = ether_aton(hostid);
218 if (eap) {
219 *eaddr = *eap;
220 bb_debug_msg("The target station address is %s\n\n", ether_ntoa(eaddr));
221#if !defined(__UCLIBC__)
222 } else if (ether_hostton(hostid, eaddr) == 0) {
223 bb_debug_msg("Station address for hostname %s is %s\n\n", hostid, ether_ntoa(eaddr));
224#endif
225 } else
226 bb_show_usage();
227}
228
229static inline int get_fill(unsigned char *pkt, struct ether_addr *eaddr, int broadcast)
230{
231 int offset, i;
232 unsigned char *station_addr = eaddr->ether_addr_octet;
233
234 if (broadcast)
235 memset(pkt+0, 0xff, 6);
236 else
237 memcpy(pkt, station_addr, 6);
238 memcpy(pkt+6, station_addr, 6);
239 pkt[12] = 0x08; /* Or 0x0806 for ARP, 0x8035 for RARP */
240 pkt[13] = 0x42;
241 offset = 14;
242
243 memset(pkt+offset, 0xff, 6);
244 offset += 6;
245
246 for (i = 0; i < 16; ++i) {
247 memcpy(pkt+offset, station_addr, 6);
248 offset += 6;
249 }
250
251 return offset;
252}
253
254static inline int get_wol_pw(const char *ethoptarg, unsigned char *wol_passwd)
255{
256 int passwd[6];
257 int byte_cnt, i;
258
259 /* handle MAC format */
260 byte_cnt = sscanf(ethoptarg, "%2x:%2x:%2x:%2x:%2x:%2x",
261 &passwd[0], &passwd[1], &passwd[2],
262 &passwd[3], &passwd[4], &passwd[5]);
263 /* handle IP format */
264 if (byte_cnt < 4)
265 byte_cnt = sscanf(ethoptarg, "%d.%d.%d.%d",
266 &passwd[0], &passwd[1], &passwd[2], &passwd[3]);
267 if (byte_cnt < 4) {
268 bb_error_msg("cannot read Wake-On-LAN pass");
269 return 0;
270 }
271
272 for (i = 0; i < byte_cnt; ++i)
273 wol_passwd[i] = passwd[i];
274
275 bb_debug_msg("password: %2.2x %2.2x %2.2x %2.2x (%d)\n\n",
276 wol_passwd[0], wol_passwd[1], wol_passwd[2], wol_passwd[3],
277 byte_cnt);
278
279 return byte_cnt;
280}