위키 피디아 : 

In Unix-like operating systems, a loop devicevnd (vnode disk), or lofi (loopback file interface) is a pseudo-device that makes a file accessible as a block device.
파일을 블럭 디바이스 처럼 엑세스 할 수 있게 해주는 가상의 장치라고 되어 있다.

이미지 등의 파일들을 하나의 장치처럼 사용하도록 마운트 하는 옵션.

예를 들어 CD의 iso 이미지나 플로피 디스크파일을 다룰 때 
하나의 파일안에 파일시스템 전체가 들어있는 경우( ex: 부트이미지 등)
loop device를 통해 해당 파일 시스템안의 파일등을 다룰 수가 있게 된다.

#mount -t ext2 -o loop,ro root.img /mnt/floppy의 형식으로 사용할 수 있으며

ro(readonly)의 옵션은 그 외에도 rw 등을 사용할 수 있다. 

그외에도 loop장치가 명시되지 않으면 ( -o loop라는 옵션만 주면) mount 는 사용하지 않은 loop장치를 찾아서 사용한다.

출처 : kldp

http://kldp.org/node/1725

 

 

참조 : http://www.joinc.co.kr/modules.php?name=News&file=article&sid=24

 

 

다음 과 같은 함수는 대몬화 하는 함수입니다.
int daemon_init(void)
{
pid_t pid;

if ( (pid = fork()) < 0)
return (-1);
else if (pid != 0)
exit(0); /* parent goes bye-bye */

/* child continues */
setsid(); /* become session leader */
chdir("."); /* change working directory */
umask(0); /* clear our file mode creation mask */

return (0);
}

함수가 이해가 안되는것이 아니고 왜 이렇게 하는지를 모르겠내요.
자세한 설명 부탁드릴게요.

 

 

 

 

답변 : xfmulder  님

 

일단 fork()해서 자신은 죽고 CHILD 를 남기는 이유는 init 의 자식이 되기 위해서이지요.
setsid() 함으로써 자신이 기존의 세션과 분리되면 제어 터미널을 잃습니다.
이때 getpgid() 하면 이전의 프로세스 그룹 으로부터도 독립되어 있게 됩니다.
참고로 프로세스와 관련된 id 는 네가지 입니다. pid, ppid, pgid(프로세스그룹), sid(세션ID) (getpid(), getppid() , getpgid() , getsid() 를 찾아보세요 )

세션id를 독립하면 자동으로 프로세스그룹ID(pgid) 도 sid 값으로 바뀝니다.
기존의 프로세스가 kill(0,SIGTERM); 하면 자신의 프로세스 그룹에 15번 시그널을 날리는데 이 데몬은 이미 프로세스그룹에서 독립했으므로 이 시그널 안받습니다. 물론 기존의 제어터미널에서도 독립했습니다.

chdir("/"); 하는건 현재디렉토리를 변경하는것. (자신이 로그를 기록할 적당한 디렉토리로 가도 됩니다. 상대PATH로 파일명 줄수 있음)

umask(0); umask 를 0 으로 했으므로 파일생성 모드 대로 생성됨.
(예를 들면 umask (022) 이면 파일을 rwxrwxrwx 로 생성해도 umask때문에
rwxr-xr-x 로 만들어 지게 됩니다)

[출처] daemon화 하는 펑션|작성자 김정은

1	filter.txt: Linux Socket Filtering
2	Written by: Jay Schulist <jschlst@samba.org>
3	
4	Introduction
5	============
6	
7		Linux Socket Filtering is derived from the Berkeley
8	Packet Filter. There are some distinct differences between
9	the BSD and Linux Kernel Filtering.
10	
11	Linux Socket Filtering (LSF) allows a user-space program to
12	attach a filter onto any socket and allow or disallow certain
13	types of data to come through the socket. LSF follows exactly
14	the same filter code structure as the BSD Berkeley Packet Filter
15	(BPF), so referring to the BSD bpf.4 manpage is very helpful in
16	creating filters.
17	
18	LSF is much simpler than BPF. One does not have to worry about
19	devices or anything like that. You simply create your filter
20	code, send it to the kernel via the SO_ATTACH_FILTER ioctl and
21	if your filter code passes the kernel check on it, you then
22	immediately begin filtering data on that socket.
23	
24	You can also detach filters from your socket via the
25	SO_DETACH_FILTER ioctl. This will probably not be used much
26	since when you close a socket that has a filter on it the
27	filter is automagically removed. The other less common case
28	may be adding a different filter on the same socket where you had another
29	filter that is still running: the kernel takes care of removing
30	the old one and placing your new one in its place, assuming your
31	filter has passed the checks, otherwise if it fails the old filter
32	will remain on that socket.
33	
34	Examples
35	========
36	
37	Ioctls-
38	setsockopt(sockfd, SOL_SOCKET, SO_ATTACH_FILTER, &Filter, sizeof(Filter));
39	setsockopt(sockfd, SOL_SOCKET, SO_DETACH_FILTER, &value, sizeof(value));
40	
41	See the BSD bpf.4 manpage and the BSD Packet Filter paper written by
42	Steven McCanne and Van Jacobson of Lawrence Berkeley Laboratory.

