1 /* $Id: upnpredirect.c,v 1.59 2011/06/04 08:57:40 nanard Exp $ */
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006-2011 Thomas Bernard
5 * This software is subject to the conditions detailed
6 * in the LICENCE file provided within the distribution */
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <netinet/in.h>
15 #include <arpa/inet.h>
22 #include "upnpredirect.h"
23 #include "upnpglobalvars.h"
24 #include "upnpevents.h"
25 #if defined(USE_NETFILTER)
26 #include "netfilter/iptcrdr.h"
29 #include "pf/obsdrdr.h"
32 #include "ipf/ipfrdr.h"
35 #include "ipfw/ipfwrdr.h"
37 #ifdef USE_MINIUPNPDCTL
41 #ifdef ENABLE_LEASEFILE
45 /* from <inttypes.h> */
51 * convert the string "UDP" or "TCP" to IPPROTO_UDP and IPPROTO_UDP */
53 proto_atoi(const char * protocol
)
55 int proto
= IPPROTO_TCP
;
56 if(strcmp(protocol
, "UDP") == 0)
61 #ifdef ENABLE_LEASEFILE
63 lease_file_add(unsigned short eport
,
68 unsigned int timestamp
)
72 if (lease_file
== NULL
) return 0;
74 fd
= fopen( lease_file
, "a");
76 syslog(LOG_ERR
, "could not open lease file: %s", lease_file
);
80 fprintf(fd
, "%s:%hu:%s:%hu:%u:%s\n",
81 ((proto
==IPPROTO_TCP
)?"TCP":"UDP"), eport
, iaddr
, iport
,
89 lease_file_remove(unsigned short eport
, int proto
)
95 char tmpfilename
[128];
96 int str_size
, buf_size
;
99 if (lease_file
== NULL
) return 0;
101 if (strlen( lease_file
) + 7 > sizeof(tmpfilename
)) {
102 syslog(LOG_ERR
, "Lease filename is too long");
106 strncpy( tmpfilename
, lease_file
, sizeof(tmpfilename
) );
107 strncat( tmpfilename
, "XXXXXX", sizeof(tmpfilename
) - strlen(tmpfilename
));
109 fd
= fopen( lease_file
, "r");
114 snprintf( str
, sizeof(str
), "%s:%u", ((proto
==IPPROTO_TCP
)?"TCP":"UDP"), eport
);
115 str_size
= strlen(str
);
117 tmp
= mkstemp(tmpfilename
);
120 syslog(LOG_ERR
, "could not open temporary lease file");
123 fchmod(tmp
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
);
124 fdt
= fdopen(tmp
, "a");
126 buf
[sizeof(buf
)-1] = 0;
127 while( fgets(buf
, sizeof(buf
)-1, fd
) != NULL
) {
128 buf_size
= strlen(buf
);
130 if (buf_size
< str_size
|| strncmp(str
, buf
, str_size
)!=0) {
131 fwrite(buf
, buf_size
, 1, fdt
);
137 if (rename(tmpfilename
, lease_file
) < 0) {
138 syslog(LOG_ERR
, "could not rename temporary lease file to %s", lease_file
);
146 /* reload_from_lease_file()
147 * read lease_file and add the rules contained
149 int reload_from_lease_file()
153 unsigned short eport
, iport
;
158 unsigned int leaseduration
;
159 unsigned int timestamp
;
164 if(!lease_file
) return -1;
165 fd
= fopen( lease_file
, "r");
167 syslog(LOG_ERR
, "could not open lease file: %s", lease_file
);
170 if(unlink(lease_file
) < 0) {
171 syslog(LOG_WARNING
, "could not unlink file %s : %m", lease_file
);
174 current_time
= time(NULL
);
175 while(fgets(line
, sizeof(line
), fd
)) {
176 syslog(LOG_DEBUG
, "parsing lease file line '%s'", line
);
178 p
= strchr(line
, ':');
180 syslog(LOG_ERR
, "unrecognized data in lease file");
184 iaddr
= strchr(p
, ':');
186 syslog(LOG_ERR
, "unrecognized data in lease file");
190 eport
= (unsigned short)atoi(p
);
191 p
= strchr(iaddr
, ':');
193 syslog(LOG_ERR
, "unrecognized data in lease file");
197 timestamp
= (unsigned int)atoi(p
);
200 syslog(LOG_ERR
, "unrecognized data in lease file");
204 desc
= strchr(p
, ':');
206 syslog(LOG_ERR
, "unrecognized data in lease file");
210 iport
= (unsigned short)atoi(p
);
211 /* trim description */
212 while(isspace(*desc
))
217 while(isspace(*p
) && (p
> desc
))
221 if(timestamp
<= current_time
) {
222 syslog(LOG_NOTICE
, "already expired lease in lease file");
225 leaseduration
= current_time
- timestamp
;
228 leaseduration
= 0; /* default value */
231 r
= upnp_redirect(rhost
, eport
, iaddr
, iport
, proto
, desc
, leaseduration
);
233 syslog(LOG_ERR
, "Failed to redirect %hu -> %s:%hu protocol %s",
234 eport
, iaddr
, iport
, proto
);
236 /* Add the redirection again to the lease file */
237 lease_file_add(eport
, iaddr
, iport
, proto_atoi(proto
),
248 * calls OS/fw dependant implementation of the redirection.
249 * protocol should be the string "TCP" or "UDP"
250 * returns: 0 on success
251 * -1 failed to redirect
252 * -2 already redirected
253 * -3 permission check failed
256 upnp_redirect(const char * rhost
, unsigned short eport
,
257 const char * iaddr
, unsigned short iport
,
258 const char * protocol
, const char * desc
,
259 unsigned int leaseduration
)
263 unsigned short iport_old
;
264 struct in_addr address
;
265 unsigned int timestamp
;
267 proto
= proto_atoi(protocol
);
268 if(inet_aton(iaddr
, &address
) < 0) {
269 syslog(LOG_ERR
, "inet_aton(%s) : %m", iaddr
);
273 if(!check_upnp_rule_against_permissions(upnppermlist
, num_upnpperm
,
274 eport
, address
, iport
)) {
275 syslog(LOG_INFO
, "redirection permission check failed for "
276 "%hu->%s:%hu %s", eport
, iaddr
, iport
, protocol
);
279 r
= get_redirect_rule(ext_if_name
, eport
, proto
,
280 iaddr_old
, sizeof(iaddr_old
), &iport_old
, 0, 0,
283 /* if existing redirect rule matches redirect request return success
284 * xbox 360 does not keep track of the port it redirects and will
285 * redirect another port when receiving ConflictInMappingEntry */
286 if(strcmp(iaddr
, iaddr_old
)==0 && iport
==iport_old
) {
287 /* redirection allready exists */
288 syslog(LOG_INFO
, "port %hu %s already redirected to %s:%hu, replacing", eport
, (proto
==IPPROTO_TCP
)?"tcp":"udp", iaddr_old
, iport_old
);
289 /* remove and then add again */
290 if(_upnp_delete_redir(eport
, proto
) < 0) {
291 syslog(LOG_ERR
, "failed to remove port mapping");
295 syslog(LOG_INFO
, "port %hu protocol %s already redirected to %s:%hu",
296 eport
, protocol
, iaddr_old
, iport_old
);
300 timestamp
= (leaseduration
> 0) ? time(NULL
) + leaseduration
: 0;
301 syslog(LOG_INFO
, "redirecting port %hu to %s:%hu protocol %s for: %s",
302 eport
, iaddr
, iport
, protocol
, desc
);
303 return upnp_redirect_internal(rhost
, eport
, iaddr
, iport
, proto
,
308 upnp_redirect_internal(const char * rhost
, unsigned short eport
,
309 const char * iaddr
, unsigned short iport
,
310 int proto
, const char * desc
,
311 unsigned int timestamp
)
313 /*syslog(LOG_INFO, "redirecting port %hu to %s:%hu protocol %s for: %s",
314 eport, iaddr, iport, protocol, desc); */
315 if(add_redirect_rule2(ext_if_name
, rhost
, eport
, iaddr
, iport
, proto
,
316 desc
, timestamp
) < 0) {
320 #ifdef ENABLE_LEASEFILE
321 lease_file_add( eport
, iaddr
, iport
, proto
, desc
, timestamp
);
323 /* syslog(LOG_INFO, "creating pass rule to %s:%hu protocol %s for: %s",
324 iaddr, iport, protocol, desc);*/
325 if(add_filter_rule2(ext_if_name
, rhost
, iaddr
, eport
, iport
, proto
, desc
) < 0) {
326 /* clean up the redirect rule */
327 #if !defined(__linux__)
328 delete_redirect_rule(ext_if_name
, eport
, proto
);
333 if(!nextruletoclean_timestamp
|| (timestamp
< nextruletoclean_timestamp
))
334 nextruletoclean_timestamp
= timestamp
;
337 /* the number of port mappings changed, we must
338 * inform the subscribers */
339 upnp_event_var_change_notify(EWanIPC
);
346 /* Firewall independant code which call the FW dependant code. */
348 upnp_get_redirection_infos(unsigned short eport
, const char * protocol
,
349 unsigned short * iport
,
350 char * iaddr
, int iaddrlen
,
351 char * desc
, int desclen
,
352 unsigned int * leaseduration
)
355 unsigned int timestamp
;
358 if(desc
&& (desclen
> 0))
360 r
= get_redirect_rule(ext_if_name
, eport
, proto_atoi(protocol
),
361 iaddr
, iaddrlen
, iport
, desc
, desclen
, ×tamp
,
363 if(r
== 0 && timestamp
> 0 && timestamp
> (current_time
= time(NULL
))) {
364 *leaseduration
= timestamp
- current_time
;
372 upnp_get_redirection_infos_by_index(int index
,
373 unsigned short * eport
, char * protocol
,
374 unsigned short * iport
,
375 char * iaddr
, int iaddrlen
,
376 char * desc
, int desclen
,
377 char * rhost
, int rhostlen
,
378 unsigned int * leaseduration
)
380 /*char ifname[IFNAMSIZ];*/
382 unsigned int timestamp
;
385 if(desc
&& (desclen
> 0))
387 if(rhost
&& (rhost
> 0))
389 if(get_redirect_rule_by_index(index
, 0/*ifname*/, eport
, iaddr
, iaddrlen
,
390 iport
, &proto
, desc
, desclen
,
391 rhost
, rhostlen
, ×tamp
,
396 current_time
= time(NULL
);
397 *leaseduration
= (timestamp
> current_time
)
398 ? (timestamp
- current_time
)
400 if(proto
== IPPROTO_TCP
)
401 memcpy(protocol
, "TCP", 4);
403 memcpy(protocol
, "UDP", 4);
408 /* called from natpmp.c too */
410 _upnp_delete_redir(unsigned short eport
, int proto
)
413 #if defined(__linux__)
414 r
= delete_redirect_and_filter_rules(eport
, proto
);
416 r
= delete_redirect_rule(ext_if_name
, eport
, proto
);
417 delete_filter_rule(ext_if_name
, eport
, proto
);
419 #ifdef ENABLE_LEASEFILE
420 lease_file_remove( eport
, proto
);
424 upnp_event_var_change_notify(EWanIPC
);
430 upnp_delete_redirection(unsigned short eport
, const char * protocol
)
432 syslog(LOG_INFO
, "removing redirect rule port %hu %s", eport
, protocol
);
433 return _upnp_delete_redir(eport
, proto_atoi(protocol
));
436 /* upnp_get_portmapping_number_of_entries()
437 * TODO: improve this code. */
439 upnp_get_portmapping_number_of_entries()
442 unsigned short eport
, iport
;
443 char protocol
[4], iaddr
[32], desc
[64], rhost
[32];
444 unsigned int leaseduration
;
446 protocol
[0] = '\0'; iaddr
[0] = '\0'; desc
[0] = '\0';
447 r
= upnp_get_redirection_infos_by_index(n
, &eport
, protocol
, &iport
,
448 iaddr
, sizeof(iaddr
),
450 rhost
, sizeof(rhost
),
457 /* functions used to remove unused rules
458 * As a side effect, delete expired rules (based on LeaseDuration) */
460 get_upnp_rules_state_list(int max_rules_number_target
)
462 /*char ifname[IFNAMSIZ];*/
464 unsigned short iport
;
465 unsigned int timestamp
;
466 struct rule_state
* tmp
;
467 struct rule_state
* list
= 0;
468 struct rule_state
* * p
;
472 /*ifname[0] = '\0';*/
473 tmp
= malloc(sizeof(struct rule_state
));
476 current_time
= time(NULL
);
477 nextruletoclean_timestamp
= 0;
478 while(get_redirect_rule_by_index(i
, /*ifname*/0, &tmp
->eport
, 0, 0,
479 &iport
, &proto
, 0, 0, 0,0, ×tamp
,
480 &tmp
->packets
, &tmp
->bytes
) >= 0)
484 /* need to remove this port mapping ? */
485 if(timestamp
<= current_time
)
487 else if((nextruletoclean_timestamp
<= current_time
)
488 || (timestamp
< nextruletoclean_timestamp
))
489 nextruletoclean_timestamp
= timestamp
;
491 tmp
->proto
= (short)proto
;
492 /* add tmp to list */
495 /* prepare next iteration */
497 tmp
= malloc(sizeof(struct rule_state
));
502 /* remove the redirections that need to be removed */
503 for(p
= &list
, tmp
= list
; tmp
; tmp
= *p
)
507 syslog(LOG_NOTICE
, "remove port mapping %hu %s because it has expired",
508 tmp
->eport
, (tmp
->proto
==IPPROTO_TCP
)?"TCP":"UDP");
509 _upnp_delete_redir(tmp
->eport
, tmp
->proto
);
517 /* return empty list if not enough redirections */
518 if(i
<=max_rules_number_target
)
530 remove_unused_rules(struct rule_state
* list
)
532 char ifname
[IFNAMSIZ
];
533 unsigned short iport
;
534 struct rule_state
* tmp
;
537 unsigned int timestamp
;
542 /* remove the rule if no traffic has used it */
543 if(get_redirect_rule(ifname
, list
->eport
, list
->proto
,
544 0, 0, &iport
, 0, 0, ×tamp
,
545 &packets
, &bytes
) >= 0)
547 if(packets
== list
->packets
&& bytes
== list
->bytes
)
549 if(_upnp_delete_redir(list
->eport
, list
->proto
) >= 0)
558 syslog(LOG_NOTICE
, "removed %d unused rules", n
);
561 /* upnp_get_portmappings_in_range()
562 * return a list of all "external" ports for which a port
565 upnp_get_portmappings_in_range(unsigned short startport
,
566 unsigned short endport
,
567 const char * protocol
,
568 unsigned int * number
)
571 proto
= proto_atoi(protocol
);
574 return get_portmappings_in_range(startport
, endport
, proto
, number
);
577 #ifdef ENABLE_6FC_SERVICE
579 upnp_check_outbound_pinhole(int proto
, int * timeout
)
582 int s
, tmptimeout
, tmptime_out
;
586 s
= retrieve_timeout("udp_timeout", timeout
);
589 case IPPROTO_UDPLITE
:
590 s
= retrieve_timeout("udp_timeout_stream", timeout
);
594 s
= retrieve_timeout("tcp_timeout_established", timeout
);
598 s
= retrieve_timeout("udp_timeout", timeout
);
599 s
= retrieve_timeout("udp_timeout_stream", &tmptimeout
);
600 s
= retrieve_timeout("tcp_timeout_established", &tmptime_out
);
601 if(tmptimeout
<tmptime_out
)
603 if(tmptimeout
<*timeout
)
604 *timeout
= tmptimeout
;
608 if(tmptime_out
<*timeout
)
609 *timeout
= tmptimeout
;
621 /* upnp_add_inboundpinhole()
622 * returns: 0 on success
623 * -1 failed to add pinhole
625 * -3 inbound pinhole disabled
628 upnp_add_inboundpinhole(const char * raddr
,
629 unsigned short rport
,
631 unsigned short iport
,
632 const char * protocol
,
633 const char * leaseTime
,
637 char iaddr_old
[40]="", proto
[6]="", idfound
[5]="", leaseTmp
[12]; // IPv6 Modification
638 snprintf(proto
, sizeof(proto
), "%.5d", atoi(protocol
));
639 unsigned short iport_old
= 0;
640 time_t current
= time(NULL
);
641 /*struct in6_addr address; // IPv6 Modification
642 if(inet_pton(AF_INET6, iaddr, &address) < 0) // IPv6 Modification
644 syslog(LOG_ERR, "inet_pton(%s) : %m", iaddr);
649 r
= get_rule_from_file(raddr
, rport
, iaddr_old
, &iport_old
, proto
, 0, 0, idfound
);
653 lt
= (int) current
+ atoi(leaseTime
);
654 snprintf(leaseTmp
, sizeof(leaseTmp
), "%d", lt
);
655 printf("LeaseTime: %d / %d -> %s\n", atoi(leaseTime
), (int)current
, leaseTmp
);
657 printf("\tCompare addr: %s // port: %d\n\t to addr: %s // port: %d\n", iaddr
, iport
, iaddr_old
, iport_old
);
658 if(r
== 1 && strcmp(iaddr
, iaddr_old
)==0 && iport
==iport_old
)
660 syslog(LOG_INFO
, "Pinhole for inbound traffic from [%s]:%hu to [%s]:%hu with protocol %s already done. Updating it.", raddr
, rport
, iaddr_old
, iport_old
, protocol
);
661 t
= upnp_update_inboundpinhole(idfound
, leaseTime
);
662 *uid
= atoi(idfound
);
667 syslog(LOG_INFO
, "Adding pinhole for inbound traffic from [%s]:%hu to [%s]:%hu with protocol %s and %s lease time.", raddr
, rport
, iaddr
, iport
, protocol
, leaseTime
);
668 s
= upnp_add_inboundpinhole_internal(raddr
, rport
, iaddr
, iport
, protocol
, uid
);
670 if(rule_file_add(raddr
, rport
, iaddr
, iport
, protocol
, leaseTmp
, uid
)<0)
674 if(nextpinholetoclean_timestamp
== 0 || (atoi(leaseTmp
) <= nextpinholetoclean_timestamp
))
676 printf("Initializing the nextpinholetoclean variables. uid = %d\n", *uid
);
677 snprintf(nextpinholetoclean_uid
, 5, "%.4d", *uid
);
678 nextpinholetoclean_timestamp
= atoi(leaseTmp
);
688 upnp_add_inboundpinhole_internal(const char * raddr
, unsigned short rport
,
689 const char * iaddr
, unsigned short iport
,
690 const char * proto
, int * uid
)
693 char cmd
[256], cmd_raw
[256], cuid
[42];
695 static const char cmdval_full_udptcp
[] = "ip6tables -I %s %d -p %s -i %s -s %s --sport %hu -d %s --dport %hu -j ACCEPT";
696 static const char cmdval_udptcp
[] = "ip6tables -I %s %d -p %s -i %s --sport %hu -d %s --dport %hu -j ACCEPT";
697 static const char cmdval_full_udplite
[] = "ip6tables -I %s %d -p %s -i %s -s %s -d %s -j ACCEPT";
698 static const char cmdval_udplite
[] = "ip6tables -I %s %d -p %s -i %s -d %s -j ACCEPT";
700 static const char cmdval_full_udptcp_raw
[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s -s %s --sport %hu -d %s --dport %hu -j TRACE";
701 static const char cmdval_udptcp_raw
[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s --sport %hu -d %s --dport %hu -j TRACE";
702 static const char cmdval_full_udplite_raw
[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s -s %s -d %s -j TRACE";
703 static const char cmdval_udplite_raw
[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s -d %s -j TRACE";
705 //printf("%s\n", raddr);
708 #ifdef IPPROTO_UDPLITE
709 if(atoi(proto
) == IPPROTO_UDPLITE
)
711 /* snprintf(cmd, sizeof(cmd), cmdval_full_udplite, miniupnpd_forward_chain, line_number, proto, ext_if_name, raddr, iaddr);
712 snprintf(cmd_raw, sizeof(cmd_raw), cmdval_full_udplite_raw, line_number, proto, ext_if_name, raddr, iaddr);*/
717 /* snprintf(cmd, sizeof(cmd), cmdval_full_udptcp, miniupnpd_forward_chain, line_number, proto, ext_if_name, raddr, rport, iaddr, iport);
718 snprintf(cmd_raw, sizeof(cmd_raw), cmdval_full_udptcp_raw, line_number, proto, ext_if_name, raddr, rport, iaddr, iport);*/
723 #ifdef IPPROTO_UDPLITE
724 if(atoi(proto
) == IPPROTO_UDPLITE
)
726 /*snprintf(cmd, sizeof(cmd), cmdval_udplite, miniupnpd_forward_chain, line_number, proto, ext_if_name, iaddr);
727 snprintf(cmd_raw, sizeof(cmd_raw), cmdval_udplite_raw, line_number, proto, ext_if_name, iaddr);*/
732 /*snprintf(cmd, sizeof(cmd), cmdval_udptcp, miniupnpd_forward_chain, line_number, proto, ext_if_name, rport, iaddr, iport);
733 snprintf(cmd_raw, sizeof(cmd_raw), cmdval_udptcp_raw, line_number, proto, ext_if_name, rport, iaddr, iport);
738 syslog(LOG_INFO
, "Adding following ip6tables rule:");
739 syslog(LOG_INFO
, " -> %s", cmd
);
740 syslog(LOG_INFO
, " -> %s", cmd_raw
);
742 // TODO Add a better checking error.
743 if(system(cmd
) < 0 || system(cmd_raw
) < 0)
748 snprintf(cuid
, sizeof(cuid
), "%.4d", rand()%c
);
750 printf("\t_add_ uid: %s\n", cuid
);
755 upnp_get_pinhole_info(const char * raddr
,
756 unsigned short rport
,
758 unsigned short * iport
,
764 * Call Firewall specific code to get IPv6 pinhole infos */
769 upnp_update_inboundpinhole(const char * uid
, const char * leasetime
)
771 /* TODO : to be implemented */
774 syslog(LOG_INFO
, "Updating pinhole for inbound traffic with ID: %s", uid
);
775 r
= check_rule_from_file(uid
, 0);
780 n
= rule_file_update(uid
, leasetime
);
781 upnp_update_expiredpinhole();
790 upnp_delete_inboundpinhole(const char * uid
)
792 /* TODO : to be implemented */
794 /* this is a alpha implementation calling ip6tables via system(),
795 * it can be usefull as an example to code the netfilter version */
797 char cmd
[256], cmd_raw
[256];
798 syslog(LOG_INFO
, "Removing pinhole for inbound traffic with ID: %s", uid
);
799 r
= check_rule_from_file(uid
, &linenum
);
802 s
= rule_file_remove(uid
, linenum
);
807 snprintf(cmd
, sizeof(cmd
), "ip6tables -t filter -D %s %d", miniupnpd_forward_chain
, linenum
);
808 snprintf(cmd_raw
, sizeof(cmd_raw
), "ip6tables -t raw -D PREROUTING %d", linenum
-1);
810 syslog(LOG_INFO
, "Deleting ip6tables rule:");
811 syslog(LOG_INFO
, " -> %s", cmd
);
812 syslog(LOG_INFO
, " -> %s", cmd_raw
);
814 // TODO Add a better checking error.
815 if(system(cmd
) < 0 || system(cmd_raw
) < 0)
821 upnp_update_expiredpinhole();
832 * -5: Result in another table
833 * -6: Result in another chain
834 * -7: Result in a chain not a rule
837 upnp_check_pinhole_working(const char * uid
,
840 unsigned short * eport
,
841 unsigned short * iport
,
845 /* TODO : to be implemented */
848 time_t expire
= time(NULL
);
849 char buf
[1024], filename
[] = "/var/log/kern.log", expire_time
[32]="";
850 int res
= -4, str_len
;
852 str_len
= strftime(expire_time
, sizeof(expire_time
), "%b %d %H:%M:%S", localtime(&expire
));
854 fd
= fopen(filename
, "r");
857 syslog(LOG_ERR
, "Get_rule: could not open file: %s", filename
);
861 syslog(LOG_INFO
, "Get_rule: Starting getting info in file %s for %s\n", filename
, uid
);
862 buf
[sizeof(buf
)-1] = 0;
863 while(fgets(buf
, sizeof(buf
)-1, fd
) != NULL
&& res
!= 1)
865 //printf("line: %s\n", buf);
866 char * r
, * t
, * c
, * p
;
867 // looking for something like filter:FORWARD:rule: or filter:MINIUPNPD:rule:
868 r
= strstr(buf
, ":rule:");
869 p
= strstr(buf
, ":policy:");
870 t
= strstr(buf
, "TRACE:"); // table pointeur
872 c
= t
+ 7; // chain pointeur
875 printf("\t** Found %.*s\n", 24 ,t
);
876 char * src
, * dst
, * sport
, * dport
, * proto
, * line
;
877 char time
[15]="", src_addr
[40], dst_addr
[40], proto_tmp
[8];
879 strncpy(time
, buf
, sizeof(time
));
880 /*if(compare_time(time, expire_time)<0)
882 printf("\t\tNot corresponding time\n");
887 printf("\trule line = %d\n", atoi(line
));
889 src
= strstr(buf
, "SRC=");
891 snprintf(src_addr
, sizeof(src_addr
), "%.*s", 39, src
);
897 dst
= strstr(buf
, "DST=");
899 snprintf(dst_addr
, sizeof(dst_addr
), "%.*s", 39, dst
);
905 proto
= strstr(buf
, "PROTO=");
907 proto_int
= atoi(protocol
);
908 if(proto_int
== IPPROTO_UDP
)
909 strcpy(proto_tmp
, "UDP");
910 else if(proto_int
== IPPROTO_TCP
)
911 strcpy(proto_tmp
, "TCP");
912 #ifdef IPPROTO_UDPLITE
913 else if(proto_int
== IPPROTO_UDPLITE
)
914 strcpy(proto_tmp
, "UDPLITE");
917 strcpy(proto_tmp
, "UnsupportedProto");
919 // printf("\tCompare eaddr: %s // protocol: %s\n\t to addr: %s // protocol: %.*s\n", eaddr, proto_tmp, src_addr, strlen(proto_tmp), proto);
920 // printf("\tCompare iaddr: %s // protocol: %s\n\t to addr: %s // protocol: %.*s\n", iaddr, proto_tmp, dst_addr, strlen(proto_tmp), proto);
922 // Check that the paquet found in trace correspond to the one we are looking for
923 if( /*(strcmp(eaddr, src_addr) == 0) &&*/ (strcmp(iaddr
, dst_addr
) == 0) && (strncmp(proto_tmp
, proto
, strlen(proto_tmp
))==0))
925 sport
= strstr(buf
, "SPT=");
927 dport
= strstr(buf
, "DPT=");
929 printf("\tCompare eport: %hu\n\t to port: %d\n", *eport
, atoi(sport
));
930 printf("\tCompare iport: %hu\n\t to port: %d\n", *iport
, atoi(dport
));
931 if(/*eport != atoi(sport) &&*/ *iport
!= atoi(dport
))
933 printf("\t\tPort not corresponding\n");
936 printf("\ttable found: %.*s\n", 6, t
);
937 printf("\tchain found: %.*s\n", 9, c
);
938 // Check that the table correspond to the filter table
939 if(strncmp(t
, "filter", 6)==0)
941 // Check that the table correspond to the MINIUPNP table
942 if(strncmp(c
, "MINIUPNPD", 9)==0)
944 *rulenum_used
= atoi(line
);
961 printf("Packet information not corresponding\n");
967 printf("\t** Policy case\n");
968 char * src
, * dst
, * sport
, * dport
, * proto
, * line
;
969 char time
[15], src_addr
[40], dst_addr
[40], proto_tmp
[8];
971 strncpy(time
, buf
, sizeof(time
));
972 /*if(compare_time(time, expire_time)<0)
974 printf("\t\tNot corresponding time\n");
979 printf("\trule line = %d\n", atoi(line
));
981 src
= strstr(buf
, "SRC=");
983 snprintf(src_addr
, sizeof(src_addr
), "%.*s", 39, src
);
989 dst
= strstr(buf
, "DST=");
991 snprintf(dst_addr
, sizeof(dst_addr
), "%.*s", 39, dst
);
997 proto
= strstr(buf
, "PROTO=");
999 proto_int
= atoi(protocol
);
1000 if(proto_int
== IPPROTO_UDP
)
1001 strcpy(proto_tmp
, "UDP");
1002 else if(proto_int
== IPPROTO_TCP
)
1003 strcpy(proto_tmp
, "TCP");
1004 #ifdef IPPROTO_UDPLITE
1005 else if(proto_int
== IPPROTO_UDPLITE
)
1006 strcpy(proto_tmp
, "UDPLITE");
1009 strcpy(proto_tmp
, "UnsupportedProto");
1011 // printf("\tCompare eaddr: %s // protocol: %s\n\t to addr: %s // protocol: %.*s\n", eaddr, proto_tmp, src_addr, strlen(proto_tmp), proto);
1012 // printf("\tCompare iaddr: %s // protocol: %s\n\t to addr: %s // protocol: %.*s\n", iaddr, proto_tmp, dst_addr, strlen(proto_tmp), proto);
1013 // Check that the paquet found in trace correspond to the one we are looking for
1014 if( (strcmp(eaddr
, src_addr
) == 0) && (strcmp(iaddr
, dst_addr
) == 0) && (strncmp(proto_tmp
, proto
, 5)==0))
1016 sport
= strstr(buf
, "SPT=");
1018 dport
= strstr(buf
, "DPT=");
1020 printf("\tCompare eport: %hu\n\t to port: %d\n", *eport
, atoi(sport
));
1021 printf("\tCompare iport: %hu\n\t to port: %d\n", *iport
, atoi(dport
));
1022 if(*eport
!= atoi(sport
) && *iport
!= atoi(dport
))
1024 printf("\t\tPort not corresponding\n");
1029 printf("Find a corresponding policy trace in the chain: %.*s\n", 10, c
);
1046 upnp_get_pinhole_packets(const char * uid
, int * packets
)
1048 /* TODO : to be implemented */
1052 r
= check_rule_from_file(uid
, &line
);
1057 snprintf(cmd
, sizeof(cmd
), "ip6tables -L MINIUPNPD %d -v", line
);
1058 return retrieve_packets(cmd
, &line
, packets
);
1066 upnp_update_expiredpinhole(void)
1070 char uid
[5], leaseTime
[12];
1072 r
= get_rule_from_leasetime(uid
, leaseTime
);
1077 strcpy(nextpinholetoclean_uid
, uid
);
1078 nextpinholetoclean_timestamp
= atoi(leaseTime
);
1086 upnp_clean_expiredpinhole()
1089 upnp_delete_inboundpinhole(nextpinholetoclean_uid
);
1091 return upnp_update_expiredpinhole();
1097 /* stuff for miniupnpdctl */
1098 #ifdef USE_MINIUPNPDCTL
1100 write_ruleset_details(int s
)
1103 unsigned short eport
, iport
;
1107 unsigned int timestamp
;
1114 write(s
, "Ruleset :\n", 10);
1115 while(get_redirect_rule_by_index(i
, 0/*ifname*/, &eport
, iaddr
, sizeof(iaddr
),
1116 &iport
, &proto
, desc
, sizeof(desc
),
1117 rhost
, sizeof(rhost
),
1119 &packets
, &bytes
) >= 0)
1121 n
= snprintf(buffer
, sizeof(buffer
),
1122 "%2d %s %s:%hu->%s:%hu "
1123 "'%s' %u %" PRIu64
" %" PRIu64
"\n",
1124 /*"'%s' %llu %llu\n",*/
1125 i
, proto
==IPPROTO_TCP
?"TCP":"UDP", rhost
,
1126 eport
, iaddr
, iport
, desc
, timestamp
, packets
, bytes
);
1127 write(s
, buffer
, n
);