libexplain
1.4.D001
|
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 : */