📄 packetstore.cc
字号:
if(val != value) return(value); // we now have a standard, can you read this Intel?, this is // STANDARD! // we know that Intel ordering is the opposite to network byte ordering // so just swap bytes all the way through // out t1 = (val & 0x00ff); t2 = (val & 0xff00) >> 8; // in val = (t1<<8); val |= t2; // we are now in a non-standard return val;}/****************************************************************************** * htoil - host to intel order (long) * ******************************************************************************/uint32_tPacketStore::htoil(uint32_t value){ uint8_t t1, t2, t3, t4; uint32_t val; // convert to a standard val = htonl(value); // check if we need to go any further // since Intel order != network order if(val != value) return(value); // we now have a standard, can you read this Intel?, this is // STANDARD! // we know that Intel ordering is the opposite to network byte ordering // so just swap bytes all the way through // out t1 = (val & 0x000000ff); t2 = (val & 0x0000ff00) >> 8; t3 = (val & 0x00ff0000) >> 16; t4 = (val & 0xff000000) >> 24; // in val = (t1<<24); val |= (t2<<16); val |= (t3<<8); val |= (t4); return(val);}/****************************************************************************** * SetAddress - set the address fiel of the packet (from/to) * ******************************************************************************/voidPacketStore::SetAddress(const struct sockaddr_in *_address){ memcpy(&address, _address, sizeof(address));}/****************************************************************************** * MakeReply - generate a reply to an incoming request * ******************************************************************************/intPacketStore::MakeReply(PacketStore &request, Options *config, struct sockaddr_in *server_addr){ // local vars option *opt = NULL; option *req_list = NULL; int pkttype = 0; uint16_t reqCSA; // first, check for a valid bootp packet if(BOOTREQUEST != request.op) { logger->Event(LEVEL_INFO, "MakeReply", 1, "Packet is not a bootp request"); return(-1); } // valid client system arch? reqCSA = request.GetCSA(); if((uint16_t)-1 == reqCSA) { logger->Event(LEVEL_INFO, "MakeReply", 1, "packet contains an unknown client system architecture"); return(-1); } // see if there are any menus for this packet if((uint16_t)-1 == config->CheckMenu(reqCSA)) return(-1); // next, check what the packet type was opt = request(43,71); if(opt == NULL) { logger->Event(LEVEL_INFO, "MakeReply", 1, "Received proxy DHCP packet"); pkttype = 1; } else { delete[] opt->data; delete opt; logger->Event(LEVEL_INFO, "MakeReply", 1, "Received PXE request packet"); pkttype = 2; } // was it a valid request packet? opt = request(53); if((NULL == opt) || (DHCPREQUEST != opt->data[0])) { logger->Event(LEVEL_INFO, "MakeReply", 1, "Packet does not contain a valid DHCP message type"); return(-1); } opt->data[0] = DHCPACK; opt->len = 1; AddOption(opt); delete[] opt->data; delete opt; // is the param request list ok? req_list = request(55); if(NULL == req_list) { logger->Event(LEVEL_INFO, "MakeReply", 1, "No parameter request list found"); return(-1); } // good packet ok, build reply memset(file, 0, 128); memset(sname, 0, 64); // copy over the basic info op = BOOTREPLY; htype = request.htype; hlen = request.hlen; hops = request.hops; xid = request.xid; secs = request.secs; magic_cookie = htonl(MAGIC_COOKIE); // slightly harder memcpy(chaddr, request.chaddr, 16); memset(&ciaddr, 0, sizeof(ciaddr)); memset(&yiaddr, 0, sizeof(yiaddr)); memcpy(&siaddr, &(server_addr->sin_addr), sizeof(siaddr)); memset(&giaddr, 0, sizeof(yiaddr)); // set the destination address memcpy(&address, &(request.address), sizeof(address)); // good, now go through the option list for(int i=0; i < req_list->len; i++) switch(req_list->data[i]) { case 43: if(-1 == GenOpt43(config, reqCSA, request, pkttype)) return(-1); break; case 54: GenOpt54(); break; case 60: GenOpt60(); break; } return(0);}/****************************************************************************** * GenOpt43 - generate reply options * ******************************************************************************/intPacketStore::GenOpt43(Options *config, int reqCSA, PacketStore &request, int pkttype){ option opt, *optptr; struct sockaddr_in t_addr; char *tmpc; int arch_id, menu_id; uint8_t req_layer; int tmpi; opt.major_no = 43; // Proxy DHCP packet if(1 == pkttype) { // minor 1 opt.minor_no = 1; t_addr.sin_addr.s_addr = htonl(config->GetMTFTPAddr()); opt.len = sizeof(t_addr.sin_addr.s_addr); opt.data = new uint8_t[opt.len]; memcpy(opt.data, &(t_addr.sin_addr.s_addr), opt.len); AddOption(&opt); delete [] opt.data; // minor 2 - n.b. Intel byte ordering - do intel have no common sense? opt.minor_no = 2; t_addr.sin_port = htois(config->GetMTFTPcport()); opt.len = sizeof(t_addr.sin_port); opt.data = new uint8_t[opt.len]; memcpy(opt.data, &(t_addr.sin_port), opt.len); AddOption(&opt); delete [] opt.data; // minor 3 - again Intel's bel^Wbig endian opt.minor_no = 3; t_addr.sin_port = htois(config->GetMTFTPsport()); opt.len = sizeof(t_addr.sin_port); opt.data = new uint8_t[opt.len]; memcpy(opt.data, &(t_addr.sin_port), opt.len); AddOption(&opt); delete [] opt.data; // minor 4 opt.minor_no = 4; opt.len = 1; opt.data = new uint8_t[opt.len]; opt.data[0] = MTFTP_OPEN_TIMEOUT; AddOption(&opt); // minor 5 opt.minor_no = 5; opt.data[0] = MTFTP_REOPEN_TIMEOUT; AddOption(&opt); // minor 6 opt.minor_no = 6; opt.data[0] = 0; // check for disabled broad/multicast if(0 == config->UseMulticast()) opt.data[0] |= DISABLE_MULTICAST; if(0 == config->UseBroadcast()) opt.data[0] |= DISABLE_BROADCAST; AddOption(&opt); delete [] opt.data; // minor 7 opt.minor_no = 7; t_addr.sin_addr.s_addr = htonl(config->GetMulticast()); opt.len = sizeof(t_addr.sin_addr.s_addr); opt.data = new uint8_t[opt.len]; memcpy(opt.data, &(t_addr.sin_addr.s_addr), opt.len); AddOption(&opt); delete [] opt.data; // minor 9 - will always be ok, as we checked the menus earlier optptr = config->MakeBootMenu(reqCSA, &arch_id, &menu_id); optptr->major_no = 43; optptr->minor_no = 9; AddOption(optptr); delete [] optptr->data; delete optptr; // minor 10 - the menu opt.minor_no = 10; tmpc = config->GetMenuPrompt(); opt.len = strlen(tmpc)+1; opt.data = new uint8_t[opt.len]; opt.data[0] = config->GetMenuTimeout(); memcpy(opt.data+1, tmpc, opt.len-1); AddOption(&opt); delete [] opt.data; delete [] tmpc; // minor 71 opt.minor_no = 71; opt.len = 4; opt.data = new uint8_t[4]; tmpi = htons(PXE_SERVER_TYPE); memcpy(opt.data, &tmpi, 2); opt.data[2] = 0; req_layer = opt.data[3] = config->GetMinLayer(arch_id, menu_id); AddOption(&opt); delete [] opt.data; } else // PXE layer request { arch_id = reqCSA; // get option 71 fromthe request packet optptr = request(43, 71); menu_id = optptr->data[0]; menu_id <<= 8; menu_id |= optptr->data[1]; // don't worry about the third byte, it is for 'credentials' req_layer = optptr->data[3]; // make the reply option opt.minor_no = 71; opt.len = 4; opt.data = new uint8_t[opt.len]; memcpy(opt.data, optptr->data, 2); opt.data[2] = 0; delete [] optptr->data; delete optptr; // which layer to get next/any if(config->CheckLayer(menu_id, arch_id, req_layer) == 0) { opt.data[3] = req_layer; } else { delete [] opt.data; return(-1); } AddOption(&opt); delete [] opt.data; } // make filename tmpc = config->MakeFilename(menu_id, arch_id, req_layer); if(strlen(tmpc) > 127) // gotta think of a better way tmpi = 127; else tmpi = strlen(tmpc); memcpy(file, tmpc, tmpi); file[tmpi] = 0; delete [] tmpc; // cool, send the reply return(0);}/****************************************************************************** * GenOpt54 - generate reply options * ******************************************************************************/intPacketStore::GenOpt54(void){ option opt; opt.len = sizeof(siaddr.s_addr); opt.major_no = 54; opt.minor_no = 0; opt.data = new uint8_t[opt.len]; memcpy(opt.data, &(siaddr.s_addr), opt.len); AddOption(&opt); delete [] opt.data; return(0);}/****************************************************************************** * GenOpt60 - generate reply options * ******************************************************************************/intPacketStore::GenOpt60(void){ option opt; opt.major_no=60; opt.minor_no=0; opt.len = strlen(DHCP_T60); opt.data = new uint8_t[opt.len]; memcpy(opt.data, DHCP_T60, opt.len); AddOption(&opt); delete [] opt.data; return(0);}/****************************************************************************** * GetCSA - get the Client System Archetecture of the packet * ******************************************************************************/uint16_tPacketStore::GetCSA(void){ uint16_t csa1, csa2; option *opt; char csac[6]; int csa1_nok=0; int csa2_nok=0; // should have received two copies of the csa, compare csa1 = csa2 = 0; // the binary packed copy opt = GetOption(93); if(NULL == opt) csa1_nok = 1; else { memcpy(&csa1, opt->data, 2); csa1 = ntohs(csa1); delete [] opt->data; delete opt; } // get the ascii packed version opt = GetOption(60); if(NULL == opt) csa2_nok = 1; else if(32 != opt->len) { csa2_nok = 1; delete [] opt->data; delete opt; } else { memcpy(csac, opt->data+15, 5); csac[5] = 0; csa2 = atoi(csac); delete [] opt->data; delete opt; } // check details if((0 == csa1_nok) && (0 == csa2_nok ) && (csa1 == csa2)) return(checkCSA(csa1)); else if ((1 == csa1_nok) && (0 == csa2_nok )) return(checkCSA(csa2)); else if ((0 == csa1_nok) && (1 == csa2_nok )) return(checkCSA(csa1)); return((uint16_t)-1);}/****************************************************************************** * checkCSA - see if we are supporting the type of arch * ******************************************************************************/uint16_tPacketStore::checkCSA(uint16_t reqCSA){ int i; for(i=0; (uint16_t)-1 != CSA_types[i].arch_id; i++) if(CSA_types[i].arch_id == reqCSA) break; return(CSA_types[i].arch_id);}/****************************************************************************** * MakeReply - pack the packet into a raw data form * ******************************************************************************/bootp_packet_t *PacketStore::PackPacket(void){ int pktlen, pos, len43; option *optptr; bootp_packet_t *opt = new bootp_packet_t; // first go through the packet and see how big it is pktlen = 241; // 255 closing tag optptr = head; while(NULL != optptr) { pktlen += optptr->len+2; // <tag>,<len>,<data> optptr = optptr->next; } optptr = head43; if(NULL != optptr) pktlen += 3; // 43,<len>,...,255 len43 = 0; while(NULL != optptr) { pktlen += optptr->len+2; // <tag>,<len>,<data> len43 = pktlen; optptr = optptr->next; } // initalise opt->data = new uint8_t[pktlen]; pos = 0; // basic packet info opt->data[0] = op; opt->data[1] = htype; opt->data[2] = hlen; opt->data[3] = hops; memcpy(opt->data+4, &xid, 4); memcpy(opt->data+8, &secs, 2); memset(opt->data+10, 0, 2); // the addresses memcpy(opt->data+12, &(ciaddr.s_addr), 4); memcpy(opt->data+16, &(yiaddr.s_addr), 4); memcpy(opt->data+20, &(siaddr.s_addr), 4); memcpy(opt->data+24, &(giaddr.s_addr), 4); // hardware addr memcpy(opt->data+28, chaddr, 16); // server name memcpy(opt->data+44, sname, 64); // filename memcpy(opt->data+108, file, 128); // magic cookie memcpy(opt->data+236, &magic_cookie, 4); // basic options pos = 240; optptr = head; while(NULL != optptr) { opt->data[pos] = optptr->major_no; opt->data[pos+1] = optptr->len; memcpy(opt->data+pos+2, optptr->data, optptr->len); pos += optptr->len+2; optptr = optptr->next; } // option 43 optptr = head43; if(NULL != optptr) { opt->data[pos] = 43; opt->data[pos+1] = len43; pos+=2; } while(NULL != optptr) { opt->data[pos] = optptr->minor_no; opt->data[pos+1] = optptr->len; memcpy(opt->data+pos+2, optptr->data, optptr->len); pos += optptr->len+2; optptr = optptr->next; } if(NULL != head43) { opt->data[pos] = 255; pos++; } // close the packet off opt->data[pos] = 255; opt->len=pos; return(opt);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -