Bug Summary

File:src/usr.sbin/npppd/npppd/npppd_subr.c
Warning:line 144, column 2
Value stored to 'sock' 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_subr.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_subr.c
1/* $OpenBSD: npppd_subr.c,v 1.21 2021/03/29 03:54:39 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 * This file provides helper functions for npppd.
30 */
31
32#include <sys/types.h>
33#include <sys/socket.h>
34#include <netinet/in.h>
35#include <netinet/ip.h>
36#include <netinet/udp.h>
37#include <netinet/tcp.h>
38#include <net/route.h>
39#include <net/if_dl.h>
40#include <net/if.h>
41#include <arpa/inet.h>
42#include <stdlib.h>
43#include <fcntl.h>
44#include <stdio.h>
45#include <syslog.h>
46#include <stddef.h>
47#include <unistd.h>
48#include <errno(*__errno()).h>
49#include <ctype.h>
50#include <string.h>
51#include <resolv.h>
52
53#include "debugutil.h"
54#include "addr_range.h"
55
56#include "npppd_defs.h"
57#include "npppd_subr.h"
58#include "privsep.h"
59
60#define MINIMUM(a, b)(((a) < (b)) ? (a) : (b)) (((a) < (b)) ? (a) : (b))
61
62static u_int16_t route_seq = 0;
63static int in_route0(int, struct in_addr *, struct in_addr *, struct in_addr *, int, const char *, uint32_t);
64#define ROUNDUP(a)((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof
(long))
\
65 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
66
67static const char *
68skip_space(const char *s)
69{
70 const char *r;
71 for (r = s; *r != '\0' && isspace((unsigned char)*r); r++)
72 ;; /* skip */
73
74 return r;
75}
76
77/**
78 * Read and store IPv4 address of name server from resolv.conf.
79 * The path of resolv.conf is taken from _PATH_RESCONF in resolv.h.
80 */
81int
82load_resolv_conf(struct in_addr *pri, struct in_addr *sec)
83{
84 FILE *filep;
85 int i;
86 struct in_addr *addr;
87 char *ap, *line, buf[BUFSIZ1024];
88
89 pri->s_addr = INADDR_NONE((u_int32_t)(0xffffffff));
90 sec->s_addr = INADDR_NONE((u_int32_t)(0xffffffff));
91
92 filep = NULL((void*)0);
93 if ((filep = priv_fopen(_PATH_RESCONF"/etc/resolv.conf")) == NULL((void*)0))
94 return 1;
95
96 i = 0;
97 while (fgets(buf, sizeof(buf), filep) != NULL((void*)0)) {
98 line = (char *)skip_space(buf);
99 if (strncmp(line, "nameserver", 10) != 0)
100 continue;
101 line += 10;
102 if (!isspace((unsigned char)*line))
103 continue;
104 while ((ap = strsep(&line, " \t\r\n")) != NULL((void*)0)) {
105 if (*ap == '\0')
106 continue;
107 if (i == 0)
108 addr = pri;
109 else
110 addr = sec;
111 if (inet_aton(ap, addr) != 1) {
112 /*
113 * FIXME: If configured IPv6, it may have IPv6
114 * FIXME: address. For the present, continue.
115 */
116 continue;
117 }
118 addr->s_addr = addr->s_addr;
119 if (++i >= 2)
120 goto end_loop;
121 }
122 }
123end_loop:
124 if (filep != NULL((void*)0))
125 fclose(filep);
126
127 return 0;
128}
129
130/* Add and delete routing entry. */
131static int
132in_route0(int type, struct in_addr *dest, struct in_addr *mask,
133 struct in_addr *gate, int mtu, const char *ifname, uint32_t rtm_flags)
134{
135 struct rt_msghdr *rtm;
136 struct sockaddr_in sdest, smask, sgate;
137 struct sockaddr_dl *sdl;
138 char dl_buf[512]; /* enough size */
139 char *cp, buf[sizeof(*rtm) + sizeof(struct sockaddr_in) * 3 +
140 sizeof(dl_buf) + 128];
141 const char *strtype;
142 int rval, flags, sock;
143
144 sock = -1;
Value stored to 'sock' is never read
145
146 ASSERT(type == RTM_ADD || type == RTM_DELETE)((void)0);;
147 if(type == RTM_ADD0x1)
148 strtype = "RTM_ADD";
149 else
150 strtype = "RTM_DELETE";
151
152 memset(buf, 0, sizeof(buf));
153 memset(&sdest, 0, sizeof(sdest));
154 memset(&smask, 0, sizeof(smask));
155 memset(&sgate, 0, sizeof(sgate));
156 memset(&dl_buf, 0, sizeof(dl_buf));
157
158 sdl = (struct sockaddr_dl *)dl_buf;
159
160 sdest.sin_addr = *dest;
161 if (mask != NULL((void*)0))
162 smask.sin_addr = *mask;
163 if (gate != NULL((void*)0))
164 sgate.sin_addr = *gate;
165
166 sdest.sin_family = smask.sin_family = sgate.sin_family = AF_INET2;
167 sdest.sin_len = smask.sin_len = sgate.sin_len = sizeof(sgate);
168
169 rtm = (struct rt_msghdr *)buf;
170
171 rtm->rtm_version = RTM_VERSION5;
172 rtm->rtm_type = type;
173 rtm->rtm_flags = rtm_flags;
174 if (gate != NULL((void*)0))
175 rtm->rtm_flags |= RTF_GATEWAY0x2;
176 if (mask == NULL((void*)0))
177 rtm->rtm_flags |= RTF_HOST0x4;
178
179 if (type == RTM_ADD0x1 && mtu > 0) {
180 rtm->rtm_inits = RTV_MTU0x1;
181 rtm->rtm_rmx.rmx_mtu = mtu;
182 }
183
184 if (type == RTM_ADD0x1)
185 rtm->rtm_flags |= RTF_UP0x1;
186
187 rtm->rtm_addrs = RTA_DST0x1;
188 if (gate != NULL((void*)0))
189 rtm->rtm_addrs |= RTA_GATEWAY0x2;
190 if (mask != NULL((void*)0))
191 rtm->rtm_addrs |= RTA_NETMASK0x4;
192#ifdef RTA_IFP0x10
193 if (ifname != NULL((void*)0))
194 rtm->rtm_addrs |= RTA_IFP0x10;
195#endif
196
197 rtm->rtm_pid = getpid();
198 route_seq = ((route_seq + 1)&0x0000ffff);
199 rtm->rtm_seq = route_seq;
200
201 cp = (char *)rtm;
202 cp += ROUNDUP(sizeof(*rtm))((sizeof(*rtm)) > 0 ? (1 + (((sizeof(*rtm)) - 1) | (sizeof
(long) - 1))) : sizeof(long))
;
203
204 memcpy(cp, &sdest, sdest.sin_len);
205 cp += ROUNDUP(sdest.sin_len)((sdest.sin_len) > 0 ? (1 + (((sdest.sin_len) - 1) | (sizeof
(long) - 1))) : sizeof(long))
;
206 if (gate != NULL((void*)0)) {
207 memcpy(cp, &sgate, sgate.sin_len);
208 cp += ROUNDUP(sgate.sin_len)((sgate.sin_len) > 0 ? (1 + (((sgate.sin_len) - 1) | (sizeof
(long) - 1))) : sizeof(long))
;
209 }
210 if (mask != NULL((void*)0)) {
211 memcpy(cp, &smask, smask.sin_len);
212 cp += ROUNDUP(smask.sin_len)((smask.sin_len) > 0 ? (1 + (((smask.sin_len) - 1) | (sizeof
(long) - 1))) : sizeof(long))
;
213 }
214#ifdef RTA_IFP0x10
215 if (ifname != NULL((void*)0)) {
216 strlcpy(sdl->sdl_data, ifname, IFNAMSIZ16);
217 sdl->sdl_family = AF_LINK18;
218 sdl->sdl_len = offsetof(struct sockaddr_dl, sdl_data)__builtin_offsetof(struct sockaddr_dl, sdl_data) +IFNAMSIZ16;
219 sdl->sdl_index = if_nametoindex(ifname);
220 memcpy(cp, sdl, sdl->sdl_len);
221 cp += ROUNDUP(sdl->sdl_len)((sdl->sdl_len) > 0 ? (1 + (((sdl->sdl_len) - 1) | (
sizeof(long) - 1))) : sizeof(long))
;
222 }
223#endif
224
225 rtm->rtm_msglen = cp - buf;
226
227 if ((sock = priv_socket(AF_ROUTE17, SOCK_RAW3, AF_UNSPEC0)) < 0) {
228 log_printf(LOG_ERR3, "socket() failed in %s() on %s : %m",
229 __func__, strtype);
230 goto fail;
231 }
232
233 if ((flags = fcntl(sock, F_GETFL3)) < 0) {
234 log_printf(LOG_ERR3, "fcntl(,F_GETFL) failed on %s : %m",
235 __func__);
236 goto fail;
237 }
238
239 if (fcntl(sock, F_SETFL4, flags | O_NONBLOCK0x0004) < 0) {
240 log_printf(LOG_ERR3, "fcntl(,F_SETFL) failed on %s : %m",
241 __func__);
242 goto fail;
243 }
244
245 if ((rval = priv_send(sock, buf, rtm->rtm_msglen, 0)) <= 0) {
246 if ((type == RTM_DELETE0x2 && errno(*__errno()) == ESRCH3) ||
247 (type == RTM_ADD0x1 && errno(*__errno()) == EEXIST17)) {
248 log_printf(LOG_DEBUG7,
249 "write() failed in %s on %s : %m", __func__,
250 strtype);
251 } else {
252 log_printf(LOG_WARNING4,
253 "write() failed in %s on %s : %m", __func__,
254 strtype);
255 }
256 goto fail;
257 }
258
259 close(sock);
260
261 return 0;
262
263fail:
264 if (sock >= 0)
265 close(sock);
266
267 return 1;
268}
269
270/** Add host routing entry. */
271int
272in_host_route_add(struct in_addr *dest, struct in_addr *gate,
273 const char *ifname, int mtu)
274{
275 return in_route0(RTM_ADD0x1, dest, NULL((void*)0), gate, mtu, ifname, 0);
276}
277
278/** Delete host routing entry. */
279int
280in_host_route_delete(struct in_addr *dest, struct in_addr *gate)
281{
282 return in_route0(RTM_DELETE0x2, dest, NULL((void*)0), gate, 0, NULL((void*)0), 0);
283}
284
285/** Add network routing entry. */
286int
287in_route_add(struct in_addr *dest, struct in_addr *mask, struct in_addr *gate,
288 const char *ifname, uint32_t rtm_flags, int mtu)
289{
290 return in_route0(RTM_ADD0x1, dest, mask, gate, mtu, ifname, rtm_flags);
291}
292
293/** Delete network routing entry. */
294int
295in_route_delete(struct in_addr *dest, struct in_addr *mask,
296 struct in_addr *gate, uint32_t rtm_flags)
297{
298 return in_route0(RTM_DELETE0x2, dest, mask, gate, 0, NULL((void*)0), rtm_flags);
299}
300
301/**
302 * Check whether a packet should reset idle timer
303 * Returns 1 to don't reset timer (i.e. the packet is "idle" packet)
304 */
305int
306ip_is_idle_packet(const struct ip * pip, int len)
307{
308 u_int16_t ip_off;
309 const struct udphdr *uh;
310
311 /*
312 * Fragmented packet is not idle packet.
313 * (Long packet which needs to fragment is not idle packet.)
314 */
315 ip_off = ntohs(pip->ip_off)(__uint16_t)(__builtin_constant_p(pip->ip_off) ? (__uint16_t
)(((__uint16_t)(pip->ip_off) & 0xffU) << 8 | ((__uint16_t
)(pip->ip_off) & 0xff00U) >> 8) : __swap16md(pip
->ip_off))
;
316 if ((ip_off & IP_MF0x2000) || ((ip_off & IP_OFFMASK0x1fff) != 0))
317 return 0;
318
319 switch (pip->ip_p) {
320 case IPPROTO_IGMP2:
321 return 1;
322 case IPPROTO_ICMP1:
323 /* Is length enough? */
324 if (pip->ip_hl * 4 + 8 > len)
325 return 1;
326
327 switch (((unsigned char *) pip)[pip->ip_hl * 4]) {
328 case 0: /* Echo Reply */
329 case 8: /* Echo Request */
330 return 0;
331 default:
332 return 1;
333 }
334 case IPPROTO_UDP17:
335 case IPPROTO_TCP6:
336 /*
337 * The place of port number of UDP and TCP is the same,
338 * so can be shared.
339 */
340 uh = (const struct udphdr *) (((const char *) pip) +
341 (pip->ip_hl * 4));
342
343 /* Is length enough? */
344 if (pip->ip_hl * 4 + sizeof(struct udphdr) > len)
345 return 1;
346
347 switch (ntohs(uh->uh_sport)(__uint16_t)(__builtin_constant_p(uh->uh_sport) ? (__uint16_t
)(((__uint16_t)(uh->uh_sport) & 0xffU) << 8 | ((
__uint16_t)(uh->uh_sport) & 0xff00U) >> 8) : __swap16md
(uh->uh_sport))
) {
348 case 53: /* DOMAIN */
349 case 67: /* BOOTPS */
350 case 68: /* BOOTPC */
351 case 123: /* NTP */
352 case 137: /* NETBIOS-NS */
353 case 520: /* RIP */
354 return 1;
355 }
356 switch (ntohs(uh->uh_dport)(__uint16_t)(__builtin_constant_p(uh->uh_dport) ? (__uint16_t
)(((__uint16_t)(uh->uh_dport) & 0xffU) << 8 | ((
__uint16_t)(uh->uh_dport) & 0xff00U) >> 8) : __swap16md
(uh->uh_dport))
) {
357 case 53: /* DOMAIN */
358 case 67: /* BOOTPS */
359 case 68: /* BOOTPC */
360 case 123: /* NTP */
361 case 137: /* NETBIOS-NS */
362 case 520: /* RIP */
363 return 1;
364 }
365 return 0;
366 default:
367 return 0;
368 }
369}
370
371/***********************************************************************
372 * Add and delete routing entry for the pool address.
373 ***********************************************************************/
374void
375in_addr_range_add_route(struct in_addr_range *range)
376{
377 struct in_addr_range *range0;
378 struct in_addr dest, mask, loop;
379
380 for (range0 = range; range0 != NULL((void*)0); range0 = range0->next){
381 dest.s_addr = htonl(range0->addr)(__uint32_t)(__builtin_constant_p(range0->addr) ? (__uint32_t
)(((__uint32_t)(range0->addr) & 0xff) << 24 | ((
__uint32_t)(range0->addr) & 0xff00) << 8 | ((__uint32_t
)(range0->addr) & 0xff0000) >> 8 | ((__uint32_t)
(range0->addr) & 0xff000000) >> 24) : __swap32md
(range0->addr))
;
382 mask.s_addr = htonl(range0->mask)(__uint32_t)(__builtin_constant_p(range0->mask) ? (__uint32_t
)(((__uint32_t)(range0->mask) & 0xff) << 24 | ((
__uint32_t)(range0->mask) & 0xff00) << 8 | ((__uint32_t
)(range0->mask) & 0xff0000) >> 8 | ((__uint32_t)
(range0->mask) & 0xff000000) >> 24) : __swap32md
(range0->mask))
;
383 loop.s_addr = htonl(INADDR_LOOPBACK)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0x7f000001))) ?
(__uint32_t)(((__uint32_t)(((u_int32_t)(0x7f000001))) & 0xff
) << 24 | ((__uint32_t)(((u_int32_t)(0x7f000001))) &
0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0x7f000001))
) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0x7f000001
))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)(
0x7f000001))))
;
384 in_route_add(&dest, &mask, &loop, LOOPBACK_IFNAME"lo0",
385 RTF_BLACKHOLE0x1000, 0);
386 }
387 log_printf(LOG_INFO6, "Added routes for pooled addresses");
388}
389
390void
391in_addr_range_delete_route(struct in_addr_range *range)
392{
393 struct in_addr_range *range0;
394 struct in_addr dest, mask, loop;
395
396 for (range0 = range; range0 != NULL((void*)0); range0 = range0->next){
397 dest.s_addr = htonl(range0->addr)(__uint32_t)(__builtin_constant_p(range0->addr) ? (__uint32_t
)(((__uint32_t)(range0->addr) & 0xff) << 24 | ((
__uint32_t)(range0->addr) & 0xff00) << 8 | ((__uint32_t
)(range0->addr) & 0xff0000) >> 8 | ((__uint32_t)
(range0->addr) & 0xff000000) >> 24) : __swap32md
(range0->addr))
;
398 mask.s_addr = htonl(range0->mask)(__uint32_t)(__builtin_constant_p(range0->mask) ? (__uint32_t
)(((__uint32_t)(range0->mask) & 0xff) << 24 | ((
__uint32_t)(range0->mask) & 0xff00) << 8 | ((__uint32_t
)(range0->mask) & 0xff0000) >> 8 | ((__uint32_t)
(range0->mask) & 0xff000000) >> 24) : __swap32md
(range0->mask))
;
399 loop.s_addr = htonl(INADDR_LOOPBACK)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0x7f000001))) ?
(__uint32_t)(((__uint32_t)(((u_int32_t)(0x7f000001))) & 0xff
) << 24 | ((__uint32_t)(((u_int32_t)(0x7f000001))) &
0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0x7f000001))
) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0x7f000001
))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)(
0x7f000001))))
;
400
401 in_route_delete(&dest, &mask, &loop, RTF_BLACKHOLE0x1000);
402 }
403 log_printf(LOG_NOTICE5, "Deleted routes for pooled addresses");
404}
405
406
407/* GETSHORT is also defined in #include <arpa/nameser_compat.h>. */
408#undef GETCHAR
409#undef GETSHORT
410#undef PUTSHORT
411
412#define GETCHAR(c, cp){ (c) = *(cp)++; } { (c) = *(cp)++; }
413#define GETSHORT(s, cp){ (s) = *(cp)++ << 8; (s) |= *(cp)++; } { \
414 (s) = *(cp)++ << 8; \
415 (s) |= *(cp)++; \
416}
417#define PUTSHORT(s, cp){ *(cp)++ = (u_char) ((s) >> 8); *(cp)++ = (u_char) (s)
; }
{ \
418 *(cp)++ = (u_char) ((s) >> 8); \
419 *(cp)++ = (u_char) (s); \
420}
421#define TCP_OPTLEN_IN_SEGMENT12 12 /* timestamp option and padding */
422#define MAXMSS(mtu)(mtu - sizeof(struct ip) - sizeof(struct tcphdr) - 12) (mtu - sizeof(struct ip) - sizeof(struct tcphdr) - \
423 TCP_OPTLEN_IN_SEGMENT12)
424
425/* adapted from FreeBSD:src/usr.sbin/ppp/tcpmss.c */
426/*
427 * Copyright (c) 2000 Ruslan Ermilov and Brian Somers <brian@Awfulhak.org>
428 * All rights reserved.
429 *
430 * Redistribution and use in source and binary forms, with or without
431 * modification, are permitted provided that the following conditions
432 * are met:
433 * 1. Redistributions of source code must retain the above copyright
434 * notice, this list of conditions and the following disclaimer.
435 * 2. Redistributions in binary form must reproduce the above copyright
436 * notice, this list of conditions and the following disclaimer in the
437 * documentation and/or other materials provided with the distribution.
438 *
439 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
440 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
441 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
442 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
443 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
444 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
445 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
446 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
447 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
448 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
449 * SUCH DAMAGE.
450 *
451 * $FreeBSD: src/usr.sbin/ppp/tcpmss.c,v 1.1.4.3 2001/07/19 11:39:54 brian Exp $
452 */
453
454/*
455 * The following macro is used to update an internet checksum. "acc" is a
456 * 32-bit accumulation of all the changes to the checksum (adding in old
457 * 16-bit words and subtracting out new words), and "cksum" is the checksum
458 * value to be updated.
459 */
460#define ADJUST_CHECKSUM(acc, cksum){ acc += cksum; if (acc < 0) { acc = -acc; acc = (acc >>
16) + (acc & 0xffff); acc += acc >> 16; cksum = (u_short
) ~acc; } else { acc = (acc >> 16) + (acc & 0xffff)
; acc += acc >> 16; cksum = (u_short) acc; } }
{ \
461 acc += cksum; \
462 if (acc < 0) { \
463 acc = -acc; \
464 acc = (acc >> 16) + (acc & 0xffff); \
465 acc += acc >> 16; \
466 cksum = (u_short) ~acc; \
467 } else { \
468 acc = (acc >> 16) + (acc & 0xffff); \
469 acc += acc >> 16; \
470 cksum = (u_short) acc; \
471 } \
472}
473
474/**
475 * Adjust mss to make IP packet be shorter than or equal MTU.
476 *
477 * @param pktp pointer that indicates IP packet
478 * @param lpktp length
479 * @param mtu MTU
480 */
481int
482adjust_tcp_mss(u_char *pktp, int lpktp, int mtu)
483{
484 int opt, optlen, acc, ip_off, mss, maxmss;
485 struct ip *pip;
486 struct tcphdr *th;
487
488 if (lpktp < sizeof(struct ip) + sizeof(struct tcphdr))
489 return 1;
490
491 pip = (struct ip *)pktp;
492 ip_off = ntohs(pip->ip_off)(__uint16_t)(__builtin_constant_p(pip->ip_off) ? (__uint16_t
)(((__uint16_t)(pip->ip_off) & 0xffU) << 8 | ((__uint16_t
)(pip->ip_off) & 0xff00U) >> 8) : __swap16md(pip
->ip_off))
;
493
494 /* exclude non-TCP packet or fragmented packet. */
495 if (pip->ip_p != IPPROTO_TCP6 || (ip_off & IP_MF0x2000) != 0 ||
496 (ip_off & IP_OFFMASK0x1fff) != 0)
497 return 0;
498
499 pktp += pip->ip_hl << 2;
500 lpktp -= pip->ip_hl << 2;
501
502 /* broken packet */
503 if (sizeof(struct tcphdr) > lpktp)
504 return 1;
505
506 th = (struct tcphdr *)pktp;
507 /* MSS is selected only from SYN segment. (See RFC 793) */
508 if ((th->th_flags & TH_SYN0x02) == 0)
509 return 0;
510
511 lpktp = MINIMUM(th->th_off << 4, lpktp)(((th->th_off << 4) < (lpktp)) ? (th->th_off <<
4) : (lpktp))
;
512
513 pktp += sizeof(struct tcphdr);
514 lpktp -= sizeof(struct tcphdr);
515
516 while (lpktp >= TCPOLEN_MAXSEG4) {
517 GETCHAR(opt, pktp){ (opt) = *(pktp)++; };
518 switch (opt) {
519 case TCPOPT_MAXSEG2:
520 GETCHAR(optlen, pktp){ (optlen) = *(pktp)++; };
521 GETSHORT(mss, pktp){ (mss) = *(pktp)++ << 8; (mss) |= *(pktp)++; };
522 maxmss = MAXMSS(mtu)(mtu - sizeof(struct ip) - sizeof(struct tcphdr) - 12);
523 if (mss > maxmss) {
524 pktp-=2;
525 PUTSHORT(maxmss, pktp){ *(pktp)++ = (u_char) ((maxmss) >> 8); *(pktp)++ = (u_char
) (maxmss); }
;
526 acc = htons(mss)(__uint16_t)(__builtin_constant_p(mss) ? (__uint16_t)(((__uint16_t
)(mss) & 0xffU) << 8 | ((__uint16_t)(mss) & 0xff00U
) >> 8) : __swap16md(mss))
;
527 acc -= htons(maxmss)(__uint16_t)(__builtin_constant_p(maxmss) ? (__uint16_t)(((__uint16_t
)(maxmss) & 0xffU) << 8 | ((__uint16_t)(maxmss) &
0xff00U) >> 8) : __swap16md(maxmss))
;
528 ADJUST_CHECKSUM(acc, th->th_sum){ acc += th->th_sum; if (acc < 0) { acc = -acc; acc = (
acc >> 16) + (acc & 0xffff); acc += acc >> 16
; th->th_sum = (u_short) ~acc; } else { acc = (acc >>
16) + (acc & 0xffff); acc += acc >> 16; th->th_sum
= (u_short) acc; } }
;
529 }
530 return 0;
531 /* NOTREACHED */
532 break;
533 case TCPOPT_EOL0:
534 return 0;
535 /* NOTREACHED */
536 break;
537 case TCPOPT_NOP1:
538 lpktp--;
539 break;
540 default:
541 GETCHAR(optlen, pktp){ (optlen) = *(pktp)++; };
542 if (optlen < 2) /* packet is broken */
543 return 1;
544 pktp += optlen - 2;
545 lpktp -= optlen;
546 break;
547 }
548 }
549 return 0;
550}