/proc/net/unix
[root@localhost c]# cat /proc/net/unix Num RefCount Protocol Flags Type St Inode Path dead2b40: 00000002 00000000 00010000 0001 01 13517 @ISCSIADM_ABSTRACT_NAMESPACE ddffc6c0: 00000002 00000000 00010000 0001 01 10821 /var/run/abrt/abrt.socket db47e480: 00000002 00000000 00010000 0001 01 13109 @ISCSID_UIP_ABSTRACT_NAMESPACE : ddffc000: 00000003 00000000 00000000 0001 03 10811 dca4c6c0: 00000003 00000000 00000000 0001 03 10800 /run/systemd/stdout-syslog-bridge dca4c900: 00000003 00000000 00000000 0001 03 10799 db47ed80: 00000003 00000000 00000000 0001 03 10639 /run/systemd/stdout-syslog-bridge db47f440: 00000003 00000000 00000000 0001 03 10088 db47e000: 00000002 00000000 00000000 0002 01 7932
検証サンプル
[root@localhost c]# cat proc_unix.c
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
void main(int argc, char * argv[])
{
struct sockaddr_un sock_addr;
int status, sock;
int file_flag = atoi(argv[1]);
int listen_flag = atoi(argv[2]);
sock = socket(AF_UNIX, SOCK_STREAM, 0);
sock_addr.sun_family = AF_UNIX;
strcpy(sock_addr.sun_path, "0123456789");
remove(sock_addr.sun_path);
if (!file_flag) {
sock_addr.sun_path[0] =0;
}
bind(sock, (struct sockaddr*) &sock_addr, sizeof(struct sockaddr_un));
if (listen_flag) {
listen(sock, 0);
}
system("cat /proc/net/unix | grep -i --text 1234");
}
結果(Pathのバイナリ部表示はgrep故です。)Num RefCount Protocol Flags Type St Inode Path [root@localhost c]# ./proc_unix.o 0 0 <--- チェックサム no-listen debf9440: 00000002 00000000 00000000 0001 01 16533 @12345678・G %顛'顛窶AG' 玩?AGYG [root@localhost c]# ./proc_unix.o 0 1 <--- チェックサム listen debf8fc0: 00000002 00000000 00010000 0001 01 16537 @12345678・G 肝?苞帥`AG 玩?AGYG [root@localhost c]# ./proc_unix.o 1 0 <--- inode no-listen debf8fc0: 00000002 00000000 00000000 0001 01 16545 0123456789 [root@localhost c]# ./proc_unix.o 1 1 <--- inode listen dca4db00: 00000002 00000000 00010000 0001 01 15641 0123456789・Numはソケットのアドレスで、/dev/kmemによるソケット属性等の更新故の実装かと。
・ソケット作成時、s->sk_refcnt=1で、bind/connect毎にインクリメントされます。
・Flagsはlistenされていると__SO_ACCEPTCON(1 << 16)で、されていないと0です。
・connectされていないとs->sk_socket=0です。
・Pathの@はソケットのunix_socket_table[]登録をinode noでなく、チェックサムとし、チェックサムのサイズは、bindシステムコールのlen引数sizeof(struct sockaddr_un)で、チェックサムは123456789でなく、&sock_addrのsizeof(struct sockaddr_un)で、異なるコマンド間でのソケットconnectするには、path名に掛かるサイズ値でbindする必要があります。
・inodeはs->addr->name->sun_pathのinodeなく、ソケット作成時に取得されるnodevでのpusedo mountされたsockfsファイルシステム下のinodeです。
実装
Num :sRefCount :s->sk_refcnt
Protocol :0
Flags :s->sk_state == TCP_LISTEN ? __SO_ACCEPTCON : 0
Type :s->sk_type
St :s->sk_socket ?
(s->sk_state == TCP_ESTABLISHED ? SS_CONNECTED : SS_UNCONNECTED):
(s->sk_state == TCP_ESTABLISHED ? SS_CONNECTING : SS_DISCONNECTING)
Inode :s->sk_socket->vfs_inode->i_ino
Path :s->addr->name->sun_path
typedef enum {
SS_FREE = 0, /* not allocated */
SS_UNCONNECTED, /* unconnected to any socket */
SS_CONNECTING, /* in process of connecting */
SS_CONNECTED, /* connected to socket */
SS_DISCONNECTING /* in process of disconnecting */
} socket_state;
#define __SO_ACCEPTCON (1 << 16) /* performed a listen */
enum sock_type {
SOCK_STREAM = 1,
SOCK_DGRAM = 2,
SOCK_RAW = 3,
SOCK_RDM = 4,
SOCK_SEQPACKET = 5,
SOCK_DCCP = 6,
SOCK_PACKET = 10,
};
root/arch/mips/include/asm/socket.hでの実装では、SOCK_DGRAM/SOCK_STREAM値は、逆転しています。
enum sock_type {
SOCK_DGRAM = 1,
SOCK_STREAM = 2,
SOCK_RAW = 3,
SOCK_RDM = 4,
SOCK_SEQPACKET = 5,
SOCK_DCCP = 6,
SOCK_PACKET = 10,
};
enum {
TCP_ESTABLISHED = 1,
TCP_SYN_SENT,
TCP_SYN_RECV,
TCP_FIN_WAIT1,
TCP_FIN_WAIT2,
TCP_TIME_WAIT,
TCP_CLOSE,
TCP_CLOSE_WAIT,
TCP_LAST_ACK,
TCP_LISTEN,
TCP_CLOSING, /* Now a valid state */
TCP_MAX_STATES /* Leave at the end! */
}
struct sockaddr_un {
__kernel_sa_family_t sun_family; /* AF_UNIX */
char sun_path[UNIX_PATH_MAX]; /* pathname */
};
static int unix_seq_show(struct seq_file *seq, void *v)
{
if (v == SEQ_START_TOKEN)
seq_puts(seq, "Num RefCount Protocol Flags Type St "
"Inode Path\n");
else {
struct sock *s = v;
struct unix_sock *u = unix_sk(s);
unix_state_lock(s);
seq_printf(seq, "%pK: %08X %08X %08X %04X %02X %5lu",
s,
atomic_read(&s->sk_refcnt),
0,
s->sk_state == TCP_LISTEN ? __SO_ACCEPTCON : 0,
s->sk_type,
s->sk_socket ?
(s->sk_state == TCP_ESTABLISHED ? SS_CONNECTED : SS_UNCONNECTED) :
(s->sk_state == TCP_ESTABLISHED ? SS_CONNECTING : SS_DISCONNECTING),
sock_i_ino(s));
if (u->addr) {
int i, len;
seq_putc(seq, ' ');
i = 0;
len = u->addr->len - sizeof(short);
if (!UNIX_ABSTRACT(s))
len--;
else {
seq_putc(seq, '@');
i++;
}
for ( ; i < len; i++)
seq_putc(seq, u->addr->name->sun_path[i]);
}
unix_state_unlock(s);
seq_putc(seq, '\n');
}
return 0;
}
len = u->addr->len - sizeof(short)は、u->addr->lenはsizeof(struct sockaddr_un)で、 __kernel_sa_family_t sun_familyサイズ分です。補足
pathのないソケットはbindされてないソケットで、実務上ではsocketpaireによるソケットという事です。socketpareはs->sk_state値によりlistenはエラーで、バックログ更新できませんが、掛かるソケットアドレスから/dev/kmemによりs->sk_stateを変更する事で、listenが動作可能となるはずです。又listenは何回コールする事が可能で、listenをエラーとさせる事でバックログ設定を不可にさせることも可能かと。






