Linux下使用原始socket收發數據包

在Linux系統中,使用非原始的socket,可以收發TCP或者UDP等網絡層數據包。如果要處理網絡層以下的數據包,比如ICMP、ARP等,或者更底層,比如鏈路層數據包,就得使用原始socket了。

創建socket

創建socket要使用socket函數,socket函數的原型為:

#include <sys/types.h>  
#include <sys/socket.h>  int socket(int domain, int type, int protocol);

其中,domain比較常用的值有:

  • AF_UNIX Unix本地通訊
  • AF_INET IPv4網絡協議
  • AF_INET6 IPv6網絡協議
  • AF_NETLINK 內核用戶界面設備
  • AF_PACKET 底層包設備

我們要處理網絡層以下的數據包,就得使用AF_PACKET

type比較常用的值有:

  • SOCK_STREAM 用于面向字節流的協議,如TCP
  • SOCK_DGRAM 用于面向數據報的協議,如UDP
  • SOCK_RAW 用于非處理的原始數據包

我們這里要使用SOCK_RAW

protocol是要使用的網絡協議。

如下代碼,創建一個原始socket:

#include <sys/types.h>
#include <sys/socket.h>int raw_socket_new () {int fd;fd = socket (PF_PACKET, SOCK_RAW, IPPROTO_RAW);if (fd < 0){fprintf (stderr, "socket error: %s\n", strerror (errno));}return fd;

綁定網口

如果我們處理非原始的數據包,可以使用網絡層綁定IP,或者連接IP(其實socket也會自動綁定IP),協議棧會自動根據IP把數據包發往特定的網絡接口,不需要綁定網口。

我們通過原始socket發送底層數據包,就需要綁定網口了。

綁定網口的方法很簡單,先使用if_nametoindex函數,找到對應網口名的編號,之后設置到struct sockaddr_ll結構中,調用bind函數就行了。

`if_nametoindex`的原型為:

#include <net/if.h>unsigned int if_nametoindex(const char *ifname);

struct sockaddr_ll的定義為:

#include <linux/if_packet.h>struct sockaddr_ll {  unsigned short  sll_family;  __be16          sll_protocol;  int             sll_ifindex;  unsigned short  sll_hatype;  unsigned char   sll_pkttype;  unsigned char   sll_halen;  unsigned char   sll_addr[8];  
};

以下函數,就把給定的網絡接口,綁定到了給定的socket上:

#include <net/if.h>
#include <linux/if_packet.h>int raw_socket_bind(int fd, const char *eth) {struct sockaddr_ll sa;memset (&sa, 0, sizeof (struct sockaddr_ll));// 原始數據包sa.sll_family = AF_PACKET;// 自定義二層協議sa.sll_protocol = htons (CUSTOM_TYPE);sa.sll_ifindex = if_nametoindex (eth);if (bind (jdpdk->fd, (struct sockaddr *)&sa, sizeof (struct sockaddr_ll))!= 0){fprintf (stderr, "bind error: %s\n", strerror (errno));return -1;}return 0;
}

二層包結構

socket創建成功,綁定了網口,就可以發送自定義的二層數據包了。

根據TCP/IP標準,二層的數據包包頭為14個字節,即6字節的目標MAC地址、6字節的源MAC地址再加2字節的包類型。

net/ethernet.h中,結構定義為:

struct ether_header  
{uint8_t  ether_dhost[ETH_ALEN]; uint8_t  ether_shost[ETH_ALEN];uint16_t ether_type;
} __attribute__ ((__packed__));

在我們使用網口發送的時候,源MAC地址可以設成全0,但是目標MAC地址,必須設置。

我們可以實現一個組包函數,把給定的數據,設上預訂的目標地址:

int raw_encode (const char *dst_mac, unsigned short type, const char *data, size_t data_len, char *packet, size_t packet_len) {assert (14 + data_len <= packet_len);memcpy (packet, dst_mac, 6);memset (packet + 6, 0, 6);* (unsigned short *) (packet + 12) = htons (type);memcpy (packet + 14, data, data_len);return 14 + data_len;
}

