1. 程式人生 > >linux核心學習筆記------iP選項處理(一)

linux核心學習筆記------iP選項處理(一)

ip首部分為固定部分和選項部分;固定部分為20個位元組,而選項部分則是變長的,最長不超過40個位元組。選項的格式分為單位元組和多位元組兩種。單位元組只包括一個位元組的選項型別,而多位元組則除一個位元組的型別之外,還包括選項長度以及選項資料。包括以下幾種ip選項:

1、選項列表的結束符

此選項標識了選項列表的結束,所有選項的結束,而不是一個選項的結束。如下圖

0 0 0 0 0 0 0 0
type=0

2、空操作

此選項一般在選項中間或者選項尾使用,用於32位邊界對齊的填充。如下圖

0 0 0 0 0 0 0 1
type=1

3、安全選項

此選項為主機提供了傳送安全級別,Compartments,處理限制以及傳輸控制碼

4、嚴格源路由選項

此選項要求資料報必須嚴格按照發送方規定的路徑經過每一個路由器,這些路由器應該是一一相連的,每兩個指定的路由器之間不能有其他為指定的路由器,且路由的順序不能改變。如果資料包在傳輸的時候無法到達指定的下一跳路由器,就會產生一個源路由失敗的目的地不可達的icmp報文。格式如下:

10001001

長度

指標

Ip地址1

Ip地址1(offset=4)

......

.......

Ip地址n

Ip地址n(offset=4n,n<9)


5、寬鬆源路由選項

此選項與嚴格源路由選項類似,不同的是,寬鬆源路由選項在選項的ip地址表中並不列出一條完整而嚴格的路徑,而是隻給出路徑中的幾個關鍵點。注:寬鬆,嚴格源路由選項都必須在ip分片的時候被複制

6、記錄路由選項

該選項用於記錄ip資料報從傳送方到接收方所經過的路徑上各個路由器的ip地址,如下圖

10001001

長度

指標

Ip地址1

Ip地址1(offset=4)

......

.......

Ip地址n

Ip地址n(offset=4n,n<9)

注意:記錄路由選項是有上限的,如果空間滿了就不會記錄後面的路由資訊

7、時間戳選項

該選項用於記錄資料報經過路由器時的當地時間。可以根據時間戳估算ip資料報從一個路由器到另一個路由器的所花的時間。如下圖:

01000100

長度

指標

OF|FG

Ip地址1

時間戳

......

Ip地址

n

時間戳

OF為溢位欄位,如果空間不夠,後面的路由資訊也不會記錄。FG標誌欄位用於定時時間戳選項的格式

FG               描述

0                  只記錄時間戳,以連續的32為字儲存

1                  記錄ip地址和時間戳

3                  傳送方對選項表進行初始化,存放了4個ip地和4個取值為0的時間戳,後續的路由器只有當匹配到ip地址才會記錄時間戳

8、路由器警告選項

該選項提醒路由器需要更仔細的檢查這個包,對內容需要做特殊處理,如下圖:

10010100 00000100 路由器警告值

在linux核心中ip選項是通過ip_options結構來表示的:
struct ip_options {
	/*
	 * 存在寬鬆源路由或嚴格源路由選項時,用來
	 * 記錄下一跳的IP地址
	 */
	__be32		faddr;
	/*
	 * 標識IP首部中選項所佔的位元組數,包括__data之後的資料,
	 * 如果有的話
	 */
	unsigned char	optlen;
	/*
	 * 記錄寬鬆源路由或嚴格源路由選項在IP首部中的偏移量,
	 * 即選項的第一個位元組的地址減去IP首部的第一個位元組的地址
	 */
	unsigned char	srr;
	/*
	 * 用於記錄路徑選項在IP首部中的偏移量
	 */
	unsigned char	rr;
	/*
	 * 用於記錄時間戳選項在IP首部中的偏移量
	 */
	unsigned char	ts;
	/*
	 * 標識該IP選項是否有資料,若有則存放在__data欄位起始的
	 * 儲存空間內,即緊跟在ip_option結構後面。這裡的資料不只
	 * 是選項資料,而是整個選項內容
	 */
	/*
	 * 標識該選項是IPOPT_SSRR,而不是IPOPT_LSRR
	 */
	unsigned char	is_strictroute:1,
			/*
			 * 表示目的地址是從源路由選項選出的
			 */
			srr_is_hit:1,
			/*
			 * 標識是否修改過IP首部,如果是則需要重新
			 * 計算IP首部校驗和
			 */
			is_changed:1,
			/*
			 * 標識有IPOPT_RR選項,需要記錄IP地址。
			 */
			rr_needaddr:1,
			/*
			 * ts_needtime標識有IPOPT_TIMESTAMP選項,需要
			 * 記錄時間戳
			 * ts_needaddr標識有IPOPT_TIMESTAMP選項,需要
			 * 記錄IP地址
			 */
			ts_needtime:1,
			ts_needaddr:1;
	/*
	 * 標識IPOPT_RA選項。路由器警告選項,表示路由器
	 * 應該更仔細地檢查這個資料包
	 */
	unsigned char	router_alert;
	/*
	 * 用於記錄商業IP安全選項在IP首部中的偏移量
	 */
	unsigned char	cipso;
	/*
	 * 未使用
	 */
	unsigned char	__pad2;
	/*
	 * 若選項有資料則從該欄位開始,使之緊跟在ip_option結構後面,
	 * 最多不超過40B
	 */
	unsigned char	__data[0];
};
程式碼中都有註釋,其中註釋來自於:http://blog.csdn.net/justlinux2010

