ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Net-SNMP-XS/XS.xs
Revision: 1.2
Committed: Wed Apr 8 10:39:32 2009 UTC (15 years, 2 months ago) by root
Branch: MAIN
Changes since 1.1: +5 -5 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 #include "EXTERN.h"
2     #include "perl.h"
3     #include "XSUB.h"
4    
5     // C99 required
6    
7     #define ASN_BOOLEAN 0x01
8     #define ASN_INTEGER 0x02
9     #define ASN_BIT_STR 0x03
10     #define ASN_OCTET_STR 0x04
11     #define ASN_NULL 0x05
12     #define ASN_OBJECT_ID 0x06
13     #define ASN_SEQUENCE 0x10
14     #define ASN_SET 0x11
15    
16     #define ASN_UNIVERSAL 0x00
17     #define ASN_APPLICATION 0x40
18     #define ASN_CONTEXT 0x80
19     #define ASN_PRIVATE 0xc0
20    
21     #define ASN_PRIMITIVE 0x00
22     #define ASN_CONSTRUCTOR 0x20
23    
24     #define ASN_LONG_LEN 0x80
25     #define ASN_EXTENSION_ID 0x1f
26     #define ASN_BIT8 0x80
27    
28 root 1.2 //#define BENCHMARK
29 root 1.1
30     static SV *msg;
31     static int errflag;
32     static U8 *buf, *cur;
33     static STRLEN len, rem;
34    
35     static void
36     error (const char *msg)
37     {
38     errflag = 1;
39    
40     printf ("<<<%s>>>\n", msg);//D
41     }
42    
43     static int
44     need (int count)
45     {
46     if (count < 0 || (int)rem < count)
47     {
48     error ("Unexpected end of message buffer");
49     return 0;
50     }
51    
52     return 1;
53     }
54    
55     static U8 *
56     getn (int count, const U8 *errres)
57     {
58     if (!need (count))
59     return (U8 *)errres;
60    
61     U8 *res = cur;
62    
63     cur += count;
64     rem -= count;
65    
66     return res;
67     }
68    
69     static U8
70     get8 (void)
71     {
72     if (rem <= 0)
73     {
74     error ("Unexpected end of message buffer");
75     return 0;
76     }
77    
78     rem--;
79     return *cur++;
80     }
81    
82     static U32
83     getb (void)
84     {
85     U32 res = 0;
86    
87     for (;;)
88     {
89     U8 c = get8 ();
90     res = (res << 7) | (c & 0x7f);
91    
92     if (!(c & 0x80))
93     return res;
94     }
95     }
96    
97     #ifdef BENCHMARK
98     static double t1;
99    
100     static double
101     tstamp (void)
102     {
103     struct timeval tv;
104     gettimeofday (&tv, 0);
105     return tv.tv_sec + tv.tv_usec * 0.000001;
106     }
107     #endif
108    
109     static U32
110     process_length (void)
111     {
112     U32 res = get8 ();
113    
114     if (res & 0x80)
115     {
116     int cnt = res & 0x7f;
117     res = 0;
118    
119     switch (cnt)
120     {
121     case 0:
122     error ("Indefinite ASN.1 lengths not supported");
123     return 0;
124    
125     default:
126     error ("ASN.1 length too long");
127     return 0;
128    
129     case 4: res = (res << 8) | get8 ();
130     case 3: res = (res << 8) | get8 ();
131     case 2: res = (res << 8) | get8 ();
132     case 1: res = (res << 8) | get8 ();
133     }
134     }
135    
136     return res;
137     }
138    
139     MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS
140    
141     void
142     set_msg (SV *msg_, SV *buf_)
143     CODE:
144     errflag = 0;
145     msg = SvREFCNT_inc (msg_);
146     buf = SvPVbyte (buf_, len);
147     cur = buf;
148     rem = len;
149 root 1.2 #ifdef BENCHMARK
150 root 1.1 t1 = tstamp ();
151 root 1.2 #endif
152 root 1.1
153     void
154     clr_msg ()
155     CODE:
156     SvREFCNT_dec (msg);
157     buf = cur = "";
158     len = rem = 0;
159 root 1.2 #ifdef BENCHMARK
160 root 1.1 printf ("%f\n", tstamp () - t1);//D
161 root 1.2 #endif
162 root 1.1
163     MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message
164    
165     void
166     _buffer_get (SV *self, int count = -1)
167     PPCODE:
168     {
169     // grrr.
170     if (count < 0)
171     {
172     hv_delete ((HV *)SvRV (self), "_index" , 6, G_DISCARD);
173     hv_delete ((HV *)SvRV (self), "_length", 7, G_DISCARD);
174     SV **svp = hv_fetch ((HV *)SvRV (self), "_buffer", 7, 1);
175     XPUSHs (sv_2mortal (newSVsv (*svp)));
176     sv_setpvn (*svp, "", 0);
177     XSRETURN (1);
178     }
179    
180     char *data = getn (count, 0);
181    
182     if (data)
183     XPUSHs (sv_2mortal (newSVpvn (data, count)));
184     }
185    
186     U32
187     index (SV *self, int ndx = -1)
188     CODE:
189     {
190     if (ndx >= 0 && ndx < len)
191     {
192     cur = buf + ndx;
193     rem = len - ndx;
194     }
195    
196     RETVAL = cur - buf;
197     }
198     OUTPUT:
199     RETVAL
200    
201     U32
202     _process_length (SV *self, ...)
203     ALIAS:
204     _process_sequence = 1
205     CODE:
206     RETVAL = process_length ();
207     OUTPUT:
208     RETVAL
209    
210     I32
211     _process_integer32 (SV *self, ...)
212     ALIAS:
213     _process_counter = 0
214     _process_gauge = 0
215     CODE:
216     {
217     U32 length = process_length ();
218    
219     if (length <= 0)
220     {
221     error ("INTEGER32 length equal to zero");
222     XSRETURN_UNDEF;
223     }
224    
225     U8 *data = getn (length, 0);
226    
227     if (!data)
228     XSRETURN_UNDEF;
229    
230     if (length > 5 || (length > 4 && data [0]))
231     {
232     error ("INTEGER32 length too long");
233     XSRETURN_UNDEF;
234     }
235    
236     U32 res = data [0] & 0x80 ? 0xffffffff : 0;
237    
238     while (length--)
239     res = (res << 8) | *data++;
240    
241     RETVAL = res;
242     }
243     OUTPUT:
244     RETVAL
245    
246     SV *
247     _process_object_identifier (SV *self, ...)
248     CODE:
249     {
250     U32 length = process_length ();
251    
252     if (length <= 0)
253     {
254     error ("OBJECT IDENTIFIER length equal to zero");
255     XSRETURN_UNDEF;
256     }
257    
258     U8 *end = cur + length;
259     U32 w = getb ();
260    
261     //TODO: leading_dots
262    
263     RETVAL = newSVpvf (".%d.%d", (int)w / 40, (int)w % 40);
264    
265     while (cur < end)
266     {
267     w = getb ();
268     sv_catpvf (RETVAL, ".%u", (unsigned int)w);
269     }
270     }
271     OUTPUT:
272     RETVAL
273    
274     SV *
275     _process_octet_string (SV *self, ...)
276     ALIAS:
277     _process_opaque = 0
278     CODE:
279     {
280     U32 length = process_length ();
281    
282     U8 *data = getn (length, 0);
283     if (!data)
284     {
285     error ("OCTET STRING too long");
286     XSRETURN_UNDEF;
287     }
288    
289     RETVAL = newSVpvn (data, length);
290     }
291     OUTPUT:
292     RETVAL
293    
294     SV *
295     _process_ipaddress (SV *self, ...)
296     CODE:
297     {
298     U32 length = process_length ();
299     if (length != 4)
300     {
301     error ("IP ADDRESS length not four");
302     XSRETURN_UNDEF;
303     }
304    
305     U8 *data = getn (4, "\x00\x00\x00\x00");
306     RETVAL = newSVpvf ("%d.%d.%d.%d", data [0], data [1], data [2], data [3]);
307     }
308     OUTPUT:
309     RETVAL
310