(root)/
util-linux-2.39/
misc-utils/
lsfd-sock.c
       1  /*
       2   * lsfd-sock.c - handle associations opening socket objects
       3   *
       4   * Copyright (C) 2021 Red Hat, Inc. All rights reserved.
       5   * Written by Masatake YAMATO <yamato@redhat.com>
       6   *
       7   * This program is free software; you can redistribute it and/or modify
       8   * it under the terms of the GNU General Public License as published by
       9   * the Free Software Foundation; either version 2 of the License, or
      10   * (at your option) any later version.
      11   *
      12   * This program is distributed in the hope that it would be useful,
      13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15   * GNU General Public License for more details.
      16   *
      17   * You should have received a copy of the GNU General Public License
      18   * along with this program; if not, write to the Free Software Foundation,
      19   * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      20   */
      21  
      22  #include <sys/types.h>
      23  #include <sys/xattr.h>
      24  
      25  #include "xalloc.h"
      26  #include "nls.h"
      27  #include "libsmartcols.h"
      28  
      29  #include "lsfd.h"
      30  #include "lsfd-sock.h"
      31  
      32  static void attach_sock_xinfo(struct file *file)
      33  {
      34  	struct sock *sock = (struct sock *)file;
      35  	sock->xinfo = get_sock_xinfo(file->stat.st_ino);
      36  }
      37  
      38  static bool sock_fill_column(struct proc *proc __attribute__((__unused__)),
      39  			     struct file *file,
      40  			     struct libscols_line *ln,
      41  			     int column_id,
      42  			     size_t column_index)
      43  {
      44  	char *str = NULL;
      45  	struct sock *sock = (struct sock *)file;
      46  	switch(column_id) {
      47  	case COL_TYPE:
      48  		if (!sock->protoname)
      49  			return false;
      50  		/* FALL THROUGH */
      51  	case COL_SOCK_PROTONAME:
      52  		if (sock->protoname)
      53  			if (scols_line_set_data(ln, column_index, sock->protoname))
      54  				err(EXIT_FAILURE, _("failed to add output data"));
      55  		return true;
      56  	case COL_NAME:
      57  		if (sock->xinfo
      58  		    && sock->xinfo->class && sock->xinfo->class->get_name) {
      59  			str = sock->xinfo->class->get_name(sock->xinfo, sock);
      60  			if (str)
      61  				break;
      62  		}
      63  		return false;
      64  	case COL_SOURCE:
      65  		if (major(file->stat.st_dev) == 0
      66  		    && strncmp(file->name, "socket:", 7) == 0) {
      67  			str = xstrdup("sockfs");
      68  			break;
      69  		}
      70  		return false;
      71  	case COL_SOCK_NETNS:
      72  		if (sock->xinfo) {
      73  			xasprintf(&str, "%llu",
      74  				  (unsigned long long)sock->xinfo->netns_inode);
      75  			break;
      76  		}
      77  		return false;
      78  	case COL_SOCK_TYPE:
      79  		if (sock->xinfo
      80  		    && sock->xinfo->class && sock->xinfo->class->get_type) {
      81  			str = sock->xinfo->class->get_type(sock->xinfo, sock);
      82  			if (str)
      83  				break;
      84  		}
      85  		return false;
      86  	case COL_SOCK_STATE:
      87  		if (sock->xinfo
      88  		    && sock->xinfo->class && sock->xinfo->class->get_state) {
      89  			str = sock->xinfo->class->get_state(sock->xinfo, sock);
      90  			if (str)
      91  				break;
      92  		}
      93  		return false;
      94  	case COL_SOCK_LISTENING:
      95  		str = xstrdup((sock->xinfo
      96  			       && sock->xinfo->class
      97  			       && sock->xinfo->class->get_listening
      98  			       && sock->xinfo->class->get_listening(sock->xinfo, sock))
      99  			      ? "1"
     100  			      : "0");
     101  		break;
     102  	default:
     103  		if (sock->xinfo && sock->xinfo->class
     104  		    && sock->xinfo->class->fill_column) {
     105  			if (sock->xinfo->class->fill_column(proc, sock->xinfo, sock, ln,
     106  							    column_id, column_index,
     107  							    &str))
     108  				break;
     109  		}
     110  		return false;
     111  	}
     112  
     113  	if (!str)
     114  		err(EXIT_FAILURE, _("failed to add output data"));
     115  	if (scols_line_refer_data(ln, column_index, str))
     116  		err(EXIT_FAILURE, _("failed to add output data"));
     117  	return true;
     118  }
     119  
     120  static void init_sock_content(struct file *file)
     121  {
     122  	int fd;
     123  
     124  	assert(file);
     125  
     126  	fd = file->association;
     127  
     128  	if (fd >= 0 || fd == -ASSOC_MEM || fd == -ASSOC_SHM) {
     129  		struct sock *sock = (struct sock *)file;
     130  		char path[PATH_MAX] = {'\0'};
     131  		char buf[256];
     132  		ssize_t len;
     133  
     134  		assert(file->proc);
     135  
     136  		if (is_opened_file(file))
     137  			sprintf(path, "/proc/%d/fd/%d", file->proc->pid, fd);
     138  		else
     139  			sprintf(path, "/proc/%d/map_files/%"PRIx64 "-%" PRIx64,
     140  				file->proc->pid,
     141  				file->map_start,
     142  				file->map_end);
     143  
     144  		len = getxattr(path, "system.sockprotoname", buf, sizeof(buf) - 1);
     145  		if (len > 0) {
     146  			buf[len] = '\0';
     147  			sock->protoname = xstrdup(buf);
     148  		}
     149  	}
     150  }
     151  
     152  static void free_sock_content(struct file *file)
     153  {
     154  	struct sock *sock = (struct sock *)file;
     155  	if (sock->protoname) {
     156  		free(sock->protoname);
     157  		sock->protoname = NULL;
     158  	}
     159  }
     160  
     161  static void initialize_sock_class(void)
     162  {
     163  	initialize_sock_xinfos();
     164  }
     165  
     166  static void finalize_sock_class(void)
     167  {
     168  	finalize_sock_xinfos();
     169  }
     170  
     171  const struct file_class sock_class = {
     172  	.super = &file_class,
     173  	.size = sizeof(struct sock),
     174  	.fill_column = sock_fill_column,
     175  	.attach_xinfo = attach_sock_xinfo,
     176  	.initialize_content = init_sock_content,
     177  	.free_content = free_sock_content,
     178  	.initialize_class = initialize_sock_class,
     179  	.finalize_class = finalize_sock_class,
     180  };