[insert project logo here (125x200px max)] Navigator Mailinglists Please report any errors or ommissions you find to our `Help' mailinglist, or post a message in the Forums. Copyright and Licensing Information Snap is (c) Jonathan T. Moore, 1999-2002 and licensed under the GNU General Public License (GPL). All other parts of Splash are (c) Willem de Bruijn, 2002-2003 and licensed under the BSD Open Source License. All sourcecode is made publicly available. Acknowledgement Splash and the Splash website are hosted by SourceForge.net |
Splash - DocumentationSNMP Plus a Lightweight API for SNAP Handlingsnap-1.1-wjdb/lib/snap_interp.cGo to the documentation of this file.00001 /* $Id: snap_interp.c,v 1.14 2003/04/02 17:01:14 wdebruij Exp $ */ 00002 00003 #include <asm/types.h> 00004 #include <netinet/ip.h> 00005 #include <sys/types.h> 00006 #include "bytecode.h" 00007 #include "config.h" 00008 #include "d_printf.h" 00009 #include "dyncheck.h" 00010 #include "io.h" 00011 #include "myassert.h" 00012 #include "packet.h" 00013 #include "timers.h" 00014 #include "exception.h" 00015 #include "wassert.h" 00016 #include "snap_kern_iface.h" 00017 #include "snap_svc_handler.h" 00018 #include "printval.h" 00019 #include "warn.h" 00020 00021 #define NIPQUAD(addr) addr << 24 >> 24, addr << 16 >> 24, addr << 8 >> 24, addr >> 24 00022 00023 #ifdef CONFIG_IP_SNAP 00024 00025 #ifndef __KERNEL__ 00026 extern int fprintf_value(packet_t *p, FILE *f, value_t *v); 00027 #endif 00028 00029 /************************************************************************/ 00030 /* macros for use in interp_packet */ 00031 00032 /* Dynamic type checks */ 00033 00034 00035 int heap_alloc(packet_t *p, int lenb, int flag, 00036 heap_obj **ho, int *hoffset) { 00037 int sizeb = lenb + sizeof(heap_obj); 00038 DYNCHECK(((void *)p->stack_max - sizeb) > (void *)p->sp); 00039 DYNCHECK(lenb <= MAX_HEAPOBJ_SZ); 00040 p->stack_max = (value_t *)((void *)p->stack_max - sizeb); 00041 *ho = (heap_obj *)((p)->stack_max); 00042 *hoffset = (void *)(p)->stack_max - (p)->heap_min; 00043 (*ho)->len = lenb; 00044 (*ho)->flag = flag; 00045 d_printf(100,"%s:%d: allocated %d-buf (f=%d) at %#x\n", 00046 __FILE__,__LINE__,lenb,flag,(unsigned int)ho); 00047 return 0; 00048 } 00049 00050 #ifdef __KERNEL__ 00051 static void resize_to_max_buffer(packet_t *p, struct iphdr **interpiph) { 00052 struct sk_buff *tmp; 00053 struct iphdr *oldiph; 00054 struct iphdr *newiph; 00055 00056 if (p->resized) { 00057 /* already resized it */ 00058 printk(KERN_WARNING "%s:%d: resizing already resized buffer\n", 00059 __FILE__,__LINE__); 00060 return; 00061 } 00062 if (!p->is_contiguous) { 00063 /* uh-oh */ 00064 printk(KERN_WARNING "%s:%d: resizing non-contiguous buffer\n", 00065 __FILE__,__LINE__); 00066 return; 00067 } 00068 00069 d_printf(50,"%s:%d: growing buffer...\n",__FILE__,__LINE__); 00070 00071 tmp = skb_grow(p->skb,3000); /* get the new buffer, copy data over */ 00072 00073 /* see if there was any additional stack */ 00074 if ((void *)(p->sp) > (void *)(p->skb->tail)) { 00075 memcpy(tmp->tail, p->skb->tail, 00076 (char *)(p->sp) - (char *)(p->skb->tail)); 00077 } 00078 00079 /* reset packet pointers */ 00080 oldiph = p->skb->nh.iph; 00081 newiph = tmp->nh.iph; 00082 *interpiph = newiph; 00083 00084 p->hdr = (header_t *)((void *)newiph + (newiph->ihl << 2)); 00085 p->code_min = (instr_t *)((void *)p->hdr + sizeof(header_t)); 00086 p->pc = (instr_t *)((void *)newiph + 00087 ((void *)p->pc - (void *)oldiph)); 00088 p->code_max = (instr_t *)((void *)p->code_min + 00089 ntohs(p->hdr->code_sizeb)); 00090 p->handler = (instr_t *)((void *)newiph + 00091 ((void *)p->handler - (void *)oldiph)); 00092 p->heap_min = (void *)p->code_max; 00093 if (p->h_alloc_ptr != NULL) { 00094 printk(KERN_WARNING "%s:%d: p->h_alloc_ptr should be NULL\n", 00095 __FILE__,__LINE__); 00096 } 00097 p->heap_max = p->heap_min + ntohs(p->hdr->heap_sizeb); 00098 p->stack_min = (value_t *)p->heap_max; 00099 p->sp = (value_t *)((void *)newiph + 00100 ((void *)p->sp - (void *)oldiph)); 00101 p->stack_max = (value_t *)tmp->end; 00102 p->h_alloc_heap_max = tmp->end; 00103 p->resized = 1; 00104 p->is_contiguous = 1; 00105 00106 d_printf(50,"%s:%d: resized packet: %d instrs, %d stack vals\n", 00107 __FILE__,__LINE__,p->code_max - p->code_min, p->sp - 00108 p->stack_min); 00109 d_printf(50,"%s:%d: hdr=0x%08x cmin=0x%08x pc=0x%08x cmax=0x%08x\n", 00110 __FILE__,__LINE__, 00111 (__u32)p->hdr, (__u32)p->code_min, (__u32)p->pc, (__u32)p->code_max); 00112 d_printf(50,"%s:%d: hmin=0x%08x hmax=0x%08x\n",__FILE__,__LINE__, 00113 (__u32)p->heap_min, (__u32)p->heap_max); 00114 d_printf(50,"%s:%d: smin=0x%08x sp=0x%08x smax=0x%08x\n", 00115 __FILE__,__LINE__, 00116 (__u32)p->stack_min, (__u32)p->sp, (__u32)p->stack_max); 00117 00118 00119 /* make the new buffer live, chuck old buffer */ 00120 kfree_skb(p->skb); 00121 p->skb = tmp; 00122 00123 return; 00124 } 00125 00126 #define ENSURE_STACK_ROOM(p,iph) \ 00127 { if (p->sp >= p->stack_max && !p->resized) \ 00128 resize_to_max_buffer(p,&(iph)); \ 00129 } 00130 00131 #define ENSURE_HEAP_ROOM(p,iph) \ 00132 { if (!p->resized) \ 00133 resize_to_max_buffer(p,&(iph)); \ 00134 } 00135 #else 00136 00137 #define ENSURE_STACK_ROOM(p,iph) 00138 #define ENSURE_HEAP_ROOM(p,iph) 00139 #endif /* __KERNEL__ */ 00140 00141 00142 #ifdef CONFIG_IP_SNAP 00143 #define DEBUGFMTCONCAT(fmt1,t,fmt2) \ 00144 (((t) == INTV) ? fmt1 "%d" fmt2 : \ 00145 (((t) == ADDRV) ? fmt1 "%d.%d.%d.%d" fmt2 : \ 00146 (((t) == TUPLEV) ? fmt1 "offs[%d]" fmt2 : \ 00147 (((t) == EXCV) ? fmt1 "exc(%d)" fmt2 : \ 00148 (((t) == STRV) ? fmt1 "\"%s\"" fmt2 : \ 00149 /* FLOATV */ fmt1 "%d.%06d" fmt2))))) 00150 #endif 00151 00152 #ifdef ADDR_IN_HEAP 00153 #endif 00154 00155 /* Instruction cases */ 00156 00157 #define INTOP(t,op,opname) { \ 00158 value_t *top1 = p->sp - 1; \ 00159 value_t *top2 = p->sp - 2; \ 00160 int result; \ 00161 \ 00162 DYNCHECK(top2 >= p->stack_min); \ 00163 DYNCHECK_TAG(*top1,INTV); \ 00164 DYNCHECK_TAG(*top2,INTV); \ 00165 result = (t)GET_INT(*top2) op (t)GET_INT(*top1); \ 00166 wassert((result <= MAX_VINT) && (result >= MIN_VINT)); \ 00167 d_printf(10,"%s:%d: pc=%d: %s %d %d = %d\n", \ 00168 __FILE__,__LINE__,(p->pc - p->code_min),opname, \ 00169 GET_INT(*top2),GET_INT(*top1),result); \ 00170 SET_TAG(*top2,INTV); \ 00171 SET_INT(*top2,result); \ 00172 p->sp--; \ 00173 p->pc++; \ 00174 break; \ 00175 } 00176 00177 #define INTFLOATOP(op,opname) { \ 00178 value_t *top1 = p->sp - 1; \ 00179 value_t *top2 = p->sp - 2; \ 00180 \ 00181 DYNCHECK(top2 >= p->stack_min); \ 00182 if (GET_TAG(*top1) == INTV) { \ 00183 int result; \ 00184 DYNCHECK_TAG(*top2,INTV); \ 00185 result = (int)GET_INT(*top2) op (int)GET_INT(*top1); \ 00186 wassert((result <= MAX_VINT) && (result >= MIN_VINT)); \ 00187 d_printf(10,"%s:%d: pc=%d: %s %d %d = %d\n", \ 00188 __FILE__,__LINE__,(p->pc - p->code_min),opname, \ 00189 GET_INT(*top2),GET_INT(*top1),result); \ 00190 SET_TAG(*top2,INTV); \ 00191 SET_INT(*top2,result); \ 00192 } else { \ 00193 float32 v1, v2, result; \ 00194 ENSURE_HEAP_ROOM(p,iph); \ 00195 top1 = p->sp - 1; \ 00196 top2 = p->sp - 2; \ 00197 DYNCHECK_TAG(*top1,FLOATV); \ 00198 DYNCHECK_TAG(*top2,FLOATV); \ 00199 GET_FLOAT(v1,p->heap_min,*top1); \ 00200 GET_FLOAT(v2,p->heap_min,*top2); \ 00201 result = v2 op v1; \ 00202 d_printf(10,"%s:%d: pc=%d: %s %d.%06d %d.%06d = %d.%06d\n", \ 00203 __FILE__,__LINE__,(p->pc - p->code_min),opname, \ 00204 (int)v2,(int)((v2 - (int)v2) * 1000000), \ 00205 (int)v1,(int)((v1 - (int)v1) * 1000000), \ 00206 (int)result,(int)((result - (int)result) * 1000000)); \ 00207 SET_TAG(*top2,FLOATV); \ 00208 SET_FLOAT(*top2,result,p); \ 00209 } \ 00210 p->sp--; \ 00211 p->pc++; \ 00212 break; \ 00213 } 00214 00215 #define INTFLOATOPI(op,opname) { \ 00216 value_t *top1 = p->sp - 1; \ 00217 value_t *top2 = p->sp - 2; \ 00218 \ 00219 DYNCHECK(top2 >= p->stack_min); \ 00220 if (GET_TAG(*top1) == INTV) { \ 00221 int result; \ 00222 DYNCHECK_TAG(*top2,INTV); \ 00223 result = (int)GET_INT(*top2) op (int)GET_INT(*top1); \ 00224 wassert((result <= MAX_VINT) && (result >= MIN_VINT)); \ 00225 d_printf(10,"%s:%d: pc=%d: %s %d %d = %d\n", \ 00226 __FILE__,__LINE__,(p->pc - p->code_min),opname, \ 00227 GET_INT(*top2),GET_INT(*top1),result); \ 00228 SET_TAG(*top2,INTV); \ 00229 SET_INT(*top2,result); \ 00230 } else { \ 00231 float32 v1, v2; \ 00232 int result; \ 00233 ENSURE_HEAP_ROOM(p,iph); \ 00234 top1 = p->sp - 1; \ 00235 top2 = p->sp - 2; \ 00236 DYNCHECK_TAG(*top1,FLOATV); \ 00237 DYNCHECK_TAG(*top2,FLOATV); \ 00238 GET_FLOAT(v1,p->heap_min,*top1); \ 00239 GET_FLOAT(v2,p->heap_min,*top2); \ 00240 result = v2 op v1; \ 00241 d_printf(10,"%s:%d: pc=%d: %s %d.%06d %d.%06d = %d.%06d\n", \ 00242 __FILE__,__LINE__,(p->pc - p->code_min),opname, \ 00243 (int)v2,(int)((v2 - (int)v2) * 1000000), \ 00244 (int)v1,(int)((v1 - (int)v1) * 1000000), \ 00245 (int)result,(int)((result - (int)result) * 1000000)); \ 00246 SET_TAG(*top2,INTV); \ 00247 SET_INT(*top2,result); \ 00248 } \ 00249 p->sp--; \ 00250 p->pc++; \ 00251 break; \ 00252 } 00253 00254 #define INTIMMOP(t,op,opname) { \ 00255 value_t *top = p->sp - 1; \ 00256 int lit; \ 00257 int result; \ 00258 \ 00259 DYNCHECK(top >= p->stack_min); \ 00260 DYNCHECK_TAG(*top,INTV); \ 00261 GET_LIT(lit,INTV,*p->pc); \ 00262 result = (t)GET_INT(*top) op (t)lit; \ 00263 wassert((result <= MAX_VINT) && (result >= MIN_VINT)); \ 00264 d_printf(10,"%s:%d: pc=%d: %s %d %d = %d\n", \ 00265 __FILE__,__LINE__,(p->pc - p->code_min),opname, \ 00266 GET_INT(*top),lit,result); \ 00267 SET_TAG(*top,INTV); \ 00268 SET_INT(*top,result); \ 00269 p->pc++; \ 00270 break; \ 00271 } 00272 00273 #define INTFLOATIMMOP(op,opname) { \ 00274 value_t *top = p->sp - 1; \ 00275 \ 00276 DYNCHECK(top >= p->stack_min); \ 00277 if (GET_TAG(*top) == INTV) { \ 00278 int lit; \ 00279 int result; \ 00280 GET_LIT(lit,INTV,*p->pc); \ 00281 result = GET_INT(*top) op lit; \ 00282 wassert((result <= MAX_VINT) && (result >= MIN_VINT)); \ 00283 d_printf(10,"%s:%d: pc=%d: %s %d %d = %d\n", \ 00284 __FILE__,__LINE__,(p->pc - p->code_min),opname, \ 00285 GET_INT(*top),lit,result); \ 00286 SET_TAG(*top,INTV); \ 00287 SET_INT(*top,result); \ 00288 } else { \ 00289 float32 f1, lit, result; \ 00290 value_t v = ZERO_VALUE_T; \ 00291 ENSURE_HEAP_ROOM(p,iph); \ 00292 top = p->sp - 1; \ 00293 DYNCHECK_TAG(*top,FLOATV); \ 00294 COPY_LIT(v,FLOATV,*p->pc); \ 00295 GET_FLOAT(lit,p->heap_min,v); \ 00296 GET_FLOAT(f1,p->heap_min,*top); \ 00297 result = f1 op lit; \ 00298 d_printf(10,"%s:%d: pc=%d: %s %d.%06d %d.%06d = %d.%06d\n", \ 00299 __FILE__,__LINE__,(p->pc - p->code_min),opname, \ 00300 (int)f1,(int)((f1 - (int)f1) * 1000000), \ 00301 (int)lit,(int)((lit - (int)lit) * 1000000), \ 00302 (int)result,(int)((result - (int)result) * 1000000)); \ 00303 SET_TAG(*top,FLOATV); \ 00304 SET_FLOAT(*top,result,p); \ 00305 } \ 00306 p->pc++; \ 00307 break; \ 00308 } 00309 00310 #define INTFLOATIMMOPI(op,opname) { \ 00311 value_t *top = p->sp - 1; \ 00312 \ 00313 DYNCHECK(top >= p->stack_min); \ 00314 if (GET_TAG(*top) == INTV) { \ 00315 int lit; \ 00316 int result; \ 00317 GET_LIT(lit,INTV,*p->pc); \ 00318 result = GET_INT(*top) op lit; \ 00319 wassert((result <= MAX_VINT) && (result >= MIN_VINT)); \ 00320 d_printf(10,"%s:%d: pc=%d: %s %d %d = %d\n", \ 00321 __FILE__,__LINE__,(p->pc - p->code_min),opname, \ 00322 GET_INT(*top),lit,result); \ 00323 SET_TAG(*top,INTV); \ 00324 SET_INT(*top,result); \ 00325 } else { \ 00326 float32 f1, lit; \ 00327 int result; \ 00328 value_t v = ZERO_VALUE_T; \ 00329 ENSURE_HEAP_ROOM(p,iph); \ 00330 top = p->sp - 1; \ 00331 DYNCHECK_TAG(*top,FLOATV); \ 00332 COPY_LIT(v,FLOATV,*p->pc); \ 00333 GET_FLOAT(lit,p->heap_min,v); \ 00334 GET_FLOAT(f1,p->heap_min,*top); \ 00335 result = f1 op lit; \ 00336 d_printf(10,"%s:%d: pc=%d: %s %d.%06d %d.%06d = %d.%06d\n", \ 00337 __FILE__,__LINE__,(p->pc - p->code_min),opname, \ 00338 (int)f1,(int)((f1 - (int)f1) * 1000000), \ 00339 (int)lit,(int)((lit - (int)lit) * 1000000), \ 00340 (int)result,(int)((result - (int)result) * 1000000)); \ 00341 SET_TAG(*top,INTV); \ 00342 SET_INT(*top,result); \ 00343 } \ 00344 p->pc++; \ 00345 break; \ 00346 } 00347 00348 #define FLOATIMMOP(op,opname) { \ 00349 value_t *top = p->sp - 1; \ 00350 value_t v = ZERO_VALUE_T; \ 00351 float32 result, f1, lit; \ 00352 \ 00353 ENSURE_HEAP_ROOM(p,iph); \ 00354 top = p->sp - 1; \ 00355 DYNCHECK(top >= p->stack_min); \ 00356 DYNCHECK_TAG(*top,FLOATV); \ 00357 COPY_LIT(v,FLOATV,*p->pc); \ 00358 GET_FLOAT(lit,p->heap_min,v); \ 00359 GET_FLOAT(f1,p->heap_min,*top); \ 00360 result = f1 op lit; \ 00361 d_printf(10,"%s:%d: pc=%d: %s %d.%06d %d.%06d = %d.%06d\n", \ 00362 __FILE__,__LINE__,(p->pc - p->code_min),opname, \ 00363 (int)f1,(int)((f1 - (int)f1) * 1000000), \ 00364 (int)lit,(int)((lit - (int)lit) * 1000000), \ 00365 (int)result,(int)((result - (int)result) * 1000000)); \ 00366 SET_TAG(*top,FLOATV); \ 00367 SET_FLOAT(*top,result,p); \ 00368 p->pc++; \ 00369 break; \ 00370 } 00371 00372 #define FLOATIMMOPI(op,opname) { \ 00373 value_t *top = p->sp - 1; \ 00374 value_t v = ZERO_VALUE_T; \ 00375 float32 f1, lit; \ 00376 int result; \ 00377 \ 00378 ENSURE_HEAP_ROOM(p,iph); \ 00379 top = p->sp - 1; \ 00380 DYNCHECK(top >= p->stack_min); \ 00381 DYNCHECK_TAG(*top,FLOATV); \ 00382 COPY_LIT(v,FLOATV,*p->pc); \ 00383 GET_FLOAT(lit,p->heap_min,v); \ 00384 GET_FLOAT(f1,p->heap_min,*top); \ 00385 result = f1 op lit; \ 00386 d_printf(10,"%s:%d: pc=%d: %s %d.%06d %d.%06d = %d.%06d\n", \ 00387 __FILE__,__LINE__,(p->pc - p->code_min),opname, \ 00388 (int)f1,(int)((f1 - (int)f1) * 1000000), \ 00389 (int)lit,(int)((lit - (int)lit) * 1000000), \ 00390 (int)result,(int)((result - (int)result) * 1000000)); \ 00391 SET_TAG(*top,INTV); \ 00392 SET_INT(*top,result); \ 00393 p->pc++; \ 00394 break; \ 00395 } 00396 00397 #define EQOP(res,opname) { \ 00398 value_t *top1 = p->sp - 1; \ 00399 value_t *top2 = p->sp - 2; \ 00400 int result; \ 00401 \ 00402 DYNCHECK(top2 >= p->stack_min); \ 00403 result = (res == eq_value(top1,top2,p)); \ 00404 if (result == -1) \ 00405 return -1; \ 00406 d_printf(10,"%s:%d: pc=%d: %s: (%s)\n", \ 00407 __FILE__,__LINE__,(p->pc - p->code_min),opname, \ 00408 (result ? "equal" : "not equal")); \ 00409 SET_TAG(*top2,INTV); \ 00410 SET_INT(*top2,result); \ 00411 p->sp--; \ 00412 p->pc++; \ 00413 break; \ 00414 } 00415 00416 #ifndef SMALL_INSTRS 00417 #define EQOPI(res,opname) { \ 00418 value_t *top = p->sp - 1; \ 00419 int result; \ 00420 \ 00421 DYNCHECK(top >= p->stack_min); \ 00422 result = (res == eq_value(top,&p->pc->arg,p)); \ 00423 d_printf(125,"%s:%d: pc=%d: %s: (%s)\n", \ 00424 __FILE__,__LINE__,(p->pc - p->code_min),opname, \ 00425 (result ? "equal" : "not equal")); \ 00426 SET_TAG(*top,INTV); \ 00427 SET_INT(*top,result); \ 00428 p->pc++; \ 00429 break; \ 00430 } 00431 #endif 00432 00433 /************************************************************************/ 00434 00435 static int eq_value(value_t *v1, value_t *v2, packet_t *p) { 00436 int result; 00437 TAG_T tag1 = GET_TAG(*v1); 00438 switch(tag1) { 00439 #ifdef SMALL_VALUES 00440 case INTV: 00441 case TUPLEV: 00442 case EXCV: 00443 case STRV: 00444 default: 00445 result = (*v1 == *v2); break; 00446 #else 00447 case EXCV: 00448 case INTV: 00449 default: 00450 result = (GET_INT(*v1) == GET_INT(*v2)) && 00451 (tag1 == GET_TAG(*v2)); 00452 break; 00453 case TUPLEV: 00454 case STRV: 00455 result = (GET_OFFS(*v1) == GET_OFFS(*v2)) && 00456 (tag1 == GET_TAG(*v2)); 00457 break; 00458 #endif 00459 case ADDRV: { 00460 uint32 addr1, addr2; 00461 if (tag1 == GET_TAG(*v2)) { 00462 GET_ADDR(addr1,p->heap_min,*v1); 00463 GET_ADDR(addr2,p->heap_min,*v2); 00464 result = (addr1 == addr2); 00465 } 00466 else 00467 result = 0; 00468 break; 00469 } 00470 case FLOATV: { 00471 float32 f1, f2; 00472 if (tag1 == GET_TAG(*v2)) { 00473 GET_FLOAT(f1,p->heap_min,*v1); 00474 GET_FLOAT(f2,p->heap_min,*v2); 00475 result = (f1 == f2); 00476 } 00477 else 00478 result = 0; 00479 break; 00480 } 00481 } 00482 return result; 00483 } 00484 00485 /* assumes packet is well-formed on entry; returns -1 on failure */ 00486 #ifdef __KERNEL__ 00487 int snap_interp_packet(struct sk_buff *skb) { 00488 #else 00489 int snap_interp_packet(packet_t *p) { 00490 #endif 00491 00492 #ifdef __KERNEL__ 00493 struct iphdr *iph = skb->nh.iph; 00494 packet_t pack; 00495 packet_t *p = &pack; 00496 #endif 00497 00498 int done; 00499 00500 #ifdef __KERNEL__ 00501 /* set up packet struct */ 00502 p->hdr = (header_t *)((void *)iph + (iph->ihl << 2)); 00503 p->rb = iph->ttl; 00504 p->code_min = (instr_t *)((void *)p->hdr + sizeof(header_t)); 00505 p->pc = p->code_min + ntohs(p->hdr->entry_point); 00506 p->code_max = (instr_t *)((void *)p->code_min + 00507 ntohs(p->hdr->code_sizeb)); 00508 p->handler = p->code_max; /* default handler */ 00509 p->heap_min = (void *)p->code_max; 00510 p->h_alloc_ptr = NULL; 00511 p->heap_max = p->heap_min + ntohs(p->hdr->heap_sizeb); 00512 p->stack_min = (value_t *)p->heap_max; 00513 p->sp = (value_t *)((void *)p->stack_min + 00514 ntohs(p->hdr->stack_sizeb)); 00515 p->stack_max = (value_t *)skb->end; 00516 p->h_alloc_heap_max = skb->end; 00517 p->resized = 0; /* haven't grown it yet */ 00518 p->is_contiguous = 1; 00519 p->skb = skb; 00520 #else 00521 p->rb = p->iph->ttl; 00522 #endif 00523 00524 print_anti_timer(1,"interp_packet"); 00525 done = 0; 00526 00527 assert(p->pc >= p->code_min); 00528 00529 d_printf(40,"%s:%d: packet src: %d.%d.%d.%d, dst: %d.%d.%d.%d\n", 00530 __FILE__,__LINE__,NIPQUAD(p->hdr->saddr),NIPQUAD(p->hdr->daddr)); 00531 d_printf(40,"%s:%d: interp_packet: %d instrs, %d stack vals, ep=%d, rb=%d\n", 00532 __FILE__,__LINE__,p->code_max - p->code_min, p->sp - 00533 p->stack_min, ntohs(p->hdr->entry_point), p->iph->ttl); 00534 d_printf(50,"%s:%d: hdr=0x%08x cmin=0x%08x pc=0x%08x cmax=0x%08x\n", 00535 __FILE__,__LINE__, 00536 (__u32)p->hdr, (__u32)p->code_min, (__u32)p->pc, (__u32)p->code_max); 00537 d_printf(50,"%s:%d: hmin=0x%08x hmax=0x%08x\n",__FILE__,__LINE__, 00538 (__u32)p->heap_min, (__u32)p->heap_max); 00539 d_printf(50,"%s:%d: smin=0x%08x sp=0x%08x smax=0x%08x\n", 00540 __FILE__,__LINE__, 00541 (__u32)p->stack_min, (__u32)p->sp, (__u32)p->stack_max); 00542 #ifdef __KERNEL__ 00543 d_printf(100,"%s:%d: skb->head=0x%08x skb->data=0x%08x skb->tail=0x%08x skb->end=0x%08x\n", 00544 __FILE__,__LINE__, 00545 (__u32)skb->head, (__u32)skb->data, (__u32)skb->tail, (__u32)skb->end); 00546 #endif 00547 00548 /* decrement resource bound on arrival */ 00549 { 00550 if (p->rb <= 1) { 00551 /* out of resource bound after decrement */ 00552 d_printf(1,"%s:%d: out of RB, dropping packet\n",__FILE__,__LINE__); 00553 #ifdef __KERNEL__ 00554 return -ICMP_TIME_EXCEEDED; 00555 #else 00556 return -1; 00557 #endif 00558 } 00559 p->rb--; 00560 } 00561 00562 while(!done) { 00563 /* if we exactly fall off the end of the code, we can assume an 00564 implicit EXIT instruction */ 00565 if (p->pc == p->code_max) { 00566 done = 1; 00567 break; 00568 } 00569 00570 DYNCHECK(p->pc < p->code_max); 00571 00572 switch(GET_OP(*p->pc)) { 00573 case EXIT: 00574 d_printf(10,"%s:%d: pc=%d: EXIT\n",__FILE__,__LINE__, 00575 (p->pc - p->code_min)); 00576 done = 1; 00577 break; 00578 00579 #ifndef SMALL_INSTRS 00580 case PUSH: 00581 d_printf(100,"%s:%d: interp: PUSH\n",__FILE__,__LINE__); 00582 ENSURE_STACK_ROOM(p,iph); 00583 DYNCHECK(p->sp < p->stack_max); 00584 COPY_VAL(*p->sp,p->pc->arg); 00585 p->sp++; 00586 p->pc++; 00587 break; 00588 #else 00589 #ifndef NDEBUG 00590 #define PUSHOP(t,opname,fmt,arg...) { \ 00591 ENSURE_STACK_ROOM(p,iph); \ 00592 DYNCHECK(p->sp < p->stack_max); \ 00593 COPY_LIT(*p->sp,t,*p->pc); \ 00594 d_printf(10,"%s:%d: pc=%d: %s " fmt "\n", \ 00595 __FILE__,__LINE__,(p->pc - p->code_min), \ 00596 opname,##arg); \ 00597 p->sp++; \ 00598 p->pc++; \ 00599 break; \ 00600 } 00601 #define PUSHWJDB(t,opname,val,fmt,arg...) { \ 00602 ENSURE_STACK_ROOM(p,iph); \ 00603 DYNCHECK(p->sp < p->stack_max); \ 00604 COPY_LIT(*p->sp,t,val); \ 00605 d_printf(10,"%s:%d: pc=%d: %s " fmt "\n", \ 00606 __FILE__,__LINE__,(p->pc - p->code_min), \ 00607 opname,##arg); \ 00608 p->sp++; \ 00609 p->pc++; \ 00610 break; \ 00611 } 00612 #else /* NDEBUG */ 00613 #define PUSHOP(t,opname,fmt,arg...) { \ 00614 ENSURE_STACK_ROOM(p,iph); \ 00615 DYNCHECK(p->sp < p->stack_max); \ 00616 COPY_LIT(*p->sp,t,*p->pc); \ 00617 p->sp++; \ 00618 p->pc++; \ 00619 break; \ 00620 } 00621 #endif /* NDEBUG */ 00622 00623 case PINT: PUSHOP(INTV,"PINT","%d",GET_LIT_VAL(*p->pc)); 00624 case PADDR: PUSHOP(ADDRV,"PADDR","%u.%u.%u.%u", 00625 NIPQUAD(GET_ADDR_VAL(p->heap_min,*p->pc))); 00626 case PTUP: PUSHOP(TUPLEV,"PTUP","offs[%d]",GET_OFFS(*p->pc)); 00627 case PEXC: PUSHOP(EXCV,"PEXC","exc(%d)",GET_LIT_VAL(*p->pc)); 00628 case PSTR: PUSHOP(STRV,"PSTR","\"%s\"", 00629 GET_STR_VAL(p->heap_min,*p->pc)); 00630 case PFLT: PUSHOP(FLOATV,"PFLT","%d.%06d", 00631 (int)GET_FLT_VAL(p->heap_min,*p->pc), 00632 (int)((GET_FLT_VAL(p->heap_min,*p->pc) - 00633 (int)GET_FLT_VAL(p->heap_min,*p->pc)) * 1000000)); 00634 #endif 00635 00636 case POP: 00637 d_printf(10,"%s:%d: pc=%d: POP\n",__FILE__,__LINE__, 00638 (p->pc - p->code_min)); 00639 DYNCHECK(p->sp > p->stack_min); 00640 p->sp--; 00641 p->pc++; 00642 break; 00643 00644 case POPI: { 00645 int n; 00646 value_t *newsp; 00647 00648 GET_LIT(n,INTV,*p->pc); 00649 DYNCHECK(n >= 0); 00650 d_printf(10,"%s:%d: pc=%d: POPI %d\n", 00651 __FILE__,__LINE__,(p->pc - p->code_min),n); 00652 newsp = p->sp - n; 00653 DYNCHECK(newsp >= p->stack_min); 00654 p->sp = newsp; 00655 p->pc++; 00656 break; 00657 } 00658 00659 case PULL: { 00660 int n; 00661 value_t *src; 00662 00663 d_printf(100,"%s:%d: interp: PULL\n",__FILE__,__LINE__); 00664 ENSURE_STACK_ROOM(p,iph); 00665 GET_LIT(n,INTV,*p->pc); 00666 DYNCHECK(n >= 0); 00667 src = p->sp - (n + 1); 00668 DYNCHECK(src >= p->stack_min); 00669 DYNCHECK(p->sp < p->stack_max); 00670 COPY_VAL(*p->sp,*src); 00671 #ifdef CONFIG_IP_SNAP_DEBUG 00672 d_printf(10,"%s:%d: pc=%d: PULL %d = ", 00673 __FILE__,__LINE__,(p->pc - p->code_min),n); 00674 if (sysctl_snap_debug_level == -1 || 00675 10 <= sysctl_snap_debug_level) { 00676 printk_value(p,p->sp); 00677 printk("\n"); 00678 } 00679 #if 0 00680 #define PULL_D_PRINTF(fmt,arg...) \ 00681 { d_printf(10,"%s:%d: pc=%d: PULL %d = " fmt "\n", \ 00682 __FILE__,__LINE__,(p->pc - p->code_min),n, \ 00683 ##arg); \ 00684 break; \ 00685 } 00686 switch(GET_TAG(*p->sp)) { 00687 case INTV: PULL_D_PRINTF("%d",GET_INT(*p->sp)); 00688 case ADDRV: PULL_D_PRINTF("%d.%d.%d.%d", 00689 NIPQUAD(GET_ADDR_VAL(p->heap_min,*p->sp))); 00690 case STRV: PULL_D_PRINTF("\"%s\"",GET_STR_VAL(p->heap_min,*p->sp)); 00691 case EXCV: PULL_D_PRINTF("exc(%d)",GET_LIT_VAL(*p->sp)); 00692 case TUPLEV: PULL_D_PRINTF("offs[%d]",GET_OFFS(*p->sp)); 00693 case FLOATV: 00694 PULL_D_PRINTF("%d.%06d", 00695 (int)GET_FLT_VAL(p->heap_min,*p->sp), 00696 (int)((GET_FLT_VAL(p->heap_min,*p->sp) - 00697 (int)GET_FLT_VAL(p->heap_min,*p->sp)) * 00698 1000000)); 00699 } 00700 #undef PULL_D_PRINTF 00701 #endif /* if 0 */ 00702 #endif /* CONFIG_IP_SNAP_DEBUG */ 00703 p->sp++; 00704 p->pc++; 00705 break; 00706 } 00707 case PULLSTACK:{ 00708 int n; 00709 value_t *src; 00710 00711 ENSURE_STACK_ROOM(p,iph); 00712 GET_LIT(n,INTV,*(p->sp -1)); 00713 DYNCHECK(n >= 0); 00714 src = p->sp - (n + 1); 00715 DYNCHECK(src >= p->stack_min); 00716 DYNCHECK(p->sp < p->stack_max); 00717 COPY_VAL(*(p->sp-1),*src); 00718 d_printf(100,"%s:%d: interp: PULLSTACK (from element %d)\n",__FILE__,__LINE__, n); 00719 p->pc++; 00720 break; 00721 } 00722 00723 case STORE: { 00724 int n; 00725 value_t *src; 00726 value_t *dst; 00727 00728 d_printf(100,"%s:%d: interp: STORE\n",__FILE__,__LINE__); 00729 GET_LIT(n,INTV,*p->pc); 00730 DYNCHECK(n >= 0); 00731 src = p->sp - 1; 00732 dst = p->sp - (n + 1); 00733 DYNCHECK(src >= p->stack_min); /* also effectively checks that 00734 the stack is non-empty */ 00735 COPY_VAL(*dst,*src); 00736 #ifdef CONFIG_IP_SNAP_DEBUG 00737 #define STORE_D_PRINTF(fmt,arg...) \ 00738 { d_printf(10,"%s:%d: pc=%d: STORE s[%d] := " fmt "\n", \ 00739 __FILE__,__LINE__,(p->pc - p->code_min),n, \ 00740 ##arg); \ 00741 break; \ 00742 } 00743 switch(GET_TAG(*src)) { 00744 case INTV: STORE_D_PRINTF("%d",GET_INT(*src)); 00745 case ADDRV: STORE_D_PRINTF("%d.%d.%d.%d", 00746 NIPQUAD(GET_ADDR_VAL(p->heap_min,*src))); 00747 case STRV: STORE_D_PRINTF("\"%s\"",GET_STR_VAL(p->heap_min,*src)); 00748 case EXCV: STORE_D_PRINTF("exc(%d)",GET_LIT_VAL(*src)); 00749 case TUPLEV: STORE_D_PRINTF("offs[%d]",GET_OFFS(*src)); 00750 case FLOATV: 00751 STORE_D_PRINTF("%d.%06d", 00752 (int)GET_FLT_VAL(p->heap_min,*src), 00753 (int)((GET_FLT_VAL(p->heap_min,*src) - 00754 (int)GET_FLT_VAL(p->heap_min,*src)) * 00755 1000000)); 00756 } 00757 #undef STORE_D_PRINTF 00758 #endif /* CONFIG_IP_SNAP_DEBUG */ 00759 p->sp--; 00760 p->pc++; 00761 break; 00762 } 00763 00764 case JI: { 00765 int jump; 00766 00767 GET_LIT(jump,INTV,*p->pc); 00768 DYNCHECK(jump > 0); 00769 d_printf(10,"%s:%d: pc=%d: JI %d\n",__FILE__,__LINE__, 00770 (p->pc - p->code_min), jump); 00771 p->pc = p->pc + jump; 00772 break; 00773 } 00774 00775 case PAJ: { 00776 value_t *top = p->sp - 1; 00777 int jump; 00778 int lit; 00779 00780 DYNCHECK(top >= p->stack_min); 00781 GET_LIT(lit,INTV,*p->pc); 00782 DYNCHECK_TAG(*top,INTV); 00783 jump = GET_INT(*top); 00784 DYNCHECK(jump + lit > 0); 00785 d_printf(10,"%s:%d: pc=%d: PAJ %d + [%d] = %d\n",__FILE__,__LINE__, 00786 (p->pc - p->code_min),lit,jump,lit+jump); 00787 p->sp--; /* pop */ 00788 p->pc = p->pc + jump + lit; 00789 break; 00790 } 00791 00792 case TPAJ: { 00793 value_t *top1 = p->sp - 1; 00794 value_t *top2 = p->sp - 2; 00795 int jump = 1; 00796 int lit; 00797 00798 DYNCHECK(top2 >= p->stack_min); 00799 DYNCHECK_TAG(*top1,INTV); 00800 if (GET_INT(*top1) == 0) { 00801 GET_LIT(lit,INTV,*p->pc); 00802 DYNCHECK_TAG(*top2,INTV); 00803 jump = GET_INT(*top2); 00804 DYNCHECK(jump + lit > 0); 00805 d_printf(10,"%s:%d: pc=%d: TPAJ %d: top=0, branch %d+[%d]=%d\n", 00806 __FILE__,__LINE__,(p->pc - p->code_min), 00807 lit,lit,jump,jump + lit); 00808 jump += lit; 00809 } else { 00810 d_printf(10,"%s:%d: pc=%d: TPAJ %d: top=%d, falling thru\n", 00811 __FILE__,__LINE__,(p->pc - p->code_min), 00812 GET_LIT_VAL(*p->pc), GET_INT(*top1)); 00813 } 00814 p->sp = p->sp - 2; /* pop */ 00815 p->pc = p->pc + jump; 00816 break; 00817 } 00818 00819 case BEZ: { 00820 value_t *top = p->sp - 1; 00821 int jump = 1; 00822 00823 DYNCHECK(top >= p->stack_min); 00824 DYNCHECK_TAG(*top,INTV); 00825 if (GET_INT(*top) == 0) { 00826 GET_LIT(jump,INTV,*p->pc); 00827 DYNCHECK(jump > 0); 00828 d_printf(10,"%s:%d: pc=%d: BEZ %d: branching ahead\n", 00829 __FILE__,__LINE__,(p->pc - p->code_min),jump); 00830 } else { 00831 d_printf(100,"%s:%d: pc=%d: BEZ %d: falling thru\n", 00832 __FILE__,__LINE__,(p->pc - p->code_min),jump); 00833 } 00834 p->sp--; /* pop */ 00835 p->pc = p->pc + jump; 00836 break; 00837 } 00838 00839 case BNE: { 00840 value_t *top = p->sp - 1; 00841 int jump = 1; 00842 00843 DYNCHECK(top >= p->stack_min); 00844 DYNCHECK_TAG(*top,INTV); 00845 if (GET_INT(*top) != 0) { 00846 GET_LIT(jump,INTV,*p->pc); 00847 DYNCHECK(jump > 0); 00848 d_printf(10,"%s:%d: pc=%d: BNE %d: branching ahead\n", 00849 __FILE__,__LINE__,(p->pc - p->code_min),jump); 00850 } else { 00851 d_printf(10,"%s:%d: pc=%d: BNE %d: falling thru\n", 00852 __FILE__,__LINE__,(p->pc - p->code_min),jump); 00853 } 00854 p->sp--; /* pop */ 00855 p->pc = p->pc + jump; 00856 break; 00857 } 00858 00859 case MKTUP: { 00860 int n, i, hoffset; 00861 value_t *newtop, *heapv, *cp; 00862 heap_obj *ho; 00863 00864 ENSURE_HEAP_ROOM(p,iph); 00865 GET_LIT(n,INTV,*p->pc); 00866 DYNCHECK(n > 0); 00867 /* check for (n-2) trailing non-mktups */ 00868 DYNCHECK((p->pc + ((n-2) > 0 ? (n-2) : 0) < p->code_max)); 00869 #ifndef NDYNCHECK 00870 for(i=1; i<n-1; i++) { 00871 /* check for non-mktup */ 00872 DYNCHECK(GET_OP(p->pc[i]) != MKTUP); 00873 } 00874 #endif 00875 /* check that the initial arguments are on the stack */ 00876 newtop = (p->sp - n); /* where to store the tuple result */ 00877 DYNCHECK(newtop >= p->stack_min); 00878 /* perform the allocation */ 00879 if (!heap_alloc(p,n*sizeof(value_t),1,&ho,&hoffset)) { 00880 /* initialize the tuple entries */ 00881 for (heapv = (value_t *)(&ho->s[0]), cp = p->sp - n, i=0; 00882 i<n; 00883 i++, heapv++, cp++) { 00884 #ifdef CONFIG_IP_SNAP_DEBUG 00885 d_printf(50,"%s:%d: MKTUP copying ",__FILE__,__LINE__); 00886 if (sysctl_snap_debug_level == -1 || 00887 50 <= sysctl_snap_debug_level) { 00888 printk_value(p,cp); 00889 printk(" ( *0x%08x = 0x%08x)\n",(__u32)cp,(unsigned int)(*cp)); 00890 } 00891 #endif 00892 *heapv = *cp; 00893 } 00894 /* store pointer on the stack */ 00895 SET_TAG(*newtop,TUPLEV); 00896 SET_OFFS(*newtop,hoffset); 00897 d_printf(10,"%s:%d: pc=%d: MKTUP %d: new offs[%d] = \n", 00898 __FILE__,__LINE__,(p->pc - p->code_min),n, 00899 GET_OFFS(*newtop)); 00900 p->sp = newtop + 1; 00901 #ifdef CONFIG_IP_SNAP_DEBUG 00902 if (sysctl_snap_debug_level == -1 || 00903 10 <= sysctl_snap_debug_level) { 00904 printk_value(p,p->sp - 1); 00905 printk("\n"); 00906 } 00907 #endif 00908 } 00909 else /* allocation failed, quit */ 00910 return -1; 00911 00912 p->pc++; 00913 break; 00914 } 00915 00916 case NTH: { 00917 value_t *top1 = p->sp - 1; 00918 int n,offs; 00919 heap_obj *ho; 00920 00921 DYNCHECK(top1 >= p->stack_min); 00922 DYNCHECK_TAG(*top1,TUPLEV); 00923 GET_LIT(n,INTV,*p->pc); 00924 DYNCHECK(n > 0); 00925 offs = GET_OFFS(*top1); 00926 ho = (heap_obj *)(p->heap_min + offs); 00927 DYNCHECK_IN_HEAP(ho); 00928 DYNCHECK((ho->len / 4) >= n); 00929 wassert((ho->len / 4) * 4 == ho->len); 00930 *top1 = ((value_t *)&(ho->s[0]))[n-1]; 00931 #ifdef CONFIG_IP_SNAP_DEBUG 00932 d_printf(10,"%s:%d: pc=%d: NTH %d: offs[%d].%d = ", 00933 __FILE__,__LINE__,(p->pc - p->code_min),n,offs,n); 00934 if (sysctl_snap_debug_level == -1 || 00935 10 <= sysctl_snap_debug_level) { 00936 printk_value(p,top1); 00937 printk("\n"); 00938 } 00939 #endif /* CONFIG_IP_SNAP_DEBUG */ 00940 p->pc++; 00941 break; 00942 } 00943 00944 case ISTUP: { /* unlike other ops, does not blow away top stack 00945 value */ 00946 value_t *top = p->sp - 1; 00947 int result; 00948 00949 DYNCHECK(top >= p->stack_min); 00950 result = (GET_TAG(*top) == TUPLEV); 00951 DYNCHECK(p->sp < p->stack_max); 00952 SET_TAG(*p->sp,INTV); 00953 SET_INT(*p->sp,result); 00954 d_printf(10,"%s:%d: pc=%d: ISTUP: %s\n",__FILE__,__LINE__, 00955 (p->pc - p->code_min),(GET_INT(*p->sp)?"yes":"no")); 00956 p->sp++; 00957 p->pc++; 00958 break; 00959 } 00960 00961 case LEN: { 00962 value_t *top = p->sp - 1; 00963 heap_obj *tup; 00964 int offs; 00965 00966 DYNCHECK(top >= p->stack_min); 00967 DYNCHECK_TAG(*top,TUPLEV); 00968 offs = GET_OFFS(*top); 00969 tup = (heap_obj *)(p->heap_min + offs); 00970 DYNCHECK_IN_HEAP(tup); 00971 SET_TAG(*top,INTV); 00972 SET_INT(*top,tup->len / sizeof(value_t)); 00973 d_printf(10,"%s:%d: pc=%d: LEN: |offs[%d]|=%d\n",__FILE__,__LINE__, 00974 (p->pc - p->code_min),offs,GET_INT(*top)); 00975 p->pc++; 00976 break; 00977 } 00978 00979 /* equality/inequality are polymorphic */ 00980 case EQ: EQOP(1,"EQ"); 00981 case NEQ: EQOP(0,"NEQ"); 00982 #ifndef SMALL_INSTRS 00983 case EQI: EQOPI(1,"EQI"); 00984 case NEQI: EQOPI(0,"NEQI"); 00985 /* these could be on floats or on ints */ 00986 case GTI: INTFLOATIMMOPI(>,"GTI"); 00987 case GEQI: INTFLOATIMMOPI(>=,"GEQI"); 00988 case LEQI: INTFLOATIMMOPI(<=,"LEQI"); 00989 case LTI: INTFLOATIMMOPI(<,"LTI"); 00990 case ADDI: INTFLOATIMMOP(+,"ADDI"); 00991 case SUBI: INTFLOATIMMOP(-,"SUBI"); 00992 case MULTI: INTFLOATIMMOP(*,"MULTI"); 00993 case DIVI: INTFLOATIMMOP(/,"DIVI"); 00994 #else 00995 #ifdef CONFIG_IP_SNAP_DEBUG 00996 #define EQOPI_D_PRINTF(opname,fmt1,fmt2,arg...) \ 00997 { d_printf(10,"%s:%d: pc=%d: %s " fmt1 ": eq? " fmt2 " (%s)\n", \ 00998 __FILE__,__LINE__,(p->pc - p->code_min),opname, \ 00999 ##arg,(result?"yes":"no")); \ 01000 break; \ 01001 } 01002 #define EQOPI(res,t,opname) \ 01003 { \ 01004 value_t v = ZERO_VALUE_T; \ 01005 int result; \ 01006 value_t *top = p->sp - 1; \ 01007 \ 01008 ENSURE_STACK_ROOM(p,iph); \ 01009 top = p->sp - 1; \ 01010 DYNCHECK(p->sp < p->stack_max); \ 01011 COPY_LIT(v,t,*p->pc); \ 01012 result = (res == eq_value(top,&v,p)); \ 01013 if (result == -1) \ 01014 return -1; \ 01015 switch(t) { \ 01016 case INTV: \ 01017 switch(GET_TAG(*top)) { \ 01018 case INTV: EQOPI_D_PRINTF(opname,"%d","%d",GET_INT(v),GET_INT(*top)); \ 01019 case ADDRV: EQOPI_D_PRINTF(opname,"%d","%d.%d.%d.%d",GET_INT(v), \ 01020 NIPQUAD(GET_ADDR_VAL(p->heap_min,*top))); \ 01021 case STRV: EQOPI_D_PRINTF(opname,"%d","\"%s\"",GET_INT(v), \ 01022 GET_STR_VAL(p->heap_min,*top)); \ 01023 case EXCV: EQOPI_D_PRINTF(opname,"%d","exc(%d)", \ 01024 GET_INT(v),GET_LIT_VAL(*top)); \ 01025 case TUPLEV: EQOPI_D_PRINTF(opname,"%d","offs[%d]", \ 01026 GET_INT(v),GET_OFFS(*top)); \ 01027 case FLOATV: EQOPI_D_PRINTF(opname,"%d","%d.%06d",GET_INT(v), \ 01028 FLTINTPAIR(GET_FLT_VAL(p->heap_min,*top))); \ 01029 } \ 01030 break; \ 01031 case ADDRV: \ 01032 switch(GET_TAG(*top)) { \ 01033 case INTV: EQOPI_D_PRINTF(opname,"%d.%d.%d.%d","%d",\ 01034 NIPQUAD(GET_ADDR_VAL(p->heap_min,v)),GET_INT(*top)); \ 01035 case ADDRV: EQOPI_D_PRINTF(opname,"%d.%d.%d.%d","%d.%d.%d.%d", \ 01036 NIPQUAD(GET_ADDR_VAL(p->heap_min,v)), \ 01037 NIPQUAD(GET_ADDR_VAL(p->heap_min,*top))); \ 01038 case STRV: EQOPI_D_PRINTF(opname,"%d.%d.%d.%d","\"%s\"", \ 01039 NIPQUAD(GET_ADDR_VAL(p->heap_min,v)), \ 01040 GET_STR_VAL(p->heap_min,*top)); \ 01041 case EXCV: EQOPI_D_PRINTF(opname,"%d.%d.%d.%d","exc(%d)", \ 01042 NIPQUAD(GET_ADDR_VAL(p->heap_min,v)), \ 01043 GET_LIT_VAL(*top)); \ 01044 case TUPLEV: EQOPI_D_PRINTF(opname,"%d.%d.%d.%d","offs[%d]", \ 01045 NIPQUAD(GET_ADDR_VAL(p->heap_min,v)), \ 01046 GET_OFFS(*top)); \ 01047 case FLOATV: EQOPI_D_PRINTF(opname,"%d.%d.%d.%d","%d.%06d", \ 01048 NIPQUAD(GET_ADDR_VAL(p->heap_min,v)), \ 01049 FLTINTPAIR(GET_FLT_VAL(p->heap_min,*top))); \ 01050 } \ 01051 break; \ 01052 case STRV: \ 01053 switch(GET_TAG(*top)) { \ 01054 case INTV: EQOPI_D_PRINTF(opname,"\"%s\"","%d", \ 01055 GET_STR_VAL(p->heap_min,v),GET_INT(*top)); \ 01056 case ADDRV: EQOPI_D_PRINTF(opname,"\"%s\"","%d.%d.%d.%d", \ 01057 GET_STR_VAL(p->heap_min,v), \ 01058 NIPQUAD(GET_ADDR_VAL(p->heap_min,*top))); \ 01059 case STRV: EQOPI_D_PRINTF(opname,"\"%s\"","\"%s\"", \ 01060 GET_STR_VAL(p->heap_min,v), \ 01061 GET_STR_VAL(p->heap_min,*top)); \ 01062 case EXCV: EQOPI_D_PRINTF(opname,"\"%s\"","exc(%d)", \ 01063 GET_STR_VAL(p->heap_min,v), \ 01064 GET_LIT_VAL(*top)); \ 01065 case TUPLEV: EQOPI_D_PRINTF(opname,"\"%s\"","offs[%d]", \ 01066 GET_STR_VAL(p->heap_min,v), \ 01067 GET_OFFS(*top)); \ 01068 case FLOATV: EQOPI_D_PRINTF(opname,"\"%s\"","%d.%06d", \ 01069 GET_STR_VAL(p->heap_min,v), \ 01070 FLTINTPAIR(GET_FLT_VAL(p->heap_min,*top))); \ 01071 } \ 01072 break; \ 01073 case EXCV: \ 01074 switch(GET_TAG(*top)) { \ 01075 case INTV: EQOPI_D_PRINTF(opname,"exc(%d)","%d", \ 01076 GET_INT(v),GET_INT(*top)); \ 01077 case ADDRV: EQOPI_D_PRINTF(opname,"exc(%d)","%d.%d.%d.%d",GET_INT(v), \ 01078 NIPQUAD(GET_ADDR_VAL(p->heap_min,*top))); \ 01079 case STRV: EQOPI_D_PRINTF(opname,"exc(%d)","\"%s\"",GET_INT(v), \ 01080 GET_STR_VAL(p->heap_min,*top)); \ 01081 case EXCV: EQOPI_D_PRINTF(opname,"exc(%d)","exc(%d)", \ 01082 GET_INT(v),GET_LIT_VAL(*top)); \ 01083 case TUPLEV: EQOPI_D_PRINTF(opname,"exc(%d)","offs[%d]", \ 01084 GET_INT(v),GET_OFFS(*top)); \ 01085 case FLOATV: EQOPI_D_PRINTF(opname,"exc(%d)","%d.%06d",GET_INT(v), \ 01086 FLTINTPAIR(GET_FLT_VAL(p->heap_min,*top))); \ 01087 } \ 01088 break; \ 01089 case TUPLEV: \ 01090 switch(GET_TAG(*top)) { \ 01091 case INTV: EQOPI_D_PRINTF(opname,"offs[%d])","%d", \ 01092 GET_OFFS(v),GET_INT(*top)); \ 01093 case ADDRV: EQOPI_D_PRINTF(opname,"offs[%d]","%d.%d.%d.%d",GET_OFFS(v), \ 01094 NIPQUAD(GET_ADDR_VAL(p->heap_min,*top))); \ 01095 case STRV: EQOPI_D_PRINTF(opname,"offs[%d]","\"%s\"",GET_OFFS(v), \ 01096 GET_STR_VAL(p->heap_min,*top)); \ 01097 case EXCV: EQOPI_D_PRINTF(opname,"offs[%d]","exc(%d)", \ 01098 GET_OFFS(v),GET_LIT_VAL(*top)); \ 01099 case TUPLEV: EQOPI_D_PRINTF(opname,"offs[%d]","offs[%d]", \ 01100 GET_OFFS(v),GET_OFFS(*top)); \ 01101 case FLOATV: EQOPI_D_PRINTF(opname,"offs[%d]","%d.%06d",GET_OFFS(v), \ 01102 FLTINTPAIR(GET_FLT_VAL(p->heap_min,*top))); \ 01103 } \ 01104 break; \ 01105 case FLOATV: \ 01106 switch(GET_TAG(*top)) { \ 01107 case INTV: EQOPI_D_PRINTF(opname,"%d.%06d","%d", \ 01108 FLTINTPAIR(GET_FLT_VAL(p->heap_min,v)), \ 01109 GET_INT(*top)); \ 01110 case ADDRV: EQOPI_D_PRINTF(opname,"%d.%06d","%d.%d.%d.%d", \ 01111 FLTINTPAIR(GET_FLT_VAL(p->heap_min,v)), \ 01112 NIPQUAD(GET_ADDR_VAL(p->heap_min,*top))); \ 01113 case STRV: EQOPI_D_PRINTF(opname,"%d.%06d","\"%s\"", \ 01114 FLTINTPAIR(GET_FLT_VAL(p->heap_min,v)), \ 01115 GET_STR_VAL(p->heap_min,*top)); \ 01116 case EXCV: EQOPI_D_PRINTF(opname,"%d.%06d","exc(%d)", \ 01117 FLTINTPAIR(GET_FLT_VAL(p->heap_min,v)), \ 01118 GET_LIT_VAL(*top)); \ 01119 case TUPLEV: EQOPI_D_PRINTF(opname,"%d.%06d","offs[%d]", \ 01120 FLTINTPAIR(GET_FLT_VAL(p->heap_min,v)), \ 01121 GET_OFFS(*top)); \ 01122 case FLOATV: EQOPI_D_PRINTF(opname,"%d.%06d","%d.%06d", \ 01123 FLTINTPAIR(GET_FLT_VAL(p->heap_min,v)), \ 01124 FLTINTPAIR(GET_FLT_VAL(p->heap_min,*top))); \ 01125 } \ 01126 break; \ 01127 } \ 01128 SET_TAG(*top,INTV); \ 01129 SET_INT(*top,result); \ 01130 p->pc++; \ 01131 break; \ 01132 } 01133 #else 01134 #define EQOPI(res,t,opname) \ 01135 { \ 01136 value_t v = ZERO_VALUE_T; \ 01137 int result; \ 01138 value_t *top = p->sp - 1; \ 01139 \ 01140 d_printf(100,"%s:%d: interp: %s\n",__FILE__,__LINE__, \ 01141 opname); \ 01142 ENSURE_STACK_ROOM(p,iph); \ 01143 top = p->sp - 1; \ 01144 DYNCHECK(p->sp < p->stack_max); \ 01145 COPY_LIT(v,t,*p->pc); \ 01146 result = (res == eq_value(top,&v,p)); \ 01147 if (result == -1) \ 01148 return -1; \ 01149 SET_TAG(*top,INTV); \ 01150 SET_INT(*top,result); \ 01151 p->pc++; \ 01152 break; \ 01153 } 01154 #define EQOPI_D_PRINTF(fmt,arg...) /**/ 01155 #endif 01156 case EQINT: EQOPI(1,INTV,"EQINT"); 01157 case EQADR: EQOPI(1,ADDRV,"EQADR"); 01158 case EQTUP: EQOPI(1,TUPLEV,"EQTUP"); 01159 case EQEXC: EQOPI(1,EXCV,"EQEXC"); 01160 case EQSTR: EQOPI(1,STRV,"EQSTR"); 01161 case EQFLT: EQOPI(1,FLOATV,"EQFLT"); 01162 01163 case NQINT: EQOPI(0,INTV,"NQINT"); 01164 case NQADR: EQOPI(0,ADDRV,"NQADR"); 01165 case NQTUP: EQOPI(0,TUPLEV,"NQTUP"); 01166 case NQEXC: EQOPI(0,EXCV,"NQEXC"); 01167 case NQSTR: EQOPI(0,STRV,"NQSTR"); 01168 case NQFLT: EQOPI(0,FLOATV,"EQFLT"); 01169 01170 /* floating point ops */ 01171 case FGTI: FLOATIMMOPI(>,"GTI"); 01172 case FGEQI: FLOATIMMOPI(>=,"GEQI"); 01173 case FLEQI: FLOATIMMOPI(<=,"LEQI"); 01174 case FLTI: FLOATIMMOPI(<,"LTI"); 01175 case FADDI: FLOATIMMOP(+,"ADDI"); 01176 case FSUBI: FLOATIMMOP(-,"SUBI"); 01177 case FMULI: FLOATIMMOP(*,"MULTI"); 01178 case FDIVI: FLOATIMMOP(/,"DIVI"); 01179 01180 /* integer ops */ 01181 case GTI: INTIMMOP(int,>,"GTI"); 01182 case GEQI: INTIMMOP(int,>=,"GEQI"); 01183 case LEQI: INTIMMOP(int,<=,"LEQI"); 01184 case LTI: INTIMMOP(int,<,"LTI"); 01185 case ADDI: INTIMMOP(int,+,"ADDI"); 01186 case SUBI: INTIMMOP(int,-,"SUBI"); 01187 case MULTI: INTIMMOP(int,*,"MULTI"); 01188 case DIVI: INTIMMOP(int,/,"DIVI"); 01189 #undef EQOPI_D_PRINTF 01190 #endif 01191 01192 /* integer and/or floating point relational and arithmetic operators */ 01193 case GT: INTFLOATOPI(>,"GT"); 01194 case GEQ: INTFLOATOPI(>=,"GEQ"); 01195 case LEQ: INTFLOATOPI(<=,"LEQ"); 01196 case LT: INTFLOATOPI(<,"LT"); 01197 case ADD: INTFLOATOP(+,"ADD"); 01198 case SUB: INTFLOATOP(-,"SUB"); 01199 case MULT: INTFLOATOP(*,"MULT"); 01200 case DIV: INTFLOATOP(/,"DIV"); 01201 01202 case NEG: { 01203 value_t *top = p->sp - 1; 01204 01205 DYNCHECK(top >= p->stack_min); 01206 if (GET_TAG(*top) == INTV) { 01207 int result; 01208 result = -(GET_INT(*top)); 01209 d_printf(10,"%s:%d: pc=%d: NEG: %d -> %d\n",__FILE__,__LINE__, 01210 (p->pc - p->code_min),GET_INT(*top),result); 01211 SET_TAG(*top,INTV); 01212 SET_INT(*top,result); 01213 } else { 01214 float32 v, result; 01215 ENSURE_HEAP_ROOM(p,iph); 01216 top = p->sp - 1; 01217 DYNCHECK_TAG(*top,FLOATV); 01218 GET_FLOAT(v,p->heap_min,*top); 01219 result = -v; 01220 d_printf(10,"%s:%d: pc=%d: NEG: %d.%06d -> %d.%06d\n", 01221 __FILE__,__LINE__,(p->pc - p->code_min), 01222 FLTINTPAIR(GET_FLT_VAL(p->heap_min,*top)), 01223 FLTINTPAIR(result)); 01224 SET_TAG(*top,FLOATV); 01225 SET_FLOAT(*top,result,p); 01226 } 01227 p->pc++; 01228 break; 01229 } 01230 01231 /* integer arithmetic operators */ 01232 case MOD: INTOP(int,%,"MOD"); 01233 case MODI: INTIMMOP(int,%,"MODI"); 01234 case XOR: INTOP(int,^,"XOR"); 01235 case XORI: INTIMMOP(int,^,"XORI"); 01236 01237 case NOT: { 01238 value_t *top = p->sp - 1; 01239 int result; 01240 01241 DYNCHECK(top >= p->stack_min); 01242 DYNCHECK_TAG(*top,INTV); 01243 result = !(GET_INT(*top)); 01244 d_printf(10,"%s:%d: pc=%d: NOT: %d -> %d\n",__FILE__,__LINE__, 01245 (p->pc - p->code_min),GET_INT(*top),result); 01246 SET_TAG(*top,INTV); 01247 SET_INT(*top,result); 01248 p->pc++; 01249 break; 01250 } 01251 01252 case LNOT: { 01253 value_t *top = p->sp - 1; 01254 int result; 01255 01256 DYNCHECK(top >= p->stack_min); 01257 DYNCHECK_TAG(*top,INTV); 01258 result = ~(GET_INT(*top)); 01259 d_printf(10,"%s:%d: pc=%d: LNOT: 0x%x -> 0x%x\n",__FILE__,__LINE__, 01260 (p->pc - p->code_min),GET_INT(*top),result); 01261 SET_TAG(*top,INTV); 01262 SET_INT(*top,result); 01263 p->pc++; 01264 break; 01265 } 01266 01267 case AND: INTOP(int,&,"AND"); 01268 case ANDI: INTIMMOP(int,&,"ANDI"); 01269 case OR: INTOP(int,|,"OR"); 01270 case ORI: INTIMMOP(int,|,"ORI"); 01271 case LSHL: INTOP(int,<<,"LSHL"); 01272 case LSHLI: INTIMMOP(int,<<,"LSHLI"); 01273 case RSHL: INTOP(uint32,>>,"RSHL"); 01274 case RSHLI: INTIMMOP(uint32,>>,"RSHLI"); 01275 case RSHA: INTOP(int,>>,"RSHA"); 01276 case RSHAI: INTIMMOP(int,>>,"RSHAI"); 01277 01278 case SNET: { 01279 value_t *top1 = p->sp - 1; 01280 value_t *top2 = p->sp - 2; 01281 uint32 result, a1, a2; 01282 01283 d_printf(100,"%s:%d: interp: SNET\n",__FILE__,__LINE__); 01284 ENSURE_HEAP_ROOM(p,iph); 01285 top1 = p->sp - 1; 01286 top2 = p->sp - 2; 01287 DYNCHECK(top2 >= p->stack_min); 01288 DYNCHECK_TAG(*top1,ADDRV); 01289 DYNCHECK_TAG(*top2,ADDRV); 01290 GET_ADDR(a1,p->heap_min,*top1); 01291 GET_ADDR(a2,p->heap_min,*top2); 01292 result = a1 & a2; 01293 d_printf(10,"%s:%d: pc=%d: SNET %d.%d.%d.%d %d.%d.%d.%d = %d.%d.%d.%d\n", 01294 __FILE__,__LINE__,(p->pc - p->code_min), 01295 NIPQUAD(GET_ADDR_VAL(p->heap_min,*top1)), 01296 NIPQUAD(GET_ADDR_VAL(p->heap_min,*top2)), 01297 NIPQUAD(result)); 01298 SET_TAG(*top2,ADDRV); 01299 SET_ADDR(*top2,result,p); 01300 p->sp--; 01301 p->pc++; 01302 break; 01303 } 01304 01305 case SNETI: { 01306 value_t *top = p->sp - 1; 01307 uint32 a1, a2, result; 01308 01309 ENSURE_HEAP_ROOM(p,iph); 01310 top = p->sp - 1; 01311 DYNCHECK(top >= p->stack_min); 01312 DYNCHECK_TAG(*top,ADDRV); 01313 #ifndef ADDR_IN_HEAP 01314 DYNCHECK_TAG(p->pc->arg,ADDRV); 01315 GET_ADDR(a1 01316 GET_ADDR(a2,p->heap_min,p->pc->arg); 01317 #else 01318 { 01319 value_t v = ZERO_VALUE_T; 01320 COPY_LIT(v,ADDRV,*p->pc); 01321 GET_ADDR(a2,p->heap_min,v); 01322 } 01323 #endif 01324 GET_ADDR(a1,p->heap_min,*top); 01325 result = a1 & a2; 01326 d_printf(10,"%s:%d: pc=%d: SNETI [%d.%d.%d.%d] %d.%d.%d.%d = %d.%d.%d.%d\n", 01327 __FILE__,__LINE__,(p->pc - p->code_min), 01328 NIPQUAD(a1), 01329 NIPQUAD(a2), 01330 NIPQUAD(result)); 01331 SET_TAG(*top,ADDRV); 01332 SET_ADDR(*top,result,p); 01333 p->pc++; 01334 break; 01335 } 01336 01337 case BCAST: { 01338 value_t *top1 = p->sp - 1; 01339 value_t *top2 = p->sp - 2; 01340 uint32 a1, a2, result; 01341 01342 d_printf(100,"%s:%d: interp: BCAST\n",__FILE__,__LINE__); 01343 ENSURE_HEAP_ROOM(p,iph); 01344 top1 = p->sp - 1; 01345 top2 = p->sp - 2; 01346 DYNCHECK(top2 >= p->stack_min); 01347 DYNCHECK_TAG(*top1,ADDRV); 01348 DYNCHECK_TAG(*top2,ADDRV); 01349 GET_ADDR(a1,p->heap_min,*top1); 01350 GET_ADDR(a2,p->heap_min,*top2); 01351 result = a1 | ~a2; 01352 d_printf(10,"%s:%d: pc=%d: BCAST %d.%d.%d.%d %d.%d.%d.%d = %d.%d.%d.%d\n", 01353 __FILE__,__LINE__,(p->pc - p->code_min), 01354 NIPQUAD(a1), 01355 NIPQUAD(a2), 01356 NIPQUAD(result)); 01357 SET_TAG(*top2,ADDRV); 01358 SET_ADDR(*top2,result,p); 01359 p->sp--; 01360 p->pc++; 01361 break; 01362 } 01363 01364 case BCASTI: { 01365 value_t *top = p->sp - 1; 01366 uint32 a1, a2, result; 01367 01368 ENSURE_HEAP_ROOM(p,iph); 01369 top = p->sp - 1; 01370 DYNCHECK(top >= p->stack_min); 01371 DYNCHECK_TAG(*top,ADDRV); 01372 #ifndef ADDR_IN_HEAP 01373 DYNCHECK_TAG(p->pc->arg,ADDRV); 01374 GET_ADDR(a2,p->heap_min,p->pc->arg); 01375 #else 01376 { 01377 value_t v = ZERO_VALUE_T; 01378 COPY_LIT(v,ADDRV,*p->pc); 01379 GET_ADDR(a2,p->heap_min,v); 01380 } 01381 #endif 01382 GET_ADDR(a1,p->heap_min,*top); 01383 result = a1 | ~a2; 01384 d_printf(10,"%s:%d: pc=%d: BCASTI [%d.%d.%d.%d] %d.%d.%d.%d = %d.%d.%d.%d\n", 01385 __FILE__,__LINE__,(p->pc - p->code_min), 01386 NIPQUAD(a1), 01387 NIPQUAD(a2), 01388 NIPQUAD(result)); 01389 SET_TAG(*top,ADDRV); 01390 SET_ADDR(*top,result,p); 01391 p->pc++; 01392 break; 01393 } 01394 01395 case ISX: { /* unlike other ops, does not blow away top stack 01396 value */ 01397 value_t *top = p->sp - 1; 01398 int result; 01399 01400 ENSURE_STACK_ROOM(p,iph); 01401 top = p->sp - 1; 01402 DYNCHECK(top >= p->stack_min); 01403 result = (GET_TAG(*top) == EXCV); 01404 DYNCHECK(p->sp < p->stack_max); 01405 d_printf(10,"%s:%d: pc=%d: ISX: (%s)\n",__FILE__,__LINE__, 01406 (p->pc - p->code_min),(result?"yes":"no")); 01407 SET_TAG(*p->sp,INTV); 01408 SET_INT(*p->sp,result); 01409 p->sp++; 01410 p->pc++; 01411 break; 01412 } 01413 01414 case GETRB: { 01415 ENSURE_STACK_ROOM(p,iph); 01416 DYNCHECK(p->sp < p->stack_max); 01417 SET_TAG(*p->sp,INTV); 01418 SET_INT(*p->sp, p->rb); 01419 d_printf(10,"%s:%d: pc=%d: GETRB = %d\n",__FILE__,__LINE__, 01420 (p->pc - p->code_min),p->rb); 01421 p->sp++; 01422 p->pc++; 01423 break; 01424 } 01425 01426 case GETSRC: { 01427 ENSURE_HEAP_ROOM(p,iph); 01428 DYNCHECK(p->sp < p->stack_max); 01429 SET_TAG(*p->sp,ADDRV); 01430 SET_ADDR(*p->sp,p->hdr->saddr,p); 01431 d_printf(10,"%s:%d: pc=%d: GETSRC = %d.%d.%d.%d\n", 01432 __FILE__,__LINE__,(p->pc - p->code_min), 01433 NIPQUAD(p->iph->saddr)); 01434 p->sp++; 01435 p->pc++; 01436 break; 01437 } 01438 01439 case GETDST: { 01440 ENSURE_HEAP_ROOM(p,iph); 01441 DYNCHECK(p->sp < p->stack_max); 01442 SET_TAG(*p->sp,ADDRV); 01443 SET_ADDR(*p->sp,p->hdr->daddr,p); 01444 d_printf(10,"%s:%d: pc=%d: GETDST = %d.%d.%d.%d\n", 01445 __FILE__,__LINE__,(p->pc - p->code_min), 01446 NIPQUAD(p->hdr->daddr)); 01447 p->sp++; 01448 p->pc++; 01449 break; 01450 } 01451 01452 case GETSPT: { 01453 ENSURE_STACK_ROOM(p,iph); 01454 DYNCHECK(p->sp < p->stack_max); 01455 SET_TAG(*p->sp,INTV); 01456 SET_INT(*p->sp,ntohs(p->hdr->sport)); 01457 d_printf(10,"%s:%d: pc=%d: GETSPT = %d\n",__FILE__,__LINE__, 01458 (p->pc - p->code_min),GET_INT(*p->sp)); 01459 p->sp++; 01460 p->pc++; 01461 break; 01462 } 01463 01464 #if 0 01465 case GETLD: { 01466 01467 #define LOAD_INT(x) ((x) >> FSHIFT) 01468 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) 01469 01470 int loadint = avenrun[0] + (FIXED_1/200); 01471 float loadavg = LOAD_INT(loadint) + (LOAD_FRAC(loadint) / 100.0); 01472 01473 ENSURE_HEAP_ROOM(p,iph); 01474 DYNCHECK(p->sp < p->stack_max); 01475 d_printf(10,"%s:%d: pc=%d: GETLD = loadavg is %d.%0d\n", 01476 __FILE__,__LINE__,(p->pc - p->code_min), 01477 LOAD_INT(loadint),LOAD_FRAC(loadint)); 01478 SET_TAG(*p->sp,FLOATV); 01479 SET_FLOAT(*p->sp,loadavg,p); 01480 p->sp++; 01481 p->pc++; 01482 break; 01483 #undef LOAD_INT 01484 #undef LOAD_FRAC 01485 } 01486 #endif 01487 01488 case SETXH: { 01489 value_t *top = p->sp - 1; 01490 int newhandler_offs = -1; 01491 instr_t *newhandler; 01492 01493 DYNCHECK(top >= p->stack_min); 01494 DYNCHECK_TAG(*top,INTV); 01495 newhandler_offs = GET_INT(*top); 01496 newhandler = p->code_min + newhandler_offs; 01497 01498 /* now check that handler falls within bounds */ 01499 DYNCHECK(newhandler > p->pc); 01500 DYNCHECK(newhandler <= p->code_max); 01501 p->handler = newhandler; 01502 d_printf(10,"%s:%d: pc=%d: SETXH = new handler at pc=%d\n", 01503 __FILE__,__LINE__,(p->pc - p->code_min), 01504 newhandler_offs); 01505 p->sp--; /* pop */ 01506 p->pc++; 01507 break; 01508 } 01509 01510 case RAISEX: { 01511 /* all control transfers must go forward */ 01512 DYNCHECK(p->handler > p->pc); 01513 p->pc = p->handler; 01514 d_printf(10,"%s:%d: pc=%d: RAISEX = throwing to pc=%d\n", 01515 __FILE__,__LINE__,(p->pc - p->code_min), 01516 (p->handler - p->code_min)); 01517 break; 01518 } 01519 01520 case HERE: { 01521 __u32 myaddr; 01522 01523 ENSURE_HEAP_ROOM(p,iph); 01524 DYNCHECK(p->sp < p->stack_max); 01525 SET_TAG(*p->sp,ADDRV); 01526 if (snap_here(&myaddr, p)) { 01527 warn("%s:%d: HERE failed!\n",__FILE__,__LINE__); 01528 return -1; 01529 } 01530 SET_ADDR(*p->sp,myaddr,p); 01531 d_printf(10,"%s:%d: pc=%d: HERE = %d.%d.%d.%d\n",__FILE__,__LINE__, 01532 (p->pc - p->code_min),NIPQUAD(GET_ADDR_VAL(p->heap_min, 01533 *p->sp))); 01534 p->sp++; 01535 p->pc++; 01536 break; 01537 } 01538 01539 case ISHERE: { 01540 value_t *top = p->sp - 1; 01541 uint32 addr; 01542 int result; 01543 01544 DYNCHECK(top >= p->stack_min); 01545 DYNCHECK_TAG(*top,ADDRV); 01546 GET_ADDR(addr,p->heap_min,*top); 01547 print_timer(1,"interp_packet"); 01548 #ifdef __KERNEL__ 01549 result = ishere(addr,p->skb); 01550 #else 01551 result = ishere(addr,p); 01552 #endif /* __KERNEL__ */ 01553 print_anti_timer(1,"interp_packet"); 01554 d_printf(10,"%s:%d: pc=%d: ISHERE [%d.%d.%d.%d]: (%s)\n", 01555 __FILE__,__LINE__,(p->pc - p->code_min), 01556 NIPQUAD(GET_ADDR_VAL(p->heap_min,*top)), 01557 (result?"yes":"no")); 01558 SET_TAG(*top,INTV); 01559 SET_INT(*top,result); 01560 p->pc++; 01561 break; 01562 } 01563 01564 case ROUTE: { 01565 value_t *top = p->sp - 1; 01566 uint32 *ret,addr; 01567 #ifdef __KERNEL__ 01568 struct rtable *rt; 01569 #endif 01570 __u32 hop = 0; 01571 01572 ENSURE_HEAP_ROOM(p,iph); 01573 top = p->sp - 1; 01574 DYNCHECK(top >= p->stack_min); 01575 DYNCHECK_TAG(*top,ADDRV); 01576 GET_ADDR(addr,p->heap_min,*top); 01577 print_timer(1,"interp_packet"); 01578 01579 #ifdef __KERNEL__ 01580 if (next_hop(&rt,addr,p->skb->nh.iph->tos)) { 01581 #else 01582 if (next_hop(&hop,addr,p->iph->tos)) { 01583 #endif 01584 /* no route found */ 01585 hop = 0; 01586 ret = &hop; 01587 } else { 01588 ret = &hop; 01589 } 01590 01591 print_anti_timer(1,"interp_packet"); 01592 DYNCHECK(ret != NULL); 01593 if (*ret != 0) { 01594 d_printf(10,"%s:%d: pc=%d: ROUTE [%d.%d.%d.%d] = %d.%d.%d.%d\n", 01595 __FILE__,__LINE__,(p->pc - p->code_min), 01596 NIPQUAD(GET_ADDR_VAL(p->heap_min,*top)), 01597 NIPQUAD(*ret)); 01598 SET_TAG(*top,ADDRV); 01599 SET_ADDR(*top,*ret,p); 01600 } 01601 else { 01602 d_printf(10,"%s:%d: pc=%d: ROUTE [%d.%d.%d.%d] -> E_NO_ROUTE!!!\n", 01603 __FILE__,__LINE__,(p->pc - p->code_min), 01604 NIPQUAD(GET_ADDR_VAL(p->heap_min,*top))); 01605 SET_TAG(*top,EXCV); 01606 SET_INT(*top,E_NO_ROUTE); 01607 } 01608 p->pc++; 01609 break; 01610 } 01611 01612 case RTDEV: { 01613 value_t *top = p->sp - 1; 01614 int err; 01615 uint32 addr; 01616 __u32 hop; 01617 int hop_out_if; 01618 01619 ENSURE_HEAP_ROOM(p,iph); 01620 top = p->sp - 1; 01621 DYNCHECK(top >= p->stack_min); 01622 DYNCHECK(p->sp < p->stack_max); 01623 DYNCHECK_TAG(*top,ADDRV); 01624 GET_ADDR(addr,p->heap_min,*top); 01625 01626 err = next_hop_and_dev(&hop,&hop_out_if,addr); 01627 01628 if (err == 0) { 01629 d_printf(10,"%s:%d: pc=%d: RTDEV [%d.%d.%d.%d] = (%d.%d.%d.%d,%d)\n", 01630 __FILE__,__LINE__,(p->pc - p->code_min), 01631 NIPQUAD(GET_ADDR_VAL(p->heap_min,*top)), 01632 NIPQUAD(hop), hop_out_if); 01633 SET_TAG(*top,ADDRV); 01634 SET_ADDR(*top,hop,p); 01635 SET_TAG(*p->sp,INTV); 01636 SET_INT(*p->sp,hop_out_if); 01637 p->sp++; 01638 } else { 01639 d_printf(10,"%s:%d: pc=%d: RTDEV [%d.%d.%d.%d] -> E_NO_ROUTE!!!\n", 01640 __FILE__,__LINE__,(p->pc - p->code_min), 01641 NIPQUAD(GET_ADDR_VAL(p->heap_min,*top))); 01642 SET_TAG(*top,EXCV); 01643 SET_INT(*top,E_NO_ROUTE); 01644 } 01645 p->pc++; 01646 break; 01647 } 01648 01649 case SEND: 01650 case DSEND: { 01651 value_t *top1 = p->sp - 1; /* dest addr */ 01652 value_t *top2 = p->sp - 2; /* RB to use */ 01653 value_t *top3 = p->sp - 3; /* stack amount */ 01654 value_t *top4 = p->sp - 4; /* entry point */ 01655 01656 int child_rb_arg; 01657 int st_amt; 01658 int ep; 01659 unsigned char child_ttl; 01660 __u32 dest; 01661 packet_t *pdup; 01662 01663 DYNCHECK(top4 >= p->stack_min); 01664 DYNCHECK_TAG(*top1,ADDRV); 01665 GET_ADDR(dest,p->heap_min,*top1); 01666 DYNCHECK_TAG(*top2,INTV); 01667 child_rb_arg = GET_INT(*top2); 01668 DYNCHECK(child_rb_arg > 0); 01669 DYNCHECK(child_rb_arg <= p->rb); 01670 child_ttl = (unsigned char)child_rb_arg; 01671 DYNCHECK_TAG(*top3,INTV); 01672 st_amt = GET_INT(*top3); 01673 DYNCHECK_TAG(*top4,INTV); 01674 ep = GET_INT(*top4); 01675 DYNCHECK(ep >= 0); 01676 p->sp -= 4; 01677 pdup = pkt_dup(p); 01678 /* if (pdup == NULL) { */ 01679 /* warn("%s:%d: failed on pdup\n",__FILE__,__LINE__); */ 01680 /* return -1; */ 01681 /* } */ 01682 /* pdup->skb->nh.iph->daddr = dest; */ 01683 /* pdup->skb->nh.iph->ttl = child_ttl; */ 01684 /* pdup->hdr->entry_point = htons(ep); */ 01685 d_printf(10,"%s:%d: pc=%d: SEND [%d.%d.%d.%d] rb=%d ep=%d sa=%d\n", 01686 __FILE__,__LINE__,(p->pc - p->code_min), 01687 NIPQUAD(dest),child_ttl,ep,st_amt); 01688 DYNCHECK(child_ttl > 0); /* ok to do dyncheck here because 01689 packet will just get dropped anyway 01690 */ 01691 /* send the request. the last parameter distinguishes between SEND and DSEND */ 01692 if (snap_send_packet(p, 01693 (st_amt == -1) ? 01694 (p->sp - p->stack_min) : 01695 st_amt, 01696 dest, child_ttl, ep, GET_OP(*p->pc) == SEND ? 0 : 1)) { 01697 warn("%s:%d: SEND or DSEND snap_send_packet failed\n", 01698 __FILE__,__LINE__); 01699 return -1; 01700 } 01701 p->rb -= child_ttl; 01702 p->pc++; 01703 break; 01704 } 01705 01706 #undef OLDSEND 01707 #ifdef OLDSEND 01708 case SEND: { 01709 value_t *top1 = p->sp - 1; /* dest addr */ 01710 value_t *top2 = p->sp - 2; /* RB to use */ 01711 value_t *top3 = p->sp - 3; /* stack amount */ 01712 value_t *top4 = p->sp - 4; /* entry point */ 01713 uint32 dest; 01714 int intrb; 01715 01716 DYNCHECK(top4 >= p->stack_min); 01717 DYNCHECK_TAG(*top1,ADDRV); 01718 GET_ADDR(dest,p->heap_min,*top1); 01719 DYNCHECK_TAG(*top2,INTV); 01720 intrb = GET_INT(*top2); 01721 p->sp -= 3; /* pop; leave room for return value */ 01722 01723 if (intrb > 0) { 01724 if (intrb <= p->rb) { 01725 uint32 dstcache; 01726 unsigned char rb = (unsigned char)intrb; 01727 unsigned char rb_cache; 01728 int ep,st_amt; 01729 01730 DYNCHECK_TAG(*top3,INTV); 01731 st_amt = GET_INT(*top3); 01732 DYNCHECK_TAG(*top4,INTV); 01733 ep = GET_INT(*top4); 01734 dstcache = p->hdr->daddr; 01735 rb_cache = p->rb; 01736 iph->daddr = dest; 01737 /* iph->ttl = rb; */ 01738 /* p->hdr->entry_point = htons(ep); */ 01739 p->sp--; 01740 d_printf(50,"%s:%d: SEND about to call snap_send_packet()\n", 01741 __FILE__,__LINE__); 01742 snap_send_packet(p, (st_amt == -1) ? (p->sp - p->stack_min) : st_amt, dest); 01743 d_printf(150,"%s:%d: back from snap_send_packet\n", 01744 __FILE__,__LINE__); 01745 print_anti_timer(1,"interp_packet"); 01746 p->sp++; 01747 /* iph->daddr = dstcache; */ 01748 /* iph->ttl = (rb_cache - rb); */ 01749 d_printf(10,"%s:%d: pc=%d: SEND %u.%u.%u.%u rb=%d st=%d ep=%d\n", 01750 __FILE__,__LINE__,(p->pc - p->code_min), 01751 NIPQUAD(dest),rb,st_amt,ep); 01752 SET_TAG(*top4,INTV); 01753 SET_INT(*top4,0); 01754 done = 1; 01755 } 01756 /* not enough resource bound */ 01757 else { 01758 d_printf(10,"%s:%d: pc=%d: SEND %d.%d.%d.%d rb=%d st=%d ep=%d (NOT ENOUGH RB!!!)\n", 01759 __FILE__,__LINE__,(p->pc - p->code_min), 01760 NIPQUAD(dest),intrb,GET_INT(*top3),GET_INT(*top4)); 01761 SET_TAG(*top4,EXCV); 01762 SET_INT(*top4,E_NOT_ENOUGH_RB); 01763 } 01764 } 01765 /* non-positive resource bound */ 01766 else { 01767 d_printf(10,"%s:%d: pc=%d: SEND %d.%d.%d.%d rb=%d st=%d ep=%d (NON-POSITIVE RB!!!)\n", 01768 __FILE__,__LINE__,(p->pc - p->code_min), 01769 NIPQUAD(dest),intrb,GET_INT(*top3),GET_INT(*top4)); 01770 SET_TAG(*top4,EXCV); 01771 SET_INT(*top4,E_NON_POSITIVE_RB); 01772 } 01773 p->pc++; 01774 break; 01775 } 01776 #endif /* OLDSEND */ 01777 01778 case HOP: { 01779 value_t *top1 = p->sp - 1; /* dest addr */ 01780 value_t *top2 = p->sp - 2; /* RB to use */ 01781 value_t *top3 = p->sp - 3; /* stack amount (-1 = whole stack) */ 01782 value_t *top4 = p->sp - 4; /* entry point */ 01783 uint32 dest; 01784 int rb; 01785 01786 DYNCHECK(top4 >= p->stack_min); 01787 DYNCHECK_TAG(*top1,ADDRV); 01788 GET_ADDR(dest,p->heap_min,*top1); 01789 DYNCHECK_TAG(*top2,INTV); 01790 rb = GET_INT(*top2); 01791 p->sp -= 3; /* pop; leave room for return value */ 01792 01793 if (rb > 0) { 01794 if (rb <= p->rb) { 01795 short rb_cache; 01796 int ep,st_amt; 01797 01798 DYNCHECK_TAG(*top3,INTV); 01799 st_amt = GET_INT(*top3); 01800 DYNCHECK_TAG(*top4,INTV); 01801 ep = GET_INT(*top4); 01802 01803 rb_cache = p->rb; 01804 p->hdr->entry_point = htons(ep); 01805 p->rb = rb; 01806 p->sp--; 01807 print_timer(1,"interp_packet"); 01808 snap_send_packet(p,st_amt,dest,rb,ep, 0); 01809 print_anti_timer(1,"interp_packet"); 01810 p->sp++; 01811 p->rb = rb_cache - rb; 01812 d_printf(10,"%s:%d: pc=%d: HOP %d.%d.%d.%d rb=%d st=%d ep=%d\n", 01813 __FILE__,__LINE__,(p->pc - p->code_min), 01814 NIPQUAD(dest), rb, st_amt, ep); 01815 SET_TAG(*top4,INTV); 01816 SET_INT(*top4,0); 01817 } 01818 /* not enough resource bound */ 01819 else { 01820 d_printf(10,"%s:%d: pc=%d: HOP %d.%d.%d.%d rb=%d st=%d ep=%d (NOT ENOUGH RB!!!)\n", 01821 __FILE__,__LINE__,(p->pc - p->code_min), 01822 NIPQUAD(dest), rb, GET_INT(*top3), GET_INT(*top4)); 01823 SET_TAG(*top4,EXCV); 01824 SET_INT(*top4,E_NOT_ENOUGH_RB); 01825 } 01826 } 01827 /* non-positive resource bound */ 01828 else { 01829 d_printf(10,"%s:%d: pc=%d: HOP %d.%d.%d.%d rb=%d st=%d ep=%d (NON-POSITIVE RB!!!)\n", 01830 __FILE__,__LINE__,(p->pc - p->code_min), 01831 NIPQUAD(dest), rb, GET_INT(*top3),GET_INT(*top4)); 01832 SET_TAG(*top4,EXCV); 01833 SET_INT(*top4,E_NON_POSITIVE_RB); 01834 } 01835 p->pc++; 01836 break; 01837 } 01838 01839 01840 01841 case FORW: 01842 case DFORW: { 01843 int herep; 01844 01845 print_timer(1,"interp_packet"); 01846 herep = ishere(p->hdr->daddr, p); 01847 print_anti_timer(1,"interp_packet"); 01848 if (herep) { 01849 d_printf(10,"%s:%d: pc=%d: FORW: at dest, falling thru\n", 01850 __FILE__,__LINE__,(p->pc - p->code_min)); 01851 } else { 01852 d_printf(10,"%s:%d: pc=%d: FORW: moving on\n", 01853 __FILE__,__LINE__,(p->pc - p->code_min)); 01854 DYNCHECK(p->rb > 0); /* OK to do dyncheck here 01855 because packet will just 01856 get dropped anyway */ 01857 print_timer(1,"interp_packet"); 01858 01859 /* send the request. the last parameter distinguishes between FORW and DFORW */ 01860 if (snap_send_packet(p, p->sp - p->stack_min, p->hdr->daddr, 01861 p->rb, ntohs(p->hdr->entry_point), GET_OP(*p->pc) == FORW ? 0 : 1)) { 01862 warn("%s:%d: snap_send_packet failed\n", 01863 __FILE__,__LINE__); 01864 return -1; 01865 } 01866 print_anti_timer(1,"interp_packet"); 01867 p->rb = 0; 01868 done = 1; 01869 } 01870 p->pc++; 01871 break; 01872 } 01873 01874 case FORWTO: 01875 case DFORWTO: { 01876 value_t *top = p->sp - 1; 01877 uint32_t dest; 01878 int herep; 01879 01880 DYNCHECK(top >= p->stack_min); 01881 DYNCHECK_TAG(*top,ADDRV); 01882 GET_ADDR(dest,p->heap_min,*top); 01883 p->sp--; 01884 print_timer(1,"interp_packet"); 01885 herep = ishere(dest,p); 01886 print_anti_timer(1,"interp_packet"); 01887 if (!herep) { 01888 d_printf(10,"%s:%d: pc=%d: FORWTO [%u.%u.%u.%u]: moving on\n", 01889 __FILE__,__LINE__,(p->pc - p->code_min), NIPQUAD(dest)); 01890 print_timer(1,"interp_packet"); 01891 DYNCHECK(p->rb > 0); /* OK to do dyncheck here 01892 because packet will just 01893 get dropped anyway */ 01894 print_timer(1,"interp_packet"); 01895 01896 /* send the request. the last parameter distinguishes between FORWTO and DFORWTO */ 01897 if (snap_send_packet(p, p->sp - p->stack_min, dest, p->rb, 01898 htons(p->hdr->entry_point), GET_OP(*p->pc) == FORWTO ? 0 : 1)) { 01899 warn("%s:%d: FORWTO snap_send_packet failed\n", 01900 __FILE__,__LINE__); 01901 return -1; 01902 } 01903 print_anti_timer(1,"interp_packet"); 01904 p->rb = 0; 01905 done = 1; 01906 } else { 01907 d_printf(10,"%s:%d: pc=%d: FORWTO [%u.%u.%u.%u]: at dest, falling thru\n", 01908 __FILE__,__LINE__,(p->pc - p->code_min), 01909 NIPQUAD(dest)); 01910 } 01911 p->pc++; 01912 break; 01913 } 01914 01915 case STACKEMPTY : 01916 PUSHWJDB(INTV,"STACKEMPTY",(p->sp == p->stack_min ? 1 : 0),"%d",(p->sp == p->stack_min ? 1 : 0)); 01917 break; 01918 case STACKCOUNT : 01919 PUSHWJDB(INTV,"STACKCOUNT",(p->sp - p->stack_min),"%d",(p->sp - p->stack_min)); 01920 break; 01921 case DEMUX:{ 01922 value_t *top1 = p->sp - 1; 01923 value_t *top2 = p->sp - 2; 01924 int pnum = 0; 01925 char *s; 01926 int slen = 0; 01927 heap_obj *ho; 01928 01929 DYNCHECK(top2 >= p->stack_min); 01930 DYNCHECK_TAG(*top1,INTV); 01931 pnum = GET_INT(*top1); 01932 DYNCHECK(pnum > 0); 01933 DYNCHECK_TAG(*top2,STRV); 01934 ho = (heap_obj *)(p->heap_min + GET_OFFS(*top2)); 01935 DYNCHECK_IN_HEAP(ho); 01936 s = (char *)&(ho->s); 01937 slen = ho->len; 01938 print_timer(1,"interp_packet"); 01939 d_printf(10,"%s:%d: pc=%d: DEMUX or DEMUXUDP [%d] bytes to port [%d]\n", 01940 __FILE__,__LINE__,(p->pc - p->code_min),slen, pnum); 01941 if (snap_demux_send(pnum,p,s,slen)) { 01942 warn("%s:%d: snap_demux_send failed\n", __FILE__,__LINE__); 01943 return -1; 01944 } 01945 print_anti_timer(1,"interp_packet"); 01946 p->sp -= 2; /* pop */ 01947 p->pc++; 01948 done = 1; /* exit after one demux */ 01949 return 0; /* return, avoid skb_free */ 01950 break; 01951 } 01952 01953 case DEMUXI:{ 01954 value_t *top = p->sp - 1; 01955 int pnum = 0; 01956 char *s; 01957 int slen = 0; 01958 heap_obj *ho; 01959 01960 DYNCHECK(top >= p->stack_min); 01961 GET_LIT(pnum,INTV,*p->pc); 01962 DYNCHECK(pnum > 0); 01963 DYNCHECK_TAG(*top,STRV); 01964 ho = (heap_obj *)(p->heap_min + GET_OFFS(*top)); 01965 DYNCHECK_IN_HEAP(ho); 01966 s = (char *)&(ho->s); 01967 slen = ho->len; 01968 print_timer(1,"interp_packet"); 01969 d_printf(10,"%s:%d: pc=%d: DEMUXI or DEMUXIUDP port %d : [%d] bytes\n", 01970 __FILE__,__LINE__,(p->pc - p->code_min),pnum,slen); 01971 if (snap_demux_send(pnum,p,s,slen)) { 01972 warn("%s:%d: snap_demux_send failed\n",__FILE__,__LINE__); 01973 return -1; 01974 } 01975 print_anti_timer(1,"interp_packet"); 01976 p->sp--; /* pop */ 01977 p->pc++; 01978 done = 1; /* exit after one demux */ 01979 return 0; /* return, avoid skb_free */ 01980 break; 01981 } 01982 01983 case PRINT: { 01984 value_t *top = p->sp - 1; 01985 01986 DYNCHECK(top >= p->stack_min); 01987 d_printf(10,"%s:%d: pc=%d: PRINT\n",__FILE__,__LINE__, 01988 (p->pc - p->code_min)); 01989 #ifdef __KERNEL__ 01990 printk(KERN_WARNING "print: "); 01991 printk_value(p,top); 01992 printk("\n"); 01993 #else 01994 fprintf(stderr,"snap_interp : print: "); 01995 fprintf_value(p,stderr,top); 01996 fprintf(stderr,"\n"); 01997 fflush(stderr); 01998 #endif 01999 p->pc++; 02000 break; 02001 } 02002 02003 #ifdef CONFIG_IP_SNAP_SVCS 02004 #if 0 02005 case SVCV: { 02006 int offs, retc; 02007 heap_obj *ho; 02008 char *s; 02009 02010 ENSURE_HEAP_ROOM(p,iph); 02011 DYNCHECK(p->sp < p->stack_max); 02012 02013 GET_LIT(offs,STRV,*p->pc); 02014 ho = (heap_obj *)(p->heap_min + offs); 02015 DYNCHECK_IN_HEAP(ho); 02016 s = (char *)&(ho->s); 02017 retc = lookup_value(p,s,p->sp); 02018 if (retc != 0) { /* not found */ 02019 d_printf(10,"%s:%d: pc=%d: SVCV \"%s\": (SERVICE NOT PRESENT!!!)\n", 02020 __FILE__,__LINE__, 02021 (p->pc - p->code_min),s); 02022 SET_TAG(*p->sp,EXCV); 02023 SET_INT(*p->sp,E_SERVICE_NOT_PRESENT); 02024 } else { 02025 d_printf(10,"%s:%d: pc=%d: SVCV \"%s\"\n",__FILE__,__LINE__, 02026 (p->pc - p->code_min),s); 02027 } 02028 p->sp++; 02029 p->pc++; 02030 break; 02031 } 02032 #endif 02033 case CALLS: { 02034 int offs; 02035 heap_obj *ho; 02036 char *s; 02037 02038 ENSURE_HEAP_ROOM(p,iph); 02039 DYNCHECK(p->sp < p->stack_max); 02040 02041 GET_LIT(offs,STRV,*p->pc); 02042 ho = (heap_obj *)(p->heap_min + offs); 02043 DYNCHECK_IN_HEAP(ho); 02044 s = (char *)&(ho->s); 02045 if (snap_svc_call_service(p,s)) { /* not found */ 02046 d_printf(10,"%s:%d: pc=%d: CALLS \"%s\": (SERVICE NOT PRESENT!!!)\n", 02047 __FILE__,__LINE__, 02048 (p->pc - p->code_min),s); 02049 SET_TAG(*p->sp,EXCV); 02050 SET_INT(*p->sp,E_SERVICE_NOT_PRESENT); 02051 p->sp++; 02052 } else { 02053 d_printf(10,"%s:%d: pc=%d: CALLS \"%s\"\n",__FILE__,__LINE__, 02054 (p->pc - p->code_min),s); 02055 } 02056 p->pc++; 02057 break; 02058 } 02059 #endif /* CONFIG_IP_SNAP_SVCS */ 02060 02061 default: 02062 warn("%s: unknown opcode: 0x%x\n",__FILE__,GET_OP(*p->pc)); 02063 return -1; 02064 } 02065 } 02066 print_timer(1,"interp_packet"); 02067 d_printf(40,"%s:%d: packet exits normally\n",__FILE__,__LINE__); 02068 02069 return 0; 02070 } 02071 02072 #endif /* CONFIG_IP_SNAP */ |