/* ----------------------------------------------------------------------- * * * Copyright 2007 H. Peter Anvin - All Rights Reserved * Copyright 2011 Timothy J Gleason <timmgleason_at_gmail.com> - All Rights Reserved * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom * the Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall * be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * ----------------------------------------------------------------------- */ /* * dhcp.c * * Adds DHCPINFO functionality to the lua.c32 binary * * gettable() returns a table of the BOOTP message fields returned by * the DHCP server for use in a Lua pxeboot script * See http://tools.ietf.org/html/rfc1542 * * lua key value RFC key * ----------------------------------------------------------------------- * opcode op message opcode * hardware.type htype Hardware address type * hardware.length hlen Hardware address length * hops hops Used by relay agents * transaction.id xid transaction id * elapsed.seconds secs Secs elapsed since client boot * flags flags DHCP Flags field * client.ip.addr ciaddr client IP addr * your.ip.addr yiaddr 'Your' IP addr. (from server) * server.ip.addr siaddr Boot server IP addr * gateway.ip.addr giaddr Relay agent IP addr * client.mac chaddr Client hardware addr * server.hostname sname Optl. boot server hostname * boot.file file boot file name (ascii path) * magic.cookie cookie Magic cookie * * getoptions() returns a table of the DHCP Options field of the BOOTP * message returned by the DHCP server for use in a Lua pxeboot script. * Many of the options are reurned formatted in as strings in a standard, * recognizable format, such as IP addresses. * * 1, 2, and 4 byte numerical options are returned as integers. * * Other Options with non-standard formats are returned as strings of the * raw binary number that was returned by the DHCP server and must be decoded * in a Lua script * * The Options table returns the Option code as the key except where there * are multiple values returned. In those cases, an extra key increment number * is added to allow individual access to each Option value. * * lua key value value Name * ----------------------------------------------------------------------- * 1 Subnet Mask * 6.1 DNS Server [element 1] * 6.2 DNS Server [element 2] * 6.3 DNS Server [element 3] * 209 PXE Configuration File * 21.1 Policy Filter [element 1] * 21.2 Policy Filter [element 2] * * Options that can have a list of values, but contain only one (like Option 6) * will not return with .sub key values. * * Usage: t = dhcp.gettable() for k,v in pairs(t) do print(k.." : "..v) end */ #include <stdio.h> #include "dhcp.h" #include "lua.h" #include "lauxlib.h" #include "lualib.h" #include <syslinux/pxe.h> #define STR_BUF_SIZE 129 /* Sized to accomdate File field in BOOTP message */ void ip_address_list(lua_State *L, uint8_t* value, uint8_t len, uint8_t option ) { static char op_name[64]; static char op_value[255]; int loop; loop = len/4; if ( loop == 1) { sprintf(op_name, "%u", option); lua_pushstring(L, op_name); sprintf(op_value, "%u.%u.%u.%u", value[0], value[1], value[2], value[3]); lua_pushstring(L, op_value); lua_settable(L,-3); } else { for (int done = 0; done < loop; done++){ sprintf(op_name, "%u.%d", option, done+1); lua_pushstring(L, op_name); sprintf(op_value, "%u.%u.%u.%u", value[0+(done*4)], value[1+(done*4)], value[2+(done*4)], value[3+(done*4)]); lua_pushstring(L, op_value); lua_settable(L,-3); } } } static int dhcp_getoptions(lua_State *L) { void* dhcpdata = 0; dhcp_t* dhcp = 0; size_t dhcplen = 0; /* Append the DHCP info */ if (pxe_get_cached_info(PXENV_PACKET_TYPE_DHCP_ACK, &dhcpdata, &dhcplen)) { return 0; } dhcp = (dhcp_t*)dhcpdata; lua_newtable(L); int done = 0; uint8_t* ptr = (uint8_t*)&dhcp->options; uint8_t len; uint8_t option; uint8_t* value; static char op_name[64]; do { option = *ptr++; len = *ptr++; value = ptr; ptr += len; switch (option) { // IP Address formatted lists, including singles case 1: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 16: case 21: /* Policy Filters - address/mask */ case 28: case 32: case 33: /* Static routes - destination/router */ case 41: case 42: case 44: case 45: case 47: case 48: case 49: case 50: case 51: case 54: case 65: case 68: case 69: case 70: case 71: case 72: case 73: case 74: case 75: case 76: ip_address_list(L, value, len, option); break; // 4byte options - numerical case 2: case 24: case 35: case 38: case 58: case 59: case 211: sprintf(op_name, "%u", option); lua_pushstring(L, op_name); lua_pushinteger(L, ntohl(*(long*)value)); lua_settable(L,-3); break; // 2byte options -numerical case 13: case 22: case 26: case 57: sprintf(op_name, "%u", option); lua_pushstring(L, op_name); lua_pushinteger(L, ntohs(*(short*)value)); lua_settable(L,-3); break; // 1byte options - numerical case 19: case 20: case 23: case 27: case 29: case 30: case 31: case 34: case 36: case 37: case 39: case 46: case 52: case 53: sprintf(op_name, "%u", option); lua_pushstring(L, op_name); lua_pushinteger(L, *value); lua_settable(L,-3); break; case 255: done = 1; break; default: sprintf(op_name, "%u", option); lua_pushstring(L, op_name); lua_pushlstring(L, (const char*)value, len); lua_settable(L,-3); break; } } while (!done); return 1; } static int dhcp_gettable(lua_State *L) { void* dhcpdata = 0; dhcp_t* dhcp = 0; size_t dhcplen = 0; static char dhcp_arg[STR_BUF_SIZE]; /* Append the DHCP info */ if (pxe_get_cached_info(PXENV_PACKET_TYPE_DHCP_ACK, &dhcpdata, &dhcplen)) { return 0; } dhcp = (dhcp_t*)dhcpdata; lua_newtable(L); lua_pushstring(L, "opcode"); lua_pushinteger(L, dhcp->op); lua_settable(L,-3); lua_pushstring(L, "hardware.type"); lua_pushinteger(L, dhcp->htype); lua_settable(L,-3); lua_pushstring(L, "hardware.length"); lua_pushinteger(L, dhcp->hlen); lua_settable(L,-3); lua_pushstring(L, "hops"); lua_pushinteger(L, dhcp->hops); lua_settable(L,-3); lua_pushstring(L, "transaction.id"); lua_pushinteger(L, ntohl(dhcp->xid)); lua_settable(L,-3); lua_pushstring(L, "elapsed.seconds"); lua_pushinteger(L, ntohs(dhcp->secs)); lua_settable(L,-3); lua_pushstring(L, "flags"); lua_pushinteger(L, ntohs(dhcp->flags)); lua_settable(L,-3); sprintf(dhcp_arg, "%u.%u.%u.%u", dhcp->ciaddr[0], dhcp->ciaddr[1], dhcp->ciaddr[2], dhcp->ciaddr[3]); lua_pushstring(L, "client.ip.addr"); lua_pushstring(L, dhcp_arg); lua_settable(L,-3); sprintf(dhcp_arg, "%u.%u.%u.%u", dhcp->yiaddr[0], dhcp->yiaddr[1], dhcp->yiaddr[2], dhcp->yiaddr[3]); lua_pushstring(L, "your.ip.addr"); lua_pushstring(L, dhcp_arg); lua_settable(L,-3); sprintf(dhcp_arg, "%u.%u.%u.%u", dhcp->siaddr[0], dhcp->siaddr[1], dhcp->siaddr[2], dhcp->siaddr[3]); lua_pushstring(L, "server.ip.addr"); lua_pushstring(L, dhcp_arg); lua_settable(L,-3); sprintf(dhcp_arg, "%u.%u.%u.%u", dhcp->giaddr[0], dhcp->giaddr[1], dhcp->giaddr[2], dhcp->giaddr[3]); lua_pushstring(L, "gateway.ip.addr"); lua_pushstring(L, dhcp_arg); lua_settable(L,-3); sprintf(dhcp_arg, "%02X:%02X:%02X:%02X:%02X:%02X", dhcp->chaddr[0], dhcp->chaddr[1], dhcp->chaddr[2], dhcp->chaddr[3], dhcp->chaddr[4], dhcp->chaddr[5]); lua_pushstring(L, "client.mac"); lua_pushstring(L, dhcp_arg); lua_settable(L,-3); snprintf(dhcp_arg, STR_BUF_SIZE, "%s", dhcp->sname); dhcp_arg[STR_BUF_SIZE-1] = 0; /* Guarantee for lua_pushstring that dhcp_arg is 0 terminated /*/ lua_pushstring(L, "server.hostname"); lua_pushstring(L, dhcp_arg); lua_settable(L,-3); snprintf(dhcp_arg, STR_BUF_SIZE, "%s", dhcp->file); dhcp_arg[STR_BUF_SIZE-1] = 0; /* Guarantee for lua_pushstring that dhcp_arg is 0 terminated /*/ lua_pushstring(L, "boot.file"); lua_pushstring(L, dhcp_arg); lua_settable(L,-3); sprintf(dhcp_arg, "%u.%u.%u.%u", dhcp->cookie[0], dhcp->cookie[1], dhcp->cookie[2], dhcp->cookie[3]); lua_pushstring(L, "magic.cookie"); lua_pushstring(L, dhcp_arg); lua_settable(L,-3); return 1; } static const luaL_Reg dhcplib[] = { {"gettable", dhcp_gettable}, {"getoptions", dhcp_getoptions}, {NULL, NULL} }; LUALIB_API int luaopen_dhcp (lua_State *L) { luaL_newlib(L, dhcplib); return 1; }