TFTP(Trivial File Transfer Protocol,簡(jiǎn)單 文件傳輸協(xié)議 )
1.tftp的服務(wù)端口號(hào)是69
2.tftp是基于udp協(xié)議的
3.tftp是明文傳輸?shù)模且环N比較輕量型的協(xié)議,一般用于bootloader加載內(nèi)核
TFTP工作流程
服務(wù)端開(kāi)啟tftp服務(wù),tftp是一種stand_alone服務(wù),不是常駐內(nèi)存的,是在有需要的時(shí)候才去調(diào)用的。首先,客戶(hù)端發(fā)送一個(gè)讀(RRQ:2個(gè)字節(jié))或者寫(xiě)(WRQ:2個(gè)字節(jié))的請(qǐng)求,數(shù)據(jù)包的目標(biāo)端口是69。對(duì)于讀或者寫(xiě)的報(bào)文格式如下:
RRQ/WRQ(2個(gè)字節(jié))+文件名(N字節(jié))+0(1字節(jié))+模式(N字節(jié))+0(1字節(jié))
目前模式字段主要有2種:netascii,這是8位的ASCII碼形式;另一種是octet,這是8位源數(shù)據(jù)類(lèi)型。對(duì)于netascii是把回車(chē)和換行(CR/LF)解釋成兩個(gè)字節(jié)的??梢圆榭? http://www.firefoxbug.net/?p=1041
tftp-server接收到數(shù)據(jù)包:如果是發(fā)現(xiàn)是讀(RRQ),就重新隨機(jī)分配一個(gè)端口,直接發(fā)送數(shù)據(jù)(DATA:2個(gè)字節(jié))+塊編號(hào)(2個(gè)字節(jié)),然后是0~512字節(jié)數(shù)據(jù)包。客戶(hù)端接收到數(shù)據(jù)包,發(fā)給服務(wù)端(ACK:2個(gè)字節(jié))+塊編號(hào)(2個(gè)字節(jié))。如果是普通的數(shù)據(jù)包,那么數(shù)據(jù)段的大小一定是512字節(jié),如果是最后一個(gè)數(shù)據(jù)包,肯定是小于512字節(jié)的。tftp就是通過(guò)發(fā)現(xiàn)了一個(gè)數(shù)據(jù)段小于512字節(jié)的數(shù)據(jù)包來(lái)聲明結(jié)束文件的傳輸了。那么一個(gè)要傳輸?shù)奈募傔€是512字節(jié)的整數(shù)倍怎么辦呢?tftp會(huì)在最后傳輸一個(gè)數(shù)據(jù)段大小是0包。
tftp-server接收到數(shù)據(jù)包:如果發(fā)現(xiàn)是寫(xiě)(WRQ),服務(wù)端就發(fā)回(ACK:2個(gè)字節(jié))+(塊編號(hào)0:2個(gè)字節(jié))的包,接著客戶(hù)端就發(fā)送(DATA:2個(gè)字節(jié))+(塊編號(hào)1:2個(gè)字節(jié))+數(shù)據(jù)段給服務(wù)端,服務(wù)端發(fā)回(ACK:2個(gè)字節(jié))+(塊編號(hào)1:2個(gè)字節(jié))。。。依次發(fā)送。
錯(cuò)誤信息是系統(tǒng)自定義的,格式主要是error(2個(gè)字節(jié))+錯(cuò)誤碼(2個(gè)字節(jié))+錯(cuò)誤信息(N個(gè)字節(jié))
下面是tftp數(shù)據(jù)包的格式圖
下面是C語(yǔ)言解析tftp包的一小段代碼:
struct tftphdr { short th_opcode; /* packet type */ union { unsigned short tu_block; /* block # */ short tu_code; /* error code */ char tu_stuff[1]; /* request packet stuff */ } __attribute__ ((__packed__)) th_u; char th_data[1]; /* data or error string */ } __attribute__ ((__packed__)); // 解析udp包,packet_buffer是用rawsocket抓出來(lái)的以太網(wǎng)包, void ParseUDPPacket(unsigned char *packet_buffer) { struct ethhdr *eth_header;//以太網(wǎng)頭 struct iphdr *ip_header; //ip頭 struct udphdr *udp_header; //tcp頭 eth_header = (struct ethhdr*)packet_buffer; ip_header = (struct iphdr*)(packet_buffer + sizeof(struct ethhdr)); udp_header = (struct udphdr*)(packet_buffer + sizeof(struct ethhdr) + ip_header->ihl*4); unsigned char *data = NULL; data = (packet_buffer + sizeof(struct ethhdr) + ip_header->ihl*4 + 8);//8代表UDP包頭 struct tftphdr *tp = (struct tftphdr *)data; // /usr/include/arpa/tftp.h tftp_print(data,ntohs(udp_header->len)-8); //ntohs(udp_header->len)-8表示udp數(shù)據(jù)包長(zhǎng)度 } /* * Print trivial file transfer program requests */ void tftp_print(register const u_char *bp, u_int length) { register const struct tftphdr *tp; register const u_char *p; register int opcode,i; static char tstr[] = " [|tftp]"; char buffer[520] = {'\0'}; tp = (const struct tftphdr *)bp; // printf(" %d", length); // printf("length of tftp_data = %d\n",length); /* Print tftp request type */ opcode = EXTRACT_16BITS(&tp->th_opcode); printf(" %s",tok2str(op2str, "tftp-#%d", opcode)); /* Bail if bogus opcode */ switch (opcode) { case RRQ: break; case WRQ: break; case ACK: break; case DATA: break; case ERROR: break; default: /* We shouldn't get here */ printf("(unknown #%d)", opcode); break; } return; }
詳細(xì)的可以查看tcpdump的源碼。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