構建ip選項是通過ip_iptions_build實現的

void ip_options_build(struct sk_buff * skb, struct ip_options * opt,
			    __be32 daddr, struct rtable *rt, int is_frag)
{
	unsigned char *iph = skb_network_header(skb);



	memcpy(&(IPCB(skb)->opt), opt, sizeof(struct ip_options));
	memcpy(iph+sizeof(struct iphdr), opt->__data, opt->optlen);
	opt = &(IPCB(skb)->opt);


	if (opt->srr)
		memcpy(iph+opt->srr+iph[opt->srr+1]-4, &daddr, 4);

	if (!is_frag) {
		if (opt->rr_needaddr)
			ip_rt_get_source(iph+opt->rr+iph[opt->rr+2]-5, rt);
		if (opt->ts_needaddr)
			ip_rt_get_source(iph+opt->ts+iph[opt->ts+2]-9, rt);
		if (opt->ts_needtime) {
			struct timespec tv;
			__be32 midtime;
			getnstimeofday(&tv);
			midtime = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC);
			memcpy(iph+opt->ts+iph[opt->ts+2]-5, &midtime, 4);
		}
		return;
	}

	if (opt->rr) {
		memset(iph+opt->rr, IPOPT_NOP, iph[opt->rr+1]);
		opt->rr = 0;
		opt->rr_needaddr = 0;
	}
	if (opt->ts) {
		memset(iph+opt->ts, IPOPT_NOP, iph[opt->ts+1]);
		opt->ts = 0;
		opt->ts_needaddr = opt->ts_needtime = 0;
	}
}
首先會獲取ip首部,將源ip選項和後面緊跟的選項資料複製到skb對應額儲存區域中。並將opt指向skb的ip_options。如果存在嚴格路由選項需要將目的地址複製到源路由選項地址列表中。如果資料包不是分片,且存在記錄路由或者時間戳選項,通過輸出路由快取獲取源地址填寫到記錄路由選項或者時間戳選項的地址部分,獲取當前的時間填寫時間戳。如果該資料包不是分片,但存在記錄路由或時間戳選項則設定為無操作

而將資料報中選項複製到指定的ip_options中,需要呼叫ip_options_echo,這個函式處理也比較清晰,這裡就不列舉出來了。

相關推薦

linux核心學習筆記------iP選項處理()

ip首部分為固定部分和選項部分;固定部分為20個位元組,而選項部分則是變長的,最長不超過40個位元組。選項的格式分為單位元組和多位元組兩種。單位元組只包括一個位元組的選項型別,而多位元組則除一個位元組的型別之外,還包括選項長度以及選項資料。包括以下幾種ip選項: 1、選項列

linux核心學習筆記------ip報文組裝

ip報文有分片就會有組裝。在接收方,只有報文的所有分片被重新組合後才會提交到上層協議。核心組裝ip報文用到了ipq結構體:(注,這系列原始碼中的註釋都來自:http://blog.csdn.net/justlinux2010) struct ipq { struct in

linux核心學習筆記------ip報文的分片

對網路比較熟悉的童鞋都知道,當傳送的ip報文長度超出了最大的傳輸單位MTU,且允許分片的情況下,就會對ip報文進行分片。在上層要傳送資料時就會呼叫dst_output,dst_output就會呼叫ip_output,而ip_output就會呼叫ip_finish_outpu

Linux核心學習筆記)——Linux核心簡介

  Unix系統業已演化成一個具有相似應用程式程式設計介面(API),並且基於相似設計理念的作業系統家族。 1、Unix的歷史   Unix是從貝爾實驗室的一個失敗的多使用者作業系統Multics中涅槃而生的。 時間 事件 19

Linux核心學習筆記) 虛擬檔案系統VFS

什麼是VFS Vritual Filesystem 是給使用者空間程式提供統一的檔案和檔案系統訪問介面的核心子系統。藉助VFS,即使檔案系統的型別不同(比如NTFS和ext3),也可以實現檔案系統之間互動(移動、複製檔案等), 從使用者空間程式的角度來看,

Python學習筆記-IP地址處理模塊Ipy

模塊 python ipy IP地址處理模塊Ipy IPy模塊可以很好的輔助我們高效完成IP的規劃工作。 參考:https://github.com/autocracy/python-ipy 安裝IPy模塊[[email protected]/* */ ~]#

Linux核心學習筆記(2)—— 程序

