[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

SourceForge.net Logo

osi-open source certified logo

Splash - Documentation

SNMP Plus a Lightweight API for SNAP Handling

Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

snap-1.1-wjdb/lib/snap_interp.c

Go 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 */