• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ----------------------------------------------------------------------- *
2  *
3  *   Copyright 2007 H. Peter Anvin - All Rights Reserved
4  *   Copyright 2011 Timothy J Gleason <timmgleason_at_gmail.com> - All Rights Reserved
5  *
6  *   Permission is hereby granted, free of charge, to any person
7  *   obtaining a copy of this software and associated documentation
8  *   files (the "Software"), to deal in the Software without
9  *   restriction, including without limitation the rights to use,
10  *   copy, modify, merge, publish, distribute, sublicense, and/or
11  *   sell copies of the Software, and to permit persons to whom
12  *   the Software is furnished to do so, subject to the following
13  *   conditions:
14  *
15  *   The above copyright notice and this permission notice shall
16  *   be included in all copies or substantial portions of the Software.
17  *
18  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20  *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22  *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23  *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  *   OTHER DEALINGS IN THE SOFTWARE.
26  *
27  * ----------------------------------------------------------------------- */
28 
29 /*
30  * dhcp.c
31  *
32  * Adds DHCPINFO functionality to the lua.c32 binary
33  *
34  * gettable() returns a table of the BOOTP message fields returned by
35  * the DHCP server for use in a Lua pxeboot script
36  * See http://tools.ietf.org/html/rfc1542
37  *
38  *	lua key value		RFC key
39  * -----------------------------------------------------------------------
40  *	opcode			op	 message opcode
41  *	hardware.type		htype	 Hardware address type
42  *	hardware.length		hlen	 Hardware address length
43  *	hops			hops	 Used by relay agents
44  *	transaction.id		xid	 transaction id
45  *	elapsed.seconds		secs	 Secs elapsed since client boot
46  *	flags			flags	 DHCP Flags field
47  *	client.ip.addr		ciaddr	 client IP addr
48  *	your.ip.addr		yiaddr	 'Your' IP addr. (from server)
49  *	server.ip.addr		siaddr	 Boot server IP addr
50  *	gateway.ip.addr		giaddr	 Relay agent IP addr
51  *	client.mac		chaddr	 Client hardware addr
52  *	server.hostname		sname	 Optl. boot server hostname
53  * 	boot.file		file	 boot file name (ascii path)
54  *	magic.cookie		cookie	 Magic cookie
55  *
56  * getoptions() returns a table of the DHCP Options field of the BOOTP
57  * message returned by the DHCP server for use in a Lua pxeboot script.
58  * Many of the options are reurned formatted in as strings in a standard,
59  * recognizable format, such as IP addresses.
60  *
61  * 1, 2, and 4 byte numerical options are returned as integers.
62  *
63  * Other Options with non-standard formats are returned as strings of the
64  * raw binary number that was returned by the DHCP server and must be decoded
65  * in a Lua script
66  *
67  * The Options table returns the Option code as the key except where there
68  * are multiple values returned. In those cases, an extra key increment number
69  * is added to allow individual access to each Option value.
70  *
71  *	lua key value		value Name
72  * -----------------------------------------------------------------------
73  *	1			Subnet Mask
74  *	6.1			DNS Server [element 1]
75  *	6.2			DNS Server [element 2]
76  *	6.3			DNS Server [element 3]
77  *	209			PXE Configuration File
78  *	21.1			Policy Filter [element 1]
79  *	21.2			Policy Filter [element 2]
80  *
81  * Options that can have a list of values, but contain only one (like Option 6)
82  * will not return with .sub key values.
83  *
84  * Usage:
85             t = dhcp.gettable()
86 
87             for k,v in pairs(t) do
88               print(k.." : "..v)
89             end
90  */
91 
92 #include <stdio.h>
93 #include "dhcp.h"
94 #include "lua.h"
95 #include "lauxlib.h"
96 #include "lualib.h"
97 #include <syslinux/pxe.h>
98 
99 #define STR_BUF_SIZE	129 /* Sized to accomdate File field in BOOTP message */
100 
101 void
ip_address_list(lua_State * L,uint8_t * value,uint8_t len,uint8_t option)102 ip_address_list(lua_State *L, uint8_t* value, uint8_t len, uint8_t option )
103 {
104   static char	op_name[64];
105   static char	op_value[255];
106   int		loop;
107 
108   loop = len/4;
109 
110   if ( loop == 1) {
111     sprintf(op_name, "%u", option);
112     lua_pushstring(L, op_name);
113     sprintf(op_value, "%u.%u.%u.%u", value[0], value[1], value[2], value[3]);
114     lua_pushstring(L, op_value);
115     lua_settable(L,-3);
116   } else {
117       for (int done = 0; done < loop; done++){
118 	sprintf(op_name, "%u.%d", option, done+1);
119 	lua_pushstring(L, op_name);
120 	sprintf(op_value, "%u.%u.%u.%u", value[0+(done*4)], value[1+(done*4)], value[2+(done*4)], value[3+(done*4)]);
121 	lua_pushstring(L, op_value);
122 	lua_settable(L,-3);
123       }
124   }
125 
126 }
127 
dhcp_getoptions(lua_State * L)128 static int dhcp_getoptions(lua_State *L)
129 {
130   void*		dhcpdata = 0;
131   dhcp_t*	dhcp = 0;
132   size_t	dhcplen = 0;
133 
134   /* Append the DHCP info */
135   if (pxe_get_cached_info(PXENV_PACKET_TYPE_DHCP_ACK,
136     &dhcpdata, &dhcplen))
137   {
138     return 0;
139   }
140 
141   dhcp = (dhcp_t*)dhcpdata;
142 
143   lua_newtable(L);
144 
145   int		done = 0;
146   uint8_t*	ptr = (uint8_t*)&dhcp->options;
147   uint8_t	len;
148   uint8_t	option;
149   uint8_t*	value;
150   static char	op_name[64];
151 
152   do {
153       option = *ptr++;
154       len = *ptr++;
155       value = ptr;
156       ptr += len;
157       switch (option) {
158 // IP Address formatted lists, including singles
159 	case 1:
160 	case 3:
161 	case 4:
162 	case 5:
163 	case 6:
164 	case 7:
165 	case 8:
166 	case 9:
167 	case 10:
168 	case 11:
169 	case 16:
170 	case 21: /* Policy Filters - address/mask */
171 	case 28:
172 	case 32:
173 	case 33: /* Static routes - destination/router */
174 	case 41:
175 	case 42:
176 	case 44:
177 	case 45:
178 	case 47:
179 	case 48:
180 	case 49:
181 	case 50:
182 	case 51:
183 	case 54:
184 	case 65:
185 	case 68:
186 	case 69:
187 	case 70:
188 	case 71:
189 	case 72:
190 	case 73:
191 	case 74:
192 	case 75:
193 	case 76:
194 	  ip_address_list(L, value, len, option);
195           break;
196 // 4byte options - numerical
197         case 2:
198         case 24:
199         case 35:
200         case 38:
201         case 58:
202         case 59:
203         case 211:
204 	  sprintf(op_name, "%u", option);
205 	  lua_pushstring(L, op_name);
206 	  lua_pushinteger(L, ntohl(*(long*)value));
207 	  lua_settable(L,-3);
208           break;
209 // 2byte options -numerical
210         case 13:
211         case 22:
212         case 26:
213         case 57:
214 	  sprintf(op_name, "%u", option);
215 	  lua_pushstring(L, op_name);
216 	  lua_pushinteger(L, ntohs(*(short*)value));
217 	  lua_settable(L,-3);
218           break;
219 // 1byte options - numerical
220         case 19:
221         case 20:
222         case 23:
223         case 27:
224         case 29:
225         case 30:
226         case 31:
227         case 34:
228         case 36:
229         case 37:
230         case 39:
231         case 46:
232         case 52:
233         case 53:
234 	  sprintf(op_name, "%u", option);
235 	  lua_pushstring(L, op_name);
236 	  lua_pushinteger(L, *value);
237 	  lua_settable(L,-3);
238           break;
239         case 255:
240           done = 1;
241 	  break;
242         default:
243 	  sprintf(op_name, "%u", option);
244 	  lua_pushstring(L, op_name);
245 	  lua_pushlstring(L, (const char*)value, len);
246 	  lua_settable(L,-3);
247           break;
248       }
249 
250     } while (!done);
251 
252   return 1;
253 }
254 
dhcp_gettable(lua_State * L)255 static int	dhcp_gettable(lua_State *L)
256 {
257   void*		dhcpdata = 0;
258   dhcp_t*	dhcp = 0;
259   size_t	dhcplen = 0;
260   static char	dhcp_arg[STR_BUF_SIZE];
261 
262   /* Append the DHCP info */
263   if (pxe_get_cached_info(PXENV_PACKET_TYPE_DHCP_ACK,
264     &dhcpdata, &dhcplen))
265   {
266     return 0;
267   }
268 
269   dhcp = (dhcp_t*)dhcpdata;
270 
271 
272   lua_newtable(L);
273 
274   lua_pushstring(L, "opcode");
275   lua_pushinteger(L, dhcp->op);
276   lua_settable(L,-3);
277 
278   lua_pushstring(L, "hardware.type");
279   lua_pushinteger(L, dhcp->htype);
280   lua_settable(L,-3);
281 
282   lua_pushstring(L, "hardware.length");
283   lua_pushinteger(L, dhcp->hlen);
284   lua_settable(L,-3);
285 
286   lua_pushstring(L, "hops");
287   lua_pushinteger(L, dhcp->hops);
288   lua_settable(L,-3);
289 
290   lua_pushstring(L, "transaction.id");
291   lua_pushinteger(L, ntohl(dhcp->xid));
292   lua_settable(L,-3);
293 
294   lua_pushstring(L, "elapsed.seconds");
295   lua_pushinteger(L, ntohs(dhcp->secs));
296   lua_settable(L,-3);
297 
298   lua_pushstring(L, "flags");
299   lua_pushinteger(L, ntohs(dhcp->flags));
300   lua_settable(L,-3);
301 
302   sprintf(dhcp_arg, "%u.%u.%u.%u", dhcp->ciaddr[0], dhcp->ciaddr[1], dhcp->ciaddr[2], dhcp->ciaddr[3]);
303   lua_pushstring(L, "client.ip.addr");
304   lua_pushstring(L, dhcp_arg);
305   lua_settable(L,-3);
306 
307   sprintf(dhcp_arg, "%u.%u.%u.%u", dhcp->yiaddr[0], dhcp->yiaddr[1], dhcp->yiaddr[2], dhcp->yiaddr[3]);
308   lua_pushstring(L, "your.ip.addr");
309   lua_pushstring(L, dhcp_arg);
310   lua_settable(L,-3);
311 
312   sprintf(dhcp_arg, "%u.%u.%u.%u", dhcp->siaddr[0], dhcp->siaddr[1], dhcp->siaddr[2], dhcp->siaddr[3]);
313   lua_pushstring(L, "server.ip.addr");
314   lua_pushstring(L, dhcp_arg);
315   lua_settable(L,-3);
316 
317   sprintf(dhcp_arg, "%u.%u.%u.%u", dhcp->giaddr[0], dhcp->giaddr[1], dhcp->giaddr[2], dhcp->giaddr[3]);
318   lua_pushstring(L, "gateway.ip.addr");
319   lua_pushstring(L, dhcp_arg);
320   lua_settable(L,-3);
321 
322   sprintf(dhcp_arg, "%02X:%02X:%02X:%02X:%02X:%02X",
323                     dhcp->chaddr[0], dhcp->chaddr[1], dhcp->chaddr[2],
324                     dhcp->chaddr[3], dhcp->chaddr[4], dhcp->chaddr[5]);
325   lua_pushstring(L, "client.mac");
326   lua_pushstring(L, dhcp_arg);
327   lua_settable(L,-3);
328 
329   snprintf(dhcp_arg, STR_BUF_SIZE, "%s", dhcp->sname);
330   dhcp_arg[STR_BUF_SIZE-1] = 0; 	/* Guarantee for lua_pushstring that dhcp_arg is 0 terminated /*/
331   lua_pushstring(L, "server.hostname");
332   lua_pushstring(L, dhcp_arg);
333   lua_settable(L,-3);
334 
335   snprintf(dhcp_arg, STR_BUF_SIZE, "%s", dhcp->file);
336   dhcp_arg[STR_BUF_SIZE-1] = 0; 	/* Guarantee for lua_pushstring that dhcp_arg is 0 terminated /*/
337   lua_pushstring(L, "boot.file");
338   lua_pushstring(L, dhcp_arg);
339   lua_settable(L,-3);
340 
341   sprintf(dhcp_arg, "%u.%u.%u.%u", dhcp->cookie[0], dhcp->cookie[1], dhcp->cookie[2], dhcp->cookie[3]);
342   lua_pushstring(L, "magic.cookie");
343   lua_pushstring(L, dhcp_arg);
344   lua_settable(L,-3);
345 
346   return 1;
347 }
348 
349 static const luaL_Reg dhcplib[] = {
350   {"gettable", dhcp_gettable},
351   {"getoptions", dhcp_getoptions},
352   {NULL, NULL}
353 };
354 
luaopen_dhcp(lua_State * L)355 LUALIB_API int luaopen_dhcp (lua_State *L) {
356   luaL_newlib(L, dhcplib);
357   return 1;
358 }
359