sendto

 

sendto 함수는 지정된 주소로 데이터를 전송하는 함수입니다.

 

int sendto (
        SOCKET  
s,
        const char FAR *  
buf,
        int  
len,
        int  
flags,
        const struct sockaddr FAR *  
to,
        int 
 tolen
);

 

Parameters

s
[입력] 소켓의 기술자를 명시합니다.

buf
[입력] 전송될 데이터를 가지고 있는 버퍼

len
[입력] 버퍼 않에 있는 데이터의 길이

flags
[입력] 
함수의 호출이 어떤일을 할지 나타내는 플래그 입니다.

to
[입력] 데이터가 전송될 원격 호스트의 어드레스를 나타냅니다.

tolen
[입력] 
to 매개변수의 크기

Remarks

sendto 함수는 소켓(접속 되었건 접속되지 않았건)에서 데이터를 접속된 상대방으로 전송하는데 사용되는 함수입니다. 메시지 지향 소켓(message-oriented sockets)에서 최대 패킷크기(getsockopt 함수로 SO_MAX_MSG_SIZE 옵션의 값을 얻어내서 최대 크기를 구할 수 있습니다.)를 초과하지 않도록 주의 해야 합니다. 만약 데이터가 전송되기에 너무 크다면, 데이터는 전송되지 않고, WSAEMSGSIZE 에러코드를 발생합니다.

to 매개변수는 소켓의 주소체계(address family)로 된 데이터가 전송될 원격 호스트의 어드레스를 나타냅니다. 물론, 브로드캐스트(broadcast) 또는 멀티캐스트 어드레스(multicast address)도 될 수 있습니다. 브로드캐스트 어드레스를 사용하여 전송할 경우 어플리케이션은 SO_BROADCAST 소켓옵션을 가능하게 하여 getsockopt 함수를 호출해야 합니다. getsockopt 함수를 이용하지 않고, 브로드캐스트 하려 한다면, sendto 함수는 실패로 돌아가고, WSAEACCES 에러코들 발생하게 됩니다. TCP/IP 에서, 어플리케이션은 그룹멤버(group member)가 되지 않고도 특정한 멀티캐스트 어드레스로 데이터를 전송할 수 있습니다.

소켓이 바인드 되지 않은 경우 유일한 값은 로컬 시스템에 의해서 할당되어 집니다. 그런다음 소켓은 바운드 된 것 처럼 마킹 됩니다. 이런 경우 어플리케이션은 로컬 소켓의 이름(name)을 얻기 위해 getsockname 함수를 사용할 수 있습니다.

send 함수의 성공적인 종료가 성공적인 데이터의 전송을 의미하지는 않는다는 점을 명심하세요.

sendto 함수는 일반적으로 접속되지 않은 소켓에 대해서, to 매개변수에 지정된 특정한 상대방 소켓으로 데이터그램을 전송하는데 사용하는 함수입니다. 하지만, 소켓(connectionless sockets : SOCK_DGRAM)이 이전에 특정한 주소로 접속되어 있다 하더라도, to 매개변수는 이전에 명시된 목적지 주소를 무시합니다. 접속지향소켓(connection-oriented socket)의 경우 to 와 tolen 매개변수는 무시되며, sendto 함수는 send 함수와 같은 작동을 하게 됩니다.

flag 매개변수는 소켓에 대해 명시된 옵션 이상의 함수동작에 영향을 미치기 위해서 사용될 수 있습니다. 함수의 의미체계는 소켓옵션 그리고, flag 매개변수에 의해서 결정되어 집니다. flag 매개변수를 이용한 방법의 경우 아래의 값을 OR 비트연산을 취해서 구성되어 집니다.

ValueMeaning
MSG_DONTROUTE
 

데이터는 라우팅 될 수 없음을 나타냅니다. 윈도우즈 소켓 시스템은

 대응하는 소켓옵션과 마찬가지로 이 값을 무시 할 수 있습니다.

MSG_OOB

데이터가 out-of-band 데이터로서 전송될 수 있음을 나타냅니다.

이 플래그는 스트림 소켓과만 사용됩니다.

Return Values

에러가 발생하지 않는다면, send 함수는 전송된 총 데이터 크기를 반환합니다. 비동기 소켓의 경우len 매개변수로 건넨 수치보다 작을 수 있습니다. 에러가 발생한 경우는 SOCKET_ERROR를 반환하고, WSAGetLastError를 이용해서 특정한 에러코드를 얻어낼 수 있습니다.

Error Codes

WSANOTINITIALISED

이 함수를 사용하기 전에 성공적인 WSAStartup 함수의 호출이

없었습니다.

WSAENETDOWN 네트웍 서브 시스템에 에러가 발생했습니다.
WSAEACCES

요청된 주소가 브로트캐스트(broadcast) 주소인데, 적절한

플래그가 셋팅되어 있지 않습니다. 브로드캐스트 어드레스의

사용을 허용하기 위해 SO_BROADCAST 매개변수를 가지고,

