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

File Contents

# Content
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 #define BENCHMARK
29
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 #ifdef BENCHMARK
150 t1 = tstamp ();
151 #endif
152
153 void
154 clr_msg ()
155 CODE:
156 SvREFCNT_dec (msg);
157 buf = cur = "";
158 len = rem = 0;
159 #ifdef BENCHMARK
160 printf ("%f\n", tstamp () - t1);//D
161 #endif
162
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