1 /*
2 * wol - wake on lan client
3 *
4 * create and assemble magic packets
5 *
6 * $Id: magic.c,v 1.9 2003/08/12 16:45:22 wol Exp $
7 *
8 * Copyright (C) 2000-2003 Thomas Krennwallner <krennwallner@aon.at>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 */
24
25
26
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif /* HAVE_CONFIG_H */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <errno.h>
34 #include <string.h> /* memset() in HP-UX */
35
36 #include "wrappers.h"
37 #include "xalloc.h"
38 #include "wol.h"
39 #include "magic.h"
40
41
42
43 /*
44 * How a Magic Packet Frame looks like:
45 *
46 * _________________________________________
47 * | 0xff | 0xff | 0xff | 0xff | 0xff | 0xff |
48 * |MAC[0]|MAC[1]|MAC[2]|MAC[3]|MAC[4]|MAC[5]|
49 * |MAC[0]|MAC[1]|MAC[2]|MAC[3]|MAC[4]|MAC[5]|
50 * |MAC[0]|MAC[1]|MAC[2]|MAC[3]|MAC[4]|MAC[5]|
51 * |MAC[0]|MAC[1]|MAC[2]|MAC[3]|MAC[4]|MAC[5]|
52 * |MAC[0]|MAC[1]|MAC[2]|MAC[3]|MAC[4]|MAC[5]|
53 * |MAC[0]|MAC[1]|MAC[2]|MAC[3]|MAC[4]|MAC[5]|
54 * |MAC[0]|MAC[1]|MAC[2]|MAC[3]|MAC[4]|MAC[5]|
55 * |MAC[0]|MAC[1]|MAC[2]|MAC[3]|MAC[4]|MAC[5]|
56 * |MAC[0]|MAC[1]|MAC[2]|MAC[3]|MAC[4]|MAC[5]|
57 * |MAC[0]|MAC[1]|MAC[2]|MAC[3]|MAC[4]|MAC[5]|
58 * |MAC[0]|MAC[1]|MAC[2]|MAC[3]|MAC[4]|MAC[5]|
59 * |MAC[0]|MAC[1]|MAC[2]|MAC[3]|MAC[4]|MAC[5]|
60 * |MAC[0]|MAC[1]|MAC[2]|MAC[3]|MAC[4]|MAC[5]|
61 * |MAC[0]|MAC[1]|MAC[2]|MAC[3]|MAC[4]|MAC[5]|
62 * |MAC[0]|MAC[1]|MAC[2]|MAC[3]|MAC[4]|MAC[5]|
63 * |MAC[0]|MAC[1]|MAC[2]|MAC[3]|MAC[4]|MAC[5]|
64 * -----------------------------------------
65 * optional SecureON (tm) password:
66 * _________________________________________
67 * |PASS0 |PASS1 |PASS2 |PASS3 |PASS4 |PASS5 |
68 * -----------------------------------------
69 */
70
71
72 /* struct for typecasting a normal magic packet */
73 struct
74 packet
75 {
76 unsigned char header[MAGIC_HEADER];
77 unsigned char addr[MAGIC_TIMES][MAC_LEN];
78 };
79
80 /* struct for typecasting a SecureON magic packet */
81 struct
82 secureon
83 {
84 unsigned char header[MAGIC_HEADER];
85 unsigned char addr[MAGIC_TIMES][MAC_LEN];
86 unsigned char passwd[MAGIC_SECUREON];
87 };
88
89
90
91 struct magic *
magic_create(int with_passwd)92 magic_create (int with_passwd)
93 {
94 struct magic *mag;
95
96 mag = (struct magic *) xmalloc (sizeof (struct magic));
97
98 if (with_passwd)
99 mag->size = sizeof (struct secureon);
100 else
101 mag->size = sizeof (struct packet);
102
103 mag->packet = (unsigned char *) xmalloc (mag->size);
104
105 return mag;
106 }
107
108
109
110 void
magic_destroy(struct magic * m)111 magic_destroy (struct magic *m)
112 {
113 XFREE ((void *) m->packet);
114 XFREE ((void *) m);
115 }
116
117
118
119 int
magic_assemble(struct magic * magic_buf,const char * mac_str,const char * passwd_str)120 magic_assemble (struct magic *magic_buf, const char *mac_str,
121 const char *passwd_str)
122 {
123 int m[MAC_LEN];
124 int j, k;
125
126
127 if (mac_str == NULL || magic_buf == NULL) return -1;
128
129 /* split the MAC address string into it's hex components */
130 if (sscanf (mac_str, "%2x:%2x:%2x:%2x:%2x:%2x",
131 &m[0], &m[1], &m[2], &m[3], &m[4], &m[5]) != MAC_LEN)
132 {
133 struct ether_addr ea;
134
135 /* lets parse /etc/ethers for ethernet name resolving
136 * FIXME: ether_hostton() is not implemented on every platform
137 */
138 if (ether_hostton (mac_str, &ea))
139 {
140 errno = EINVAL;
141 return -1;
142 }
143
144 for (j = 0; j < MAC_LEN; ++j)
145 m[j] = ea.ETHER_ADDR_OCTET[j];
146 }
147
148 /* accommodate the packet chunk's size to the packet type */
149 if (passwd_str && magic_buf->size != sizeof (struct secureon))
150 {
151 magic_buf->packet = \
152 (unsigned char *) xrealloc ((void *) magic_buf->packet,
153 sizeof (struct secureon));
154 magic_buf->size = sizeof (struct secureon);
155 }
156 else if (passwd_str == NULL && magic_buf->size != sizeof (struct packet))
157 {
158 magic_buf->packet = \
159 (unsigned char *) xrealloc ((void *) magic_buf->packet,
160 sizeof (struct packet));
161 magic_buf->size = sizeof (struct packet);
162 }
163
164
165 /* assemble magic packet header */
166 memset ((void *) magic_buf->packet, 0xff, MAGIC_HEADER);
167
168 /* and now the data */
169 for (j = 0; j < MAGIC_TIMES; j++)
170 {
171 for (k = 0; k < MAC_LEN; k++)
172 ((struct packet *) magic_buf->packet)->addr[j][k] = \
173 (unsigned char) m[k];
174 }
175
176 /* add the SecureON passwd */
177 if (passwd_str)
178 {
179 int s[MAGIC_SECUREON];
180
181 /* split the password string into it's hex components */
182 if (sscanf (passwd_str, "%2x-%2x-%2x-%2x-%2x-%2x",
183 &s[0], &s[1], &s[2], &s[3], &s[4], &s[5]) != MAGIC_SECUREON)
184 {
185 errno = EINVAL;
186 return -2;
187 }
188
189 for (j = 0; j < MAGIC_SECUREON; j++)
190 ((struct secureon *) magic_buf->packet)->passwd[j] = \
191 (unsigned char) s[j];
192 }
193
194 return 0;
195 }
196