setsockopt 함수를 호출 해야 합니다.

WSAEINVAL

알 수 없는 플래그가 사용되었거나, SO_OOBINLINE 옵션을

가능하게 한 상태 에서 MSG_OOB 플래그가 소켓에 대해서

명시되었습니다. 또는 len 매개변수가 0 이거나 0보다 작습니다.

WSAEINTR

블록킹 호출이 WSACancelBlockingCall 함수에서

취소되었습니다.

WSAEINPROGRESS

블럭킹 윈속 v1.1 이 현재 진행 중이거나, 서비스 프로바이더가

콜백 함수를 여전히 처리하고 있습니다.

WSAEFAULT buf 매개변수가 제대로 된 형태가 아닙니다.
WSAENETRESET 연산이 진행되고 있는 도중 접속이 끊겨버렸습니다.
WSAENOBUFS 전송하기 위해 사용할 수 있는 버퍼 공간이 없습니다.
WSAENOTCONN 소켓이 접속된 상태가 아닙니다.
WSAENOTSOCK 기술자(descriptor)가 소켓 기술자가 아닙니다.
WSAEOPNOTSUPP

MSG_OOB 가 명시되었지만, 소켓은 SOCK_STREAM 과 같은

형태의 스트림 형태가 아닙니다.

WSAESHUTDOWN 소켓이 셧다운 되었습니다.
WSAEWOULDBLOCK

소켓이 넌블록킹(비동기)로 마킹되어 있고, 수신 연산이 블록킹

상태입니다.

WSAEMSGSIZE

소켓이 메시지 지향형(message oriented)이고, 메시지의

크기가 허용할 수 있는 최대 크기 보다 큽니다.

WSAEHOSTUNREACH

네트웍 시스템 장애 등에 의해서 원격호스트까지 도달 할 수

없습니다.

WSAECONNABORTED

가상 연결 회로망이 타임아웃이나 다른 실패 때문에 끊어져

버렸습니다.

WSAECONNRESET

가상 회로망이 원격지에서 "hard"나 "abortive" 종료를 수행해서

리셋되었습니다.

WSAEADDRNOTAVAIL

원격지 주소가 올바를 형태가 아닙니다. 예를들어 ADDR_ANY와

 같은 형태는 잘못된 형태입니다.

WSAEAFNOSUPPORT 지정된 어드레스 체계가 이 소켓에서 사용될 수 없습니다.
WSAEDESTADDRREQ 목적지 주소가 필요합니다.
WSAENETUNREACH 웍격 시스템까지 네트웍이 도달할 수 없습니다.
WSAETIMEDOUT

접속이 네트웍 실패나 상대방 시스템의 응답 실패로 인하여 드랍

되어 버렸습니다.

 

QuickInfo

Windows NT : 사용가능
Windows : 사용가능
Windows CE : 버젼 1.0 그리고 그이후의 버젼에서 사용가능
Header :
          Win16/32 : winsock.h
          Win32-II : winsock2.h
Import Library :
          Win16 : winsock.lib
          Win32 : wsock32.lib
          Win32-II : ws2_32.lib

 

See Also

overviewrecvrecvfromselectsendsocketWSAAsyncSelectWSAEventSelect

 

 

출처 : DEVPIA 곽용진님 style  APIs

[출처] [Socket] sendto|작성자 임종배

http://softwaredocuments.blogspot.com/2009/10/294-linux-and.html



Linux: SOCK_PACKET and PF_PACKET


There are two methods of receiving packets from the datalink layer under Linux. The original method, which is more widely available but less flexible, is to create a socket of type SOCK_PACKET. The newer method, which introduces more filtering and performance features, is to create a socket of family PF_PACKET. To do either, we must have sufficient privileges (similar to creating a raw socket), and the third argument to socket must be a nonzero value specifying the Ethernet frame type. When using PF_PACKET sockets, the second argument to socket can be SOCK_DGRAM, for "cooked" packets with the link-layer header removed, or SOCK_RAW, for the complete link-layer packet. SOCK_PACKET sockets only return the complete link layer packet. For example, to receive all frames from the datalink, we write


fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));        /* newer systems*/
fd = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL)); /* older systems*/
This would return frames for all protocols that the datalink receives.

If we wanted only IPv4 frames, the call would be


fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));          /* newer systems */
fd = socket(AF_INET, SOCK_PACKET, htons(ETH_P_IP)); /* older systems */
Other constants for the final argument are ETH_P_ARP and ETH_P_IPV6, for example.

Specifying a protocol of ETH_P_xxx tells the datalink which frame types to pass to the socket for the frames the datalink receives. If the datalink supports a promiscuous mode (e.g., an Ethernet), then the device must also be put into a promiscuous mode, if desired. This is done with a PACKET_ADD_MEMBERSHIP socket option, using a packet_mreq structure specifying an interface and an action of PACKET_MR_PROMISC. On older systems, this is done instead by an ioctl of SIOCGIFFLAGS to fetch the flags, setting the IFF_PROMISC flag, and then storing the flags with SIOCSIFFLAGS. Unfortunately, with this method, multiple promiscuous listeners can interfere with each other and a buggy program can leave promiscuous mode on even after it exits.