來源:《Linux核心設計與實現(第2版)》第三章 Robert Love 知識點很少,蝸牛慢慢爬~~~ 1. 什麼是程序? 程序是處於執行期的程式以及它所包含的資源的總稱。所謂的資源,像開啟的檔案、掛起的訊號、核心內部資料、處理器狀態、地址空間、一

Linux核心學習筆記四】記憶體管理-夥伴系統

1.夥伴系統演算法描述       linux系統採用夥伴系統演算法來解決外碎片問題。主要做法是記錄現存的空閒連續頁框塊的情況,以儘量避免為滿足對小塊的請求而分割大的空閒塊。      夥伴系統演算法中,把所有的空閒頁框分為11個組,每個組對應一個連結串列,每個連結串列分

Linux核心學習筆記九——核心記憶體管理方式

一 頁        核心把物理頁作為記憶體管理的基本單位;記憶體管理單元(MMU)把虛擬地址轉換為物理 地址,通常以頁為單位進行處理。MMU以頁大小為單位來管理系統中的也表。        32位系統:頁大小4KB        64位系統:頁大小8KB 核心

篇文章帶你入門Linux——馬哥Linux基礎學習筆記

更改密碼 自帶 ctime 詳細信息 內嵌 桌面環境 地址定界 格式符 p s 1.課程體系: 中級: 初級:系統基礎 中級:系統管理、服務安全及服務管理、Shell腳本; 高級: MySQL數據庫; cache & stor

Linux學習筆記第七周次課(3月19日)

w vmstat top sar nload 10.1 使用w查看系統負載10.2 vmstat命令顯示狀態,每一秒一次,共5次,命令為#vmstat 1 5r,run表示運行;b,block表示阻塞,阻止;swpd,虛擬內存,若這個值大於0,表示內存不夠用;si磁盤輸入虛擬內存;so虛擬

Linux學習筆記(三十)日常運維三

ifconfig一、linux網絡相關、 ifconfig ifconfig //查看網卡ip(yum install net-tools) ifup ens33/ifdown ens33 //開啟網卡,關閉網卡,只有一個網卡時,一旦關閉了網卡就會斷開遠程鏈接,只能去服務器主機重新打

Linux學習筆記十二周次課(4月23日)

lnmp linux nginx mysql php 12.1 LNMP架構介紹12.2 MySQL安裝進入下載目錄cd /usr/local/src查看已下載的文件ls查看進程是否運行ps aux | grep mysql刪除安裝目錄rm -rf /usr/local/mysql刪除服務

Linux視訊學習筆記)--系統分割槽

宣告:本系列文章是博主根據 “兄弟連新版Linux視訊教程”做的筆記和視訊截圖,只為學習和教學使用,不適用任何商業用途。 PS:如果對Linux感興趣,建議去看《細說Linux》,沈超老師和李明老師的教學風格我很喜歡:)   視訊2.1-VMWare虛擬機器安裝與使用

Linux開發學習筆記

安裝虛擬機器並聯網 1、安裝虛擬機器vmware: 安裝完vmware並開啟——》點選建立新的虛擬機器——》自定義——》下一步——》選擇稍後安裝作業系統——》選擇Linux Ubuntu 64位——》給虛擬機器取名字、選擇安裝路徑——》配置處理器數量1和核心數量2——》虛擬機器記憶體選擇

nginx 原始碼學習筆記(二十)—— event 模組(二) ——事件驅動核心ngx_process_events_and_timers

首先繼續回憶下,之前子執行緒執行操作裡面有一個未涉及的內容ngx_process_events_and_timers,今天我們就來研究下這個函式。 本篇文章來自於:http://blog.csdn.net/lengzijian/article/details/7601730 先來看一下第十九

linux驅動學習筆記---s5pv210()

1,解壓核心原始碼 tar -xvf linux-3.0.8.tar.bz2 2,核心的編譯步驟:     a,設定交叉工具鏈--目標檔案執行在arm處理上, 修改Makefile          195 ARCH            ?= arm          1

Linux netfilter 學習筆記 之三 ip層netfilter的table、rule、match、target結構分析

基於linux2.6.21 上一節分析了ip層hook回撥函式的註冊以及呼叫流程,本節我們就開始分析每一個模組的具體實現。 工欲善其事必先利其器,一個功能模組的程式碼實現與其資料結構的設計有很大的關

Linux學習筆記

對於一個做前臺的的開發人員來將,成功安裝好Linux這種高大上的東西,瞬間心情爆滿,真爽呀;接下來就一步一步的記錄我的學習之路吧,方便自己資料的查閱 所謂好記性不如爛筆頭呀!!! 在安裝好之後,第一件

linux核心學習之網路篇——IP和TCP結構體原始碼

今天只是看一下IP協議的結構體和TCP的結構體所控制的欄位。 首先看一下IP的欄位,就是傳說中ip協議中的包頭欄位。 struct iphdr { #if defined(__LITTLE_ENDIAN_BITFIELD) __u8 ihl:4, version:4