Bug Summary

File:src/usr.sbin/npppd/npppd/npppd_pool.c
Warning:line 303, column 5
Value stored to 'result' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name npppd_pool.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/npppd/npppd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/npppd/npppd/../common -I /usr/src/usr.sbin/npppd/npppd -I /usr/src/usr.sbin/npppd/npppd/../pptp -I /usr/src/usr.sbin/npppd/npppd/../l2tp -I /usr/src/usr.sbin/npppd/npppd/../pppoe -D USE_NPPPD_PPTP -D USE_NPPPD_L2TP -D USE_NPPPD_PPPOE -D __COPYRIGHT(x)= -D __RCSID(x)= -D NPPPD_MAX_IFACE=8 -D NPPPD_MAX_POOL=8 -D USE_NPPPD_MPPE -D USE_NPPPD_PIPEX -D USE_NPPPD_RADIUS -D USE_SA_COOKIE -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/npppd/npppd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/npppd/npppd/npppd_pool.c
1/* $OpenBSD: npppd_pool.c,v 1.10 2017/05/30 17:22:00 yasuoka Exp $ */
2
3/*-
4 * Copyright (c) 2009 Internet Initiative Japan Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28/**@file */
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <netinet/in.h>
32#include <net/route.h>
33#include <netinet/ip.h>
34#include <arpa/inet.h>
35#include <net/if_dl.h>
36#include <stdio.h>
37#include <time.h>
38#include <event.h>
39#include <string.h>
40#include <errno(*__errno()).h>
41#include <unistd.h>
42#include <syslog.h>
43#include <stdlib.h>
44#include <stdarg.h>
45#include <netdb.h>
46
47#include "slist.h"
48#include "debugutil.h"
49#include "addr_range.h"
50#include "radish.h"
51#include "npppd_local.h"
52#include "npppd_pool.h"
53#include "npppd_subr.h"
54#include "net_utils.h"
55
56#ifdef NPPPD_POOL_DEBUG
57#define NPPPD_POOL_DBG(x) npppd_pool_log x
58#define NPPPD_POOL_ASSERT(cond) \
59 if (!(cond)) { \
60 fprintf(stderr(&__sF[2]), \
61 "\nASSERT(" #cond ") failed on %s() at %s:%d.\n"\
62 , __func__, __FILE__"/usr/src/usr.sbin/npppd/npppd/npppd_pool.c", __LINE__62); \
63 abort(); \
64 }
65#else
66#define NPPPD_POOL_ASSERT(cond)
67#define NPPPD_POOL_DBG(x)
68#endif
69#define A(v)((0xff000000 & (v)) >> 24), ((0x00ff0000 & (v))
>> 16), ((0x0000ff00 & (v)) >> 8), (0x000000ff
& (v))
((0xff000000 & (v)) >> 24), ((0x00ff0000 & (v)) >> 16), \
70 ((0x0000ff00 & (v)) >> 8), (0x000000ff & (v))
71#define SA(sin4)((struct sockaddr *)(sin4)) ((struct sockaddr *)(sin4))
72
73#define SHUFLLE_MARK0xffffffffL 0xffffffffL
74static int npppd_pool_log(npppd_pool *, int, const char *, ...) __printflike(3, 4)__attribute__((__format__ (__printf__, 3, 4)));
75static int is_valid_host_address (uint32_t);
76static int npppd_pool_regist_radish(npppd_pool *, struct in_addr_range *,
77 struct sockaddr_npppd *, int );
78
79
80/***********************************************************************
81 * npppd_pool object management
82 ***********************************************************************/
83/** Initialize npppd_poll. */
84int
85npppd_pool_init(npppd_pool *_this, npppd *base, const char *name)
86{
87 memset(_this, 0, sizeof(npppd_pool));
88
89 strlcpy(_this->ipcp_name, name, sizeof(_this->ipcp_name));
90 _this->npppd = base;
91 slist_init(&_this->dyna_addrs);
92
93 _this->initialized = 1;
94
95 return 0;
96}
97
98/** Start to use npppd_pool. */
99int
100npppd_pool_start(npppd_pool *_this)
101{
102 return 0; /* nothing to do */
103}
104
105/** Finalize npppd_poll. */
106void
107npppd_pool_uninit(npppd_pool *_this)
108{
109 _this->initialized = 0;
110
111 slist_fini(&_this->dyna_addrs);
112 free(_this->addrs);
113 _this->addrs = NULL((void *)0);
114 _this->addrs_size = 0;
115 _this->npppd = NULL((void *)0);
116}
117
118/** Reload configuration. */
119int
120npppd_pool_reload(npppd_pool *_this)
121{
122 int i, count, addrs_size;
123 struct sockaddr_npppd *addrs;
124 struct in_addr_range *pool, *dyna_pool, *range;
125 char buf0[BUFSIZ1024], buf1[BUFSIZ1024];
126 struct ipcpconf *ipcp;
127
128 addrs = NULL((void *)0);
129 pool = NULL((void *)0);
130 dyna_pool = NULL((void *)0);
131 buf0[0] = '\0';
132
133 TAILQ_FOREACH(ipcp, &_this->npppd->conf.ipcpconfs, entry)for((ipcp) = ((&_this->npppd->conf.ipcpconfs)->tqh_first
); (ipcp) != ((void *)0); (ipcp) = ((ipcp)->entry.tqe_next
))
{
134 if (strcmp(ipcp->name, _this->ipcp_name) == 0) {
135 dyna_pool = ipcp->dynamic_pool;
136 pool = ipcp->static_pool;
137 }
138 }
139
140 addrs_size = 0;
141 for (range = dyna_pool; range != NULL((void *)0); range = range->next)
142 addrs_size++;
143 for (range = pool; range != NULL((void *)0); range = range->next)
144 addrs_size++;
145
146 if ((addrs = calloc(addrs_size + 1, sizeof(struct sockaddr_npppd)))
147 == NULL((void *)0)) {
148 /* addr_size + 1 because of avoiding calloc(0). */
149 npppd_pool_log(_this, LOG_WARNING4,
150 "calloc() failed in %s: %m", __func__);
151 goto fail;
152 }
153
154 /* Register dynamic pool address with RADISH. */
155 count = 0;
156 for (i = 0, range = dyna_pool; range != NULL((void *)0); range = range->next, i++){
157 if (npppd_pool_regist_radish(_this, range, &addrs[count], 1))
158 goto fail;
159 if (count == 0)
160 strlcat(buf0, "dyn_pool=[", sizeof(buf0));
161 else
162 strlcat(buf0, ",", sizeof(buf0));
163 snprintf(buf1, sizeof(buf1), "%d.%d.%d.%d/%d",
164 A(range->addr)((0xff000000 & (range->addr)) >> 24), ((0x00ff0000
& (range->addr)) >> 16), ((0x0000ff00 & (range
->addr)) >> 8), (0x000000ff & (range->addr))
, netmask2prefixlen(range->mask));
165 strlcat(buf0, buf1, sizeof(buf0));
166 count++;
167 }
168 if (i > 0)
169 strlcat(buf0, "] ", sizeof(buf0));
170
171 /* Register static pool address with RADISH. */
172 for (i = 0, range = pool; range != NULL((void *)0); range = range->next, i++) {
173 if (npppd_pool_regist_radish(_this, range, &addrs[count], 0))
174 goto fail;
175 if (i == 0)
176 strlcat(buf0, "pool=[", sizeof(buf0));
177 else
178 strlcat(buf0, ",", sizeof(buf0));
179 snprintf(buf1, sizeof(buf1), "%d.%d.%d.%d/%d",
180 A(range->addr)((0xff000000 & (range->addr)) >> 24), ((0x00ff0000
& (range->addr)) >> 16), ((0x0000ff00 & (range
->addr)) >> 8), (0x000000ff & (range->addr))
, netmask2prefixlen(range->mask));
181 strlcat(buf0, buf1, sizeof(buf0));
182 count++;
183 }
184 if (i > 0)
185 strlcat(buf0, "]", sizeof(buf0));
186
187 npppd_pool_log(_this, LOG_INFO6, "%s", buf0);
188
189 count = 0;
190 slist_add(&_this->dyna_addrs, (void *)SHUFLLE_MARK0xffffffffL);
191 for (range = dyna_pool; range != NULL((void *)0); range = range->next) {
192 if (count >= NPPPD_MAX_POOLED_ADDRS8192)
193 break;
194 for (i = 0; i <= ~(range->mask); i++) {
195 if (!is_valid_host_address(range->addr + i))
196 continue;
197 if (count >= NPPPD_MAX_POOLED_ADDRS8192)
198 break;
199 slist_add(&_this->dyna_addrs,
200 (void *)(uintptr_t)(range->addr + i));
201 count++;
202 }
203 }
204 free(_this->addrs);
205 _this->addrs = addrs;
206 _this->addrs_size = addrs_size;
207
208 return 0;
209fail:
210 free(addrs);
211
212 return 1;
213}
214
215static int
216npppd_pool_regist_radish(npppd_pool *_this, struct in_addr_range *range,
217 struct sockaddr_npppd *snp, int is_dynamic)
218{
219 int rval;
220 struct sockaddr_in sin4a, sin4b;
221 struct sockaddr_npppd *snp0;
222 npppd_pool *npool0;
223
224 memset(&sin4a, 0, sizeof(sin4a));
225 memset(&sin4b, 0, sizeof(sin4b));
226 sin4a.sin_len = sin4b.sin_len = sizeof(sin4a);
227 sin4a.sin_family = sin4b.sin_family = AF_INET2;
228 sin4a.sin_addr.s_addr = htonl(range->addr)(__uint32_t)(__builtin_constant_p(range->addr) ? (__uint32_t
)(((__uint32_t)(range->addr) & 0xff) << 24 | ((__uint32_t
)(range->addr) & 0xff00) << 8 | ((__uint32_t)(range
->addr) & 0xff0000) >> 8 | ((__uint32_t)(range->
addr) & 0xff000000) >> 24) : __swap32md(range->addr
))
;
229 sin4b.sin_addr.s_addr = htonl(range->mask)(__uint32_t)(__builtin_constant_p(range->mask) ? (__uint32_t
)(((__uint32_t)(range->mask) & 0xff) << 24 | ((__uint32_t
)(range->mask) & 0xff00) << 8 | ((__uint32_t)(range
->mask) & 0xff0000) >> 8 | ((__uint32_t)(range->
mask) & 0xff000000) >> 24) : __swap32md(range->mask
))
;
230
231 snp->snp_lensin4.sin_len = sizeof(struct sockaddr_npppd);
232 snp->snp_familysin4.sin_family = AF_INET2;
233 snp->snp_addrsin4.sin_addr.s_addr = htonl(range->addr)(__uint32_t)(__builtin_constant_p(range->addr) ? (__uint32_t
)(((__uint32_t)(range->addr) & 0xff) << 24 | ((__uint32_t
)(range->addr) & 0xff00) << 8 | ((__uint32_t)(range
->addr) & 0xff0000) >> 8 | ((__uint32_t)(range->
addr) & 0xff000000) >> 24) : __swap32md(range->addr
))
;
234 snp->snp_masksin4mask.sin_addr.s_addr = htonl(range->mask)(__uint32_t)(__builtin_constant_p(range->mask) ? (__uint32_t
)(((__uint32_t)(range->mask) & 0xff) << 24 | ((__uint32_t
)(range->mask) & 0xff00) << 8 | ((__uint32_t)(range
->mask) & 0xff0000) >> 8 | ((__uint32_t)(range->
mask) & 0xff000000) >> 24) : __swap32md(range->mask
))
;
235 snp->snp_data_ptr = _this;
236 if (is_dynamic)
237 snp->snp_type = SNP_DYN_POOL2;
238 else
239 snp->snp_type = SNP_POOL1;
240
241 if ((snp0 = rd_lookup(SA(&sin4a)((struct sockaddr *)(&sin4a)), SA(&sin4b)((struct sockaddr *)(&sin4b)),
242 _this->npppd->rd)) != NULL((void *)0)) {
243 /*
244 * Immediately after the radish tree is initialized,
245 * assuming that it has only POOL entry.
246 */
247 NPPPD_POOL_ASSERT(snp0->snp_type != SNP_PPP);
248 npool0 = snp0->snp_data_ptr;
249
250 if (!is_dynamic && npool0 == _this)
251 /* Already registered as dynamic pool address. */
252 return 0;
253
254 npppd_pool_log(_this, LOG_WARNING4,
255 "%d.%d.%d.%d/%d is already defined as '%s'(%s)",
256 A(range->addr)((0xff000000 & (range->addr)) >> 24), ((0x00ff0000
& (range->addr)) >> 16), ((0x0000ff00 & (range
->addr)) >> 8), (0x000000ff & (range->addr))
, netmask2prefixlen(range->mask),
257 npool0->ipcp_name, (snp0->snp_type == SNP_POOL1)
258 ? "static" : "dynamic");
259 goto fail;
260 }
261 if ((rval = rd_insert(SA(&sin4a)((struct sockaddr *)(&sin4a)), SA(&sin4b)((struct sockaddr *)(&sin4b)), _this->npppd->rd,
262 snp)) != 0) {
263 errno(*__errno()) = rval;
264 npppd_pool_log(_this, LOG_WARNING4,
265 "rd_insert(%d.%d.%d.%d/%d) failed: %m",
266 A(range->addr)((0xff000000 & (range->addr)) >> 24), ((0x00ff0000
& (range->addr)) >> 16), ((0x0000ff00 & (range
->addr)) >> 8), (0x000000ff & (range->addr))
, netmask2prefixlen(range->mask));
267 goto fail;
268 }
269
270 return 0;
271fail:
272 return 1;
273
274}
275
276/***********************************************************************
277 * API
278 ***********************************************************************/
279/** Assign dynamic pool address. */
280uint32_t
281npppd_pool_get_dynamic(npppd_pool *_this, npppd_ppp *ppp)
282{
283 int shuffle_cnt;
284 uintptr_t result = 0;
285 struct sockaddr_npppd *snp;
286 npppd_ppp *ppp0;
287
288 shuffle_cnt = 0;
289 slist_itr_first(&_this->dyna_addrs);
290 while (slist_length(&_this->dyna_addrs) > 1 &&
291 slist_itr_has_next(&_this->dyna_addrs)) {
292 result = (uintptr_t)slist_itr_next(&_this->dyna_addrs);
293 if (result == 0)
294 break;
295 /* shuffle */
296 if ((uint32_t)result == SHUFLLE_MARK0xffffffffL) {
297 /*
298 * When the free list is empty, SHUFLLE_MARK is
299 * retrieved twice sequentially. This means there is
300 * no address to use.
301 */
302 if (shuffle_cnt++ > 0) {
303 result = 0;
Value stored to 'result' is never read
304 break;
305 }
306 NPPPD_POOL_DBG((_this, LOG_DEBUG, "shuffle"));
307 slist_itr_remove(&_this->dyna_addrs);
308 slist_shuffle(&_this->dyna_addrs);
309 slist_add(&_this->dyna_addrs, (void *)result);
310 slist_itr_first(&_this->dyna_addrs);
311 continue;
312 }
313 slist_itr_remove(&_this->dyna_addrs);
314
315 switch (npppd_pool_get_assignability(_this, (uint32_t)result,
316 0xffffffffL, &snp)) {
317 case ADDRESS_OK0:
318 /* only succeed here */
319 return (uint32_t)result;
320 default:
321 /*
322 * Used as a interface address
323 */
324 continue;
325 case ADDRESS_BUSY2:
326 /*
327 * Used by the previous configuration.
328 */
329 NPPPD_POOL_ASSERT(snp != NULL);
330 NPPPD_POOL_ASSERT(snp->snp_type == SNP_PPP);
331 ppp0 = snp->snp_data_ptr;
332 ppp0->assigned_pool = _this;
333 ppp0->assign_dynapool = 1; /* need to return */
334 continue;
335 }
336 break;
337 }
338 return (uint32_t)0;
339}
340
341inline static int
342npppd_is_ifcace_ip4addr(npppd *_this, uint32_t ip4addr)
343{
344 int i;
345
346 for (i = 0; i < countof(_this->iface)(sizeof(_this->iface) / sizeof((_this->iface)[0])); i++) {
347 if (npppd_iface_ip_is_ready(&_this->iface[i])((&_this->iface[i])->initialized != 0 && (&
_this->iface[i])->ip4addr.s_addr != ((u_int32_t)(0x00000000
)))
&&
348 _this->iface[i].ip4addr.s_addr == ip4addr)
349 return 1;
350 }
351
352 return 0;
353}
354
355/** Assign IP address. */
356int
357npppd_pool_assign_ip(npppd_pool *_this, npppd_ppp *ppp)
358{
359 int rval;
360 uint32_t ip4;
361 void *rtent;
362 struct sockaddr_in addr = {
363 .sin_family = AF_INET2,
364 .sin_len = sizeof(struct sockaddr_in)
365 }, mask = {
366 .sin_family = AF_INET2,
367 .sin_len = sizeof(struct sockaddr_in),
368 };
369 struct sockaddr_npppd *snp;
370
371 ip4 = ntohl(ppp->ppp_framed_ip_address.s_addr)(__uint32_t)(__builtin_constant_p(ppp->snp.sin4.sin_addr.s_addr
) ? (__uint32_t)(((__uint32_t)(ppp->snp.sin4.sin_addr.s_addr
) & 0xff) << 24 | ((__uint32_t)(ppp->snp.sin4.sin_addr
.s_addr) & 0xff00) << 8 | ((__uint32_t)(ppp->snp
.sin4.sin_addr.s_addr) & 0xff0000) >> 8 | ((__uint32_t
)(ppp->snp.sin4.sin_addr.s_addr) & 0xff000000) >>
24) : __swap32md(ppp->snp.sin4.sin_addr.s_addr))
;
372
373 /* If the address contains dynamic pool address list, delete it. */
374 slist_itr_first(&_this->dyna_addrs);
375 while (slist_itr_has_next(&_this->dyna_addrs)) {
376 if ((uintptr_t)slist_itr_next(&_this->dyna_addrs) != ip4)
377 continue;
378 slist_itr_remove(&_this->dyna_addrs);
379 break;
380 }
381
382 addr.sin_addr = ppp->ppp_framed_ip_addresssnp.sin4.sin_addr;
383 mask.sin_addr = ppp->ppp_framed_ip_netmasksnp.sin4mask.sin_addr;
384 addr.sin_addr.s_addr &= mask.sin_addr.s_addr;
385
386 if (rd_delete(SA(&addr)((struct sockaddr *)(&addr)), SA(&mask)((struct sockaddr *)(&mask)), _this->npppd->rd, &rtent) == 0) {
387 snp = rtent;
388 /* It has duplicate address entry. change from pool to PPP. */
389 NPPPD_POOL_ASSERT(snp != NULL);
390 NPPPD_POOL_ASSERT(snp->snp_type != SNP_PPP);
391 ppp->snp.snp_next = snp;
392 NPPPD_POOL_DBG((_this, DEBUG_LEVEL_2,
393 "pool %s/32 => %s(ppp=%d)",
394 inet_ntoa(ppp->ppp_framed_ip_address), ppp->username,
395 ppp->id));
396 }
397 NPPPD_POOL_DBG((_this, LOG_DEBUG, "rd_insert(%s) %s",
398 inet_ntoa(addr.sin_addr), ppp->username));
399 if ((rval = rd_insert((struct sockaddr *)&addr,
400 (struct sockaddr *)&mask, _this->npppd->rd, &ppp->snp)) != 0) {
401 errno(*__errno()) = rval;
402 log_printf(LOG_INFO6, "rd_insert(%s) failed: %m",
403 inet_ntoa(ppp->ppp_framed_ip_addresssnp.sin4.sin_addr));
404 return 1;
405 }
406
407 return 0;
408}
409
410/** Release IP address. */
411void
412npppd_pool_release_ip(npppd_pool *_this, npppd_ppp *ppp)
413{
414 void *item;
415 int rval;
416 struct sockaddr_npppd *snp;
417 struct sockaddr_in addr = {
418 .sin_family = AF_INET2,
419 .sin_len = sizeof(struct sockaddr_in)
420 }, mask = {
421 .sin_family = AF_INET2,
422 .sin_len = sizeof(struct sockaddr_in),
423 };
424
425 /*
426 * `_this' may be NULL. It was gone because of a configuration change.
427 */
428 if (!ppp_ip_assigned(ppp)(ppp->snp.sin4.sin_addr.s_addr != 0))
429 return;
430
431 addr.sin_addr = ppp->ppp_framed_ip_addresssnp.sin4.sin_addr;
432 mask.sin_addr = ppp->ppp_framed_ip_netmasksnp.sin4mask.sin_addr;
433 addr.sin_addr.s_addr &= mask.sin_addr.s_addr;
434
435 if ((rval = rd_delete((struct sockaddr *)&addr,
436 (struct sockaddr *)&mask, ppp->pppd->rd, &item)) != 0) {
437 errno(*__errno()) = rval;
438 log_printf(LOG_INFO6, "Unexpected error: "
439 "rd_delete(%s) failed: %m",
440 inet_ntoa(ppp->ppp_framed_ip_addresssnp.sin4.sin_addr));
441 }
442 snp = item;
443
444 if (_this != NULL((void *)0) && ppp->assign_dynapool != 0) {
445 NPPPD_POOL_ASSERT(_this == ppp->assigned_pool);
446 /* return to dynamic address pool list */
447 slist_add(&((npppd_pool *)ppp->assigned_pool)->dyna_addrs,
448 (void *)(uintptr_t)ntohl((__uint32_t)(__builtin_constant_p(ppp->snp.sin4.sin_addr.s_addr
) ? (__uint32_t)(((__uint32_t)(ppp->snp.sin4.sin_addr.s_addr
) & 0xff) << 24 | ((__uint32_t)(ppp->snp.sin4.sin_addr
.s_addr) & 0xff00) << 8 | ((__uint32_t)(ppp->snp
.sin4.sin_addr.s_addr) & 0xff0000) >> 8 | ((__uint32_t
)(ppp->snp.sin4.sin_addr.s_addr) & 0xff000000) >>
24) : __swap32md(ppp->snp.sin4.sin_addr.s_addr))
449 ppp->ppp_framed_ip_address.s_addr)(__uint32_t)(__builtin_constant_p(ppp->snp.sin4.sin_addr.s_addr
) ? (__uint32_t)(((__uint32_t)(ppp->snp.sin4.sin_addr.s_addr
) & 0xff) << 24 | ((__uint32_t)(ppp->snp.sin4.sin_addr
.s_addr) & 0xff00) << 8 | ((__uint32_t)(ppp->snp
.sin4.sin_addr.s_addr) & 0xff0000) >> 8 | ((__uint32_t
)(ppp->snp.sin4.sin_addr.s_addr) & 0xff000000) >>
24) : __swap32md(ppp->snp.sin4.sin_addr.s_addr))
);
450 }
451
452 if (snp != NULL((void *)0) && snp->snp_next != NULL((void *)0)) {
453 /*
454 * The radish entry is registered as a list. Insert the next
455 * of the list to the radish tree.
456 */
457 if (rd_insert(SA(&addr)((struct sockaddr *)(&addr)), SA(&mask)((struct sockaddr *)(&mask)), ppp->pppd->rd,
458 snp->snp_next) != 0) {
459 log_printf(LOG_INFO6, "Unexpected error: "
460 "rd_insert(%s) failed: %m",
461 inet_ntoa(ppp->ppp_framed_ip_addresssnp.sin4.sin_addr));
462 }
463 NPPPD_POOL_DBG((_this, DEBUG_LEVEL_2,
464 "pool %s/%d <= %s(ppp=%d)",
465 inet_ntoa(ppp->ppp_framed_ip_address),
466 netmask2prefixlen(ntohl(ppp->ppp_framed_ip_netmask.s_addr)),
467 ppp->username, ppp->id));
468 snp->snp_next = NULL((void *)0);
469 }
470}
471
472/**
473 * Check if specified address is assignable.
474 * @return {@link ::#ADDRESS_OK} or {@link ::#ADDRESS_RESERVED} or
475 * {@link ::#ADDRESS_BUSY} or {@link ::#ADDRESS_INVALID} or
476 * {@link ::#ADDRESS_OUT_OF_POOL}
477 */
478int
479npppd_pool_get_assignability(npppd_pool *_this, uint32_t ip4addr,
480 uint32_t ip4mask, struct sockaddr_npppd **psnp)
481{
482 struct radish *radish;
483 struct sockaddr_in sin4;
484 struct sockaddr_npppd *snp;
485
486 NPPPD_POOL_ASSERT(ip4mask != 0);
487 NPPPD_POOL_DBG((_this, LOG_DEBUG, "%s(%08x,%08x)", __func__, ip4addr,
488 ip4mask));
489
490 if (netmask2prefixlen(htonl(ip4mask)(__uint32_t)(__builtin_constant_p(ip4mask) ? (__uint32_t)(((__uint32_t
)(ip4mask) & 0xff) << 24 | ((__uint32_t)(ip4mask) &
0xff00) << 8 | ((__uint32_t)(ip4mask) & 0xff0000) >>
8 | ((__uint32_t)(ip4mask) & 0xff000000) >> 24) : __swap32md
(ip4mask))
) == 32) {
491 if (!is_valid_host_address(ip4addr))
492 return ADDRESS_INVALID3;
493 }
494
495 memset(&sin4, 0, sizeof(sin4));
496
497 sin4.sin_len = sizeof(sin4);
498 sin4.sin_family = AF_INET2;
499 sin4.sin_addr.s_addr = htonl(ip4addr)(__uint32_t)(__builtin_constant_p(ip4addr) ? (__uint32_t)(((__uint32_t
)(ip4addr) & 0xff) << 24 | ((__uint32_t)(ip4addr) &
0xff00) << 8 | ((__uint32_t)(ip4addr) & 0xff0000) >>
8 | ((__uint32_t)(ip4addr) & 0xff000000) >> 24) : __swap32md
(ip4addr))
;
500
501 if (npppd_is_ifcace_ip4addr(_this->npppd, sin4.sin_addr.s_addr))
502 return ADDRESS_RESERVED1;
503 /* Not to assign interface address */
504
505 if (rd_match(SA(&sin4)((struct sockaddr *)(&sin4)), _this->npppd->rd, &radish)) {
506 do {
507 snp = radish->rd_rtent;
508 if (snp->snp_type == SNP_POOL1 ||
509 snp->snp_type == SNP_DYN_POOL2) {
510 if (psnp != NULL((void *)0))
511 *psnp = snp;
512 if (snp->snp_data_ptr == _this)
513 return ADDRESS_OK0;
514 else
515 return ADDRESS_RESERVED1;
516 }
517 if (snp->snp_type == SNP_PPP3) {
518 if (psnp != NULL((void *)0))
519 *psnp = snp;
520 return ADDRESS_BUSY2;
521 }
522 } while (rd_match_next(SA(&sin4)((struct sockaddr *)(&sin4)), _this->npppd->rd, &radish,
523 radish));
524 }
525
526 return ADDRESS_OUT_OF_POOL4;
527}
528/***********************************************************************
529 * miscellaneous functions
530 ***********************************************************************/
531/**
532 * Check if valid host address.
533 * <pre>
534 * There are some issues that it uses host address as broadcast address
535 * in natural mask, so it is not correct.
536 * The issue is as follows:
537 * (1) BSDs treat the following packet as it is not forwarded and
538 * is received as the packet to myself.
539 * (2) The issue that Windows can't use L2TP/IPsec when Windows is assigned
540 * IP address .255.</pre>
541 */
542static int
543is_valid_host_address(uint32_t addr)
544{
545 if (IN_CLASSA(addr)(((u_int32_t)(addr) & ((u_int32_t)(0x80000000))) == ((u_int32_t
)(0x00000000)))
)
546 return ((IN_CLASSA_HOST((u_int32_t)(0x00ffffff)) & addr) == 0 ||
547 (IN_CLASSA_HOST((u_int32_t)(0x00ffffff)) & addr) == IN_CLASSA_HOST((u_int32_t)(0x00ffffff)))? 0 : 1;
548 if (IN_CLASSB(addr)(((u_int32_t)(addr) & ((u_int32_t)(0xc0000000))) == ((u_int32_t
)(0x80000000)))
)
549 return ((IN_CLASSB_HOST((u_int32_t)(0x0000ffff)) & addr) == 0 ||
550 (IN_CLASSB_HOST((u_int32_t)(0x0000ffff)) & addr) == IN_CLASSB_HOST((u_int32_t)(0x0000ffff)))? 0 : 1;
551 if (IN_CLASSC(addr)(((u_int32_t)(addr) & ((u_int32_t)(0xe0000000))) == ((u_int32_t
)(0xc0000000)))
)
552 return ((IN_CLASSC_HOST((u_int32_t)(0x000000ff)) & addr) == 0 ||
553 (IN_CLASSC_HOST((u_int32_t)(0x000000ff)) & addr) == IN_CLASSC_HOST((u_int32_t)(0x000000ff)))? 0 : 1;
554
555 return 0;
556}
557
558/** Record log that begins the label based this instance. */
559static int
560npppd_pool_log(npppd_pool *_this, int prio, const char *fmt, ...)
561{
562 int status;
563 char logbuf[BUFSIZ1024];
564 va_list ap;
565
566 /*
567 * npppd_pool_release_ip is called as _this == NULL,
568 * so it can't NPPPD_POOL_ASSERT(_this != NULL).
569 */
570 va_start(ap, fmt)__builtin_va_start(ap, fmt);
571 snprintf(logbuf, sizeof(logbuf), "ipcp=%s pool %s",
572 (_this == NULL((void *)0))? "null" : _this->ipcp_name, fmt);
573 status = vlog_printf(prio, logbuf, ap);
574 va_end(ap)__builtin_va_end(ap);
575
576 return status;
577}