TFTP(Trivial File Transfer Protocol,簡單 文件傳輸協議 )
1.tftp的服務端口號是69
2.tftp是基于udp協議的
3.tftp是明文傳輸的,是一種比較輕量型的協議,一般用于bootloader加載內核
TFTP工作流程
服務端開啟tftp服務,tftp是一種stand_alone服務,不是常駐內存的,是在有需要的時候才去調用的。首先,客戶端發送一個讀(RRQ:2個字節)或者寫(WRQ:2個字節)的請求,數據包的目標端口是69。對于讀或者寫的報文格式如下:
RRQ/WRQ(2個字節)+文件名(N字節)+0(1字節)+模式(N字節)+0(1字節)
目前模式字段主要有2種:netascii,這是8位的ASCII碼形式;另一種是octet,這是8位源數據類型。對于netascii是把回車和換行(CR/LF)解釋成兩個字節的。可以查看 http://www.firefoxbug.net/?p=1041
tftp-server接收到數據包:如果是發現是讀(RRQ),就重新隨機分配一個端口,直接發送數據(DATA:2個字節)+塊編號(2個字節),然后是0~512字節數據包。客戶端接收到數據包,發給服務端(ACK:2個字節)+塊編號(2個字節)。如果是普通的數據包,那么數據段的大小一定是512字節,如果是最后一個數據包,肯定是小于512字節的。tftp就是通過發現了一個數據段小于512字節的數據包來聲明結束文件的傳輸了。那么一個要傳輸的文件剛還是512字節的整數倍怎么辦呢?tftp會在最后傳輸一個數據段大小是0包。
tftp-server接收到數據包:如果發現是寫(WRQ),服務端就發回(ACK:2個字節)+(塊編號0:2個字節)的包,接著客戶端就發送(DATA:2個字節)+(塊編號1:2個字節)+數據段給服務端,服務端發回(ACK:2個字節)+(塊編號1:2個字節)。。。依次發送。
錯誤信息是系統自定義的,格式主要是error(2個字節)+錯誤碼(2個字節)+錯誤信息(N個字節)
下面是tftp數據包的格式圖
下面是C語言解析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抓出來的以太網包, void ParseUDPPacket(unsigned char *packet_buffer) { struct ethhdr *eth_header;//以太網頭 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數據包長度 } /* * 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; }
詳細的可以查看tcpdump的源碼。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

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