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