/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 :s
RefCount :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をエラーとさせる事でバックログ設定を不可にさせることも可能かと。

最終更新 2016/10/08 14:36:36 - north
(2016/10/08 14:17:52 作成)


検索

アクセス数
3569968
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。