1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 #ifndef _SOCKFS_SOCKFILTER_H
  26 #define _SOCKFS_SOCKFILTER_H
  27 
  28 #include <sys/kstat.h>
  29 #include <sys/list.h>
  30 #include <sys/mutex.h>
  31 #include <sys/socket.h>
  32 #include <sys/socketvar.h>
  33 #include <sys/sockfilter.h>
  34 
  35 #ifdef  __cplusplus
  36 extern "C" {
  37 #endif
  38 
  39 struct sonode;
  40 struct sockparams;
  41 
  42 typedef struct sof_module       sof_module_t;
  43 typedef struct sof_entry_kstat  sof_entry_kstat_t;
  44 typedef struct sof_entry        sof_entry_t;
  45 typedef struct sof_instance     sof_instance_t;
  46 typedef struct sof_kstat        sof_kstat_t;
  47 
  48 #define SOF_MAXNAMELEN          FILNAME_MAX
  49 #define SOF_MAXSOCKTUPLECNT     32
  50 #define SOF_MODPATH             SOCKMOD_PATH
  51 
  52 struct sof_module {
  53         char            *sofm_name;
  54         sof_ops_t       sofm_ops;
  55         uint_t          sofm_refcnt;
  56         list_node_t     sofm_node;
  57 };
  58 
  59 struct sof_kstat {
  60         kstat_named_t   sofks_defer_closed;
  61         kstat_named_t   sofks_defer_close_backlog;
  62         kstat_named_t   sofks_defer_close_failed_backlog_too_big;
  63 };
  64 
  65 #define SOF_GLOBAL_STAT_BUMP(s) \
  66         atomic_inc_64(&sof_stat.sofks_##s.value.ui64)
  67 
  68 /*
  69  * Per filter statistics.
  70  */
  71 struct sof_entry_kstat {
  72         kstat_named_t   sofek_nactive;          /* # of consumers */
  73         kstat_named_t   sofek_tot_active_attach;
  74         kstat_named_t   sofek_tot_passive_attach;
  75         kstat_named_t   sofek_ndeferred;        /* # of deferred conns */
  76         kstat_named_t   sofek_attach_failures;
  77 };
  78 
  79 /*
  80  * Socket filter entry - one for each configured filter (added and
  81  * removed by soconfig(1M)).
  82  *
  83  * sofe_flags, sofe_refcnt and sofe_mod are protected by sofe_lock, and all
  84  * other fields are write once.
  85  */
  86 struct sof_entry {
  87         char            sofe_name[SOF_MAXNAMELEN];      /* filter name */
  88         char            sofe_modname[MODMAXNAMELEN];    /* filter module */
  89         sof_hint_t      sofe_hint;                      /* order hint */
  90         char            *sofe_hintarg;                  /* hint argument */
  91         list_node_t     sofe_node;                      /* global list node */
  92         uint_t          sofe_socktuple_cnt;             /* # of socket tuples */
  93         sof_socktuple_t *sofe_socktuple;                /* socket tuple list */
  94 
  95         sof_entry_kstat_t sofe_kstat;                   /* filter stats */
  96         kstat_t         *sofe_ksp;
  97 
  98         kmutex_t        sofe_lock;
  99         char            sofe_flags;                     /* SOFEF_* flags */
 100         uint_t          sofe_refcnt;                    /* # of instances */
 101         sof_module_t    *sofe_mod;                      /* filter module */
 102 };
 103 
 104 /* Filter entry flags */
 105 #define SOFEF_AUTO      0x1     /* automatic filter */
 106 #define SOFEF_PROG      0x2     /* programmatic filter */
 107 #define SOFEF_CONDEMED  0x4     /* removed by soconfig(1M) */
 108 
 109 /*
 110  * Socket filter instance - one for each socket using a sof_entry_t
 111  */
 112 struct sof_instance {
 113         sof_ops_t       *sofi_ops;      /* filter ops */
 114         void            *sofi_cookie;   /* filter cookie (from attach) */
 115         char            sofi_flags;     /* instance flags (SOFIF_*) */
 116         sof_instance_t  *sofi_prev;     /* up the stack */
 117         sof_instance_t  *sofi_next;     /* down the stack */
 118         struct sonode   *sofi_sonode;   /* socket instance is attached to */
 119         sof_entry_t     *sofi_filter;   /* filter this is an instance of */
 120 };
 121 
 122 /* Filter instance flags */
 123 #define SOFIF_BYPASS            0x1     /* filter does not want any callbacks */
 124 #define SOFIF_DEFER             0x2     /* defer notification of socket */
 125 #define SOFIF_RCV_FLOWCTRL      0x4     /* flow control recv path */
 126 #define SOFIF_SND_FLOWCTRL      0x8     /* flow control send path */
 127 
 128 #define SOF_STAT_ADD(i, s, v) \
 129         atomic_add_64(&(i)->sofi_filter->sofe_kstat.sofek_##s.value.ui64, (v))
 130 
 131 extern void     sof_init(void);
 132 
 133 extern void     sof_entry_free(sof_entry_t *);
 134 extern int      sof_entry_add(sof_entry_t *);
 135 extern sof_entry_t *sof_entry_remove_by_name(const char *);
 136 extern int      sof_entry_proc_sockparams(sof_entry_t *, struct sockparams *);
 137 
 138 extern int      sof_sockparams_init(struct sockparams *);
 139 extern void     sof_sockparams_fini(struct sockparams *);
 140 
 141 extern int      sof_sonode_autoattach_filters(struct sonode *, cred_t *);
 142 extern int      sof_sonode_inherit_filters(struct sonode *, struct sonode *);
 143 extern void     sof_sonode_closing(struct sonode *);
 144 extern void     sof_sonode_cleanup(struct sonode *);
 145 extern void     sof_sonode_notify_filters(struct sonode *, sof_event_t,
 146     uintptr_t);
 147 extern boolean_t sof_sonode_drop_deferred(struct sonode *);
 148 
 149 extern int      sof_setsockopt(struct sonode *, int, const void *, socklen_t,
 150     struct cred *);
 151 extern int      sof_getsockopt(struct sonode *, int, void *, socklen_t *,
 152     struct cred *);
 153 
 154 extern int      sof_rval2errno(sof_rval_t);
 155 
 156 #define SOF_INTERESTED(inst, op)                        \
 157         (!((inst)->sofi_flags & SOFIF_BYPASS) && \
 158         (inst)->sofi_ops->sofop_##op != NULL)
 159 
 160 /*
 161  * SOF_FILTER_OP traverses the filter stack for sonode `so' top-down,
 162  * calling `op' for each filter with the supplied `args'. A non-negative
 163  * return value indicates that a filter action was taken.
 164  */
 165 #define __SOF_FILTER_OP(so, op, cr, ...)                \
 166         sof_instance_t *__inst;                                 \
 167         sof_rval_t __rval;                                      \
 168                                                                 \
 169         for (__inst = (so)->so_filter_top; __inst != NULL;   \
 170             __inst = __inst->sofi_next) {                    \
 171                 if (!SOF_INTERESTED(__inst, op))                \
 172                         continue;                               \
 173                 __rval = (__inst->sofi_ops->sofop_##op)((sof_handle_t)__inst,\
 174                     __inst->sofi_cookie, __VA_ARGS__, cr);   \
 175                 DTRACE_PROBE2(filter__action, (sof_instance_t), __inst,\
 176                     (sof_rval_t), __rval);                      \
 177                 if (__rval != SOF_RVAL_CONTINUE)                \
 178                         return (sof_rval2errno(__rval));        \
 179         }                                                       \
 180         return (-1);
 181 
 182 extern mblk_t   *sof_filter_data_out_from(struct sonode *so,
 183     sof_instance_t *, mblk_t *, struct nmsghdr *, cred_t *, int *);
 184 extern mblk_t   *sof_filter_data_in_proc(struct sonode *so,
 185     mblk_t *, mblk_t **);
 186 extern int      sof_filter_bind(struct sonode *, struct sockaddr *,
 187     socklen_t *, cred_t *);
 188 extern int      sof_filter_listen(struct sonode *, int *, cred_t *);
 189 extern int      sof_filter_connect(struct sonode *, struct sockaddr *,
 190     socklen_t *, cred_t *);
 191 extern int      sof_filter_accept(struct sonode *, cred_t *);
 192 extern int      sof_filter_shutdown(struct sonode *, int *, cred_t *);
 193 extern int      sof_filter_getsockname(struct sonode *, struct sockaddr *,
 194     socklen_t *, cred_t *);
 195 extern int      sof_filter_getpeername(struct sonode *, struct sockaddr *,
 196     socklen_t *, cred_t *);
 197 extern int      sof_filter_setsockopt(struct sonode *, int, int, void *,
 198     socklen_t *, cred_t *);
 199 extern int      sof_filter_getsockopt(struct sonode *, int, int, void *,
 200     socklen_t *, cred_t *);
 201 extern int      sof_filter_ioctl(struct sonode *, int, intptr_t, int,
 202     int32_t *, cred_t *);
 203 
 204 #define SOF_FILTER_DATA_OUT(so, mp, msg, cr, errp) \
 205         sof_filter_data_out_from(so, (so)->so_filter_top, mp, msg, cr, errp)
 206 #define SOF_FILTER_DATA_OUT_FROM(so, inst, mp, msg, cr, errp) \
 207         sof_filter_data_out_from(so, inst, mp, msg, cr, errp)
 208 
 209 #ifdef  __cplusplus
 210 }
 211 #endif
 212 
 213 #endif  /* _SOCKFS_SOCKFILTER_H */