오랜만에 초심으로 돌아가 리눅스 프로그램을 까보았습니다. 사실 선생님 한분이 도와주셨어요. 네트워크 전공 이신지 네트워크 위주로 시작했습니다.
1. 리눅스 커널 소스 가져오기
$ wget으로 웹에서 데이터 가져옴
2. 커널 소스 태깅하기
$ make tags
3. iphdr : ip 프로토콜
struct iphdr {
__u8 ihl:4, // 길이 : 5*4 byte
version:4;
__u8 tos; // type of service - 현재 미사용
__be16 tot_len; // byte 단위, data length = tot_len -ihl*4
__be16 id; // 패킷을 나눴을 때 동일한 패킷임을 확인하는 Id
__be16 frag_off; // 패킷을 나눈 경우 순서 확인용, 위치값을 넣는다.*
__u8 ttl; // time to live 생존 타임, 루프 돌게 되는 경우 자동 폭파~
__u8 protocol; // 상위 레이어 명시
__sum16 check;
__be32 saddr;
__be32 daddr;
};
* frag_off를 순서로 기입한 것이 아니라 떨어진 위치를 기입한 이유가 무엇일까.
-> 최초에 패킷이 조각 난 후, 또 다시 조각 날 수도 있다. 이때 순서 값을 사용했다면 코드 더러워졌을 듯. 그냥 떨어진 거리, 위치로 하면 또 다시 위치 값을 넣어주면 그만이다.
-> NF도 frag_off에 존재한다. 0이면 마지막 패킷.
* ARP
IP는 알고, 상대편 Mac Addr를 모를때 전송하는 방법.
1. Mac 브로드캐스트
2. IP가 맞는 경우 응답
-> 관련 데이터(맵핑)를 계속 업데이트 하여 속도를 빠르게 함 $ arp -a
* Ip 라우팅
1. 직접 전달 - 동일 네트워크 안에서 전달
2. 간접 전달 - 나와 너가 서로 다른 네트워크, 여러 라우터를 통해서 전달 ( 가장 적은 hop을 가진 경로로.)
4. tcphdr : tcp 프로토콜
-> ip 프로토콜의 업그레이드 버전
struct tcphdr {
__be16 source; // my port num
__be16 dest; // your port num
__be32 seq;
__be32 ack_seq;
__u16 doff:4,
res1:4,
cwr:1, // 각 비트들이 유효한지 아닌지 알려주는 값들(아래들도)
ece:1,
urg:1,
ack:1,
psh:1,
rst:1,
syn:1,
fin:1;
__be16 window;
__sum16 check;
__be16 urg_ptr;
};
TCP는 유실이 없음 -> seq를 주기 때문에 가능. -> 3way handshaking통해 첫 seq를 주고 받음
window : 남은 버퍼 사이즈를 알려주는 용. 상대방은 이 만큼(윈도우크기)만 나에게 전달한다. tcp 수신버퍼가 busy 할 때 사용. 버퍼 유실을 막음.
5. udphdr
struct udphdr {
__be16 source;
__be16 dest;
__be16 len;
__sum16 check;
};
초간단.
tcp의 기능을 다 뺀 것이 udp, 단 빠르다.
6. ip addr setting - endian
인텔 - little endian ( 순서가 거꾸로 저장 됨 -> 현재 많이 사용)
IBM - big endian ( 정순으로 저장 -> 표준 )
인텔을 정순(big endian)으로 바꾸어줘야 한다.
#define htonl(ip) ((ip<<24)&0xff000000|(ip<<8)&0xff0000|(ip>>8)&0xff00|(ip>>24)&0xff)
7. IP addr conversion
Domain name -> 32bit : getthostbyname()
32bit -> domain name : gethostbyaddr()
dotted decimal -> 32bit : inet_addr(), inet_aton()
32bit -> dotted decimal -> inet_ntoa()
#include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
extern int h_errno;
int main(int argc, char **argv)
{
if (argc != 2 )
{
printf ("err arg");
return 0;
}
int i;
struct hostent *he;
struct in_addr addr;
he = gethostbyname(argv[1]);
printf ("h_name : %s\n",he->h_name);
for ( i = 0; he->h_aliases[i]; i++)
{
printf("[%d]h_aliases : [%s]\n",i,he->h_aliases[i]);
}
for ( i = 0; he->h_addr_list[i]; i++)
{
addr.s_addr = *(unsigned *)he->h_addr_list[i];
printf("[%d]h_addr : [%s]\n",i,inet_ntoa(addr));
}
return 0;
}
참고
* 이진수 : 1111 = 10진수 15
* 16진수 : 0000 = 이진수 4자리 * 4개 즉, 이진수 0000 0000 0000 0000
* 8bit = 1byte
* port : 어플리케이션을 구분하게 해줌, 21 : ftp, 22 : ssh 등등. 다 확인하고 싶다면 /etc/services
* 책 : 유닉스 네트워크 프로그래밍 Vol.1 - 네트워크의 대가 리차드.(안에 소스가 good)
* http://www.kohala.com/ - 리차드 씨 추모 사이트. 소스가 존재
* 네트워크에 대한 기본적인 내용들은 아래 사이트에 정리되어 있음.
1. 면접 단기 -> 네크워크
2. 네크워크
'IT > Linux(Unix)' 카테고리의 다른 글
남들은 자주 안쓰지만 나는 자주쓰는 VI 꿀팁들 (0) | 2024.10.19 |
---|---|
리눅스 프로그래밍 - 커널 소스 분석하기 ( ftp 서버 구현, 쓰래드 다루기 ) (0) | 2022.08.03 |
리눅스 프로그래밍 - 커널 소스 분석 ( 소켓, 서버 ) (0) | 2022.07.21 |
[VI] Xshell 에러 해결 모음집 (0) | 2021.05.04 |