소켓 프로그래밍 주석에 대한 질문입니다
파랑새
아래의소스 코드는 리눅스 환경에서 작성한 내용입니다. TCP 방식에서 한 개의 SYN 신호를 발생시키는 기능을 수행합니다. 혹시 관심 있는 분은 그대로 복사 떠서 리눅스(제 경우에는 페도라 코어 8입니다)에서 gcc tcpsyn.c -o tcpsyn로 컴파일해서 ./tcpsyn 1.1.1.1 23 2.2.2.2 23 100과 같은 식으로 실행해 보세요. 1.1.1.1 23은 목적지이고, 2.2.2.2 23은 출발지입니다. 100은 SEQ 번호입니다. SEQ 번호는 임의 설정입니다.
//tcpsyn.c
#include stdio.h
#include stdlib.h
#include string.h
#include unistd.h
#include sys/types.h
#include sys/socket.h
#include netinet/in_systm.h
#include netinet/in.h
#include netinet/ip.h
#define __FAVOR_BSD
#include netinet/tcp.h
#include arpa/inet.h
#define CHKADDRESS(_saddr_) \
{\
u_char *p = (char *)&(_saddr_);\
if ((p[0] == 10)\
|| (p[0] == 168 && 16 = p[1] && p[1] = 31)\
|| (p[0] == 192 && p[1] == 168) )\
;\
else {\
fprintf(stderr, IP address error.\n);\
exit(EXIT_FAILURE);\
}\
}
enum {CMD_NAME, DST_IP, DST_PORT, SRC_IP, SRC_PORT, SEQ};
#define MAXDATA 1500
struct packet_tcp {
struct ip ip;
struct tcphdr tcp;
u_char data[MAXDATA];
};
void make_ip_header(struct ip *ip, int src_ip, int dst_ip, int len);
void make_tcp_header(struct packet_tcp *packet, int src_ip, int src_port, int dst_ip, int dst_port, int seq, int ack, int datalen);
u_short checksum(u_short *data, int len);
//main 함수의 시작 -------------------------------------------------------------------------------------(1)
int main(int argc, char *argv[])
{
struct packet_tcp send; //송신 TCP Packet
struct sockaddr_in dest; //출발지 주소
u_int src_ip; //출발지 IP 주소
u_int dst_ip; //목적지 IP 주소
u_short src_port; //출발지 Port 번호
u_short dst_port; //목적지 Port 번호
int s; //Socket File Descriptor
tcp_seq seq; //일련 번호
tcp_seq ack; //확인 응답 번호
int datalen; //Data Size
int iplen; //IP Header 길이
int on = 1; //ON
//인수 검사 ----------------------------------------------------------------------------------------- (2)
if(argc != 6)
{
fprintf(stderr, usage: %s dst_ip dst_port src_ip src_port seq\n, argv[CMD_NAME]);
exit(EXIT_FAILURE);
}
//RAW Socket 개방 --------------------------------------------------------------------------------- (3)
if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) 0)
{
perror(socket(SOCK_RAW));
exit(EXIT_FAILURE);
}
//임의의 IP Header 작성 ---------------------------------------------------------------------------- (4)
if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) 0)
{
perror(setsockopt(IPPROTO_IP, IP_HDRINCL));
exit(EXIT_FAILURE);
}
//Header 값 설정(명령어 인수에서 헤더로 설정한 값을 인출) ------------------------------------------- (5)
memset((char *) &dest, 0, sizeof(dest));
dest.sin_family = AF_INET;
dst_ip = dest.sin_addr.s_addr = inet_addr(argv[DST_IP]);
src_ip = inet_addr(argv[SRC_IP]);
sscanf(argv[DST_PORT], %hu, &dst_port);
sscanf(argv[SRC_PORT], %hu, &src_port);
sscanf(argv[SEQ], %ul, &seq);
ack = 0;
datalen = 0;
iplen = datalen + sizeof(send.ip) + sizeof(send.tcp);
memset((char *) &send, 0, sizeof(send));
//TCP Header 작성 ------------------------------------------------------------------------------- (6)
make_tcp_header(&send, src_ip,src_port, dst_ip,dst_port, seq,ack, datalen);
//IP Header의 작성 ------------------------------------------------------------------------------- (7)
make_ip_header(&(send.ip), src_ip, dst_ip, iplen);
CHKADDRESS(dst_ip);
//SYN 신호 송신 ---------------------------------------------------------------------------------- (8)
printf(SYN send to %s.\n, argv[DST_IP]);
if(sendto(s, (char *)&send, iplen, 0, (struct sockaddr *) &dest, sizeof(dest)) 0)
{
perror(sendto);
exit(EXIT_FAILURE);
}
//RAW Socket 종료 ------------------------------------------------------------------------------ (9)
close(s);
//main 함수의 종료 ------------------------------------------------------------------------------ (10)
return EXIT_SUCCESS;
}
void make_tcp_header(struct packet_tcp *packet, int src_ip, int src_port, int dst_ip, int dst_port, int seq, int ack, int datalen)
{
packet-tcp.th_seq = htonl(seq);
packet-tcp.th_ack = htonl(ack);
packet-tcp.th_sport = htons(src_port);
packet-tcp.th_dport = htons(dst_port);
packet-tcp.th_off = 5;
packet-tcp.th_flags = TH_SYN;
packet-tcp.th_win = htons(8192);
packet-tcp.th_urp = 0;
//의사 Header 작성 ---------------------------------------------------------------------------- (11)
packet-ip.ip_ttl = 0;
packet-ip.ip_p = IPPROTO_TCP;
packet-ip.ip_src.s_addr = _addr = src_ip;
packet-ip.ip_dst.s_addr = dst_ip;
packet-ip.ip_sum = htons(sizeof(packet-tcp) + datalen);
//검사합의 계산
#define PSEUDO_HEADER_LEN 12
packet-tcp.th_sum = 0;
packet-tcp.th_sum = checksum((u_short *)(&(packet-ip.ip_ttl)), PSEUDO_HEADER_LEN + sizeof(packet-tcp) + datalen);
}
void make_ip_header(struct ip *ip, int src_ip, int dst_ip, int iplen)
{
ip-ip_v = IPVERSION;
ip-ip_hl = sizeof(struct ip) 2;
ip-ip_id = 0;
#ifdef __linux
//Linux RAW IP의 경우 ------------------------------------------------------------------------- (12)
ip-ip_len = htons(iplen);
ip-ip_off = htons(0);
#else
ip-ip_len = iplen;
ip-ip_off = IP_DF;
#endif
ip-ip_ttl = 2;
ip-ip_p = IPPROTO_TCP;
ip-ip_src.s_addr = src_ip;
ip-ip_dst.s_addr = dst_ip;
//검사합의 계산
ip-ip_sum = 0;
ip-ip_sum = checksum((u_short *)ip, sizeof(struct ip));
}
//검사합 관련 검은 상자(Black Box 처리)
u_short checksum(u_short *data, int len)
{
u_long sum = 0; //구한 검사합
//2 Bytes씩 가산
for(; len 1; len -=2)
{
sum += *data++;
if(sum & 0x80000000)
sum = (sum & 0xffff) + (sum 16);
}
//Data Size가 기수 Byte인 경우 처리
if(len == 1)
{
u_short i = 0;
*(u_char*)(&i) = *(u_char *)data;
sum += i;
}
//항에 넘는 수는 되돌림
while(sum 16)
sum = (sum & 0xffff) + (sum 16);
return (sum==0xffff)? sum : ~sum;
}
혹시 사용하실 분 계시면, 주석에 나타난 숫자는 모두 삭제해 주세요. 제가 질문하기 위해 임의로 붙인 숫자입니다.
질문 1) 중간중간에 나타난 (1)번부터 (12)번까지 설정한 주석의 내용이 정확한지요?
질문 2) 3번 주석에서 말하는 RAW Socket 이란 무엇인가요?Socket이면Socket이지, 도대체 RAW Socket의 의미는 구체적으로 무엇인지요?
질문 3) 4번과 7번 주석의 차이는 무엇인지요? 4번 부분을 빼고 7번 부분만 있다면 어떻게 동작하는지요?
질문 4) 11번 주석처럼 TCP 헤더 부분에 IP 헤더의 내용을 추가하는 구체적인 이유라도 있는지요?
질문 5) 12번 주석의 의미는 무엇인가요?
내용이 그리 재밌는 것 같지 않네요. 감사합니다. 꾸벅! ^^
번호 | 제 목 | 글쓴이 | 날짜 |
---|---|---|---|
2692343 | scnaf에 자꾸 선언을 참조하라는데;; (8) | 도래 | 2025-04-22 |
2692282 | 도스상에서 생성된 exe파일에 press~ 뜨게 하기 (4) | 회사원 | 2025-04-21 |
2692256 | scanf("%*c"); ㅠㅠ 고수님들 | 거북이 | 2025-04-21 |
2692230 | 하노이탑 질문입니다. (1) | 미쁘다 | 2025-04-21 |
2692210 | 정보 올림피아드 문제인데.. 풀이 과정이 궁금합니다.(재귀함수) (5) | 물티슈 | 2025-04-20 |
2692144 | C언어와 리눅스에 대한 질문입니다. | 싴흐한세여니 | 2025-04-20 |
2692114 | 컨텍스트 스위칭하는데 걸리는 시간 측정.. | YourWay | 2025-04-19 |
2692086 | 간접참조 연산자, 증감연산자 질문이용! (2) | 블랙캣 | 2025-04-19 |
2692056 | 주석좀 달아주세요. 몇개적엇는데 몇개만달아주세요. (2) | DevilsTears | 2025-04-19 |
2691978 | 진수 쉽게 이해하는법... (3) | 지지않는 | 2025-04-18 |
2691949 | getchar() 한 문자를 입력받는 함수 질문 | 채꽃 | 2025-04-18 |
2691919 | 배열 정렬 및 합치기 질문입니다. | 사과 | 2025-04-18 |
2691845 | c언어왕초보 질문이 있습니다........ | 루나 | 2025-04-17 |
2691815 | void add(int num); 함수... (4) | 살랑살랑 | 2025-04-17 |
2691756 | 명령 프롬프트 스크롤바가 없어요 | 두메꽃 | 2025-04-16 |
2691725 | 자료구조에 관련해서 질문이 있어 글을 올립니다. | 누리알찬 | 2025-04-16 |
2691697 | if 문에서 구조체 배열에 저장되있던 문자열 검사하는 법 ? (2) | 민트맛사탕 | 2025-04-16 |
2691678 | C언어 함수 질문이요~!!! | 연보라 | 2025-04-15 |
2691650 | 반복문 | 돋가이 | 2025-04-15 |
2691618 | 링크드리스트 개념 질문이예요 (3) | 맨마루 | 2025-04-15 |