Some differences are evident when comparing this Linux feature to BPF and DLPI:


  1. The Linux feature provides no kernel buffering and kernel filtering is only available on newer systems (via theSO_ATTACH_FILTER socket option). There is a normal socket receive buffer, but multiple frames cannot be buffered together and passed to the application with a single read. This increases the overhead involved in copying the potentially voluminous amounts of data from the kernel to the application.

  2. SOCK_PACKET provides no filtering by device. (PF_PACKET sockets can be linked to a device by calling bind.) IfETH_P_IP is specified in the call to socket, then all IPv4 packets from all devices (Ethernets, PPP links, SLIP links, and the loopback device, for example) are passed to the socket. A generic socket address structure is returned by recvfrom, and the sa_data member contains the device name (e.g., eth0). The application must then discard data from any device in which it is not interested. The problem again is too much data can be returned to the application, which can get in the way when monitoring a high-speed network.

bind

 

bind 함수는 로컬 인터페이스 어드레스와 포트번호를 소켓과 서로 연관되게 묶는 함수입니다.

 

int bind (
    SOCKET 
s,
    const struct sockaddr FAR* 
name,
    int 
namelen
);

 

Parameters

s
[입력] 로컬어드레스와 아직 묶여지지 않은 소켓 기술자(descriptor).

name 
[입력] 소켓에 할당하기위한 
SOCKADDR 구조체로 이루어진 주소.

namelen 
[입력] 
name 매개변수의 크기 (일반적으로 sizeof(SOCKADDR) 요로케 쓰입니다).

 

Remarks

처음 만들어 질 때 소켓은 그와 관련된 로컬 어드레스를 가지지 않습니다. 따라서 bind 함수는connect 나 listen 함수를 뒤이어 호출하기 전에, 접속되지 않은 소켓에 사용됩니다. 이 함수는 접속지향형소켓(stream socket : TCP)이나 비접속(datagram : UDP) 소켓 이나 모두 사용합니다. 소켓이 socket 함수를 호출해서 생성될 때, 소켓은 이름공간(name space)에 존재합니다. 하지만, 할당된 이름을 가지지는 않습니다. 그러므로, 이름 지여지지 않은 소켓과 로컬 어드레스를 연결지우기 위해서 이 함수는 사용됩니다.

이 함수에 의해서 할당되어 지는 이름은 세가지 부분으로 구성됩니다. (인터넷 주소 체계를 사용할 때 : 주소체계(address family), 호스트주소(host address), 어플리케이션에 사용되는 포트번호(port number)) WinSock2 에서는 name 매개변수는 SOCKADDR 구조체의 포인터로 반드시 넘겨야 한다라는 그런 규정은 없습니다. 그저 윈도우즈 소켓 1.1 과의 호환성 때문에 남았는 산물정도라고 생각해 두세요. 서비스 프로바이더는 namelen 의 메모리 사이즈 블록 포인터에 대해 연관을 받지 않습니다. 메모리 블록에서 첫번째 2Byte (SOCKADDR 구조체의 sa_family에 해당되는 부분입니다) 는 소켓을 생성하는데 사용되는 어드레스 체계(address family)를 가지고 있어야 합니다. 그렇지 않다면, WSAEFAULT 에러가 발생 할 것입니다.

만약 어플리케이션이 어떤 로컬 어드레스를 할당 할 것인지 고려하지 않고 사용된다면, name 매개변수의 sa_data 멤버를 위해 INADDR_ANY 라는 상수값을 명시해야 합니다. 이 상수값을 사용하면, 적절한 네트웍 주소를 사용하기 위해 기본이되는 서비스 프로바이더를 적용하게 됩니다. 이 상수값은 한 개 이상의 네트웍 인터페이스나 주소가 있는 호스트일 경우 어플리케이션 프로그래밍을 간략히 하기 위해서 사용됩니다. 대부분의 프로그램은 인터페이스 어드레스에 대해 INADDR_ANY를 사용합니다.

TCP/IP에서 포트번호가 0으로 명시된 경우에는 서비스 프로바이더가 어플리케이션을 위한 고유한 포트번호(1024~5000 사이의 값)를 할당합니다.  어플리케이션은 주소와 포트를 알기위해 bind 된 후에 getsockname 함수를 사용할 수 있습니다. 만약 인터넷 주소가 INADDR_ANY 로 사용되어 있다면, getsockname 함수는 접속되기 전까지는 사용하지 못합니다. (몇몇 주소들은 호스트가 multihome 일 경우 올바를 수도 있기 때문입니다) 0번 포트가 아닌 특정한 포트 번호를 바인딩하는 것은 클라이언트 어플리케이션을 무용지물이 되게 합니다. 왜냐하면, 다른 소켓에 이미 그 포트 번호를 사용하고 있을 경우 충돌 할 수 있는 위험이 있기 때문입니다. 따라서, 클라이언트 프로그램이 포트 0을 지정하는 반면, 서버 프로그램은 대개 자신의 포트 번호를 지정합니다.