發送

發送函數就比較簡單,跟網絡層的發送沒有區別。

int raw_send (int fd, const char *data, int data_len) {int ret;ret = send (fd, data, data_len, 0);  if (ret != data_len)  {  fprintf (stderr, "send error: %s\n", strerror (errno));       }return ret;
}

接收

接收函數也同樣,只是記得接收成功以后,偏移14字節(即二層包頭以后)才是我們的應用層數據:

int raw_recv (int fd, char *packet, size_t packet_len) {int ret;ret = recv (fd, packet, packet_len, 0);return ret;
}

原始socket示例:arp組包

根據TCP/IP協議,當我們網絡層使用TCP、UDP或者ICMP等使用IP地址作為目標的數據包時,協議棧要查詢本機的arp表,找到IP地址對應的MAC地址。

如果查詢失敗,就會發送arp請求,通過arp響應來得到目標MAC地址。

所以,arp協議有兩種數據包:一種是arp請求,一種是arp響應。對應到arp結構中,就是操作碼的值為1或者2。

linux/if_arp.h中,有arp包的包頭結構:

struct arphdr {  __be16          ar_hrd;__be16          ar_pro;unsigned char   ar_hln;unsigned char   ar_pln;__be16          ar_op;  
};

在arp的包體中,分別是發送MAC、發送IP、目標MAC與目標IP。

  • 當arp請求的時候,設置arp包頭中的操作碼為1,另外設置發送MAC(即本機MAC)與目標IP,發送IP與目標MAC置空。

當arp響應的時候,設置arp包頭中的操作碼為2,另外設置發送MAC(即本機MAC)、發送IP(即本機IP)、目標MAC(即請求時的發送MAC),目標IP置空。

我們寫一個組包函數:

