Ndis filter driver
באחד מהפרויקטים עליהם עבדתי לאחרונה היתה דרישה ליירט כל network packet שנכנס או יוצא מהNIC (ללא כל קשר לאפליקציה המקבלת או שולחת אותו ) לחפש pattern מסוים באותו הpacket של רצף bytes מסויים ואם הpattern מופיע לבצע באותו packet שינוי .
כמובן ששינוי ה packet מצריך חישוב מחדש של ה checksum בהתחשב בפרוטוקול של ההודעה הנשלחת .
שתי טכנולוגיות נשקלו על ידנו לטובת מימוש הדרישה :
WFP קיצור של Windows Filtering Platform שהינו פלטפורמה לירוט של תעבורת רשת ,שהינה זמינה החל מwindows vista . זו גם הטכנולוגיה המומלצת בכל פה על ידי אנשי מיקרוסופט כמו אולר שוויצרי לצרכים כאילו .
NDIS filter driver שהינה סוג של kernel driver שמשמ לירוט ושינוי של תעבורת רשת.
אל אף היתרון הגדול של wfp המאפשר עבודה בuser mode בחרנו לממש את הדרישה כNDIS filter driver . וזאת מכמה סיבות בהן:
גמישות –NDIS filter drivers חושפים יכולות אשר WFP לא חושף לדוגמא אפשרות לעבד OID requests
מבחינת פשטות של קידוד הפתרון יותר פשוט לכתוב NDIS Filter driver מאשר WFP .המבנה של אפליקצית wfp יותר מסובך מndis filter driver .
מכיוון שיש לנו בקבוצה יותר ניסיון בכתיבת ותחזוקת NDIS drivers מאשר ב WFP .
כמו כן ישנה דוגמא שהינה השלד של ה פתרון שלנו בWindows driver kit ורוב הדוגמאות שמצאנו של WFP היו בנושא של inspection של packets ופילטור של packets ולא של שינוי.
בניגוד לחלק מהקטגוריות של wdm drivers ,דיבאגינג והרצה של NDIS drivers ניתן לעשות בvirtual machine דבר שמקל מאוד את הפיתוח .
הדוגמא שיצאנו ממנה הינה :NDISLWF.SYS אשר נמצאת בnetwork\ndis\filter שהינה דוגמא של ndis 6.0 filter driver .
פעולות ההכנה שביצענו בדוגמא היו :
1.הוספת תמיכה ב tracing באמצאות wpp חשבנו על האפשרות של תמיכה מלאה ב etw עם אפשרות של יכולות לשאילתות לגבי מספר ה packets ששונו , יחסית למספר הpackets שהתקבלו וכד אבל נראה כי לא היה לזה צורך מבחינת הנדסת המוצר ומכיוון שהוספת תמיכה בetw בהרבה יותר מורכבת מאשר wpp ,הסתפקנו בwpp .
מכיוון שעבודה עם virtual machine לצורך פיתוח dirvers לא רואים את ה output של DbgPrint החלפנו את כל הקריאות של DbgPrint ב DoTraceMessage של ה Wpp
2.הוספת תמיכה ב kmdf שזה nice to have וממש לא must .
המרחב הטריטוריאלי של הFilter driver בndis stack נמצא בין ה miniport adapter ל protocol driver כלומר המידע שמגיע עליו הינו מידע גולמי ישר מהNIC או row data שצריך להישלח לndis ,אין לנו בזמן העיבוד אינדיקציה לגבי הprotocol של ההודעה אבל אנו יודעים שהתשתית איננו מערבבת בין הודעות כלומר לא תגיע חצי הודעה או שתי הודעות באותה קריאה .

הapi של מימוש ה driver מבוסס על פקודות מספריית הndis .
המבנה של ה Ndis filter driver הינו מאוד פשוט ומבוסס על רישום להודעות callback של התשתית.רישום לחלק מההודעות הינו חובה ולחלקן כאופציה . בסיום הטיפול בcallback הdriver צריך לקרא לפקודת ndis שמזרימה את ההודעה ל filter driver הבאה בתור.
כך שהpattern של ה driver נראה כ Observable pattern בשילוב עם chain of responsibility.
במהלך הביצוע של הDriverEntery ה Driver מבצע רושם את עצמו כ Ndis filter driver באמצעות קריאה לNdisFRegisterFilterDriver.
NdisFRegisterFilterDriver מקבל כפרמטר את הstruct של
NDIS_FILTER_DRIVER_CHARACTERISTICS שמכיל את הpointers ל callbacks של NDIS לדוגמא :
SendNetBufferListsHandler נקרא עבור הודעות שנשלחות ל nic .
הcallback של SendNetBufferListsHandler מכיל referance ל NBL שמכיל את ה row data שנשלח בצורה של network buffer list .
בסיום עיבוד המידע הdriver חייב לקרא ל NdisMSendNetBufferListsComplete על מנת להמשיך את דרכו של ה NBL לעבר ה Miniport adapter של ה ndis
בישום שלנו היינו צריכים רק לשנות את ה payload בתנאים מסוימים כך שכל הודעה שהתקבלה ב callback אחרי עיבדו סינכרוני של המידע מיד המשכנו את התהליך על ידי קריאה ל NdisMSendNetBufferListsComplete ,יחד עם זאת ניתן לעבד את המידע אסינכרונית לקבוץ ולהפריד הודעות (חשוב להקפיד על הסדר של השליחה מהcallback).
הישום שלנו ממש את הטיפול ב SendNetBufferListsHandler בצורה הבאה

בפוסטים הבאים אני אפרט את המימוש של ה filter לעומק.