usbmodeswitch: Updated to v.1.2.6 from shibby's branch.
[tomato.git] / release / src / router / miniupnpd / upnppermissions.c
blob0fd43f711327cac46c3815fc2864077250f5cb8b
1 /* $Id: upnppermissions.c,v 1.17 2012/02/15 22:43:34 nanard Exp $ */
2 /* MiniUPnP project
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006-2012 Thomas Bernard
5 * This software is subject to the conditions detailed
6 * in the LICENCE file provided within the distribution */
8 #include <ctype.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <syslog.h>
13 #include <netinet/in.h>
14 #include <arpa/inet.h>
15 #include <unistd.h>
16 #include "config.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
24 int
25 read_permission_line(struct upnpperm * perm,
26 char * p)
28 char * q;
29 int n_bits;
30 int i;
32 /* first token: (allow|deny) */
33 while(isspace(*p))
34 p++;
35 if(0 == memcmp(p, "allow", 5))
37 perm->type = UPNPPERM_ALLOW;
38 p += 5;
40 else if(0 == memcmp(p, "deny", 4))
42 perm->type = UPNPPERM_DENY;
43 p += 4;
45 else
47 return -1;
49 while(isspace(*p))
50 p++;
52 /* second token: eport or eport_min-eport_max */
53 if(!isdigit(*p))
54 return -1;
55 for(q = p; isdigit(*q); q++);
56 if(*q=='-')
58 *q = '\0';
59 i = atoi(p);
60 if(i > 65535)
61 return -1;
62 perm->eport_min = (u_short)i;
63 q++;
64 p = q;
65 while(isdigit(*q))
66 q++;
67 *q = '\0';
68 i = atoi(p);
69 if(i > 65535)
70 return -1;
71 perm->eport_max = (u_short)i;
72 if(perm->eport_min > perm->eport_max)
73 return -1;
75 else if(isspace(*q))
77 *q = '\0';
78 i = atoi(p);
79 if(i > 65535)
80 return -1;
81 perm->eport_min = perm->eport_max = (u_short)i;
83 else
85 return -1;
87 p = q + 1;
88 while(isspace(*p))
89 p++;
91 /* third token: ip/mask */
92 if(!isdigit(*p))
93 return -1;
94 for(q = p; isdigit(*q) || (*q == '.'); q++);
95 if(*q=='/')
97 *q = '\0';
98 if(!inet_aton(p, &perm->address))
99 return -1;
100 q++;
101 p = q;
102 while(isdigit(*q))
103 q++;
104 if(*q == '.')
106 while(*q == '.' || isdigit(*q))
107 q++;
108 if(!isspace(*q))
109 return -1;
110 *q = '\0';
111 if(!inet_aton(p, &perm->mask))
112 return -1;
114 else if(!isspace(*q))
115 return -1;
116 else
118 *q = '\0';
119 n_bits = atoi(p);
120 if(n_bits > 32)
121 return -1;
122 perm->mask.s_addr = htonl(n_bits ? (0xffffffffu << (32 - n_bits)) : 0);
125 else if(isspace(*q))
127 *q = '\0';
128 if(!inet_aton(p, &perm->address))
129 return -1;
130 perm->mask.s_addr = 0xffffffffu;
132 else
134 return -1;
136 p = q + 1;
138 /* fourth token: iport or iport_min-iport_max */
139 while(isspace(*p))
140 p++;
141 if(!isdigit(*p))
142 return -1;
143 for(q = p; isdigit(*q); q++);
144 if(*q=='-')
146 *q = '\0';
147 i = atoi(p);
148 if(i > 65535)
149 return -1;
150 perm->iport_min = (u_short)i;
151 q++;
152 p = q;
153 while(isdigit(*q))
154 q++;
155 *q = '\0';
156 i = atoi(p);
157 if(i > 65535)
158 return -1;
159 perm->iport_max = (u_short)i;
160 if(perm->iport_min > perm->iport_max)
161 return -1;
163 else if(isspace(*q) || *q == '\0')
165 *q = '\0';
166 i = atoi(p);
167 if(i > 65535)
168 return -1;
169 perm->iport_min = perm->iport_max = (u_short)i;
171 else
173 return -1;
175 #ifdef DEBUG
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);
180 #endif
181 return 0;
184 #ifdef USE_MINIUPNPDCTL
185 void
186 write_permlist(int fd, const struct upnpperm * permary,
187 int nperms)
189 int l;
190 const struct upnpperm * perm;
191 int i;
192 char buf[128];
193 write(fd, "Permissions :\n", 14);
194 for(i = 0; i<nperms; i++)
196 perm = permary + 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);
202 if(l<0)
203 return;
204 write(fd, buf, l);
207 #endif
209 /* match_permission()
210 * returns: 1 if eport, address, iport matches the permission rule
211 * 0 if no match */
212 static int
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))
217 return 0;
218 if( (iport < perm->iport_min) || (perm->iport_max < iport))
219 return 0;
220 if( (address.s_addr & perm->mask.s_addr)
221 != (perm->address.s_addr & perm->mask.s_addr) )
222 return 0;
223 return 1;
227 check_upnp_rule_against_permissions(const struct upnpperm * permary,
228 int n_perms,
229 u_short eport, struct in_addr address,
230 u_short iport)
232 int i;
233 for(i=0; i<n_perms; i++)
235 if(match_permission(permary + i, eport, address, iport))
237 syslog(LOG_DEBUG,
238 "UPnP permission rule %d matched : port mapping %s",
239 i, (permary[i].type == UPNPPERM_ALLOW)?"accepted":"rejected"
241 return (permary[i].type == UPNPPERM_ALLOW);
244 syslog(LOG_DEBUG, "no permission rule matched : accept by default (n_perms=%d)", n_perms);
245 return 1; /* Default : accept */