[ CnUnix ] in KIDS 글 쓴 이(By): swhan (Nameless1) 날 짜 (Date): 2005년 3월 17일 목요일 오후 05시 58분 03초 제 목(Title): [질문] UDP packet에서 IP TOS읽기 socket으로 UDP datagram을 수신하는 모듈이 있습니다. IP header에서 TOS와 IP option field를 읽어야 합니다. recvmsg() call을 처음 쓰는거라 제대로 쓴건지도 모르겠습니다. 웹질을 해도 샘플소스는 찾기 힘들군요. 실행 환경은 vxworks이지만, 일단 테스트를 위해서 Linux 2.6.9, gcc 3.4.2 와 FreeBSD 5.2.1 gcc 3.3.3으로 실행해본 결과, control field및 recvmsg후의 TTL값 모두가 0으로 나옵니다. 루트로 실행해도 마찬가지입니다. 아래 테스트 코드를 첨부합니다. 도대체 뭐를 잘못했을까요? setsockopt를 몇 개 추가해야하나요? ----- recvmsg.c ----- #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> int main(void) { struct sockaddr_in myaddr; int addrlen; int sfd = socket(AF_INET, SOCK_DGRAM, 0); if( sfd < 0) { printf("socket fail errno=%d", errno); return -errno; } myaddr.sin_family = AF_INET; addrlen = sizeof(struct sockaddr_in); myaddr.sin_port = htons(3434); myaddr.sin_addr.s_addr = INADDR_ANY; if( bind(sfd, (struct sockaddr*)&myaddr, addrlen) < 0) { printf("bind fail errno=%d", errno); return -errno; } { int ttrue = 0; if( setsockopt(sfd, IPPROTO_IP, IP_RECVOPTS, &ttrue, sizeof(ttrue)) < 0) { printf("setsockopt fail errno=%d", errno); return -errno; } int ttl = 139; setsockopt(sfd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); setsockopt(sfd, IPPROTO_IP, IP_HDRINCL, &ttl, sizeof(ttl)); printf("\n ttl=%d\n", ttl); // setsockopt(sfd, IPPROTO_IP, IP_RECVDSTADDR,&true, sizeof(true)); } { struct msghdr msg; struct iovec iov[1]; unsigned char buf[10240]; ssize_t len; struct sockaddr_in remoteaddr; unsigned char control[9024]; struct cmsghdr *cmsg; int ii = 0; memset(&msg, 0, sizeof(msg)); memset(&iov, 0, sizeof(iov)); iov[0].iov_base = buf; iov[0].iov_len = sizeof(buf); msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_name = &remoteaddr; msg.msg_namelen = sizeof(remoteaddr); msg.msg_control = control; msg.msg_controllen = 9024; msg.msg_flags=0; len = recvmsg(sfd, &msg, 0); printf("len = %d\n", len); for(ii = 0; ii < 10; ii++) { printf("%02X ", buf[ii]); } printf("\n port =%d, ADDR= %08X\n",ntohs(remoteaddr.sin_port), remoteaddr.sin_addr.s_addr); printf("flag=%d\n", msg.msg_flags); printf("controllen=%d\n", msg.msg_controllen); int ttl; int datalen; getsockopt(sfd, IPPROTO_IP, IP_TTL, &ttl, &datalen); printf("\n ttl=%d, datalen=%d\n", ttl, datalen); int *ttlptr; int received_ttl; /* Receive auxiliary data in msgh */ for(cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg,cmsg)) { printf("\nlevel = %d, type = %d ", cmsg->cmsg_level, cmsg->cmsg_type); if(cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_TTL){ ttlptr = (int *) CMSG_DATA(cmsg); received_ttl = *ttlptr; printf(" IP/TTL"); } else if(cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_TOS){ ttlptr = (int *) CMSG_DATA(cmsg); received_ttl = *ttlptr; printf(" IP/TTL"); } else if(cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_OPTIONS){ ttlptr = (int *) CMSG_DATA(cmsg); received_ttl = *ttlptr; printf(" IP/OPTIONS"); } } } return 0; } -----여기까지--- |