connect  함수를 호출하기 전에는 bind 함수와 같이 소켓과 어드레스를 묶는 함수가 사실상 필요치 않습니다. 소켓이 묶이기 전에 connect 함수가 호출될 경우 bind 함수가 INADDR_ANY 의 어드레스와 포트 번호 0을 이용하여 소켓에 대해 호출된 것처럼 소켓은 자동으로 묶이게 됩니다. 대부분의 클라이언트 어플리케이션은 로컬 인터페이스 어드레스나 특별한 포트 값을 지정할 필요가 없습니다. 따라서 bind함수를 호출하기 전에 connect 함수를 호출함으로써 이들 어플리케이션에 대한 단계를 줄일 수 있습니다. 일반적으로 서버 어플리케이션은 Well-known 포트와 묶인 소켓을 생성해야 합니다. 이를 위해 bind 함수는 대부분 서버에 대해 명확하게 호출되어야 합니다.

Windows CE : IrSocket 에서의 구현...

  • Af_irda.h를 포함 시켜주어야 합니다.
  • SOCKADDR_IRDA_wcesdk_SOCKADDR_IRDA 구조체가 addr 매개변수로 사용됩니다.
  • WSAENETDOWN 에러코드는 지원되지 않습니다.
  • INADDR_ANY와 같은 와일드 카드 주소는 지원되지 않습니다.

    IrSocket 클라이언트는 connect 함수를 사용하기 전에 bind 함수를 호출해야 합니다. 만약 서비스 이름이 "LSAP-SELxxx"형태(xxx는 0~255사이의 십진 정수) 라면, 주소는 서비스 이름 보다 특정한 LSAP-SEL xxx를 의미합니다. LSAP-SELxxx 서비스 이름은 IAS를 발생하지 않을 것입니다. 소켓은 특정한 IAS를 무시한 LSAP-SEL을 직접적으로 묶을것입니다.

Return Values

에러가 없는 경우 0을 리턴합니다. 에러가 발생한 경우는 SOCKET_ERROR을 리턴합니다. 그리고,WSAGetLastError 함수를 호출해서 특정한 에러코드를 리턴 할 수 있습니다.

Error Codes

WSANOTINITIALISED

이 함수를 사용하기 전에 성공적인 WSAStartup 함수의 호출이

 없었습니다.

WSAENETDOWN

네트웍 서브 시스템에 에러가 발생했습니다.

WSAEADDRINUSE
 
 

프로세스가 이미 같은 어드레스로 바운드 되어있고, 소켓이

SO_REUSEADDR로 재 사용 어드레스라는 항목을 마크 하지

않았습니다. 한 예로, IP 주소와 포트가 af_inet 경우로 바운드

되어있는 경우입니다. (setsockopt 함수에 의한 SO_REUSEADDR

소켓 옵션에 대해서 참고하세요)

WSAEADDRNOTAVAIL 지정된 주소가 정확한 주소가 아닙니다.
WSAEFAULT
 
 

name이나 namelen 매개변수가 올바르지 않습니다. namelen 매개

변수가 너무 작거나, name 매개변수가 연관된 주소체계에 대해서

잘못된 주소 형태를 포함하고 있습니다. 또는, 메모리 블록의

첫 번째 2Byte 가 소켓 기술자 s와 연관된 주소체계와 일치하지

않습니다.

WSAEINPROGRESS

블럭킹 윈속 v1.1 이 현재 진행 중이거나, 서비스 프로바이더가

콜백 함수를 여전히 처리하고 있습니다.

WSAEINVAL 소켓이 이미 특정주소와 바인드 되어 있습니다.
WSAENOBUFS 너무 많은 접속으로 인하여 버퍼가 충분하지 않습니다.
WSAENOTSOCK

기술자(descriptor)가 소켓 기술자가 아닙니다.

 

 

QuickInfo

Windows NT : 사용가능
Windows : 사용가능
Windows CE : 버젼 1.0 그리고 그이후의 버젼에서 사용가능
Header :
          Win16/32 : winsock.h
          Win32-II : winsock2.h
Import Library :
          Win16 : winsock.lib
          Win32 : wsock32.lib
          Win32-II : ws2_32.lib

See Also

overviewconnectgetsocknamelistensetsockoptsocketWSACancelBlockingCall

 

 

출처 : DEVPIA 곽용진님 style  APIs

[출처] [Socket] bind|작성자 임종배

리눅스에 SOCK_PACKET이라는 소켓이 있는데, 이것을 이용하면 어떤 MAC 프레임도 만들어서 전송할 수 있다. 사용방법은 코드를 보면 쉽게 알수 있다. 그리고, root만 가능하다. (ether_wake.c 를 참조하여 작성하였음.)

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
#include <sys/socket.h>
 
#include <sys/types.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <sys/socket.h>

