libexplain  1.4.D001
libexplain/buffer/sock_fprog.c
Go to the documentation of this file.
00001 /*
00002  * libexplain - Explain errno values returned by libc functions
00003  * Copyright (C) 2010, 2011, 2013 Peter Miller
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU Lesser General Public License as
00007  * published by the Free Software Foundation; either version 3 of the
00008  * License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public License
00016  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 #include <libexplain/ac/linux/filter.h>
00020 
00021 #include <libexplain/buffer/int.h>
00022 #include <libexplain/buffer/pointer.h>
00023 #include <libexplain/buffer/sock_fprog.h>
00024 #include <libexplain/parse_bits.h>
00025 #include <libexplain/is_efault.h>
00026 #include <libexplain/sizeof.h>
00027 
00028 
00029 #ifdef HAVE_LINUX_FILTER_H
00030 
00031 static void
00032 explain_buffer_filter_code(explain_string_buffer_t *sb, int value)
00033 {
00034     static const explain_parse_bits_table_t class_table[] =
00035     {
00036         { "BPF_LD", BPF_LD },
00037         { "BPF_LDX", BPF_LDX },
00038         { "BPF_ST", BPF_ST },
00039         { "BPF_STX", BPF_STX },
00040         { "BPF_ALU", BPF_ALU },
00041         { "BPF_JMP", BPF_JMP },
00042         { "BPF_RET", BPF_RET },
00043         { "BPF_MISC", BPF_MISC },
00044     };
00045 
00046     static const explain_parse_bits_table_t size_table[] =
00047     {
00048         { "BPF_W", BPF_W },
00049         { "BPF_H", BPF_H },
00050         { "BPF_B", BPF_B },
00051     };
00052 
00053     static const explain_parse_bits_table_t mode_table[] =
00054     {
00055         { "BPF_IMM", BPF_IMM },
00056         { "BPF_ABS", BPF_ABS },
00057         { "BPF_IND", BPF_IND },
00058         { "BPF_MEM", BPF_MEM },
00059         { "BPF_LEN", BPF_LEN },
00060         { "BPF_MSH", BPF_MSH },
00061     };
00062 
00063     static const explain_parse_bits_table_t op_table[] =
00064     {
00065         { "BPF_ADD", BPF_ADD },
00066         { "BPF_SUB", BPF_SUB },
00067         { "BPF_MUL", BPF_MUL },
00068         { "BPF_DIV", BPF_DIV },
00069         { "BPF_OR", BPF_OR },
00070         { "BPF_AND", BPF_AND },
00071         { "BPF_LSH", BPF_LSH },
00072         { "BPF_RSH", BPF_RSH },
00073         { "BPF_NEG", BPF_NEG },
00074         { "BPF_JA", BPF_JA },
00075         { "BPF_JEQ", BPF_JEQ },
00076         { "BPF_JGT", BPF_JGT },
00077         { "BPF_JGE", BPF_JGE },
00078         { "BPF_JSET", BPF_JSET },
00079     };
00080 
00081     static const explain_parse_bits_table_t src_table[] =
00082     {
00083         { "BPF_K", BPF_K },
00084         { "BPF_X", BPF_X },
00085     };
00086 
00087     static const explain_parse_bits_table_t rval_table[] =
00088     {
00089         { "BPF_A", BPF_A },
00090     };
00091 
00092     static const explain_parse_bits_table_t miscop_table[] =
00093     {
00094         { "BPF_TAX", BPF_TAX },
00095         { "BPF_TXA", BPF_TXA },
00096     };
00097 
00098     explain_parse_bits_print_single
00099     (
00100         sb,
00101         BPF_CLASS(value),
00102         class_table,
00103         SIZEOF(class_table)
00104     );
00105 
00106     switch (BPF_CLASS(value))
00107     {
00108     case BPF_LD:
00109     case BPF_LDX:
00110     case BPF_ST:
00111     case BPF_STX:
00112         explain_string_buffer_puts(sb, " | ");
00113         explain_parse_bits_print_single
00114         (
00115             sb,
00116             BPF_SIZE(value),
00117             size_table,
00118             SIZEOF(size_table)
00119         );
00120         explain_string_buffer_puts(sb, " | ");
00121         explain_parse_bits_print_single
00122         (
00123             sb,
00124             BPF_MODE(value),
00125             mode_table,
00126             SIZEOF(mode_table)
00127         );
00128         break;
00129 
00130     case BPF_ALU:
00131     case BPF_JMP:
00132         explain_string_buffer_puts(sb, " | ");
00133         explain_parse_bits_print_single
00134         (
00135             sb,
00136             BPF_SIZE(value),
00137             op_table,
00138             SIZEOF(op_table)
00139         );
00140         explain_string_buffer_puts(sb, " | ");
00141         explain_parse_bits_print_single
00142         (
00143             sb,
00144             BPF_MODE(value),
00145             src_table,
00146             SIZEOF(src_table)
00147         );
00148         break;
00149 
00150     case BPF_RET:
00151         explain_string_buffer_puts(sb, " | ");
00152         explain_parse_bits_print_single
00153         (
00154             sb,
00155             BPF_SIZE(value),
00156             rval_table,
00157             SIZEOF(rval_table)
00158         );
00159         explain_string_buffer_puts(sb, " | ");
00160         explain_parse_bits_print_single
00161         (
00162             sb,
00163             BPF_MODE(value),
00164             src_table,
00165             SIZEOF(src_table)
00166         );
00167         break;
00168 
00169     case BPF_MISC:
00170         explain_string_buffer_puts(sb, " | ");
00171         explain_parse_bits_print_single
00172         (
00173             sb,
00174             BPF_MODE(value),
00175             miscop_table,
00176             SIZEOF(miscop_table)
00177         );
00178         break;
00179 
00180     default:
00181         break;
00182     }
00183 }
00184 
00185 
00186 static int
00187 print_k(int code)
00188 {
00189     switch (BPF_CLASS(code))
00190     {
00191     case BPF_LD:
00192     case BPF_LDX:
00193         switch (BPF_MODE(code))
00194         {
00195         case BPF_ABS:
00196         case BPF_IND:
00197         case BPF_MSH:
00198         case BPF_IMM:
00199         case BPF_MEM:
00200             return 1;
00201 
00202         default:
00203             return 0;
00204         }
00205 
00206     case BPF_ST:
00207     case BPF_STX:
00208         return 1;
00209 
00210     case BPF_JMP:
00211         if (code == (BPF_JMP | BPF_JA))
00212             return 1;
00213         /* fall through... */
00214 
00215     case BPF_ALU:
00216     case BPF_RET:
00217         return (BPF_SRC(code) == BPF_K);
00218 
00219     case BPF_MISC:
00220         return 0;
00221 
00222     default:
00223         return 0;
00224     }
00225 }
00226 
00227 
00228 static int
00229 print_j(int code)
00230 {
00231     switch (BPF_CLASS(code))
00232     {
00233     case BPF_JMP:
00234         return 1;
00235 
00236     default:
00237         return 0;
00238     }
00239     return 0;
00240 }
00241 
00242 
00243 static void
00244 explain_buffer_sock_filter_array(explain_string_buffer_t *sb,
00245     const struct sock_filter *data, size_t len)
00246 {
00247     const struct sock_filter *end;
00248 
00249     if (len > BPF_MAXINSNS)
00250         len = BPF_MAXINSNS;
00251     if (explain_is_efault_pointer(data, sizeof(*data) * len))
00252     {
00253         explain_buffer_pointer(sb, data);
00254         return;
00255     }
00256 
00257     explain_string_buffer_puts(sb, "{ ");
00258     for (end = data + len; data < end; ++data)
00259     {
00260         int             code;
00261 
00262         code = data->code;
00263         if (print_k(code))
00264         {
00265             if (print_j(code))
00266             {
00267                 explain_string_buffer_puts(sb, "BPF_JUMP(");
00268                 explain_buffer_filter_code(sb, code);
00269                 explain_string_buffer_puts(sb, ", ");
00270                 explain_buffer_int(sb, data->k);
00271                 explain_string_buffer_puts(sb, ", ");
00272                 explain_buffer_int(sb, data->jt);
00273                 explain_string_buffer_puts(sb, ", ");
00274                 explain_buffer_int(sb, data->jf);
00275                 explain_string_buffer_putc(sb, ')');
00276             }
00277             else
00278             {
00279                 explain_string_buffer_puts(sb, "BPF_STMT(");
00280                 explain_buffer_filter_code(sb, code);
00281                 explain_string_buffer_puts(sb, ", ");
00282                 explain_buffer_int(sb, data->k);
00283                 explain_string_buffer_putc(sb, ')');
00284             }
00285         }
00286         else
00287         {
00288             explain_string_buffer_puts(sb, "{ code = ");
00289             explain_buffer_filter_code(sb, code);
00290             if (print_j(code))
00291             {
00292                 explain_string_buffer_puts(sb, ", jt = ");
00293                 explain_buffer_int(sb, data->jt);
00294                 explain_string_buffer_puts(sb, ", jf = ");
00295                 explain_buffer_int(sb, data->jf);
00296             }
00297             if (print_k(code))
00298             {
00299                 explain_string_buffer_puts(sb, ", k = ");
00300                 explain_buffer_int(sb, data->k);
00301             }
00302             explain_string_buffer_puts(sb, " }");
00303         }
00304         explain_string_buffer_puts(sb, ", ");
00305     }
00306     explain_string_buffer_puts(sb, "}");
00307 }
00308 
00309 
00310 void
00311 explain_buffer_sock_fprog(explain_string_buffer_t *sb,
00312     const struct sock_fprog *data)
00313 {
00314     if (explain_is_efault_pointer(data, sizeof(*data)))
00315     {
00316         explain_buffer_pointer(sb, data);
00317         return;
00318     }
00319 
00320     explain_string_buffer_puts(sb, "{ len = ");
00321     explain_buffer_uint(sb, data->len);
00322     explain_string_buffer_puts(sb, ", filter = ");
00323     explain_buffer_sock_filter_array(sb, data->filter, data->len);
00324     explain_string_buffer_puts(sb, " }");
00325 }
00326 
00327 #else
00328 
00329 void
00330 explain_buffer_sock_fprog(explain_string_buffer_t *sb,
00331     const struct sock_fprog *data)
00332 {
00333     explain_buffer_pointer(sb, data);
00334 }
00335 
00336 #endif
00337 
00338 
00339 /* vim: set ts=8 sw=4 et : */