Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- 교촌치킨 신메뉴
- 용인맛집
- 치킨 신메뉴
- 수원 맛집
- BBQ 신메뉴
- 황리단길기념품
- 냉동만두 추천
- 서현 맛집
- 분당맛집
- 황리단길디저트
- 분당 맛집
- 순천맛집
- 동성로맛집
- 편스토랑
- 순천디저트
- 푸라닭
- cu 편의점
- 대구동성로맛집
- 서현역중식
- 오뚜기 라면
- 수지 술집
- 편의점 추천
- 마켓컬리 추천
- CU 편의점 추천
- 경주맛집
- 서현역맛집
- 편의점 신제품
- 황리단길맛집
- CU편의점 추천
- CU편의점
Archives
- Today
- Total
일상 메모장
sk_buff 에서 Mac header, IP v4 and v6 header, TCP header 파싱 본문
안녕하세요.
오늘은 커널내부에서 네트워크 패킷을 관리하는 구조체인 sk_buff structure 를 각 네트워크 헤더별로
파싱하는 방법을 포스팅하겠습니다.
우선 각 함수를 설명하기 전에 기본적으로 sk_buff 의 멤버 변수들을 먼저 확인해보도록 하겠습니다.
sk_buff 는 headroom, tailroom, 그리고 실제 데이터가 들어있는 영역이 아래와 같이 있습니다.
이 위치를 표시하기 위해 아래와 같이 head, data, tail, end 변수를 사용합니다.
head ~ data 는 head room.
data ~ tail 은 실제 데이터가 들어있는 room
tail ~ end 는 tail room 입니다.
그리고 sk_buff 구조체는 mac header, network header(ex:IP), transport header(ex: TCP, UDP)의 offset을 기억하는
mac_header, network_header, transport_header를 멤버 변수로 가지고 있습니다.
Ethernet header
- ethhdr (ethernet header) 구조체
/* linux/if_ether.h 에 위치 */
struct ethhdr {
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */
__be16 h_proto; /* packet type ID field */
} __attribute__((packed));
- eth_hdr(), skb_mac_header() 함수 선언부
#include <linux/if_ether.h>
struct ethhdr *eth_hdr(const struct sk_buff *skb);
/* 또는 */
#include <linux/skbuff.h>
unsigned char *skb_mac_header(const struct sk_buff *skb);
- 설명
- eth_hdr() 내부에서는 실제로 skb_mac_header() 함수를 호출하는 구조입니다.
- 내부 구현은 sk_buff 의 시작위치인 skb->head 에 skb->mac_header 의 offset 위치를 더한값을 리턴합니다.
skb->head + skb->mac_header
IP header v4 and v6(Network layer)
IPv4 관련
- iphdr 구조체
#include <linux/ip.h>
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
version:4;
#else defined (__BIG_ENDIAN_BITFIELD)
__u8 version:4,
ihl:4;
#else
#error "Please fix <asm/byteorder.h>"
#endif
__u8 tos;
__be16 tot_len;
__be16 id;
__be16 frag_off;
__u8 ttl;
__u8 protocol;
__sum16 check;
__be32 saddr;
__be32 daddr;
/*The options start here. */
};
- ip_hdr(), skb_network_header() 함수 선언부
#include <linux/ip.h>
struct iphdr *ip_hdr(const struct sk_buff *skb);
/* 또는 */
#include <linux/skbuff.h>
unsigned char *skb_network_header(const struct sk_buff *skb);
- 설명
- ip_hdr() 내부에서는 실제로 skb_network_header() 함수를 호출하는 구조입니다.
- 내부 구현은 sk_buff 의 시작위치인 skb->head 에 skb->network_header 의 offset 위치를 더한값을 리턴합니다.
skb->head + skb->network_header
IPv6 관련
- ipv6hdr
#include <linux/ipv6.h>
struct ipv6hdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 priority:4,
version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
__u8 version:4,
priority:4;
#else
#error "Please fix <asm/byteorder.h>"
#endif
__u8 flow_lbl[3];
__be16 payload_len;
__u8 nexthdr;
__u8 hop_limit;
struct in6_addr saddr;
struct in6_addr daddr;
};
- ipv6_hdr(), skb_network_header() 함수 선언부
#include <linux/ipv6.h>
struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb);
/* 또는 */
#include <linux/skbuff.h>
unsigned char *skb_network_header(const struct sk_buff *skb);
- 설명
- ip_hdr() 내부에서는 실제로 skb_network_header() 함수를 호출하는 구조입니다.
- 내부 구현은 sk_buff 의 시작위치인 skb->head 에 skb->network_header 의 offset 위치를 더한값을 리턴합니다.
skb->head + skb->network_header - 그런데 실제로 파싱할때는 network header가 IPv4인지 IPv6 인지 알지 모르기때문에 ip_hdr()로 먼저 ip header를 얻어낸후 iphdr 와 ipv6hdr 구조체의 처음 version, priority의 사이즈가 같기 때문에, iphdr->version 이
4면 그대로 사용하면 되고, iphdr->version 이 6이면 ipv6_hdr() 함수를 사용해서 다시 파싱하면 됩니다.
TCP header (Transport layer)
- tcphdr 구조체
#include <linux/tcp.h>
struct tcphdr {
__be16 source;
__be16 dest;
__be32 seq;
__be32 ack_seq;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u16 res1:4,
doff:4,
fin:1,
syn:1,
rst:1,
psh:1,
ack:1,
urg:1,
ece:1,
cwr:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u16 doff:4,
res1:4,
cwr:1,
ece:1,
urg:1,
ack:1,
psh:1,
rst:1,
syn:1,
fin:1;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
__be16 window;
__sum16 check;
__be16 urg_ptr;
}
- tcp_hdr(), skb_mac_header() 함수 선언부
#include <linux/tcp.h>
struct tcphdr *tcp_hdr(const struct sk_buff *skb);
/* 또는 */
#include <linux/skbuff.h>
unsigned char *skb_transport_header(const struct sk_buff *skb);
- 설명
- tcp_hdr() 내부에서는 실제로 skb_transport_header() 함수를 호출하는 구조입니다.
- 내부 구현은 sk_buff 의 시작위치인 skb->head 에 skb->tranport_header 의 offset 위치를 더한값을 리턴합니다.
skb->head + skb->transport_header
오늘 포스팅은 여기서 마치겠습니다. 다음에는 위의 함수를 사용하지 않고,
각 헤더들의(mac header, ip header, tcp header) 멤버들을 사용해서 헤더를 가져오는 방법을 포스팅하겠습니다.
그 전에 각 헤더들의 역할에 대해서 설명하는게 먼저 있는게 좋겠네요 ㅎㅎ
읽어주셔서 감사합니다.
'Kernel TCP IP' 카테고리의 다른 글
TCP header (+ TCP 옵션) (0) | 2019.12.31 |
---|---|
TCP timers (Persistent, Keep alive, Time wait) (0) | 2019.12.27 |
TCP timer (Retransmission timer) (0) | 2019.12.26 |
TCP sliding window 개념 (0) | 2019.12.21 |
struct sk_buff 관련 함수 (1) | 2019.12.20 |