#include <net/ethernet.h>
#include <arpa/inet.h>
#include <netinet/if_ether.h>
#include <memory.h>void
buf_encode_arp (uint8_t *buf, uint16_t opcode, const uint8_t *source_mac,  const uint8_t *dst_mac, unsigned long sip, unsigned long dip)  
{struct ether_header *hdr;  hdr = (struct ether_header *)buf;  if (source_mac)  {  memcpy (hdr->ether_shost, source_mac, sizeof hdr->ether_shost);}// arp請求的時候,二層目標MAC地址填全0xFF,否則填全0memset (hdr->ether_dhost, opcode == 1 ? 0xFF : 0, sizeof hdr->ether_dhost);if (dst_mac)  {  memcpy (hdr->ether_dhost, dst_mac, sizeof hdr->ether_dhost);}hdr->ether_type = htons (ETHERTYPE_ARP);struct ether_arp *arp = (struct ether_arp *)(hdr + 1);// 設置arp包頭arp->ea_hdr.ar_hrd = htons (1);arp->ea_hdr.ar_pro = htons (0x800);arp->ea_hdr.ar_hln = 6;arp->ea_hdr.ar_pln = sizeof (uint32_t);arp->ea_hdr.ar_op = htons (opcode);// 根據輸入參數,設置arp包體memset (arp->arp_sha, 0, sizeof arp->arp_sha);if (source_mac)  {  memcpy (arp->arp_sha, source_mac, sizeof arp->arp_sha);}  memset (arp->arp_tha, 0, sizeof arp->arp_tha);if (dst_mac)  {  memcpy (arp->arp_tha, dst_mac, sizeof arp->arp_tha);}memcpy (&arp->arp_spa, &sip, 4);memcpy (&arp->arp_tpa, &dip, 4);
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/915073.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/915073.shtml
英文地址,請注明出處:http://en.pswp.cn/news/915073.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

暑期自學嵌入式——Day05補充(C語言階段)

接續上文&#xff1a;暑期自學嵌入式——Day05&#xff08;C語言階段&#xff09;-CSDN博客 主頁點關注不迷路喲。你的點贊、收藏&#xff0c;一鍵三連&#xff0c;是我持續更新的動力喲&#xff01;&#xff01;&#xff01; 主頁&#xff1a; 一位搞嵌入式的 genius-CSDN博…

.NET Core EFCore零基礎快速入門簡單使用

一、什么是 Entity Framework (EF) Core Entity Framework (EF) Core 是輕量化、可擴展和跨平臺版的對象關系映射程序 (O/RM)數據訪問技術&#xff0c;。 它將開發人員從編寫大量 SQL 語句中解放出來。 二、EF的相關程序包 Microsoft.EntityFrameworkCore 核心程序包&#x…

AAC音頻格式

目錄 AAC音頻格式介紹 主要特點 技術優勢 常見文件擴展名 應用領域 AAC與PCM的區別與優勢對比 基本概念差異 主要技術區別 各自優勢 PCM的優勢 AAC的優勢 應用場景選擇 AAC音頻數據格式解析 1. AAC 文件格式 (1) ADIF (Audio Data Interchange Format) (2) ADT…

pom.xml文件中的${}變量從哪里傳值

在 Maven 的 pom.xml 文件中&#xff0c;${} 格式的變量&#xff08;稱為屬性占位符&#xff09;的值來源主要有以下幾種途徑&#xff1a; 1. ?內置屬性&#xff08;Maven 預定義&#xff09;?? ${project.basedir}&#xff1a;項目根目錄${project.version}&#xff1a;項…

【人工智能】項目案例分析:使用TensorFlow進行大規模對象檢測

????歡迎大家來到我們的天空???? ?? 作者簡介:我們的天空 ??《頭銜》:大廠高級軟件測試工程師,阿里云開發者社區專家博主,CSDN人工智能領域新星創作者。 ??《博客》:人工智能,深度學習,機器學習,python,自然語言處理,AIGC等分享。 所屬的專欄:TensorF…

C++---cout、cerr、clog

在C編程里&#xff0c;cout、cerr和clog是標準庫提供的重要輸出流對象&#xff0c;在數據輸出方面發揮著關鍵作用。 一、cout&#xff1a;標準輸出流 cout 是 std::ostream 類的對象&#xff0c;其作用是向標準輸出設備&#xff08;一般是控制臺&#xff09;輸出數據。它和 C 語…

脈沖神經網絡(Spiking Neural Network, SNN)與知識蒸餾(Knowledge Distillation, KD)

目錄 脈沖神經網絡&#xff08;Spiking Neural Network, SNN&#xff09; 知識蒸餾&#xff08;Knowledge Distillation, KD&#xff09; 三種類別 三種變體 脈沖神經網絡&#xff08;Spiking Neural Network, SNN&#xff09; 收到生物神經系統的啟發&#xff0c;設計的&a…

使用Java完成下面項目

第一題&#xff1a;從控制臺輸入十個學生的成績&#xff0c;使用list集合來保存數據&#xff0c; 遍歷并打印其中成績不及格的成績&#xff0c;打印最高成績&#xff0c;最低成績&#xff0c;并計算及格率代碼如下public class Home1 {public static void main(String[] args) …

龍虎榜——20250718

上證指數今天上漲收陽線&#xff0c;繼續在5天均線保持強勢上漲&#xff0c;個股下跌稍多&#xff0c;大盤股上漲為主。深證指數收小陽線&#xff0c;繼續在5天均線上&#xff0c;總體保持強勢&#xff0c;調整更多是小票。2025年7月18日龍虎榜行業方向分析1. 醫藥醫療? 代表標…

2025年華為認證之HCIE-云計算方向的報考流程

一、先搞明白&#xff1a;HCIE - 云計算認證到底是啥&#xff1f; HCIE - 云計算&#xff08;華為認證 ICT 專家 - 云計算&#xff09;是華為體系里云計算領域的頂級認證&#xff0c;說白了&#xff0c;就是證明你有能力搞定大型企業的云平臺設計、部署和運維。現在政企、金融…

什么是私有化部署企業即時通訊?吱吱企業即時通訊安全嗎?

在企業數字化轉型加速的今天&#xff0c;溝通工具的選擇已經從滿足簡單溝通&#xff0c;升級為“安全、高效、可控”。其中&#xff0c;“私有化部署企業即時通訊”成為許多中小型企業、跨國企業以及數據敏感型企業的核心需求。 那么&#xff0c;究竟什么是私有化部署&#xff…

Vue3 中使用 Element Plus 實現自定義按鈕的 ElNotification 提示框

在 Vue3 項目中&#xff0c;我們經常會用到 ElNotification 作為消息提醒組件&#xff0c;尤其是在異步操作、任務完成或用戶需要交互確認時。然而&#xff0c;Element Plus 默認的 Notification 是非交互式的&#xff0c;不能直接嵌入按鈕或事件。 今天我們來實現一個帶自定義…

下載webrtc M114版本源碼只能使用外網googlesource源-命令版

聲網、國內源都不行&#xff0c;只能外網googlesource源&#xff01;&#xff01;&#xff01; 二、創建 Ubuntu 容器&#xff08;帶目錄掛載&#xff09; 拉取Ubuntu鏡像 docker pull ubuntu:22.04創建并啟動容器&#xff08;掛載Windows目錄到容器&#xff09; docker run -i…

Linux運維新手的修煉手扎之第21天

Nginx服務和Tomcat服務1 負載均衡語法格式&#xff1a;upstream[一個或多個]rootubuntu24-13:~# vim /etc/nginx/conf.d/vhost.confupstream group1 {server 10.0.0.16;}upstream group2 {server 10.0.0.14;}server {listen 80;server_name sswang1.magedu.com;location / {pro…

TrOCR: 基于Transformer的光學字符識別方法,使用預訓練模型

溫馨提示&#xff1a; 本篇文章已同步至"AI專題精講" TrOCR: 基于Transformer的光學字符識別方法&#xff0c;使用預訓練模型 摘要 文本識別是文檔數字化中的一個長期研究問題。現有方法通常基于CNN進行圖像理解&#xff0c;基于RNN進行字符級文本生成。此外&#…

西門子工業軟件全球高級副總裁兼大中華區董事總經理梁乃明先生一行到訪庭田科技

概要2025年6月&#xff0c;西門子工業軟件全球高級副總裁兼大中華區董事總經理梁乃明先生一行到訪我司。庭田科技總經理聶春文攜銷售團隊對西門子代表團表示熱烈歡迎&#xff0c;并就當前業務發展方向及未來行業聚焦領域與代表團展開深入交流。 聶春文總經理及銷售團隊陪同西門…

在 Jenkins 中使用 SSH 部署密鑰

本文檔介紹了如何在 Jenkins 中配置 SSH 部署密鑰&#xff0c;以便更穩定地拉取 Git 倉庫代碼&#xff0c;避免常見的 RPC 錯誤。 1. 背景 在使用 Jenkins 進行持續集成時&#xff0c;常常需要從 Git 倉庫拉取代碼。如果使用 HTTP/HTTPS 協議&#xff0c;有時會遇到 RPC 錯誤&…

小紅書采集工具:無水印圖片一鍵獲取,同步采集筆記與評論

我用python語言開發了一款名為“爬xhs圖片軟件”的工具&#xff0c;該工具不僅能采集圖片&#xff0c;還可獲取筆記數據、評論數據等內容。 軟件界面長這個樣子&#xff1a; 采集到的圖片&#xff1a;演示視頻&#xff1a;https://live.csdn.net/v/485813介紹文章、想你所想&am…

Java行為型模式---命令模式

命令模式基礎概念命令模式&#xff08;Command Pattern&#xff09;是一種行為型設計模式&#xff0c;其核心思想是將請求封裝為一個對象&#xff0c;從而使你可以用不同的請求對客戶進行參數化&#xff0c;對請求排隊或記錄請求日志&#xff0c;以及支持可撤銷的操作。命令模式…

Android性能優化之包體積優化

一、包體積組成與瓶頸分析 1. 典型 APK 結構占比 #mermaid-svg-KEUQMlEifvHlk1CV {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-KEUQMlEifvHlk1CV .error-icon{fill:#552222;}#mermaid-svg-KEUQMlEifvHlk1CV .erro…