Download presentation
Presentation is loading. Please wait.
1
Passing Credentials And File Description
PL 실험실 석사 1학기 박병태
2
목 차 Ancillary Data 소개 I/O Vector 소개 sendmsg(2)와 recvmsg(2) 함수
Socket Server의 테스트
3
Ancillary Data 소개 특징 credential은 보조데이타의 부분으로 수락 보조데이터는 보통의 자료를 수반
보조데이터는 여러 개의 보조 항목을 포함
4
I/O Vector 소개(1) I/O Vector(struct iovec) struct iovec
ptr_t iov_base; /*시작 주소*/ size_t iov_len; /*바이트 길이*/ Struct iovec은 하나의 백터 원리로 정의된다 보통 이구조체는 여러 개의 요소에서 배열처럼 사용 readv(2)와 writev(2)의 함수에서 사용
5
I/O Vector 소개(2) readv(2)와 writev[2] 함수 함수의 원형
#include <sys/uio.h> int readv(int fd, const struct iovec *vector, int count) int writev(int fd, const struct iovec *vector, int count) 3가지 인수의 대한 설명 int fd : 파일 기술자 const struct iovec *vector : 읽고 쓰기 위해 사용되는 I/O vector Int count: 사용하는 백터 요소의 수
6
I/O Vector 소개(3) writev(2)를 사용하는 예제 17.1 순서도 함수선언/초기화 Iovec iov[] 정의
스트링 길이 결정 Writev(2) 시스템 콜
7
I/O Vector 소개(4) 소스분석(예제 17.1) 물리적으로 분리된 스트링 세개를 정의
9 : static char part2[] = “ THIS IS FROM WRITEV”; 10: static char part3[] = “]\n”; 11: static char part1[] = “[“; 물리적으로 분리된 스트링 세개를 정의 12: struct iovec iov[3]; I/O vector iov[3] 이 정의 14: iov[0].iov_base = part1; 15: iov[0].iov_len = strlen(part1); 14라인에서 첫번째 스트링의 포인터를 I/O Vector에 할당 15라인에서 첫번째 스트링의 길이가 결정 23: writev(1, iov, 3); 23라인에서 writev 시스템 콜이 실행된다. 인수의 1은 표준출력에 사용되고 I/Ovector 배열 iov이 제공되고 3은 세개의 값을가진 3개의 인자로 정의 된다.
8
I/O Vector 소개(5) 실행 실행결과 $ make writev
gcc -g -c -D_GNU_SOURCE -Wall -Wreturn -type writev.c gcc writev -O -o writev $ ./writev [THIS IS FROM WRITEV] $
9
sendmsg(2)와 recvmsg(2) 함수(1)
# include <sys/types.h> # include <sys/socket.h> int sendmsg(int s, const struct msghdr *msg, unsigned int flags); Sendmsg에 대한 설명 보내는 메시지 소켓 S 구조체 포인터 msg메시지 헤더는 이 함수호출의 연산자를 제어. 선택적 플래그 비트 인수. 이것은 send(2)와 sendto(2)의 함수호출에 유효한 같은 플래그 임. 이 함수의 리턴값은 보낸 바이트 수
10
sendmsg(2)와 recvmsg(2) 함수(2)
함수의 원형 # include <sys/type.h> # include <sys/socket.h> int recvmsg(int s, struct msghdr *msg, unsigned int flags); recvmsg에 대한 설명 메시지를 받는 소켓 s 구조체 포인터 msg 메시지 헤더는 함수호출의 연산자 제어 선택적 플래그 비트 인수. 이것은 recv(2)와 recvfrom(2)함수호출에 유용한 같은 플래그 이함수의 리턴값은 받은 바이트의 수
11
sendmsg(2)와 recvmsg(2) 함수(3)
Struct msghdr의 이해 구조체의 정의 Struct msghdr{ void *msg_name; socklen_t msg_namelen; struct iovec msg_iov; size_t *msg_iovlen; void msg_control; size_t msg_controllen; int msg_flags; } 이 구조체 맴버는 4개의 그룹으로 나눌수 있다. 소켓 주소 맴버 msg_name과 msg_namelen 참조 I/O vector msg_iov 와 msg_iovlen 보조자료 버퍼 맴버 msg_control와 msg_controllen 받아진 메시지 플레그 비트 msg_flags.
12
Ancillary Data 구조체와 매크로(1)
struct cmsghdr 구조체 소개 구조체의 정의 struct cmsghdr{ socklen_t cmsg_len; int cmsg_level; int cmsg_type; /* u_char cmsg_data[];*/ }; 구조체 맴버에 대한 설명 cmsg_len은 구조상의 헤더의 크기를 포함하는 보조 자료의 바이트 총계 이 값은 CMSG_LEN()매크로에 의해 계산 cmsg_level이 값는 시작되고 있는 프로토콜 수준 cmsg_type 이 값 제어 통제 메시지 형 cmsg_data 이 멤버는 실제로는 존재하지 않는다. 그것은 설명에서 추가 보조 자료가 물리적으로 위치하는지 설명하는 것을 나타내어진다
13
Ancillary Data 구조체와 매크로(2)
Msg_controlen CMSG_SPACE() CMSG_SPACE() CMSG_LEN() CMSG_LEN() cmsghdr cmsghdr cmsg_data[] cmsg_data[] ancillary object number 1 number 2 padding cmsg_type() padding cmsg_type() cmsg_len() cmsg_len() cmsg_level() cmsg_level() Figure 17.1
14
Ancillary Data 구조체와 매크로(3)
cmsg(3) 매크로 소개 cmsg(3) 구성 # include <sys/socket.h> struct cmsghdr *CMSG_FIRSTHDR(struct msghdr *msgh); size_t CMSG_ALIGN(size_t length); size_t CMSG_SPACE(size_t length); size_t CMSG_LEN(size_t length); void *CMSG_DATA(struct cmsghdr *cmsg); - 몇개의 매크로는 다른 유닉스에서는 사용가능하지 않는다 (예를 들어, FreeBSD 유닉스에는 CMSG_AIGN(), CMSG_SPACE(), CMSG_SPACE() 매크로가 없다.)
15
Ancillary Data 구조체와 매크로(4)
보조데이타 루프 예제 struct msghdr msgh; /*Message Hdr*/ struct cmsghdr *cmsg /* Ptr to ancillary hdr*/ int *fd_ptr; /* Ptr fo file descript*/ int received_fd; /*the file descriptor*/ for (cmsg=CMSG_FIRSTHDR(&msgh); cmsg!=NULL; cmsg=CMSG_NXTHDR(&msgh,cmsg)){ if(cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS){ fd_ptr = (int*) CMSG_DATA(cmsg); received_fd = *fd_ptr; break; } if(cmsg == NULL) { /* Error : No file descriptor recv`d */
16
Ancillary Data 구조체와 매크로(5)
보조데이타 생성 sturuct msghdr msg; /*Message header*/ struct cmsghdr cmsg; /*Ptr to ancillary hdr*/ int fd; /*File descriptor to send*/ char buf[CMSG_SPACE(sizeof fd)]; /*Anc. Buf */ int fd_ptr; /*Ptr to file descriptor*/ msg.msg_control = buf; msg.msg_controllen = sizeof buf; cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof fd); /*Initialize the payload:*/ fd_ptr = (int *) CMSG_DATA(cmsg); *fd_ptr = fd; /* Sum of the length of all control messages in the buffer: */ msg.msg_controllen = cmsg -> cmsg_len;
17
Ancillary Data 예제 recvcred.c(예제 17.4) 순서도 초 기 화 구조체 msghdr 초기화
초 기 화 구조체 msghdr 초기화 Recv_fd() 호출 메시지 수신 사용자 인증
18
Ancillary Data 예제 초기화[32-49] 32: int s, /*Socket*/
33: struct ucred *credp, /*Credential buffer*/ 34: void *buf, /*receiving Data buffer*/ 35: unsigned bufsiz, /* Recv. Data buf size*/ 36: void *addr, /*Received Peer address*/ 37: socklen_t *alen) /* Ptr to addr length*/ 38: 39: int z; 40: struct msghdr msgh; /* Message header */ 41: struct iovec iov[1]; /* I/O vector */ 42: struct cmsghdr *cmsgp=NULL; 43: char mbuf[CMSG_SPACE(sizeof * credp)]; 44: 45: /* 46: *Zero out message areas: 47: */ 48: memset(&msgh,0,sizeof msgh); 49: memset(&mbuf,0,sizeof mbuf);
19
Ancillary Data 예제 구조체 msghdr 초기화 72: msgh.msg_control=mbuf;
54: msgh.msg_name=addr; 55: msgh.msg_namelen=alen?*alen : 0; 60: msgh.msg_iov=iov; 61: msgh.msg_iovlen=1; 66: iov[0].iov_base=buf; 67: iov[0].iov_len=bufsiz; 72: msgh.msg_control=mbuf; 73: msgh.msg_controllen=sizeof mbuf;
20
Ancillary Data 예제 메시지 수신 78: do 79: z=recvmsg(s,&msgh,0);
80: while (z==-1 && errno == EINTR); 81: 82: if(z==1) 83: return -1; /*Failed:check errno*/ 84: 85: /* 86: * If ptr alen is non-NULL, return the 87: * returned address length (datagrams): 88; */ 89: if(alen) 90: *alen=msgh.msg_namelen; 91: 92: /* 93: *Walk the list of control messages: 94: /* 95: for(cmsgp=CMSG_FIRSTHDR(&msgh); 96: cmsgp != NULL; 97: cmsgp=CMSG_NXTHDR(&msgh,cmsgp) ) 98: 99: if(cmsgp->cmsg_lever == SOL_SOCKET 100: && cmsgp->cmsg_type==SCM_CREDENTIALS)
21
Ancillary Data 예제 사용자 인증 95: for(cmsgp=CMSG_FIRSTHDR(&msgh);
96: cmsgp != NULL; 97: cmsgp=CMSG_NXTHDR(&msgh,cmsgp) ) 98: 99: if(cmsgp->cmsg_lever == SOL_SOCKET 100: && cmsgp->cmsg_type==SCM_CREDENTIALS) 101: 102: /* 103: *Pass back credentials struct: 104: */ 105: *credp=* 106: (struct ucred *) CMSG_DATA(cmsgp); 107: 108: return z; /* 3 of data byes read */ 117: errno=ENOENT; 118: return -1;
22
c=accept(s,(struct sockaddr *) fgets(getbuf,sizeof getbuf,rx); .
Ancillary Data 예제 간단한 웹 서버(예제 17.5) 순서도 c=accept(s,(struct sockaddr *) &a_cln,*alen); 함수선언/초기화 rx=fdopen(c,"r"); tx=fdopen(dup(c),"w"); 소켓 생성/바인드 Socket(); bind(); fgets(getbuf,sizeof getbuf,rx); . Reqport(80) 호출 fput(); Listen(2) 호출 fclose() ;
23
Ancillary Data 예제 reqport() 함수 순서도(예제 17.6) 소켓 생성 connect(2) 호출
write(2) 호출 recv-fd() 호출 close() 호출
24
Ancillary Data 예제 recv_fd 함수 순서도(예제 17.7) 선 언 msghdr 구조체 초기화 memset();
선 언 msghdr 구조체 초기화 memset(); Recv_fd() 호출 구조체 msghdr 초기화 메시지 수신 종 료
25
Ancillary Data 예제 소스분석 구조체 msghdr 초기화 43: msgh.msg_iov = iov;
44: msgh.msg_iovlen = 1; 50: iov[0].iov_base = dbuf; 51: iov[0].iov_len = sizeof dbuf; 56: msgh.msg_control = buf; 57: msgh.msg_controllen = sizeof buf;
26
Ancillary Data 예제 메시지 수신 62: do 63: z=recvmsg(s,&ms호,0);
64: while (z== -1 && reeno == EINTR); 65: 66: if (z==-1) 67: return -1; /* Failed: see errno*/ 73: for ( cmsgp = CMSG_FIRSTHDR(&msgh); 74: cmsgp !=NULL; 75: cmsgp = CMSG_NXTHDR(&msgh, cmsgp) 76: 77: if (cmsgp->cmsg_level == SOL_SOCKET 78: && cmsgp -> cmsg_type == SCM_RIGHTS) 82: return *(int *) CMSG_DATA(cmsgp); 92: if (z== sizeof (int) ) 93: errno = *(int *)dbuf; /* Rcvd errno*/ 94: else 95: errno = ENOENT; /*Default errno*/ 96: 97: return -1; /* Return failure indication */
27
Ancillary Data 예제 sockserv 서버 프로그램 순서도(예제 17.8) 함 수 선언 listen(2); 호출
초 기 화 연결을 기다림 accept(); UserID 생성 Fputs(); 종 료 socket(); 호출
28
Ancillary Data 예제 Send_fd() 함수
순서도(예제 17.9) 함 수 선언 Client process 송신 sendmsg(); 메시지 clear memset(); 구조체 msghdr 초기화
29
Ancillary Data 예제 구조체 msghdr 초기화 33: memset(&msgh,0,sizeof msgh);
34: memset(buf,0,sizeof buf); 39: msgh.msg_name = addr; 40: msgh.msg_namelen = alen; 45: msgh.msg_iov = iov; 46: msgh.msg_iovlen = 1; 54: iov[0].iov_base = &er; 55: iov[0].iov_len = sizeof er; 60: msgh.msg_control = buf; 61: msgh.msg_controllen = sizeof buf;
30
Ancillary Data 예제 메시지 clear client process 송신
67: cmsgp = CMSG_FIRSTHDR(&msgh); 68: cmsgp->cmsg_level = SOL_SOCKET; 69: cmsgp->cmsg_type = SCM_RIGHTS; 70: cmsgp->cmsg_len = CMSG_LEN(sizeof fd); 75: *((int *)CMSG_DATA(cmsgp)) = fd; 76: msgh.msg_controllen = cmsgp->cmsg_len; client process 송신 81: do { 82: z = sendmsg(s,&msgh,0); 83: } while ( z == -1 && errno == EINTR ); 84: 85: return z == -1 ? -1 : 0;
31
Socket Server의 테스트 결과 $ ./web80 stand_alone
Permission denied: binding port 80 $
32
Socket Server의 테스트 Sockserv 테스트 예제 1 예제 2 $ su root Pssword:
# ./sockserv fred & [1] 1077 # $ ./web80 & [1] 1079 $
33
Socket Server의 테스트 예제 3 $ telnet 127.0.0.1 80 Trying 127.0.0.1...
Connected to Escape character is '^]'. GET/something <HTML> <HEAD> <TITLE> Test Page for this little web80 server</TITLE> </HEAD> <BODY> <H1>web80 Worked!</H1> <H2>From PID Nov 20 12:39: </H2> </BODY> </HTML> Connection closed by foreign host. $
34
참고자료 쓰기 함수 SCM_RIGHTS와 SCM_CREDENTIALS 함수 추가된 특징 write(2) 단순한 소켓쓰기 함수
함수 추가된 특징 write(2) 단순한 소켓쓰기 함수 send(2) 플래그 인자 추가 sendto(2) 소켓주소와 소켓길이 인자 추가 writev(2) 플래그와 소켓주소는 없고, 분산해서 쓰기 sendmsg(2) 플래그와 소켓주소와 길이 추가 분산된 쓰기 cmsg_level 설 명 SCM_RIGHTS 보조데이터 개체는 파일기술자이다 SCM_CREDENTIALS 보조데이터는 신임장 정보를 포함한 구조체이다
35
참고자료 struct msghdr msg_flags values Flag bit 설명 MSG_EOR
이 플래그 비트는 레코드를 끝까지 받았을 때 설정된다. 이것은 보통은 SOCK_SEQPACKET 소켓 형으로 사용된다 MSG_TRUNC 이 플래그 비트는 데이터그램의 끝부분이 짤려졌을 때를 나타낸다 왜냐하면 버퍼를 받을 때 너무나 작아서 이것을 적용할 수가 없다 MSG_CTRUNC 이 비트는 몇몇의 제어(보조) 데이터가 버퍼가 너무 작기 때문에 절삭되었다는 것을 지적한다 MSG_OOB 이 비트는 데이터가 범위를 넘거나 빨리 받아 졌다는 것을 지적한다 MSG_ERRQUEUE 이 플래그 비트는 데이터를 받지 않았다는 것을 지적한다. 그러나 확장된 애러를 돌려준다.
36
참고자료
Similar presentations