int send_packet(char *ifname, unsigned char *outpack, int pktsize)
{
        struct sockaddr whereto;
        int s;
        int one=1;
        int i;
 
        if ((s = socket(AF_INET, SOCK_PACKET, SOCK_PACKET)) < 0) {
                if (errno == EPERM)
                        fprintf(stderr, "send_packet must run as root\n");
                else
                        perror("send_packet: socket");
        }
 
        /* Don't revert if debugging allows a normal user to get the raw socket. */
        setuid(getuid());
 
        if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&one, sizeof(one)) < 0)
                perror("setsockopt: SO_BROADCAST");
 
        whereto.sa_family = 0;
        strcpy(whereto.sa_data, ifname);
 
        if ((i = sendto(s, outpack, pktsize, 0, &whereto, sizeof(whereto))) < 0)
                perror("sendto");
 
        return 0;
}

PF_PACKET 초간단 강좌
일반적인 소켓은 TCP 또는 UDP 데이터를 다룬다. 바꾸어 말하자면 소켓을 이용해서 주고 받는 데이터는 TCP(또는 UDP) 레이어의 데이터 뿐이라는 것이다. 그 이하 레이어는 보낼때나 받을때 신경을 쓸 필요가 없는것이다. 우리가 데이터를 건데면 커널은 알아서 IP 헤더와 이더넷 헤더를 붙여서 보내주고, 받을때도 앞의 헤더들을 다 띄어내고 TCP/UDP 데이터만 건데 준다.

이러한 방식은 일반적으로 편리하지만, 때로는 TCP이하의 레이어를 건드려야만 할때가 있다. 이럴때 사용할 수 있는 것이 바로 Raw소켓이다. 하지만 Raw소켓은 IP레이어까지만 조작이 가능하다. 만약에 이더넷 레이어까지 건드리고 싶다면 어떻게 해야 할까.

가장 좋은 해결책은 pcap라이브러리를 사용하는 것이다. pcap은 다양한 플랫폼에 포팅되어있으므로 이식성 좋은 코드를 작성할 수 있다. 하지만 리눅스에서만 쓸것이라면 단연 PF_PACKET을 추천한다. PF_PACKET은 특정한 라이브러리 없이 일반적인 소켓을 사용하는 것과 유사하게 이더넷 레이어까지 조작할수있는 방법을 제공한다.

사용법은


socket(PF_PACKET, int socket_type, int protocol);

이런식으로 소켓생성시에 PF_PACKET을 명시해주면 된다. 너무 간단한가? 그것이 바로 이 PF_PACKET의 장점이다. 이렇게 생성된 소켓은 작성한 데이터를 원하는 레이어까지 그대로 전달한다. 단지 주소를 표시할때, sockaddr_ll 구조체를 사용해야하는 점이 다르다.

예를 들어 다음의 코드를 보자


struct icmp_packet
{
      struct ethhdr eth;
      struct iphdr ip;
      struct icmphdr icmp;
      char data[1472];
} __attribute__ ((packed)); 

int sock;
struct icmp_packet packet;
struct sockaddr_ll dest;

sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL);
dest.sll_family = PF_PACKET;
dest.sll_protocol = htons(ETH_P_IP);
dest.sll_ifindex = 사용하고자하는 인터페이스의 인덱스;
memcpy(dest.sll_addr, 받을 대상의 MAC,6);

// packet의 내용을 적당히 잘 채워준다 (체크섬까지 해야하는거 알죠!)

sendto(sock, &packet, sizeof(icmp_packet), 0, (struct sockaddr *) &dest, sizeof(dest));

라고한다면, 이미 이더넷 헤더와 IP헤더를 포함하고 있는 packet을 바로 네트워크로 보내버린다(따로 IP헤더를 만들지도 않고 ARP도 하지않는다).

사용법을 정리하자면,
1. PF_PACKET으로 소켓을 연다.
2. 이더넷 레이어까지 포함하는 데이터를 만든다.
3. sockaddr_ll 구조체에 받을 대상의 MAC을 넣는다.
4. send!

이렇게 할 경우 이더넷 레이어까지 사용자가 원하는대로 조작이 가능해진다. 위의 예는 PING을 쏠때, 발신자의 이더넷 주소를 조작하기 위한 코드의 일부분이다. 이런 방식을 응용한다면, 이더넷 소스 어드레스를 바꿔 보낸다던지 하는 조작이 가능하다(ARP패킷을 만들어서 보낼수도 있다).

만약에 이더넷 레이어를 포함한 패킷전체를 받고싶다면, bind를 이용하면된다. 일단 참고문서는 man packet(man 페이지 답게 그렇게 자세하지는 않다). UNP최신판에는 PF_PACKET에 대해 나와있다고 하는데, 확인해보지는 않았다.

Posted by jungjun at 2004년 11월 04일 06:07 PM | 리눅스 다이어리 
TrackBack URL: http://jungjun.net/mt/mt-tb.cgi/43 

I/O port에 접근하기 위해 필요한 루틴들은 /usr/include/asm/io.h에 모두 포함되어 있으므로 단순히 C프로그램에서 #include 를 포함하기만 하면 된다. 다른 라이브러리는 필요없다. 

