1 /* $Id: upnppermissions.c,v 1.19 2014/03/13 10:11:24 nanard Exp $ */
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006-2014 Thomas Bernard
5 * This software is subject to the conditions detailed
6 * in the LICENCE file provided within the distribution */
13 #include <netinet/in.h>
14 #include <arpa/inet.h>
17 #include "upnppermissions.h"
19 /* read_permission_line()
20 * parse the a permission line which format is :
21 * (deny|allow) [0-9]+(-[0-9]+) ip/mask [0-9]+(-[0-9]+)
22 * ip/mask is either 192.168.1.1/24 or 192.168.1.1/255.255.255.0
25 read_permission_line(struct upnpperm
* perm
,
32 /* first token: (allow|deny) */
35 if(0 == memcmp(p
, "allow", 5))
37 perm
->type
= UPNPPERM_ALLOW
;
40 else if(0 == memcmp(p
, "deny", 4))
42 perm
->type
= UPNPPERM_DENY
;
52 /* second token: eport or eport_min-eport_max */
55 for(q
= p
; isdigit(*q
); q
++);
62 perm
->eport_min
= (u_short
)i
;
71 perm
->eport_max
= (u_short
)i
;
72 if(perm
->eport_min
> perm
->eport_max
)
81 perm
->eport_min
= perm
->eport_max
= (u_short
)i
;
91 /* third token: ip/mask */
94 for(q
= p
; isdigit(*q
) || (*q
== '.'); q
++);
98 if(!inet_aton(p
, &perm
->address
))
106 while(*q
== '.' || isdigit(*q
))
111 if(!inet_aton(p
, &perm
->mask
))
114 else if(!isspace(*q
))
122 perm
->mask
.s_addr
= htonl(n_bits
? (0xffffffffu
<< (32 - n_bits
)) : 0);
128 if(!inet_aton(p
, &perm
->address
))
130 perm
->mask
.s_addr
= 0xffffffffu
;
138 /* fourth token: iport or iport_min-iport_max */
143 for(q
= p
; isdigit(*q
); q
++);
150 perm
->iport_min
= (u_short
)i
;
159 perm
->iport_max
= (u_short
)i
;
160 if(perm
->iport_min
> perm
->iport_max
)
163 else if(isspace(*q
) || *q
== '\0')
169 perm
->iport_min
= perm
->iport_max
= (u_short
)i
;
176 printf("perm rule added : %s %hu-%hu %08x/%08x %hu-%hu\n",
177 (perm
->type
==UPNPPERM_ALLOW
)?"allow":"deny",
178 perm
->eport_min
, perm
->eport_max
, ntohl(perm
->address
.s_addr
),
179 ntohl(perm
->mask
.s_addr
), perm
->iport_min
, perm
->iport_max
);
184 #ifdef USE_MINIUPNPDCTL
186 write_permlist(int fd
, const struct upnpperm
* permary
,
190 const struct upnpperm
* perm
;
193 write(fd
, "Permissions :\n", 14);
194 for(i
= 0; i
<nperms
; i
++)
197 l
= snprintf(buf
, sizeof(buf
), "%02d %s %hu-%hu %08x/%08x %hu-%hu\n",
199 (perm
->type
==UPNPPERM_ALLOW
)?"allow":"deny",
200 perm
->eport_min
, perm
->eport_max
, ntohl(perm
->address
.s_addr
),
201 ntohl(perm
->mask
.s_addr
), perm
->iport_min
, perm
->iport_max
);
209 /* match_permission()
210 * returns: 1 if eport, address, iport matches the permission rule
213 match_permission(const struct upnpperm
* perm
,
214 u_short eport
, struct in_addr address
, u_short iport
)
216 if( (eport
< perm
->eport_min
) || (perm
->eport_max
< eport
))
218 if( (iport
< perm
->iport_min
) || (perm
->iport_max
< iport
))
220 if( (address
.s_addr
& perm
->mask
.s_addr
)
221 != (perm
->address
.s_addr
& perm
->mask
.s_addr
) )
227 /* match_permission_internal()
228 * returns: 1 if address, iport matches the permission rule
231 match_permission_internal(const struct upnpperm
* perm
,
232 struct in_addr address
, u_short iport
)
234 if( (iport
< perm
->iport_min
) || (perm
->iport_max
< iport
))
236 if( (address
.s_addr
& perm
->mask
.s_addr
)
237 != (perm
->address
.s_addr
& perm
->mask
.s_addr
) )
244 check_upnp_rule_against_permissions(const struct upnpperm
* permary
,
246 u_short eport
, struct in_addr address
,
250 for(i
=0; i
<n_perms
; i
++)
252 if(match_permission(permary
+ i
, eport
, address
, iport
))
255 "UPnP permission rule %d matched : port mapping %s",
256 i
, (permary
[i
].type
== UPNPPERM_ALLOW
)?"accepted":"rejected"
258 return (permary
[i
].type
== UPNPPERM_ALLOW
);
261 syslog(LOG_DEBUG
, "no permission rule matched : accept by default (n_perms=%d)", n_perms
);
262 return 1; /* Default : accept */