| /* ----------------------------------------------------------------------- * |
| * |
| * 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; |
| } |