그리고 gcc로 컴파일할 때 최적화 옵션(gcc -O1 혹은 그 이상)을 잊지 말아야 한다. 
또한 디버깅을 위해서는 디버거 옵션(gcc -g)을 넣는 것도 중요하다. 

정리하자면 컴파일할 때는 다음의 옵션을 꼭 넣는다. 
% gcc -g -O2 ... 

Linux에서는 어떤 port에 접근하려고 할 때 프로그램에 접근 권한을 주어야 한다. 
이런 기능은 ioperm()이라는 함수에 의해서 이루어진다. 
ioperm()은 unistd.h에 선언되어 있으므로 사용하려면 이를 포함해야 한다. 

문법은 ioperm(from, num, turn_on)으로 from은 접근 권한을 주는 첫 번째 포트번호이고, num은 from으로부터 연속되는 포트의 갯수이다. 

예를 들어, ioperm(0x300, 5, 1)이면 0x300 포트부터 0x304번 포트까지의 접근 권한을 주는 것이다. 
turn_on에 Boolean으로 1을 주면 허가, 0을 주면 접근을 금지 시킨다. 

ioperm이라는 함수는 프로그램이 root의 권한을 가지고 있어야 실행된다. 그리고 ioperm 에서 접근허가 된 포트라도 프로그램이 끝나면 자동적으로 접근금지가 되므로 굳이 ioperm( , ,0)을 줄 필요는 없다. 

ioperm()은 0x000부터 0x3FF 까지의 포트에만 접근할 수 있게 한다. 

더 높은 포트에 접근하려고 하면 iopl()이라는 함수를 사용하여야 한다. 
iopl()은 모든 포트에 대한 접근허가를 단 한번에 준다. 

그러므로 조심하여야 한다. 잘못된 포트로의 접근은 켬퓨터에 치명적인 문제를 일으킬 수 있다. 

포트에 실질적으로 값을 쓰고 읽는 기능을 주는 함수는 inb()/outb()이다. 

원하는 포트(port)에서 한 바이트(8bit)를 읽기 위해서는 inb(port)를, 쓰기 위해서는 outb(value, port)를 사용하는 데 value는 주고자 하는 값이다. 

두 바이트씩 즉 16bit씩 읽고 쓰기 위해서는 inw(port)/outw(value, port)를 사용하는데, 이는 실질적으로 port로 지정한 포트와 그 다음 포트를 합쳐서 읽고 쓰는 것이다. 

또한 32bit씩 읽고자 한다면 inl(port)/outl(value, port)를 사용하며 이는 지정된 port 에서 연속적으로 이어서 4포트를 한꺼번에 읽고 쓰는 것이다. 

포트를  읽고 쓸 때는 근사적으로 1microsecond(백만분의 1초)가 소요된다. 

또한 포트에 접근한 후에 값을 읽고 쓰는 것을 보다 확실히 하기 위해서 약간의 delay시간을 줄 수 있는 데, 이에 쓰이는 함수는 inb_p()/outb_p()와 같이 함수 끝에 _p를 붙이는 것이다. 

이는 pause를 의미하며, delay시간은 io.h에 정의되어 있는 매크로를 사용하여 조종되어질 수 있고, 초기치는 약 4 microsecond 이다. 

이를 바꾸는 방법은 #define REALLY_SLOW_IO (value) 이므로 이를 이용하면 된다. 
그런데 이 pause시간을 정하는 매크로는 0x80포트를 통하여 이루어 지므로 이에 대한 접근권한을 주는 것을 잊지 말아야 한다.

출처 : http://gnudevel.tistory.com/33http://gnudevel.tistory.com/33

setsockopt

 

setsockopt 함수는 소켓 옵션을 설정하는 함수입니다.

 

int setsockopt (
        SOCKET 
 s,

        int  
level,
        int 
 optname,
        const char FAR *
  optval,
        int  
optlen
);

 

Parameters

