File: | libs/libnatpmp/natpmp.c |
Location: | line 214, column 31 |
Description: | The left operand of '!=' is a garbage value |
1 | /* $Id: natpmp.c,v 1.8 2008/07/02 22:33:06 nanard Exp $ */ | |||
2 | /* libnatpmp | |||
3 | * Copyright (c) 2007-2008, Thomas BERNARD <miniupnp@free.fr> | |||
4 | * http://miniupnp.free.fr/libnatpmp.html | |||
5 | * | |||
6 | * Permission to use, copy, modify, and/or distribute this software for any | |||
7 | * purpose with or without fee is hereby granted, provided that the above | |||
8 | * copyright notice and this permission notice appear in all copies. | |||
9 | * | |||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ | |||
17 | #ifdef __linux__1 | |||
18 | #ifndef _DEFAULT_SOURCE1 | |||
19 | #define _DEFAULT_SOURCE1 | |||
20 | #endif | |||
21 | #define _BSD_SOURCE1 1 | |||
22 | #endif | |||
23 | #include <string.h> | |||
24 | #include <time.h> | |||
25 | #ifndef _MSC_VER | |||
26 | #include <sys/time.h> | |||
27 | #endif | |||
28 | #ifdef WIN32 | |||
29 | #include <winsock2.h> | |||
30 | #include <Ws2tcpip.h> | |||
31 | #include <io.h> | |||
32 | #define EWOULDBLOCK11 WSAEWOULDBLOCK | |||
33 | #define ECONNREFUSED111 WSAECONNREFUSED | |||
34 | ||||
35 | static int gettimeofday(struct timeval* p, void* tz /* IGNORED */) { | |||
36 | union { | |||
37 | long long ns100; /*time since 1 Jan 1601 in 100ns units */ | |||
38 | FILETIME ft; | |||
39 | } _now; | |||
40 | ||||
41 | GetSystemTimeAsFileTime( &(_now.ft) ); | |||
42 | p->tv_usec=(long)((_now.ns100 / 10LL) % 1000000LL ); | |||
43 | p->tv_sec= (long)((_now.ns100-(116444736000000000LL))/10000000LL); | |||
44 | return 0; | |||
45 | } | |||
46 | ||||
47 | #else | |||
48 | #include <errno(*__errno_location ()).h> | |||
49 | #include <unistd.h> | |||
50 | #include <fcntl.h> | |||
51 | #include <sys/types.h> | |||
52 | #include <sys/socket.h> | |||
53 | #define closesocketclose close | |||
54 | #endif | |||
55 | #include "natpmp.h" | |||
56 | #include "getgateway.h" | |||
57 | ||||
58 | int initnatpmp(natpmp_t * p) | |||
59 | { | |||
60 | #ifdef WIN32 | |||
61 | u_long ioctlArg = 1; | |||
62 | #else | |||
63 | int flags; | |||
64 | #endif | |||
65 | struct sockaddr_in addr; | |||
66 | if(!p) | |||
67 | return NATPMP_ERR_INVALIDARGS(-1); | |||
68 | memset(p, 0, sizeof(natpmp_t)); | |||
69 | p->s = socket(PF_INET2, SOCK_DGRAMSOCK_DGRAM, 0); | |||
70 | if(p->s < 0) | |||
71 | return NATPMP_ERR_SOCKETERROR(-2); | |||
72 | #ifdef WIN32 | |||
73 | if(ioctlsocket(p->s, FIONBIO, &ioctlArg) == SOCKET_ERROR) | |||
74 | return NATPMP_ERR_FCNTLERROR(-11); | |||
75 | #else | |||
76 | if((flags = fcntl(p->s, F_GETFL3, 0)) < 0) | |||
77 | return NATPMP_ERR_FCNTLERROR(-11); | |||
78 | if(fcntl(p->s, F_SETFL4, flags | O_NONBLOCK04000) < 0) | |||
79 | return NATPMP_ERR_FCNTLERROR(-11); | |||
80 | #endif | |||
81 | ||||
82 | if(getdefaultgateway(&(p->gateway)) < 0) | |||
83 | return NATPMP_ERR_CANNOTGETGATEWAY(-3); | |||
84 | ||||
85 | memset(&addr, 0, sizeof(addr)); | |||
86 | addr.sin_family = AF_INET2; | |||
87 | addr.sin_port = htons(NATPMP_PORT)(__extension__ ({ unsigned short int __v, __x = (unsigned short int) ((5351)); if (__builtin_constant_p (__x)) __v = ((unsigned short int) ((((__x) >> 8) & 0xff) | (((__x) & 0xff ) << 8))); else __asm__ ("rorw $8, %w0" : "=r" (__v) : "0" (__x) : "cc"); __v; })); | |||
88 | addr.sin_addr.s_addr = p->gateway; | |||
89 | if(connect(p->s, (struct sockaddr *)&addr, sizeof(addr)) < 0) | |||
90 | return NATPMP_ERR_CONNECTERR(-8); | |||
91 | return 0; | |||
92 | } | |||
93 | ||||
94 | int closenatpmp(natpmp_t * p) | |||
95 | { | |||
96 | if(!p) | |||
97 | return NATPMP_ERR_INVALIDARGS(-1); | |||
98 | if(closesocketclose(p->s) < 0) | |||
99 | return NATPMP_ERR_CLOSEERR(-4); | |||
100 | return 0; | |||
101 | } | |||
102 | ||||
103 | int sendpendingrequest(natpmp_t * p) | |||
104 | { | |||
105 | int r; | |||
106 | /* struct sockaddr_in addr;*/ | |||
107 | if(!p) | |||
108 | return NATPMP_ERR_INVALIDARGS(-1); | |||
109 | /* memset(&addr, 0, sizeof(addr)); | |||
110 | addr.sin_family = AF_INET; | |||
111 | addr.sin_port = htons(NATPMP_PORT); | |||
112 | addr.sin_addr.s_addr = p->gateway; | |||
113 | r = (int)sendto(p->s, p->pending_request, p->pending_request_len, 0, | |||
114 | (struct sockaddr *)&addr, sizeof(addr));*/ | |||
115 | r = (int)send(p->s, p->pending_request, p->pending_request_len, 0); | |||
116 | return (r<0) ? NATPMP_ERR_SENDERR(-10) : r; | |||
117 | } | |||
118 | ||||
119 | int sendnatpmprequest(natpmp_t * p) | |||
120 | { | |||
121 | int n; | |||
122 | if(!p) | |||
123 | return NATPMP_ERR_INVALIDARGS(-1); | |||
124 | /* TODO : check if no request is allready pending */ | |||
125 | p->has_pending_request = 1; | |||
126 | p->try_number = 1; | |||
127 | n = sendpendingrequest(p); | |||
128 | gettimeofday(&p->retry_time, NULL((void*)0)); // check errors ! | |||
129 | p->retry_time.tv_usec += 250000; /* add 250ms */ | |||
130 | if(p->retry_time.tv_usec >= 1000000) { | |||
131 | p->retry_time.tv_usec -= 1000000; | |||
132 | p->retry_time.tv_sec++; | |||
133 | } | |||
134 | return n; | |||
135 | } | |||
136 | ||||
137 | int getnatpmprequesttimeout(natpmp_t * p, struct timeval * timeout) | |||
138 | { | |||
139 | struct timeval now; | |||
140 | if(!p || !timeout) | |||
141 | return NATPMP_ERR_INVALIDARGS(-1); | |||
142 | if(!p->has_pending_request) | |||
143 | return NATPMP_ERR_NOPENDINGREQ(-6); | |||
144 | if(gettimeofday(&now, NULL((void*)0)) < 0) | |||
145 | return NATPMP_ERR_GETTIMEOFDAYERR(-12); | |||
146 | timeout->tv_sec = p->retry_time.tv_sec - now.tv_sec; | |||
147 | timeout->tv_usec = p->retry_time.tv_usec - now.tv_usec; | |||
148 | if(timeout->tv_usec < 0) { | |||
149 | timeout->tv_usec += 1000000; | |||
150 | timeout->tv_sec--; | |||
151 | } | |||
152 | return 0; | |||
153 | } | |||
154 | ||||
155 | int sendpublicaddressrequest(natpmp_t * p) | |||
156 | { | |||
157 | if(!p) | |||
158 | return NATPMP_ERR_INVALIDARGS(-1); | |||
159 | //static const unsigned char request[] = { 0, 0 }; | |||
160 | p->pending_request[0] = 0; | |||
161 | p->pending_request[1] = 0; | |||
162 | p->pending_request_len = 2; | |||
163 | // TODO: return 0 instead of sizeof(request) ?? | |||
164 | return sendnatpmprequest(p); | |||
165 | } | |||
166 | ||||
167 | int sendnewportmappingrequest(natpmp_t * p, int protocol, | |||
168 | uint16_t privateport, uint16_t publicport, | |||
169 | uint32_t lifetime) | |||
170 | { | |||
171 | uint16_t *n; | |||
172 | uint32_t *m; | |||
173 | ||||
174 | if(!p || (protocol!=NATPMP_PROTOCOL_TCP(2) && protocol!=NATPMP_PROTOCOL_UDP(1))) | |||
175 | return NATPMP_ERR_INVALIDARGS(-1); | |||
176 | p->pending_request[0] = 0; | |||
177 | p->pending_request[1] = (char)protocol; | |||
178 | p->pending_request[2] = 0; | |||
179 | p->pending_request[3] = 0; | |||
180 | n = (uint16_t *)(p->pending_request + 4); *n = htons(privateport)(__extension__ ({ unsigned short int __v, __x = (unsigned short int) (privateport); if (__builtin_constant_p (__x)) __v = (( unsigned short int) ((((__x) >> 8) & 0xff) | (((__x ) & 0xff) << 8))); else __asm__ ("rorw $8, %w0" : "=r" (__v) : "0" (__x) : "cc"); __v; })); | |||
181 | n = (uint16_t *)(p->pending_request + 6); *n = htons(publicport)(__extension__ ({ unsigned short int __v, __x = (unsigned short int) (publicport); if (__builtin_constant_p (__x)) __v = ((unsigned short int) ((((__x) >> 8) & 0xff) | (((__x) & 0xff ) << 8))); else __asm__ ("rorw $8, %w0" : "=r" (__v) : "0" (__x) : "cc"); __v; })); | |||
182 | m = (uint32_t *)(p->pending_request + 8); *m = htonl(lifetime)(__extension__ ({ unsigned int __v, __x = (lifetime); if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000) >> 24) | (((__x ) & 0x00ff0000) >> 8) | (((__x) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) << 24)); else __asm__ ( "bswap %0" : "=r" (__v) : "0" (__x)); __v; })); | |||
183 | ||||
184 | //*((uint16_t *)(p->pending_request + 4)) = htons(privateport); | |||
185 | //*((uint16_t *)(p->pending_request + 6)) = htons(publicport); | |||
186 | //*((uint32_t *)(p->pending_request + 8)) = htonl(lifetime); | |||
187 | p->pending_request_len = 12; | |||
188 | return sendnatpmprequest(p); | |||
189 | } | |||
190 | ||||
191 | int readnatpmpresponse(natpmp_t * p, natpmpresp_t * response) | |||
192 | { | |||
193 | unsigned char buf[16]; | |||
194 | struct sockaddr_in addr; | |||
195 | socklen_t addrlen = sizeof(addr); | |||
196 | int n; | |||
197 | if(!p) | |||
198 | return NATPMP_ERR_INVALIDARGS(-1); | |||
199 | n = recvfrom(p->s, (char *)buf, sizeof(buf), 0, | |||
200 | (struct sockaddr *)&addr, &addrlen); | |||
201 | if(n<0) | |||
202 | switch(errno(*__errno_location ())) { | |||
203 | /*case EAGAIN:*/ | |||
204 | case EWOULDBLOCK11: | |||
205 | n = NATPMP_TRYAGAIN(-100); | |||
206 | break; | |||
207 | case ECONNREFUSED111: | |||
208 | n = NATPMP_ERR_NOGATEWAYSUPPORT(-7); | |||
209 | break; | |||
210 | default: | |||
211 | n = NATPMP_ERR_RECVFROM(-5); | |||
212 | } | |||
213 | /* check that addr is correct (= gateway) */ | |||
214 | else if(addr.sin_addr.s_addr != p->gateway) | |||
| ||||
215 | n = NATPMP_ERR_WRONGPACKETSOURCE(-9); | |||
216 | else { | |||
217 | response->resultcode = ntohs(*((uint16_t *)(buf + 2)))(__extension__ ({ unsigned short int __v, __x = (unsigned short int) (*((uint16_t *)(buf + 2))); if (__builtin_constant_p (__x )) __v = ((unsigned short int) ((((__x) >> 8) & 0xff ) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0" : "=r" (__v) : "0" (__x) : "cc"); __v; })); | |||
218 | response->epoch = ntohl(*((uint32_t *)(buf + 4)))(__extension__ ({ unsigned int __v, __x = (*((uint32_t *)(buf + 4))); if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x) & 0x0000ff00) << 8) | (((__x) & 0x000000ff ) << 24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" ( __x)); __v; })); | |||
219 | if(buf[0] != 0) | |||
220 | n = NATPMP_ERR_UNSUPPORTEDVERSION(-14); | |||
221 | else if(buf[1] < 128 || buf[1] > 130) | |||
222 | n = NATPMP_ERR_UNSUPPORTEDOPCODE(-15); | |||
223 | else if(response->resultcode != 0) { | |||
224 | switch(response->resultcode) { | |||
225 | case 1: | |||
226 | n = NATPMP_ERR_UNSUPPORTEDVERSION(-14); | |||
227 | break; | |||
228 | case 2: | |||
229 | n = NATPMP_ERR_NOTAUTHORIZED(-51); | |||
230 | break; | |||
231 | case 3: | |||
232 | n = NATPMP_ERR_NETWORKFAILURE(-52); | |||
233 | break; | |||
234 | case 4: | |||
235 | n = NATPMP_ERR_OUTOFRESOURCES(-53); | |||
236 | break; | |||
237 | case 5: | |||
238 | n = NATPMP_ERR_UNSUPPORTEDOPCODE(-15); | |||
239 | break; | |||
240 | default: | |||
241 | n = NATPMP_ERR_UNDEFINEDERROR(-49); | |||
242 | } | |||
243 | } else { | |||
244 | response->type = buf[1] & 0x7f; | |||
245 | if(buf[1] == 128) | |||
246 | //response->publicaddress.addr = *((uint32_t *)(buf + 8)); | |||
247 | response->pnu.publicaddress.addr.s_addr = *((uint32_t *)(buf + 8)); | |||
248 | else { | |||
249 | response->pnu.newportmapping.privateport = ntohs(*((uint16_t *)(buf + 8)))(__extension__ ({ unsigned short int __v, __x = (unsigned short int) (*((uint16_t *)(buf + 8))); if (__builtin_constant_p (__x )) __v = ((unsigned short int) ((((__x) >> 8) & 0xff ) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0" : "=r" (__v) : "0" (__x) : "cc"); __v; })); | |||
250 | response->pnu.newportmapping.mappedpublicport = ntohs(*((uint16_t *)(buf + 10)))(__extension__ ({ unsigned short int __v, __x = (unsigned short int) (*((uint16_t *)(buf + 10))); if (__builtin_constant_p ( __x)) __v = ((unsigned short int) ((((__x) >> 8) & 0xff ) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0" : "=r" (__v) : "0" (__x) : "cc"); __v; })); | |||
251 | response->pnu.newportmapping.lifetime = ntohl(*((uint32_t *)(buf + 12)))(__extension__ ({ unsigned int __v, __x = (*((uint32_t *)(buf + 12))); if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x) & 0x0000ff00) << 8) | (((__x) & 0x000000ff ) << 24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" ( __x)); __v; })); | |||
252 | } | |||
253 | n = 0; | |||
254 | } | |||
255 | } | |||
256 | return n; | |||
257 | } | |||
258 | ||||
259 | int readnatpmpresponseorretry(natpmp_t * p, natpmpresp_t * response) | |||
260 | { | |||
261 | int n; | |||
262 | if(!p || !response) | |||
| ||||
263 | return NATPMP_ERR_INVALIDARGS(-1); | |||
264 | if(!p->has_pending_request) | |||
265 | return NATPMP_ERR_NOPENDINGREQ(-6); | |||
266 | n = readnatpmpresponse(p, response); | |||
267 | if(n<0) { | |||
268 | if(n==NATPMP_TRYAGAIN(-100)) { | |||
269 | struct timeval now; | |||
270 | gettimeofday(&now, NULL((void*)0)); // check errors ! | |||
271 | if(timercmp(&now, &p->retry_time, >=)(((&now)->tv_sec == (&p->retry_time)->tv_sec ) ? ((&now)->tv_usec >= (&p->retry_time)-> tv_usec) : ((&now)->tv_sec >= (&p->retry_time )->tv_sec))) { | |||
272 | int delay, r; | |||
273 | if(p->try_number >= 9) { | |||
274 | return NATPMP_ERR_NOGATEWAYSUPPORT(-7); | |||
275 | } | |||
276 | /*printf("retry! %d\n", p->try_number);*/ | |||
277 | delay = 250 * (1<<p->try_number); // ms | |||
278 | /*for(i=0; i<p->try_number; i++) | |||
279 | delay += delay;*/ | |||
280 | p->retry_time.tv_sec += (delay / 1000); | |||
281 | p->retry_time.tv_usec += (delay % 1000) * 1000; | |||
282 | if(p->retry_time.tv_usec >= 1000000) { | |||
283 | p->retry_time.tv_usec -= 1000000; | |||
284 | p->retry_time.tv_sec++; | |||
285 | } | |||
286 | p->try_number++; | |||
287 | r = sendpendingrequest(p); | |||
288 | if(r<0) | |||
289 | return r; | |||
290 | } | |||
291 | } | |||
292 | } else { | |||
293 | p->has_pending_request = 0; | |||
294 | } | |||
295 | return n; | |||
296 | } | |||
297 | ||||
298 | #ifdef ENABLE_STRNATPMPERR | |||
299 | const char * strnatpmperr(int r) | |||
300 | { | |||
301 | const char * s; | |||
302 | switch(r) { | |||
303 | case NATPMP_ERR_INVALIDARGS(-1): | |||
304 | s = "invalid arguments"; | |||
305 | break; | |||
306 | case NATPMP_ERR_SOCKETERROR(-2): | |||
307 | s = "socket() failed"; | |||
308 | break; | |||
309 | case NATPMP_ERR_CANNOTGETGATEWAY(-3): | |||
310 | s = "cannot get default gateway ip address"; | |||
311 | break; | |||
312 | case NATPMP_ERR_CLOSEERR(-4): | |||
313 | #ifdef WIN32 | |||
314 | s = "closesocket() failed"; | |||
315 | #else | |||
316 | s = "close() failed"; | |||
317 | #endif | |||
318 | break; | |||
319 | case NATPMP_ERR_RECVFROM(-5): | |||
320 | s = "recvfrom() failed"; | |||
321 | break; | |||
322 | case NATPMP_ERR_NOPENDINGREQ(-6): | |||
323 | s = "no pending request"; | |||
324 | break; | |||
325 | case NATPMP_ERR_NOGATEWAYSUPPORT(-7): | |||
326 | s = "the gateway does not support nat-pmp"; | |||
327 | break; | |||
328 | case NATPMP_ERR_CONNECTERR(-8): | |||
329 | s = "connect() failed"; | |||
330 | break; | |||
331 | case NATPMP_ERR_WRONGPACKETSOURCE(-9): | |||
332 | s = "packet not received from the default gateway"; | |||
333 | break; | |||
334 | case NATPMP_ERR_SENDERR(-10): | |||
335 | s = "send() failed"; | |||
336 | break; | |||
337 | case NATPMP_ERR_FCNTLERROR(-11): | |||
338 | s = "fcntl() failed"; | |||
339 | break; | |||
340 | case NATPMP_ERR_GETTIMEOFDAYERR(-12): | |||
341 | s = "gettimeofday() failed"; | |||
342 | break; | |||
343 | case NATPMP_ERR_UNSUPPORTEDVERSION(-14): | |||
344 | s = "unsupported nat-pmp version error from server"; | |||
345 | break; | |||
346 | case NATPMP_ERR_UNSUPPORTEDOPCODE(-15): | |||
347 | s = "unsupported nat-pmp opcode error from server"; | |||
348 | break; | |||
349 | case NATPMP_ERR_UNDEFINEDERROR(-49): | |||
350 | s = "undefined nat-pmp server error"; | |||
351 | break; | |||
352 | case NATPMP_ERR_NOTAUTHORIZED(-51): | |||
353 | s = "not authorized"; | |||
354 | break; | |||
355 | case NATPMP_ERR_NETWORKFAILURE(-52): | |||
356 | s = "network failure"; | |||
357 | break; | |||
358 | case NATPMP_ERR_OUTOFRESOURCES(-53): | |||
359 | s = "nat-pmp server out of resources"; | |||
360 | break; | |||
361 | default: | |||
362 | s = "Unknown libnatpmp error"; | |||
363 | } | |||
364 | return s; | |||
365 | } | |||
366 | #endif | |||
367 |