kemix: added functions to get proto string and id
[sip-router] / src / modules / kemix / kemix_mod.c
1 /**
2  * Copyright (C) 2019 Daniel-Constantin Mierla (asipto.com)
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Kamailio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * Kamailio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "../../core/sr_module.h"
28 #include "../../core/dprint.h"
29 #include "../../core/kemi.h"
30 #include "../../core/parser/parse_uri.h"
31 #include "../../core/parser/parse_from.h"
32 #include "../../core/parser/parse_to.h"
33
34 MODULE_VERSION
35
36 struct module_exports exports = {
37         "kemix",         /* module name */
38         DEFAULT_DLFLAGS, /* dlopen flags */
39         0,               /* cmd (cfg function) exports */
40         0,               /* param exports */
41         0,               /* RPC method exports */
42         0,               /* pseudo-variables exports */
43         0,               /* response handling function */
44         0,               /* module init function */
45         0,               /* per-child init function */
46         0                /* module destroy function */
47 };
48
49
50 /**
51  *
52  */
53 static sr_kemi_xval_t _sr_kemi_kx_xval = {0};
54
55 /**
56  *
57  */
58 static sr_kemi_xval_t* ki_kx_get_ruri(sip_msg_t *msg)
59 {
60         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
61
62         if(msg==NULL) {
63                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
64                 return &_sr_kemi_kx_xval;
65         }
66
67         if(msg->first_line.type == SIP_REPLY) {
68                 /* REPLY doesnt have a ruri */
69                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
70                 return &_sr_kemi_kx_xval;
71         }
72
73         if(msg->parsed_uri_ok==0 /* R-URI not parsed*/ && parse_sip_msg_uri(msg)<0) {
74                 LM_ERR("failed to parse the R-URI\n");
75                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
76                 return &_sr_kemi_kx_xval;
77         }
78
79         _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
80         if (msg->new_uri.s!=NULL) {
81                 _sr_kemi_kx_xval.v.s = msg->new_uri;
82         } else {
83                 _sr_kemi_kx_xval.v.s = msg->first_line.u.request.uri;
84         }
85         return &_sr_kemi_kx_xval;
86 }
87
88 /**
89  *
90  */
91 static sr_kemi_xval_t* ki_kx_get_ouri(sip_msg_t *msg)
92 {
93         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
94
95         if(msg==NULL) {
96                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
97                 return &_sr_kemi_kx_xval;
98         }
99
100         if(msg->first_line.type == SIP_REPLY) {
101                 /* REPLY doesnt have a ruri */
102                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
103                 return &_sr_kemi_kx_xval;
104         }
105
106         if(msg->parsed_uri_ok==0 /* R-URI not parsed*/ && parse_sip_msg_uri(msg)<0) {
107                 LM_ERR("failed to parse the R-URI\n");
108                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
109                 return &_sr_kemi_kx_xval;
110         }
111
112         _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
113         _sr_kemi_kx_xval.v.s = msg->first_line.u.request.uri;
114         return &_sr_kemi_kx_xval;
115 }
116
117 /**
118  *
119  */
120 static sr_kemi_xval_t* ki_kx_get_furi(sip_msg_t *msg)
121 {
122         to_body_t *xto = NULL;
123
124         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
125
126         if(msg==NULL) {
127                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
128                 return &_sr_kemi_kx_xval;
129         }
130         if(parse_from_header(msg)<0) {
131                 LM_ERR("cannot parse From header\n");
132                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
133                 return &_sr_kemi_kx_xval;
134         }
135         if(msg->from==NULL || get_from(msg)==NULL) {
136                 LM_DBG("no From header\n");
137                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
138                 return &_sr_kemi_kx_xval;
139         }
140
141         xto = get_from(msg);
142         _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
143         _sr_kemi_kx_xval.v.s = xto->uri;
144         return &_sr_kemi_kx_xval;
145 }
146
147 /**
148  *
149  */
150 static sr_kemi_xval_t* ki_kx_get_turi(sip_msg_t *msg)
151 {
152         to_body_t *xto = NULL;
153
154         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
155
156         if(msg==NULL) {
157                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
158                 return &_sr_kemi_kx_xval;
159         }
160         if(parse_to_header(msg)<0) {
161                 LM_ERR("cannot parse To header\n");
162                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
163                 return &_sr_kemi_kx_xval;
164         }
165         if(msg->to==NULL || get_to(msg)==NULL) {
166                 LM_DBG("no To header\n");
167                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
168                 return &_sr_kemi_kx_xval;
169         }
170
171         xto = get_to(msg);
172         _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
173         _sr_kemi_kx_xval.v.s = xto->uri;
174         return &_sr_kemi_kx_xval;
175 }
176
177 /**
178  *
179  */
180 static sr_kemi_xval_t* ki_kx_get_xuri_attr(sip_msg_t *msg, sip_uri_t *puri,
181                 int iattr, int xmode)
182 {
183         if(iattr==1) {
184                 /* username */
185                 if(puri->user.s==NULL || puri->user.len<=0) {
186                         sr_kemi_xval_null(&_sr_kemi_kx_xval, xmode);
187                         return &_sr_kemi_kx_xval;
188                 }
189                 _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
190                 _sr_kemi_kx_xval.v.s = puri->user;
191                 return &_sr_kemi_kx_xval;
192         } else if(iattr==2) {
193                 /* domain */
194                 if(puri->host.s==NULL || puri->host.len<=0) {
195                         sr_kemi_xval_null(&_sr_kemi_kx_xval, xmode);
196                         return &_sr_kemi_kx_xval;
197                 }
198                 _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
199                 _sr_kemi_kx_xval.v.s = puri->host;
200                 return &_sr_kemi_kx_xval;
201         }
202         LM_ERR("unknown attribute id: %d\n", iattr);
203         sr_kemi_xval_null(&_sr_kemi_kx_xval, xmode);
204         return &_sr_kemi_kx_xval;
205 }
206
207 /**
208  *
209  */
210 static sr_kemi_xval_t* ki_kx_get_ruri_attr(sip_msg_t *msg, int iattr, int xmode)
211 {
212         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
213
214         if(msg==NULL || msg->first_line.type == SIP_REPLY) {
215                 sr_kemi_xval_null(&_sr_kemi_kx_xval, xmode);
216                 return &_sr_kemi_kx_xval;
217         }
218
219         if(msg->parsed_uri_ok==0 /* R-URI not parsed*/ && parse_sip_msg_uri(msg)<0) {
220                 LM_ERR("failed to parse the R-URI\n");
221                 sr_kemi_xval_null(&_sr_kemi_kx_xval, xmode);
222                 return &_sr_kemi_kx_xval;
223         }
224         return ki_kx_get_xuri_attr(msg, &(msg->parsed_uri), iattr, xmode);
225 }
226
227 /**
228  *
229  */
230 static sr_kemi_xval_t* ki_kx_get_ruser(sip_msg_t *msg)
231 {
232         return ki_kx_get_ruri_attr(msg, 1, SR_KEMI_XVAL_NULL_NONE);
233 }
234
235 /**
236  *
237  */
238 static sr_kemi_xval_t* ki_kx_getw_ruser(sip_msg_t *msg)
239 {
240         return ki_kx_get_ruri_attr(msg, 1, SR_KEMI_XVAL_NULL_PRINT);
241 }
242
243 /**
244  *
245  */
246 static sr_kemi_xval_t* ki_kx_gete_ruser(sip_msg_t *msg)
247 {
248         return ki_kx_get_ruri_attr(msg, 1, SR_KEMI_XVAL_NULL_EMPTY);
249 }
250
251 /**
252  *
253  */
254 static sr_kemi_xval_t* ki_kx_get_rhost(sip_msg_t *msg)
255 {
256         return ki_kx_get_ruri_attr(msg, 2, SR_KEMI_XVAL_NULL_NONE);
257 }
258
259 /**
260  *
261  */
262 static sr_kemi_xval_t* ki_kx_getw_rhost(sip_msg_t *msg)
263 {
264         return ki_kx_get_ruri_attr(msg, 2, SR_KEMI_XVAL_NULL_PRINT);
265 }
266
267 /**
268  *
269  */
270 static sr_kemi_xval_t* ki_kx_gete_rhost(sip_msg_t *msg)
271 {
272         return ki_kx_get_ruri_attr(msg, 2, SR_KEMI_XVAL_NULL_EMPTY);
273 }
274
275 /**
276  *
277  */
278 static sr_kemi_xval_t* ki_kx_get_furi_attr(sip_msg_t *msg, int iattr, int xmode)
279 {
280         sip_uri_t *uri;
281
282         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
283         uri=parse_from_uri(msg);
284         if(uri==NULL) {
285                 sr_kemi_xval_null(&_sr_kemi_kx_xval, xmode);
286                 return &_sr_kemi_kx_xval;
287         }
288
289         return ki_kx_get_xuri_attr(msg, uri, iattr, xmode);
290 }
291
292 /**
293  *
294  */
295 static sr_kemi_xval_t* ki_kx_get_fuser(sip_msg_t *msg)
296 {
297         return ki_kx_get_furi_attr(msg, 1, SR_KEMI_XVAL_NULL_NONE);
298 }
299
300 /**
301  *
302  */
303 static sr_kemi_xval_t* ki_kx_getw_fuser(sip_msg_t *msg)
304 {
305         return ki_kx_get_furi_attr(msg, 1, SR_KEMI_XVAL_NULL_PRINT);
306 }
307
308 /**
309  *
310  */
311 static sr_kemi_xval_t* ki_kx_gete_fuser(sip_msg_t *msg)
312 {
313         return ki_kx_get_furi_attr(msg, 1, SR_KEMI_XVAL_NULL_EMPTY);
314 }
315
316 /**
317  *
318  */
319 static sr_kemi_xval_t* ki_kx_get_fhost(sip_msg_t *msg)
320 {
321         return ki_kx_get_furi_attr(msg, 2, SR_KEMI_XVAL_NULL_NONE);
322 }
323
324 /**
325  *
326  */
327 static sr_kemi_xval_t* ki_kx_getw_fhost(sip_msg_t *msg)
328 {
329         return ki_kx_get_furi_attr(msg, 2, SR_KEMI_XVAL_NULL_PRINT);
330 }
331
332 /**
333  *
334  */
335 static sr_kemi_xval_t* ki_kx_gete_fhost(sip_msg_t *msg)
336 {
337         return ki_kx_get_furi_attr(msg, 2, SR_KEMI_XVAL_NULL_EMPTY);
338 }
339
340 /**
341  *
342  */
343 static sr_kemi_xval_t* ki_kx_get_ua_mode(sip_msg_t *msg, int rmode)
344 {
345         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
346         if(msg==NULL) {
347                 sr_kemi_xval_null(&_sr_kemi_kx_xval, rmode);
348                 return &_sr_kemi_kx_xval;
349         }
350         if(msg->user_agent==NULL && ((parse_headers(msg, HDR_USERAGENT_F, 0)==-1)
351                         || (msg->user_agent==NULL))) {
352                 sr_kemi_xval_null(&_sr_kemi_kx_xval, rmode);
353                 return &_sr_kemi_kx_xval;
354         }
355
356         _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
357         _sr_kemi_kx_xval.v.s = msg->user_agent->body;
358         return &_sr_kemi_kx_xval;
359 }
360
361 /**
362  *
363  */
364 static sr_kemi_xval_t* ki_kx_get_ua(sip_msg_t *msg)
365 {
366         return ki_kx_get_ua_mode(msg, SR_KEMI_XVAL_NULL_NONE);
367 }
368
369 /**
370  *
371  */
372 static sr_kemi_xval_t* ki_kx_gete_ua(sip_msg_t *msg)
373 {
374         return ki_kx_get_ua_mode(msg, SR_KEMI_XVAL_NULL_EMPTY);
375 }
376
377 /**
378  *
379  */
380 static sr_kemi_xval_t* ki_kx_getw_ua(sip_msg_t *msg)
381 {
382         return ki_kx_get_ua_mode(msg, SR_KEMI_XVAL_NULL_PRINT);
383 }
384
385 /**
386  *
387  */
388 static sr_kemi_xval_t* ki_kx_get_srcip(sip_msg_t *msg)
389 {
390         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
391         if(msg==NULL) {
392                 sr_kemi_xval_null(&_sr_kemi_kx_xval, SR_KEMI_XVAL_NULL_NONE);
393                 return &_sr_kemi_kx_xval;
394         }
395
396         _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
397         _sr_kemi_kx_xval.v.s.s = ip_addr2a(&msg->rcv.src_ip);
398         _sr_kemi_kx_xval.v.s.len = strlen(_sr_kemi_kx_xval.v.s.s);
399         return &_sr_kemi_kx_xval;
400 }
401
402 /**
403  *
404  */
405 static sr_kemi_xval_t* ki_kx_get_srcport(sip_msg_t *msg)
406 {
407         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
408         if(msg==NULL) {
409                 _sr_kemi_kx_xval.vtype = SR_KEMIP_INT;
410                 _sr_kemi_kx_xval.v.n = 0;
411                 return &_sr_kemi_kx_xval;
412         }
413
414         _sr_kemi_kx_xval.vtype = SR_KEMIP_INT;
415         _sr_kemi_kx_xval.v.n = (int)msg->rcv.src_port;
416         return &_sr_kemi_kx_xval;
417 }
418
419 /**
420  *
421  */
422 static sr_kemi_xval_t* ki_kx_get_rcvip(sip_msg_t *msg)
423 {
424         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
425         if(msg==NULL || msg->rcv.bind_address==NULL
426                         || msg->rcv.bind_address->address_str.s==NULL) {
427                 sr_kemi_xval_null(&_sr_kemi_kx_xval, SR_KEMI_XVAL_NULL_NONE);
428                 return &_sr_kemi_kx_xval;
429         }
430
431         _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
432         _sr_kemi_kx_xval.v.s = msg->rcv.bind_address->address_str;
433         return &_sr_kemi_kx_xval;
434 }
435
436 /**
437  *
438  */
439 static sr_kemi_xval_t* ki_kx_get_rcvport(sip_msg_t *msg)
440 {
441         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
442         if(msg==NULL || msg->rcv.bind_address==NULL) {
443                 _sr_kemi_kx_xval.vtype = SR_KEMIP_INT;
444                 _sr_kemi_kx_xval.v.n = 0;
445                 return &_sr_kemi_kx_xval;
446         }
447
448         _sr_kemi_kx_xval.vtype = SR_KEMIP_INT;
449         _sr_kemi_kx_xval.v.n = (int)msg->rcv.bind_address->port_no;
450         return &_sr_kemi_kx_xval;
451 }
452
453 /**
454  *
455  */
456 static sr_kemi_xval_t* ki_kx_get_proto(sip_msg_t *msg)
457 {
458         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
459         if(msg==NULL) {
460                 sr_kemi_xval_null(&_sr_kemi_kx_xval, SR_KEMI_XVAL_NULL_EMPTY);
461                 return &_sr_kemi_kx_xval;
462         }
463
464         _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
465         if(get_valid_proto_string(msg->rcv.proto, 0, 0, &_sr_kemi_kx_xval.v.s)<0) {
466                 sr_kemi_xval_null(&_sr_kemi_kx_xval, SR_KEMI_XVAL_NULL_EMPTY);
467         }
468
469         return &_sr_kemi_kx_xval;
470 }
471
472 /**
473  *
474  */
475 static int ki_kx_get_protoid(sip_msg_t *msg)
476 {
477         if(msg==NULL) {
478                 return -1;
479         }
480
481         _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
482         return (int)msg->rcv.proto;
483 }
484
485 /**
486  *
487  */
488 /* clang-format off */
489 static sr_kemi_t sr_kemi_kx_exports[] = {
490         { str_init("kx"), str_init("get_ruri"),
491                 SR_KEMIP_XVAL, ki_kx_get_ruri,
492                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
493                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
494         },
495         { str_init("kx"), str_init("get_ruser"),
496                 SR_KEMIP_XVAL, ki_kx_get_ruser,
497                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
498                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
499         },
500         { str_init("kx"), str_init("getw_ruser"),
501                 SR_KEMIP_XVAL, ki_kx_getw_ruser,
502                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
503                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
504         },
505         { str_init("kx"), str_init("gete_ruser"),
506                 SR_KEMIP_XVAL, ki_kx_gete_ruser,
507                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
508                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
509         },
510         { str_init("kx"), str_init("get_rhost"),
511                 SR_KEMIP_XVAL, ki_kx_get_rhost,
512                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
513                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
514         },
515         { str_init("kx"), str_init("getw_rhost"),
516                 SR_KEMIP_XVAL, ki_kx_getw_rhost,
517                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
518                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
519         },
520         { str_init("kx"), str_init("gete_rhost"),
521                 SR_KEMIP_XVAL, ki_kx_gete_rhost,
522                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
523                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
524         },
525         { str_init("kx"), str_init("get_ouri"),
526                 SR_KEMIP_XVAL, ki_kx_get_ouri,
527                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
528                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
529         },
530         { str_init("kx"), str_init("get_furi"),
531                 SR_KEMIP_XVAL, ki_kx_get_furi,
532                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
533                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
534         },
535         { str_init("kx"), str_init("get_fuser"),
536                 SR_KEMIP_XVAL, ki_kx_get_fuser,
537                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
538                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
539         },
540         { str_init("kx"), str_init("getw_fuser"),
541                 SR_KEMIP_XVAL, ki_kx_getw_fuser,
542                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
543                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
544         },
545         { str_init("kx"), str_init("gete_fuser"),
546                 SR_KEMIP_XVAL, ki_kx_gete_fuser,
547                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
548                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
549         },
550         { str_init("kx"), str_init("get_fhost"),
551                 SR_KEMIP_XVAL, ki_kx_get_fhost,
552                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
553                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
554         },
555         { str_init("kx"), str_init("getw_fhost"),
556                 SR_KEMIP_XVAL, ki_kx_getw_fhost,
557                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
558                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
559         },
560         { str_init("kx"), str_init("gete_fhost"),
561                 SR_KEMIP_XVAL, ki_kx_gete_rhost,
562                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
563                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
564         },
565         { str_init("kx"), str_init("get_turi"),
566                 SR_KEMIP_XVAL, ki_kx_get_turi,
567                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
568                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
569         },
570         { str_init("kx"), str_init("get_ua"),
571                 SR_KEMIP_XVAL, ki_kx_get_ua,
572                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
573                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
574         },
575         { str_init("kx"), str_init("gete_ua"),
576                 SR_KEMIP_XVAL, ki_kx_gete_ua,
577                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
578                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
579         },
580         { str_init("kx"), str_init("getw_ua"),
581                 SR_KEMIP_XVAL, ki_kx_getw_ua,
582                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
583                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
584         },
585         { str_init("kx"), str_init("get_srcip"),
586                 SR_KEMIP_XVAL, ki_kx_get_srcip,
587                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
588                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
589         },
590         { str_init("kx"), str_init("get_srcport"),
591                 SR_KEMIP_XVAL, ki_kx_get_srcport,
592                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
593                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
594         },
595         { str_init("kx"), str_init("get_rcvip"),
596                 SR_KEMIP_XVAL, ki_kx_get_rcvip,
597                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
598                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
599         },
600         { str_init("kx"), str_init("get_rcvport"),
601                 SR_KEMIP_XVAL, ki_kx_get_rcvport,
602                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
603                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
604         },
605         { str_init("kx"), str_init("get_proto"),
606                 SR_KEMIP_XVAL, ki_kx_get_proto,
607                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
608                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
609         },
610         { str_init("kx"), str_init("get_protoid"),
611                 SR_KEMIP_INT, ki_kx_get_protoid,
612                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
613                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
614         },
615
616         { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
617 };
618
619 /**
620  *
621  */
622 int mod_register(char *path, int *dlflags, void *p1, void *p2)
623 {
624         sr_kemi_modules_add(sr_kemi_kx_exports);
625         return 0;
626 }