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