Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/networking/ether-wake.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 532 by niro, Sat Sep 1 22:45:15 2007 UTC revision 816 by niro, Fri Apr 24 18:33:46 2009 UTC
# Line 70  Line 70 
70  #include <netinet/ether.h>  #include <netinet/ether.h>
71  #include <linux/if.h>  #include <linux/if.h>
72    
73  #include "busybox.h"  #include "libbb.h"
74    
75  /* Note: PF_INET, SOCK_DGRAM, IPPROTO_UDP would allow SIOCGIFHWADDR to  /* Note: PF_INET, SOCK_DGRAM, IPPROTO_UDP would allow SIOCGIFHWADDR to
76   * work as non-root, but we need SOCK_PACKET to specify the Ethernet   * work as non-root, but we need SOCK_PACKET to specify the Ethernet
# Line 92  void bb_debug_dump_packet(unsigned char Line 92  void bb_debug_dump_packet(unsigned char
92   printf("packet dump:\n");   printf("packet dump:\n");
93   for (i = 0; i < pktsize; ++i) {   for (i = 0; i < pktsize; ++i) {
94   printf("%2.2x ", outpack[i]);   printf("%2.2x ", outpack[i]);
95   if (i % 20 == 19) puts("");   if (i % 20 == 19) bb_putchar('\n');
96   }   }
97   printf("\n\n");   printf("\n\n");
98  }  }
99  #else  #else
100  # define bb_debug_msg(fmt, args...)  # define bb_debug_msg(fmt, args...)             ((void)0)
101  # define bb_debug_dump_packet(outpack, pktsize)  # define bb_debug_dump_packet(outpack, pktsize) ((void)0)
102  #endif  #endif
103    
104  static inline void get_dest_addr(const char *arg, struct ether_addr *eaddr);  /* Convert the host ID string to a MAC address.
105  static inline int get_fill(unsigned char *pkt, struct ether_addr *eaddr, int broadcast);   * The string may be a:
106  static inline int get_wol_pw(const char *ethoptarg, unsigned char *wol_passwd);   *    Host name
107     *    IP address string
108     *    MAC address string
109    */
110    static void get_dest_addr(const char *hostid, struct ether_addr *eaddr)
111    {
112     struct ether_addr *eap;
113    
114  int ether_wake_main(int argc, char *argv[])   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    
126    static int get_fill(unsigned char *pkt, struct ether_addr *eaddr, int broadcast)
127  {  {
128   char *ifname = "eth0", *pass = NULL;   int i;
129   unsigned long flags;   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    
152    static 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    }
180    
181    int ether_wake_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
182    int ether_wake_main(int argc UNUSED_PARAM, char **argv)
183    {
184     const char *ifname = "eth0";
185     char *pass;
186     unsigned flags;
187   unsigned char wol_passwd[6];   unsigned char wol_passwd[6];
188   int wol_passwd_sz = 0;   int wol_passwd_sz = 0;
   
189   int s; /* Raw socket */   int s; /* Raw socket */
190   int pktsize;   int pktsize;
191   unsigned char outpack[1000];   unsigned char outpack[1000];
# Line 120  int ether_wake_main(int argc, char *argv Line 194  int ether_wake_main(int argc, char *argv
194   struct whereto_t whereto; /* who to wake up */   struct whereto_t whereto; /* who to wake up */
195    
196   /* handle misc user options */   /* handle misc user options */
197   flags = getopt32(argc, argv, "bi:p:", &ifname, &pass);   opt_complementary = "=1";
198   if (optind == argc)   flags = getopt32(argv, "bi:p:", &ifname, &pass);
199   bb_show_usage();   if (flags & 4) /* -p */
  if (pass)  
200   wol_passwd_sz = get_wol_pw(pass, wol_passwd);   wol_passwd_sz = get_wol_pw(pass, wol_passwd);
201     flags &= 1; /* we further interested only in -b [bcast] flag */
202    
203   /* create the raw socket */   /* create the raw socket */
204   s = make_socket();   s = make_socket();
205    
206   /* now that we have a raw socket we can drop root */   /* now that we have a raw socket we can drop root */
207   xsetuid(getuid());   /* xsetuid(getuid()); - but save on code size... */
208    
209   /* look up the dest mac address */   /* look up the dest mac address */
210   get_dest_addr(argv[optind], &eaddr);   get_dest_addr(argv[optind], &eaddr);
211    
212   /* fill out the header of the packet */   /* fill out the header of the packet */
213   pktsize = get_fill(outpack, &eaddr, flags /*& 1 [OPT_BROADCAST]*/);   pktsize = get_fill(outpack, &eaddr, flags /* & 1 OPT_BROADCAST */);
214    
215   bb_debug_dump_packet(outpack, pktsize);   bb_debug_dump_packet(outpack, pktsize);
216    
# Line 146  int ether_wake_main(int argc, char *argv Line 220  int ether_wake_main(int argc, char *argv
220   struct ifreq if_hwaddr;   struct ifreq if_hwaddr;
221    
222   strncpy(if_hwaddr.ifr_name, ifname, sizeof(if_hwaddr.ifr_name));   strncpy(if_hwaddr.ifr_name, ifname, sizeof(if_hwaddr.ifr_name));
223   if (ioctl(s, SIOCGIFHWADDR, &if_hwaddr) < 0)   ioctl_or_perror_and_die(s, SIOCGIFHWADDR, &if_hwaddr, "SIOCGIFHWADDR on %s failed", ifname);
  bb_perror_msg_and_die("SIOCGIFHWADDR on %s failed", ifname);  
224    
225   memcpy(outpack+6, if_hwaddr.ifr_hwaddr.sa_data, 6);   memcpy(outpack+6, if_hwaddr.ifr_hwaddr.sa_data, 6);
226    
# Line 174  int ether_wake_main(int argc, char *argv Line 247  int ether_wake_main(int argc, char *argv
247   bb_debug_dump_packet(outpack, pktsize);   bb_debug_dump_packet(outpack, pktsize);
248    
249   /* This is necessary for broadcasts to work */   /* This is necessary for broadcasts to work */
250   if (flags /*& 1 [OPT_BROADCAST]*/) {   if (flags /* & 1 OPT_BROADCAST */) {
251   if (setsockopt_broadcast(s) < 0)   if (setsockopt_broadcast(s) != 0)
252   bb_perror_msg("SO_BROADCAST");   bb_perror_msg("SO_BROADCAST");
253   }   }
254    
# Line 183  int ether_wake_main(int argc, char *argv Line 256  int ether_wake_main(int argc, char *argv
256   {   {
257   struct ifreq ifr;   struct ifreq ifr;
258   strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));   strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
259   if (ioctl(s, SIOCGIFINDEX, &ifr) == -1)   xioctl(s, SIOCGIFINDEX, &ifr);
  bb_perror_msg_and_die("SIOCGIFINDEX");  
260   memset(&whereto, 0, sizeof(whereto));   memset(&whereto, 0, sizeof(whereto));
261   whereto.sll_family = AF_PACKET;   whereto.sll_family = AF_PACKET;
262   whereto.sll_ifindex = ifr.ifr_ifindex;   whereto.sll_ifindex = ifr.ifr_ifindex;
# Line 197  int ether_wake_main(int argc, char *argv Line 269  int ether_wake_main(int argc, char *argv
269   whereto.sa_family = 0;   whereto.sa_family = 0;
270   strcpy(whereto.sa_data, ifname);   strcpy(whereto.sa_data, ifname);
271  #endif  #endif
272     xsendto(s, outpack, pktsize, (struct sockaddr *)&whereto, sizeof(whereto));
273   if (sendto(s, outpack, pktsize, 0, (struct sockaddr *)&whereto, sizeof(whereto)) < 0)   if (ENABLE_FEATURE_CLEAN_UP)
274   bb_perror_msg(bb_msg_write_error);   close(s);
   
  close(s);  
   
275   return EXIT_SUCCESS;   return EXIT_SUCCESS;
276  }  }
   
 /* Convert the host ID string to a MAC address.  
  * The string may be a:  
  *    Host name  
  *    IP address string  
  *    MAC address string  
 */  
 static inline void get_dest_addr(const char *hostid, struct ether_addr *eaddr)  
 {  
  struct ether_addr *eap;  
   
  eap = ether_aton(hostid);  
  if (eap) {  
  *eaddr = *eap;  
  bb_debug_msg("The target station address is %s\n\n", ether_ntoa(eaddr));  
 #if !defined(__UCLIBC__)  
  } else if (ether_hostton(hostid, eaddr) == 0) {  
  bb_debug_msg("Station address for hostname %s is %s\n\n", hostid, ether_ntoa(eaddr));  
 #else  
 # warning Need to implement ether_hostton() for uClibc  
 #endif  
  } else  
  bb_show_usage();  
 }  
   
 static inline int get_fill(unsigned char *pkt, struct ether_addr *eaddr, int broadcast)  
 {  
  int offset, i;  
  unsigned char *station_addr = eaddr->ether_addr_octet;  
   
  if (broadcast)  
  memset(pkt+0, 0xff, 6);  
  else  
  memcpy(pkt, station_addr, 6);  
  memcpy(pkt+6, station_addr, 6);  
  pkt[12] = 0x08; /* Or 0x0806 for ARP, 0x8035 for RARP */  
  pkt[13] = 0x42;  
  offset = 14;  
   
  memset(pkt+offset, 0xff, 6);  
  offset += 6;  
   
  for (i = 0; i < 16; ++i) {  
  memcpy(pkt+offset, station_addr, 6);  
  offset += 6;  
  }  
   
  return offset;  
 }  
   
 static inline int get_wol_pw(const char *ethoptarg, unsigned char *wol_passwd)  
 {  
  int passwd[6];  
  int byte_cnt, i;  
   
  /* handle MAC format */  
  byte_cnt = sscanf(ethoptarg, "%2x:%2x:%2x:%2x:%2x:%2x",  
                   &passwd[0], &passwd[1], &passwd[2],  
                   &passwd[3], &passwd[4], &passwd[5]);  
  /* handle IP format */  
  if (byte_cnt < 4)  
  byte_cnt = sscanf(ethoptarg, "%d.%d.%d.%d",  
                   &passwd[0], &passwd[1], &passwd[2], &passwd[3]);  
  if (byte_cnt < 4) {  
  bb_error_msg("cannot read Wake-On-LAN pass");  
  return 0;  
  }  
   
  for (i = 0; i < byte_cnt; ++i)  
  wol_passwd[i] = passwd[i];  
   
  bb_debug_msg("password: %2.2x %2.2x %2.2x %2.2x (%d)\n\n",  
              wol_passwd[0], wol_passwd[1], wol_passwd[2], wol_passwd[3],  
              byte_cnt);  
   
  return byte_cnt;  
 }  

Legend:
Removed from v.532  
changed lines
  Added in v.816