Home | History | Annotate | Download | only in src
      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
    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 
    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 
    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 
    355 LUALIB_API int luaopen_dhcp (lua_State *L) {
    356   luaL_newlib(L, dhcplib);
    357   return 1;
    358 }
    359