UNIX domain protocols

advertisement
Unix Domain Protocols
• Unix domain socket address structure
• Unix domain socket client-server
• Descriptor passing with Unix domain socket
• Readings
– UNP Sections 14.4 and 14.5, Ch15
1
Unix Domain Protocols
• Used for client-server communication on a single
machine
– Use same API as with regular client-server
– Both stream and datagram sockets are supported
– Local IPC (inter-process communication)
• Why do we need this?
– Efficiency (faster than TCP/UDP socket on same machine)
– Passing (file) descriptors
– More security checks (passing credentials such as pid)
2
Address Structure
• Open a socket using UNIX domain socket
socket(AF_LOCAL, SOCK_STREAM, 0)
socket(AF_LOCAL, SOCK_DGRAM, 0)
– AF_LOCAL, AF_UNIX (historical)
• UNIX domain socket address structure
#include <sys/un.h>
struct sockaddr_un {
sa_family_t sun_family; /*AF_LOCAL or AF_UNIX */
char
sun_path[104]; /* null-terminated path name */
}
3
A Few Notes
• sun_path is null-terminated file pathname
– Must not exist in file system
– Should be absolute pathname
– connect: access permission of sun_path is verified like open
with write-only access
• Unix domain stream socket similar to TCP
• Unix domain datagram socket similar to UDP
• For Unix domain datagram client
– connect and sendto will not automatically bind socket to
local address
– Server cannot return datagram to client without bind
4
Binding a Unix Domain Socket
• example1.c
–
–
–
–
Use absolute path for path name
bind will fail if the file exists
Pathname can potentially overrun the sun_path buffer
Otherwise, it is very similar to a TCP socket
5
Client-Server Using Unix Domain Protocols
• example2.c and example3.c
– Echo server and client
– connect needs a pathname that is currently bound to an
open UNIX domain socket of the same type
– Permission test for connect is the same as that for open with
write-only access
– connect will fail if the listening queue is full
• UNIX domain datagram sockets are similar to UDP
sockets
– Sender must bind first for the receiver to reply
6
Full-Duplex Stream Pipe
• #include <sys/socket.h>
• int socketpair(int family, int type, int protocol, int sockfd[2]);
–
–
–
–
–
Create two sockets connected together
Family: AF_LOCAL
Type: SOCK_STREAM or SOCK_DGRAM
Protocol: 0
Full-duplex stream pipe. Both can be used for read and write
– Example example4.c
7
Passing Descriptors
• What we have learned
– Parent open files and pass to child processes
• What if child wants to pass back file descriptors to
parent?
• What if two unrelated processes want to pass file
descriptors?
• Unix domain socket can handle all these
8
Passing Descriptors
• Involves creating a new descriptor in receiving
process
– referring to the same system open file table entry
– It is normal that we see different descriptor numbers in
sending and receiving processes
– It is OK for the sending process to close the file after calling
sendmsg
9
recvmsg and sendmsg Functions
#include <sys/socket.h>
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
ssize_t sendmsg(int sockfd, struct msghdr *msg, int flags);
struct msghdr {
void
socklen_t
struct iovec
int
void
socklen_t
int
*msg_name; //protocol address
msg_namelen;
*msg_iov; // array to hold data
msg_iovlen;
*msg_control; // ancillary data
// link to cmsghdr struct
msg_controllen;
msg_flags;
};
struct iovec {
void
*iov_base; // starting address of buffer
size_t iov_len; // size of buffer
};
10
Control Message Header
struct cmsghdr {
socklen_t
cmsg_len; // length in bytes
int
cmsg_level; // socket option level
int
cmsg_type; // socket option type
// followed by unsigned char cmsg_data[]
};
• A number of macros provided to access cmsghdr
from msghdr
– struct cmsghdr *CMSG_FIRSTHDR(struct msghdr *)
– struct cmsghdr *CMSG_NXTHDR(struct msghdr *, struct
cmsghdr*)
– unsigned char *CMSG_DATA(struct cmsghdr *)
– etc
11
Passing Descriptor
• Goal: passing open file descriptor in the kernel
(process file descriptor entries are used to reference
to the kernel entry).
– Create a UNIX domain socket
– Send open the descriptor with open, pipe etc (get the
reference)
– Send process build msghdr structure containing the
descriptor to pass (using the reference), and call sendmsg
– Receiving process call recvmsg to receive the descriptor on
the domain socket (the reference can be different, but the
kernel open file entry would be the same).
12
Passing Descriptor Example
• Example5.c
– Waiting for incoming request to open a specified file
– After opening the file, send back the file descriptor
• Example6.c
– Send specified file to server
– After receiving file descriptor returned from server, print the
content of the file
13
Passing Credentials
• cmsg_level: SOL_SOCKET
• cmsg_type: SCM_CREDS
struct cmsgcred {
pid_t cmcred_pid; // PID of sending process
uid_t cmcred_uid; // real UID
uid_t cmcred_euid; // effective UID
gid_t cmcred_gid; // real GID
short cmcred_ngroups; // num of grps
gid_t cmcred_groups[CMGROUP_MAX];
};
14
Download