s
[
입력대상 소켓의 기술자(descriptor)를 명시합니다.

 

level
[
입력소켓 옵션 레벨이 정의 되며, SOL_SOCKET  IPPROTO_TCP 중 하나가 될 수 있습니다.

 

optname
[
입력셋팅 하기위한 소켓옵션 값입니다.

 

optval
[
입력검색된 옵션을 저장 하기위한 데이터 버퍼를 포인트 합니다.

 

optlen
[
입력optval 매개변수 버퍼의 크기

 

Remarks

setsockopt 함수는 지정된 소켓의 옵션을 특정한 형태(type), 상태(state)로 결합하기 위해서 지정한 소켓옵션 값을 셋팅하는 함수입니다비록 여러 프로토콜 레벨로의 소켓 옵션이 존재 할 순 있다 하더라도가장 우선하는 레벨이 존재하게 됩니다옵션은 소켓 연산에 영향을 미칩니다예를들어 발송된 데이터(OOB 데이터를 예로 들 수 있습니다를 일반 데이터 스트림으로 수신했을때나소켓으로 브로드캐스트(broadcast) 메세지를 전송할때 영향을 미치게 됩니다.

이 함수에서 사용 할 수 있는 두가지 형태의 소켓옵션이 있습니다활성화 또는 비활성화 시키기 위한 Boolean 옵션과수형(integer) 또는 구조체를 요구하는 옵션이 있습니다. Boolean 옵션을 활성화 하기 위해서 optval 매개변수는 0이 아닌 정수를 포인트 하고비활성화 하기 위해서  0을 포인트 합니다optlen 매개변수는 Boolean 옵션에 대해서는 sizeof(int)로 설정 해야만 합니다다른 옵션들에 대해서optval 매개변수는 설정하고자 하는 정수(integer)나 구조체를 넘겨야 하고optlen 매개변수는 정수(integer) 또는 구조체의 길이를 넘겨야 합니다아래에 setsockopt 함수에서 사용 할 수 있는 옵션들을 간단한 설명과 함께 나열 해 보았습니다.

level = SOL_SOCKET

옵션값(Value)

데이터형태(Type)

의미(Meaning)

SO_BROADCAST 
 

BOOL
 

소켓으로 브로드캐스트(broadcast) 메세지를 전송 할 수 있도록 합니다.

SO_DEBUG

BOOL

디버깅 정보를 레코딩 합니다.

SO_DONTLINGER


BOOL


 

소켓을 종료(close)할때 보내지지 않은 데이터를 보내기위해서 블럭킹 상태가 되지 않도록 합니다이 옵션을 셋팅하는 것은 LINGER구조체의 멤버중 l_onoff 0으로 셋팅하고SO_LINGER 옵션을 셋팅 했을때와 같은 효력을 발휘합니다.

SO_DONTROUTE

BOOL

라우팅 하지 않고직접 인터페이스로 보냅니다.

SO_GROUP_PRIORITY




 

int




 

차후에 소켓그룹을 사용하기위해 예약 되어있습니다소켓그룹의 일부분인 소켓을 만들기위해 관련된 우선사항을 명시합니다
(
우아아아악정말 해석 못해 먹겠네여... 원문을 첨가 하겠습니다

Reserved for future use with socket groups. Specify the relative priority to be established for sockets that are part of a socket group.

SO_KEEPALIVE

BOOL

Keepalives를 전송합니다.

SO_LINGER
 

struct LINGER
 

아직 전송되지 않은 데이터가 있을 경우 소켓을 종료(close)할때 대기합니다.

SO_OOBINLINE
 

BOOL
 

일반 데이터 스트림(normal data stream)으로 out-of-band 데이터를 수신합니다.

SO_RCVBUF

 

int

 

데이터를 수신하기 위한 총 버퍼공간을 명시합니다요놈은 SO_MAX_MSG_SIZE , TCP Window의 크기와 상관이 없습니다.

SO_REUSEADDR
 

BOOL
 

이미 사용되고 있는 어드레스를 바인드 할 수 있도록 합니다.

SO_SNDBUF

 

int

 

데이터를 전송하기 위한 총 버퍼공간을 명시합니다요놈은 SO_MAX_MSG_SIZE , TCP Window의 크기와는 상관이 없습니다.

level = IPPROTO_TCP

TCP_NODELAY
 

BOOL
 

전송합병(send coalescing)을 위해Nagle 알고리즘을 비 활성화 합니다.

 

Return Values

에러가 발생하지 않으면setsockopt 함수는 0을 반환합니다에러가 발생하면, SOCKET_ERROR을 반환하면WSAGetLastError 함수를 이용해서 특정 에러 코드를 얻어낼 수 있습니다.

 

Error Codes

WSANOTINITIALISED

이 함수를 사용하기 전에 성공적인 WSAStartup 함수의 호출이 없었습니다.

WSAENETDOWN

네트웍 서브 시스템에 에러가 발생했습니다.

WSAEFAULT

optval 또는 optlen 매개변수 중의 하나가 올바르지 않거나 optlen 매개변수의 값이 너무 작습니다.

WSAEINPROGRESS

블럭킹 윈속 v1.1 이 현재 진행 중이거나서비스 프로바이더가 콜백 함수를 여전히 처리하고 있습니다.

WSAEINVAL

level 매개변수가 잘못됐거나알 수 없는 값 입니다.

WSAENETRESET

SO_KEEPALIVE가 설정 되었을때접속이 타입아웃 되었습니다.

WSAENOPROTOOPT

알 수 없는 옵션이거나지원지지 않는 옵션을 사용 했습니다.

WSAENOTCONN

SO_KEEPALIVE가 설정 되었을때접속이 리셋 되었습니다.

WSAENOTSOCK

기술자(descriptor)가 소켓 기술자가 아닙니다.

 

QuickInfo

 

Windows NT : 사용가능
Windows : 
사용가능
Windows CE : 
버젼 1.0 그리고 그이후의 버젼에서 사용가능
Header :
          Win16/32 : winsock.h
          Win32-II : winsock2.h
Import Library :
          Win16 : winsock.lib
          Win32 : wsock32.lib
          Win32-II : ws2_32.lib

See Also

overviewbindgetsockoptioctlsocketsocketWSAAsyncSelectWSAEventSelect

+ Recent posts