原始套介面提供以下三種tcp及udp套介面一般不提供的功能。
1. 使用原始套介面可以讀寫icmpv4,igmpv4,icmpv6分組。例如:ping程式,就使用原始套介面傳送icmp回射請求,並接受icmp回射應答。
2. 使用原始套介面可以讀寫特殊的ipv4資料報,核心不處理這些資料報的ipv4協議字段。
3. 利用原始套介面,好似用ip_hdrincl套介面選項可以構造自己的ipv4頭部。
建立乙個原始套介面涉及以下幾步:
(1)當第二個引數是sock_raw時,呼叫socket函式建立乙個原始套介面。第三個引數(協議)一般不應為0,例如,為了建立乙個ipv4原始套介面,我們可以這樣寫:
int sockfd;
sockfd = socket(af_inet, sock_raw, protocol);
其中protocol引數值為形如ipproto_***的常值,由netinet/in.h標頭檔案定義,如ipproto_igmp。但要注意,標頭檔案裡定義了乙個協議名,如ipproto_egp,並不意味這核心肯定支援它。
(2)可以設定ip_hdrincl套介面選項:
= 1;
if ( setsockopt(sockfd, ipproto_ip, ip_hdrincl, &on
, sizeof(on
)) < 0 )
(3) 可以對原始套介面呼叫bind函式,但並不常用。
(4)在原始套介面上可呼叫connect函式,但也不常用。connect函式僅設定目的位址,再重申一遍:埠號對原始套介面而言沒有意義。對於輸出而言,呼叫connect之後,由於目的位址已經指定,我們可以呼叫write或send,而不是sendto了。
原始套介面的輸出遵循以下規則:
(1)普通輸出通過呼叫sendto或sendmsg並指定目的ip位址來完成。如果套介面已經連線,也可以呼叫write,writev或send
(2)如果ip_hdrincl選項未設定,則核心寫的資料起始位址指ip頭部之後的第乙個位元組。因為這種情況下,核心將構造ip頭部,並將它安在來自程序的資料之前。核心將ipv4頭部的協議字段設定成使用者在呼叫socket函式時所給的第三個引數。
(3)如果ip_hdrincl選項已設定,則核心寫的資料起始位址指ip頭部的第乙個位元組。使用者所提供的資料大小值必須包括頭部的位元組數,此時程序構造除了以下兩項以外的整個ip頭部:(a)ipv4標識字段可以設為0,要求核心設定該值 (b)ipv4頭部的校驗和由核心來計算和儲存。
(4)對於超出外出介面mtu的分組,核心將其分片。
接收到的哪些ip分組將傳遞給原始套介面:
(1)接收到的tcp分組和udp分組決不會傳遞給任何原始套介面,如果乙個程序希望讀取包括tcp或udp分組的ip資料報,那麼它們必須在資料鏈路層讀入
(2)當核心處理完icmp訊息之後,絕大部分icmp分組將傳遞給原始套介面。對源自berkeley的實現而言,除了回射請求,時間戳請求和位址掩碼請求將完全由核心處理以外,所有收到的icmp分組都將傳遞給某個原始套介面。
(3)當核心處理完igmp訊息之後,所有igmp分組都將傳遞給某個原始套介面。
(5)如果資料報以片段形式到達,則該分組將在所有片段到達並重組後才傳給原始套介面。
當核心準備好乙個待傳遞的資料報之後,核心將對所有程序的原始套介面進行檢查,以尋找所有匹配的套介面。每個匹配的套介面都將收到乙個該ip資料報的拷貝。以下是對每個原始套介面所做的三個測試,只有當這三個測試都為真時,資料報才會遞送給該套介面。
(1)如果在建立原始套介面時,所指定的protocol引數不為零(socket的第三個引數),則接收到的資料報的協議欄位應與該值匹配。否則該資料報將不遞送給該套介面。
(2)如果此原始套介面之上繫結了乙個本地ip位址,那麼接收到的資料報的目的ip位址應與該繫結位址相匹配,否則該資料報將不遞送給該套介面。
(3)如果此原始套介面通過呼叫connect指定了乙個對方ip位址,那麼接收到的資料報的源ip位址應與該連線位址相匹配,否則該資料報將不遞送給該套介面。
#include
void icmp6_filter_setpassall(struct icmp6_filter * filt);
void icmp6_filter_setblockall(struct icmp6_filter * filt);
void icmp6_filter_setpass(int msgtype, struct icmp6_filter * filt);
void icmp6_filter_setblock(int msgtype, struct icmp6_filter * filt);
int icmp6_filter_willpass(int msgtype, const
struct icmp6_filter * filt);
int icmp6_filter_willblock(int msgtype, const
struct icmp6_filter * filt);
/*返回值:如果過濾器傳遞(阻塞)相應訊息型別為1,否則為0 */
以上這些巨集呼叫中的filt引數是乙個指向某個icmp6_filter變數的指標,前四個巨集修改此icmp6_filter變數,後兩個巨集檢查它。msgtype引數值在0~255之間,指定icmp訊息型別。
setpassall巨集設定所有訊息型別均可傳遞給應用程序。setblockall巨集設定沒有訊息型別可傳遞。作為預設,當乙個icmpv6原始套介面建立時,所有icmpv6訊息型別可傳遞給其應用程序。
setpass巨集開啟某個訊息型別向該應用程序的傳遞,而setblock巨集阻塞某個訊息型別的傳遞。如果給定訊息型別可以由過濾器傳遞時,willpass巨集返回1,否則返回0,如果給定訊息型別被過濾器所阻塞時,willblock巨集返回1,否則返回0
第二十五章 狂風
氈帳外寒風吹,而氈帳內卻很暖和。滕青山喝著熱奶茶,吃了大塊羊肉,還有大盆的手拌炒麵。雖然沒九州大地上菜餚精緻,可也是吃地全身舒坦。大哥!一名穿著灰色皮袍子的青年走進氈帳內。原先正和滕青山談的正高興的查布,見這人進來,不由臉色一沉 你來,有什麼事?嘖嘖。那青年瞥了滕青山一眼,當看到滕青山身上的破棉祅不...
第二十五章 中介者模式
中介者模式 ediator 用乙個中介物件來封裝一系列的物件互動。中介者使物件不需要顯示的相互引用,從而使其耦合鬆散,而且可以獨立的改變它們之間的互動。優點 ediator的出現減少了各個colleague的耦合,使得可以獨立改變和復用各個colleague類和mediator。由於把物件如何協作進...
第二十五章 使用觸發器
如果想要某條語句 或某些語句 在事件發生時自動執行,此時就需要觸發器。如果需要在某個表發生更改時自動進行一些其他的處理。這確切地說就需要觸發器。觸發器是mysql響應以下任意語句而自動執行的一條mysql語句 或位於 begin 和 end 語句之間的一組語 句 delete insert upda...