xref: /freebsd/sys/netinet/libalias/alias.c (revision fb2ea26f3c3681f5ef639af9c798a631d800864b)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2001 Charles Mott <cm@linktel.net>
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 
29 #include <sys/cdefs.h>
30 /*
31     Alias.c provides supervisory control for the functions of the
32     packet aliasing software.  It consists of routines to monitor
33     TCP connection state, protocol-specific aliasing routines,
34     fragment handling and the following outside world functional
35     interfaces: SaveFragmentPtr, GetFragmentPtr, FragmentAliasIn,
36     PacketAliasIn and PacketAliasOut.
37 
38     The other C program files are briefly described. The data
39     structure framework which holds information needed to translate
40     packets is encapsulated in alias_db.c.  Data is accessed by
41     function calls, so other segments of the program need not know
42     about the underlying data structures.  Alias_ftp.c contains
43     special code for modifying the ftp PORT command used to establish
44     data connections, while alias_irc.c does the same for IRC
45     DCC. Alias_util.c contains a few utility routines.
46 
47     Version 1.0 August, 1996  (cjm)
48 
49     Version 1.1 August 20, 1996  (cjm)
50 	PPP host accepts incoming connections for ports 0 to 1023.
51 	(Gary Roberts pointed out the need to handle incoming
52 	 connections.)
53 
54     Version 1.2 September 7, 1996 (cjm)
55 	Fragment handling error in alias_db.c corrected.
56 	(Tom Torrance helped fix this problem.)
57 
58     Version 1.4 September 16, 1996 (cjm)
59 	- A more generalized method for handling incoming
60 	  connections, without the 0-1023 restriction, is
61 	  implemented in alias_db.c
62 	- Improved ICMP support in alias.c.  Traceroute
63 	  packet streams can now be correctly aliased.
64 	- TCP connection closing logic simplified in
65 	  alias.c and now allows for additional 1 minute
66 	  "grace period" after FIN or RST is observed.
67 
68     Version 1.5 September 17, 1996 (cjm)
69 	Corrected error in handling incoming UDP packets with 0 checksum.
70 	(Tom Torrance helped fix this problem.)
71 
72     Version 1.6 September 18, 1996 (cjm)
73 	Simplified ICMP aliasing scheme.  Should now support
74 	traceroute from Win95 as well as FreeBSD.
75 
76     Version 1.7 January 9, 1997 (cjm)
77 	- Out-of-order fragment handling.
78 	- IP checksum error fixed for ftp transfers
79 	  from aliasing host.
80 	- Integer return codes added to all
81 	  aliasing/de-aliasing functions.
82 	- Some obsolete comments cleaned up.
83 	- Differential checksum computations for
84 	  IP header (TCP, UDP and ICMP were already
85 	  differential).
86 
87     Version 2.1 May 1997 (cjm)
88 	- Added support for outgoing ICMP error
89 	  messages.
90 	- Added two functions PacketAliasIn2()
91 	  and PacketAliasOut2() for dynamic address
92 	  control (e.g. round-robin allocation of
93 	  incoming packets).
94 
95     Version 2.2 July 1997 (cjm)
96 	- Rationalized API function names to begin
97 	  with "PacketAlias..."
98 	- Eliminated PacketAliasIn2() and
99 	  PacketAliasOut2() as poorly conceived.
100 
101     Version 2.3 Dec 1998 (dillon)
102 	- Major bounds checking additions, see FreeBSD/CVS
103 
104     Version 3.1 May, 2000 (salander)
105 	- Added hooks to handle PPTP.
106 
107     Version 3.2 July, 2000 (salander and satoh)
108 	- Added PacketUnaliasOut routine.
109 	- Added hooks to handle RTSP/RTP.
110 
111     See HISTORY file for additional revisions.
112 */
113 
114 #ifdef _KERNEL
115 #include <sys/param.h>
116 #include <sys/systm.h>
117 #include <sys/mbuf.h>
118 #include <sys/sysctl.h>
119 #else
120 #include <sys/types.h>
121 #include <stdlib.h>
122 #include <stdio.h>
123 #include <ctype.h>
124 #include <dlfcn.h>
125 #include <errno.h>
126 #include <string.h>
127 #endif
128 
129 #include <netinet/in_systm.h>
130 #include <netinet/in.h>
131 #include <netinet/ip.h>
132 #include <netinet/ip_icmp.h>
133 #include <netinet/tcp.h>
134 #include <netinet/udp.h>
135 
136 #ifdef _KERNEL
137 #include <netinet/libalias/alias.h>
138 #include <netinet/libalias/alias_local.h>
139 #include <netinet/libalias/alias_mod.h>
140 #else
141 #include <err.h>
142 #include "alias.h"
143 #include "alias_local.h"
144 #include "alias_mod.h"
145 #endif
146 
147 /*
148  * Define libalias SYSCTL Node
149  */
150 #ifdef SYSCTL_NODE
151 
152 SYSCTL_DECL(_net_inet);
153 SYSCTL_DECL(_net_inet_ip);
154 SYSCTL_NODE(_net_inet_ip, OID_AUTO, alias, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
155     "Libalias sysctl API");
156 
157 #endif
158 
159 static __inline int
twowords(void * p)160 twowords(void *p)
161 {
162 	uint8_t *c = p;
163 
164 #if BYTE_ORDER == LITTLE_ENDIAN
165 	uint16_t s1 = ((uint16_t)c[1] << 8) + (uint16_t)c[0];
166 	uint16_t s2 = ((uint16_t)c[3] << 8) + (uint16_t)c[2];
167 #else
168 	uint16_t s1 = ((uint16_t)c[0] << 8) + (uint16_t)c[1];
169 	uint16_t s2 = ((uint16_t)c[2] << 8) + (uint16_t)c[3];
170 #endif
171 	return (s1 + s2);
172 }
173 
174 /* TCP Handling Routines
175 
176     TcpMonitorIn()  -- These routines monitor TCP connections, and
177     TcpMonitorOut()    delete a link when a connection is closed.
178 
179 These routines look for SYN, FIN and RST flags to determine when TCP
180 connections open and close.  When a TCP connection closes, the data
181 structure containing packet aliasing information is deleted after
182 a timeout period.
183 */
184 
185 /* Local prototypes */
186 static void	TcpMonitorIn(uint16_t, struct alias_link *);
187 
188 static void	TcpMonitorOut(uint16_t, struct alias_link *);
189 
190 static void
TcpMonitorIn(uint16_t th_flags,struct alias_link * lnk)191 TcpMonitorIn(uint16_t th_flags, struct alias_link *lnk)
192 {
193 	switch (GetStateIn(lnk)) {
194 	case ALIAS_TCP_STATE_NOT_CONNECTED:
195 		if (th_flags & TH_RST)
196 			SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED);
197 		else if (th_flags & TH_SYN)
198 			SetStateIn(lnk, ALIAS_TCP_STATE_CONNECTED);
199 		break;
200 	case ALIAS_TCP_STATE_CONNECTED:
201 		if (th_flags & (TH_FIN | TH_RST))
202 			SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED);
203 		break;
204 	}
205 }
206 
207 static void
TcpMonitorOut(uint16_t th_flags,struct alias_link * lnk)208 TcpMonitorOut(uint16_t th_flags, struct alias_link *lnk)
209 {
210 	switch (GetStateOut(lnk)) {
211 	case ALIAS_TCP_STATE_NOT_CONNECTED:
212 		if (th_flags & TH_RST)
213 			SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED);
214 		else if (th_flags & TH_SYN)
215 			SetStateOut(lnk, ALIAS_TCP_STATE_CONNECTED);
216 		break;
217 	case ALIAS_TCP_STATE_CONNECTED:
218 		if (th_flags & (TH_FIN | TH_RST))
219 			SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED);
220 		break;
221 	}
222 }
223 
224 /* Protocol Specific Packet Aliasing Routines
225 
226     IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
227     IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
228     ProtoAliasIn(), ProtoAliasOut()
229     UdpAliasIn(), UdpAliasOut()
230     TcpAliasIn(), TcpAliasOut()
231 
232 These routines handle protocol specific details of packet aliasing.
233 One may observe a certain amount of repetitive arithmetic in these
234 functions, the purpose of which is to compute a revised checksum
235 without actually summing over the entire data packet, which could be
236 unnecessarily time consuming.
237 
238 The purpose of the packet aliasing routines is to replace the source
239 address of the outgoing packet and then correctly put it back for
240 any incoming packets.  For TCP and UDP, ports are also re-mapped.
241 
242 For ICMP echo/timestamp requests and replies, the following scheme
243 is used: the ID number is replaced by an alias for the outgoing
244 packet.
245 
246 ICMP error messages are handled by looking at the IP fragment
247 in the data section of the message.
248 
249 For TCP and UDP protocols, a port number is chosen for an outgoing
250 packet, and then incoming packets are identified by IP address and
251 port numbers.  For TCP packets, there is additional logic in the event
252 that sequence and ACK numbers have been altered (as in the case for
253 FTP data port commands).
254 
255 The port numbers used by the packet aliasing module are not true
256 ports in the Unix sense.  No sockets are actually bound to ports.
257 They are more correctly thought of as placeholders.
258 
259 All packets go through the aliasing mechanism, whether they come from
260 the gateway machine or other machines on a local area network.
261 */
262 
263 /* Local prototypes */
264 static int	IcmpAliasIn1(struct libalias *, struct ip *);
265 static int	IcmpAliasIn2(struct libalias *, struct ip *);
266 static int	IcmpAliasIn(struct libalias *, struct ip *);
267 
268 static int	IcmpAliasOut1(struct libalias *, struct ip *, int create);
269 static int	IcmpAliasOut2(struct libalias *, struct ip *);
270 static int	IcmpAliasOut(struct libalias *, struct ip *, int create);
271 
272 static int	ProtoAliasIn(struct libalias *la, struct in_addr ip_src,
273 		    struct ip *pip, u_char ip_p, u_short *ip_sum);
274 static int	ProtoAliasOut(struct libalias *la, struct ip *pip,
275 		    struct in_addr ip_dst, u_char ip_p, u_short *ip_sum,
276 		    int create);
277 
278 static int	UdpAliasIn(struct libalias *, struct ip *);
279 static int	UdpAliasOut(struct libalias *, struct ip *, int, int create);
280 
281 static int	TcpAliasIn(struct libalias *, struct ip *);
282 static int	TcpAliasOut(struct libalias *, struct ip *, int, int create);
283 
284 /*
285     De-alias incoming echo and timestamp replies.
286     Alias incoming echo and timestamp requests.
287 */
288 static int
IcmpAliasIn1(struct libalias * la,struct ip * pip)289 IcmpAliasIn1(struct libalias *la, struct ip *pip)
290 {
291 	struct alias_link *lnk;
292 	struct icmp *ic;
293 	int ret;
294 
295 	LIBALIAS_LOCK_ASSERT(la);
296 	ic = (struct icmp *)ip_next(pip);
297 
298 	/* Get source address from ICMP data field and restore original data */
299 	ret = FindIcmpIn(la, pip->ip_src, pip->ip_dst, ic->icmp_id, 1, &lnk);
300 	if (ret == PKT_ALIAS_OK) {
301 		u_short original_id;
302 		int accumulate;
303 
304 		original_id = GetOriginalPort(lnk);
305 
306 		/* Adjust ICMP checksum */
307 		accumulate = ic->icmp_id;
308 		accumulate -= original_id;
309 		ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
310 
311 		/* Put original sequence number back in */
312 		ic->icmp_id = original_id;
313 
314 		/* Put original address back into IP header */
315 		{
316 			struct in_addr original_address;
317 
318 			original_address = GetOriginalAddress(lnk);
319 			DifferentialChecksum(&pip->ip_sum,
320 			    &original_address, &pip->ip_dst, 2);
321 			pip->ip_dst = original_address;
322 		}
323 	}
324 	return (ret);
325 }
326 
327 /*
328     Alias incoming ICMP error messages containing
329     IP header and first 64 bits of datagram.
330 */
331 static int
IcmpAliasIn2(struct libalias * la,struct ip * pip)332 IcmpAliasIn2(struct libalias *la, struct ip *pip)
333 {
334 	struct ip *ip;
335 	struct icmp *ic, *ic2;
336 	struct udphdr *ud;
337 	struct tcphdr *tc;
338 	struct alias_link *lnk;
339 	int ret;
340 
341 	LIBALIAS_LOCK_ASSERT(la);
342 	ic = (struct icmp *)ip_next(pip);
343 	ip = &ic->icmp_ip;
344 
345 	ud = (struct udphdr *)ip_next(ip);
346 	tc = (struct tcphdr *)ip_next(ip);
347 	ic2 = (struct icmp *)ip_next(ip);
348 
349 	if (ip->ip_p == IPPROTO_UDP) {
350 		ret = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
351 		    ud->uh_dport, ud->uh_sport,
352 		    IPPROTO_UDP, 0, &lnk);
353 		if (ret != PKT_ALIAS_OK)
354 			return (ret);
355 	} else if (ip->ip_p == IPPROTO_TCP) {
356 		ret = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
357 		    tc->th_dport, tc->th_sport,
358 		    IPPROTO_TCP, 0, &lnk);
359 		if (ret != PKT_ALIAS_OK)
360 			return (ret);
361 	} else if (ip->ip_p == IPPROTO_ICMP) {
362 		if (ic2->icmp_type == ICMP_ECHO ||
363 		    ic2->icmp_type == ICMP_TSTAMP) {
364 			ret = FindIcmpIn(la, ip->ip_dst, ip->ip_src,
365 			    ic2->icmp_id, 0, &lnk);
366 			if (ret != PKT_ALIAS_OK)
367 				return (ret);
368 		} else
369 			lnk = NULL;
370 	} else
371 		lnk = NULL;
372 
373 	if (lnk != NULL) {
374 		if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
375 			int accumulate, accumulate2;
376 			struct in_addr original_address;
377 			u_short original_port;
378 
379 			original_address = GetOriginalAddress(lnk);
380 			original_port = GetOriginalPort(lnk);
381 
382 			/* Adjust ICMP checksum */
383 			accumulate = twowords(&ip->ip_src);
384 			accumulate -= twowords(&original_address);
385 			accumulate += ud->uh_sport;
386 			accumulate -= original_port;
387 			accumulate2 = accumulate;
388 			accumulate2 += ip->ip_sum;
389 			ADJUST_CHECKSUM(accumulate, ip->ip_sum);
390 			accumulate2 -= ip->ip_sum;
391 			ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
392 
393 			/* Un-alias address in IP header */
394 			DifferentialChecksum(&pip->ip_sum,
395 			    &original_address, &pip->ip_dst, 2);
396 			pip->ip_dst = original_address;
397 
398 			/* Un-alias address and port number of
399 			 * original IP packet fragment contained
400 			 * in ICMP data section */
401 			ip->ip_src = original_address;
402 			ud->uh_sport = original_port;
403 		} else if (ip->ip_p == IPPROTO_ICMP) {
404 			int accumulate, accumulate2;
405 			struct in_addr original_address;
406 			u_short original_id;
407 
408 			original_address = GetOriginalAddress(lnk);
409 			original_id = GetOriginalPort(lnk);
410 
411 			/* Adjust ICMP checksum */
412 			accumulate = twowords(&ip->ip_src);
413 			accumulate -= twowords(&original_address);
414 			accumulate += ic2->icmp_id;
415 			accumulate -= original_id;
416 			accumulate2 = accumulate;
417 			accumulate2 += ip->ip_sum;
418 			ADJUST_CHECKSUM(accumulate, ip->ip_sum);
419 			accumulate2 -= ip->ip_sum;
420 			ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
421 
422 			/* Un-alias address in IP header */
423 			DifferentialChecksum(&pip->ip_sum,
424 			    &original_address, &pip->ip_dst, 2);
425 			pip->ip_dst = original_address;
426 
427 			/* Un-alias address of original IP packet and
428 			 * sequence number of embedded ICMP datagram */
429 			ip->ip_src = original_address;
430 			ic2->icmp_id = original_id;
431 		}
432 		return (PKT_ALIAS_OK);
433 	}
434 	return (PKT_ALIAS_IGNORED);
435 }
436 
437 static int
IcmpAliasIn(struct libalias * la,struct ip * pip)438 IcmpAliasIn(struct libalias *la, struct ip *pip)
439 {
440 	struct icmp *ic;
441 	int iresult;
442 	size_t dlen;
443 
444 	LIBALIAS_LOCK_ASSERT(la);
445 
446 	dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
447 	if (dlen < ICMP_MINLEN)
448 		return (PKT_ALIAS_IGNORED);
449 
450 	/* Return if proxy-only mode is enabled */
451 	if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
452 		return (PKT_ALIAS_OK);
453 
454 	ic = (struct icmp *)ip_next(pip);
455 
456 	iresult = PKT_ALIAS_IGNORED;
457 	switch (ic->icmp_type) {
458 	case ICMP_ECHOREPLY:
459 	case ICMP_TSTAMPREPLY:
460 		if (ic->icmp_code == 0) {
461 			iresult = IcmpAliasIn1(la, pip);
462 		}
463 		break;
464 	case ICMP_UNREACH:
465 	case ICMP_SOURCEQUENCH:
466 	case ICMP_TIMXCEED:
467 	case ICMP_PARAMPROB:
468 		if (dlen < ICMP_ADVLENMIN ||
469 		    dlen < (size_t)ICMP_ADVLEN(ic))
470 			return (PKT_ALIAS_IGNORED);
471 		iresult = IcmpAliasIn2(la, pip);
472 		break;
473 	case ICMP_ECHO:
474 	case ICMP_TSTAMP:
475 		iresult = IcmpAliasIn1(la, pip);
476 		break;
477 	}
478 	return (iresult);
479 }
480 
481 /*
482     Alias outgoing echo and timestamp requests.
483     De-alias outgoing echo and timestamp replies.
484 */
485 static int
IcmpAliasOut1(struct libalias * la,struct ip * pip,int create)486 IcmpAliasOut1(struct libalias *la, struct ip *pip, int create)
487 {
488 	struct alias_link *lnk;
489 	struct icmp *ic;
490 	int ret;
491 
492 	LIBALIAS_LOCK_ASSERT(la);
493 	ic = (struct icmp *)ip_next(pip);
494 
495 	/* Save overwritten data for when echo packet returns */
496 	ret = FindIcmpOut(la, pip->ip_src, pip->ip_dst, ic->icmp_id, create,
497 	    &lnk);
498 	if (ret == PKT_ALIAS_OK) {
499 		u_short alias_id;
500 		int accumulate;
501 
502 		alias_id = GetAliasPort(lnk);
503 
504 		/* Since data field is being modified, adjust ICMP checksum */
505 		accumulate = ic->icmp_id;
506 		accumulate -= alias_id;
507 		ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
508 
509 		/* Alias sequence number */
510 		ic->icmp_id = alias_id;
511 
512 		/* Change source address */
513 		{
514 			struct in_addr alias_address;
515 
516 			alias_address = GetAliasAddress(lnk);
517 			DifferentialChecksum(&pip->ip_sum,
518 			    &alias_address, &pip->ip_src, 2);
519 			pip->ip_src = alias_address;
520 		}
521 	}
522 	return (ret);
523 }
524 
525 /*
526     Alias outgoing ICMP error messages containing
527     IP header and first 64 bits of datagram.
528 */
529 static int
IcmpAliasOut2(struct libalias * la,struct ip * pip)530 IcmpAliasOut2(struct libalias *la, struct ip *pip)
531 {
532 	struct ip *ip;
533 	struct icmp *ic, *ic2;
534 	struct udphdr *ud;
535 	struct tcphdr *tc;
536 	struct alias_link *lnk;
537 	int ret;
538 
539 	LIBALIAS_LOCK_ASSERT(la);
540 	ic = (struct icmp *)ip_next(pip);
541 	ip = &ic->icmp_ip;
542 
543 	ud = (struct udphdr *)ip_next(ip);
544 	tc = (struct tcphdr *)ip_next(ip);
545 	ic2 = (struct icmp *)ip_next(ip);
546 
547 	if (ip->ip_p == IPPROTO_UDP) {
548 		ret = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
549 		    ud->uh_dport, ud->uh_sport,
550 		    IPPROTO_UDP, 0, &lnk);
551 		if (ret != PKT_ALIAS_OK)
552 			return (ret);
553 	} else if (ip->ip_p == IPPROTO_TCP) {
554 		ret = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
555 		    tc->th_dport, tc->th_sport,
556 		    IPPROTO_TCP, 0, &lnk);
557 		if (ret != PKT_ALIAS_OK)
558 			return (ret);
559 	} else if (ip->ip_p == IPPROTO_ICMP) {
560 		if (ic2->icmp_type == ICMP_ECHO ||
561 		    ic2->icmp_type == ICMP_TSTAMP) {
562 			ret = FindIcmpOut(la, ip->ip_dst, ip->ip_src,
563 			    ic2->icmp_id, 0, &lnk);
564 			if (ret != PKT_ALIAS_OK)
565 				return (ret);
566 		} else
567 			lnk = NULL;
568 	} else
569 		lnk = NULL;
570 
571 	if (lnk != NULL) {
572 		if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
573 			int accumulate;
574 			struct in_addr alias_address;
575 			u_short alias_port;
576 
577 			alias_address = GetAliasAddress(lnk);
578 			alias_port = GetAliasPort(lnk);
579 
580 			/* Adjust ICMP checksum */
581 			accumulate = twowords(&ip->ip_dst);
582 			accumulate -= twowords(&alias_address);
583 			accumulate += ud->uh_dport;
584 			accumulate -= alias_port;
585 			ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
586 
587 			/*
588 			 * Alias address in IP header if it comes from the host
589 			 * the original TCP/UDP packet was destined for.
590 			 */
591 			if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
592 				DifferentialChecksum(&pip->ip_sum,
593 				    &alias_address, &pip->ip_src, 2);
594 				pip->ip_src = alias_address;
595 			}
596 			/* Alias address and port number of original IP packet
597 			 * fragment contained in ICMP data section */
598 			ip->ip_dst = alias_address;
599 			ud->uh_dport = alias_port;
600 		} else if (ip->ip_p == IPPROTO_ICMP) {
601 			int accumulate;
602 			struct in_addr alias_address;
603 			u_short alias_id;
604 
605 			alias_address = GetAliasAddress(lnk);
606 			alias_id = GetAliasPort(lnk);
607 
608 			/* Adjust ICMP checksum */
609 			accumulate = twowords(&ip->ip_dst);
610 			accumulate -= twowords(&alias_address);
611 			accumulate += ic2->icmp_id;
612 			accumulate -= alias_id;
613 			ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
614 
615 			/*
616 			 * Alias address in IP header if it comes from the host
617 			 * the original ICMP message was destined for.
618 			 */
619 			if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
620 				DifferentialChecksum(&pip->ip_sum,
621 				    &alias_address, &pip->ip_src, 2);
622 				pip->ip_src = alias_address;
623 			}
624 			/* Alias address of original IP packet and
625 			 * sequence number of embedded ICMP datagram */
626 			ip->ip_dst = alias_address;
627 			ic2->icmp_id = alias_id;
628 		}
629 		return (PKT_ALIAS_OK);
630 	}
631 	return (PKT_ALIAS_IGNORED);
632 }
633 
634 static int
IcmpAliasOut(struct libalias * la,struct ip * pip,int create)635 IcmpAliasOut(struct libalias *la, struct ip *pip, int create)
636 {
637 	int iresult;
638 	struct icmp *ic;
639 
640 	LIBALIAS_LOCK_ASSERT(la);
641 	(void)create;
642 
643 	/* Return if proxy-only mode is enabled */
644 	if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
645 		return (PKT_ALIAS_OK);
646 
647 	ic = (struct icmp *)ip_next(pip);
648 
649 	iresult = PKT_ALIAS_IGNORED;
650 	switch (ic->icmp_type) {
651 	case ICMP_ECHO:
652 	case ICMP_TSTAMP:
653 		if (ic->icmp_code == 0) {
654 			iresult = IcmpAliasOut1(la, pip, create);
655 		}
656 		break;
657 	case ICMP_UNREACH:
658 	case ICMP_SOURCEQUENCH:
659 	case ICMP_TIMXCEED:
660 	case ICMP_PARAMPROB:
661 		iresult = IcmpAliasOut2(la, pip);
662 		break;
663 	case ICMP_ECHOREPLY:
664 	case ICMP_TSTAMPREPLY:
665 		iresult = IcmpAliasOut1(la, pip, create);
666 	}
667 	return (iresult);
668 }
669 
670 /*
671   Handle incoming IP packets. The
672   only thing which is done in this case is to alias
673   the dest IP address of the packet to our inside
674   machine.
675 */
676 static int
ProtoAliasIn(struct libalias * la,struct in_addr ip_src,struct ip * pip,u_char ip_p,u_short * ip_sum)677 ProtoAliasIn(struct libalias *la, struct in_addr ip_src,
678     struct ip *pip, u_char ip_p, u_short *ip_sum)
679 {
680 	struct alias_link *lnk;
681 	int ret;
682 
683 	LIBALIAS_LOCK_ASSERT(la);
684 	/* Return if proxy-only mode is enabled */
685 	if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
686 		return (PKT_ALIAS_OK);
687 
688 	ret = FindProtoIn(la, ip_src, pip->ip_dst, ip_p, &lnk);
689 	if (ret == PKT_ALIAS_OK) {
690 		struct in_addr original_address;
691 
692 		original_address = GetOriginalAddress(lnk);
693 
694 		/* Restore original IP address */
695 		DifferentialChecksum(ip_sum,
696 		    &original_address, &pip->ip_dst, 2);
697 		pip->ip_dst = original_address;
698 	}
699 	return (ret);
700 }
701 
702 /*
703   Handle outgoing IP packets. The
704   only thing which is done in this case is to alias
705   the source IP address of the packet.
706 */
707 static int
ProtoAliasOut(struct libalias * la,struct ip * pip,struct in_addr ip_dst,u_char ip_p,u_short * ip_sum,int create)708 ProtoAliasOut(struct libalias *la, struct ip *pip,
709     struct in_addr ip_dst, u_char ip_p, u_short *ip_sum, int create)
710 {
711 	struct alias_link *lnk;
712 	int ret;
713 
714 	LIBALIAS_LOCK_ASSERT(la);
715 
716 	/* Return if proxy-only mode is enabled */
717 	if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
718 		return (PKT_ALIAS_OK);
719 
720 	if (!create)
721 		return (PKT_ALIAS_IGNORED);
722 
723 	ret = FindProtoOut(la, pip->ip_src, ip_dst, ip_p, &lnk);
724 	if (ret == PKT_ALIAS_OK) {
725 		struct in_addr alias_address;
726 
727 		alias_address = GetAliasAddress(lnk);
728 
729 		/* Change source address */
730 		DifferentialChecksum(ip_sum,
731 		    &alias_address, &pip->ip_src, 2);
732 		pip->ip_src = alias_address;
733 	}
734 	return (ret);
735 }
736 
737 #define MF_ISSET(_pip) (ntohs((_pip)->ip_off) & IP_MF)
738 #define FRAG_NO_HDR(_pip) (ntohs((_pip)->ip_off) & IP_OFFMASK)
739 
740 static struct udphdr *
ValidateUdpLength(struct ip * pip)741 ValidateUdpLength(struct ip *pip)
742 {
743 	struct udphdr *ud;
744 	size_t dlen;
745 
746 #ifdef _KERNEL
747 	KASSERT(!FRAG_NO_HDR(pip), ("header-less fragment isn't expected here"));
748 #endif
749 	dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
750 	if (dlen < sizeof(struct udphdr))
751 		return (NULL);
752 	ud = (struct udphdr *)ip_next(pip);
753 	if (!MF_ISSET(pip) && dlen < ntohs(ud->uh_ulen))
754 		return (NULL);
755 	return (ud);
756 }
757 
758 static int
UdpAliasIn(struct libalias * la,struct ip * pip)759 UdpAliasIn(struct libalias *la, struct ip *pip)
760 {
761 	struct udphdr *ud;
762 	struct alias_link *lnk;
763 	int ret;
764 
765 	LIBALIAS_LOCK_ASSERT(la);
766 
767 	ud = ValidateUdpLength(pip);
768 	if (ud == NULL)
769 		return (PKT_ALIAS_IGNORED);
770 
771 	ret = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
772 	    ud->uh_sport, ud->uh_dport,
773 	    IPPROTO_UDP, !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY), &lnk);
774 	if (ret != PKT_ALIAS_OK)
775 		return (ret);
776 	{
777 		struct in_addr alias_address;
778 		struct in_addr original_address;
779 		struct in_addr proxy_address;
780 		u_short alias_port;
781 		u_short proxy_port;
782 		int accumulate;
783 		int error;
784 		struct alias_data ad = {
785 			.lnk = lnk,
786 			.oaddr = &original_address,
787 			.aaddr = &alias_address,
788 			.aport = &alias_port,
789 			.sport = &ud->uh_sport,
790 			.dport = &ud->uh_dport,
791 			.maxpktsize = 0
792 		};
793 
794 		alias_address = GetAliasAddress(lnk);
795 		original_address = GetOriginalAddress(lnk);
796 		proxy_address = GetProxyAddress(lnk);
797 		alias_port = ud->uh_dport;
798 		ud->uh_dport = GetOriginalPort(lnk);
799 		proxy_port = GetProxyPort(lnk);
800 
801 		/* Walk out chain. */
802 		error = find_handler(IN, UDP, la, pip, &ad);
803 		/* If we cannot figure out the packet, ignore it. */
804 		if (error < 0)
805 			return (PKT_ALIAS_IGNORED);
806 
807 		/* If UDP checksum is not zero, then adjust since
808 		 * destination port is being unaliased and
809 		 * destination address is being altered. */
810 		if (ud->uh_sum != 0) {
811 			accumulate = alias_port;
812 			accumulate -= ud->uh_dport;
813 			accumulate += twowords(&alias_address);
814 			accumulate -= twowords(&original_address);
815 
816 			/* If this is a proxy packet, modify checksum
817 			 * because of source change.*/
818 			if (proxy_port != 0) {
819 				accumulate += ud->uh_sport;
820 				accumulate -= proxy_port;
821 			}
822 
823 			if (proxy_address.s_addr != 0) {
824 				accumulate += twowords(&pip->ip_src);
825 				accumulate -= twowords(&proxy_address);
826 			}
827 
828 			ADJUST_CHECKSUM(accumulate, ud->uh_sum);
829 		}
830 
831 		/* XXX: Could the two if's below be concatenated to one ? */
832 		/* Restore source port and/or address in case of proxying*/
833 		if (proxy_port != 0)
834 			ud->uh_sport = proxy_port;
835 
836 		if (proxy_address.s_addr != 0) {
837 			DifferentialChecksum(&pip->ip_sum,
838 			    &proxy_address, &pip->ip_src, 2);
839 			pip->ip_src = proxy_address;
840 		}
841 
842 		/* Restore original IP address */
843 		DifferentialChecksum(&pip->ip_sum,
844 		    &original_address, &pip->ip_dst, 2);
845 		pip->ip_dst = original_address;
846 
847 		return (PKT_ALIAS_OK);
848 	}
849 }
850 
851 static int
UdpAliasOut(struct libalias * la,struct ip * pip,int maxpacketsize,int create)852 UdpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
853 {
854 	struct udphdr *ud;
855 	struct alias_link *lnk;
856 	struct in_addr dest_address;
857 	struct in_addr proxy_server_address;
858 	u_short dest_port;
859 	u_short proxy_server_port;
860 	int proxy_type, ret;
861 
862 	LIBALIAS_LOCK_ASSERT(la);
863 
864 	ud = ValidateUdpLength(pip);
865 	if (ud == NULL)
866 		return (PKT_ALIAS_IGNORED);
867 
868 	/* Return if proxy-only mode is enabled and not proxyrule found.*/
869 	proxy_type = ProxyCheck(la, &proxy_server_address, &proxy_server_port,
870 	    pip->ip_src, pip->ip_dst, ud->uh_dport, pip->ip_p);
871 	if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
872 		return (PKT_ALIAS_OK);
873 
874 	/* If this is a transparent proxy, save original destination,
875 	 * then alter the destination and adjust checksums */
876 	dest_port = ud->uh_dport;
877 	dest_address = pip->ip_dst;
878 
879 	if (proxy_type != 0) {
880 		int accumulate;
881 
882 		accumulate = twowords(&pip->ip_dst);
883 		accumulate -= twowords(&proxy_server_address);
884 
885 		ADJUST_CHECKSUM(accumulate, pip->ip_sum);
886 
887 		if (ud->uh_sum != 0) {
888 			accumulate = twowords(&pip->ip_dst);
889 			accumulate -= twowords(&proxy_server_address);
890 			accumulate += ud->uh_dport;
891 			accumulate -= proxy_server_port;
892 			ADJUST_CHECKSUM(accumulate, ud->uh_sum);
893 		}
894 		pip->ip_dst = proxy_server_address;
895 		ud->uh_dport = proxy_server_port;
896 	}
897 	ret = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
898 	    ud->uh_sport, ud->uh_dport,
899 	    IPPROTO_UDP, create, &lnk);
900 	if (ret != PKT_ALIAS_OK)
901 		return (ret);
902 	{
903 		u_short alias_port;
904 		struct in_addr alias_address;
905 		struct alias_data ad = {
906 			.lnk = lnk,
907 			.oaddr = NULL,
908 			.aaddr = &alias_address,
909 			.aport = &alias_port,
910 			.sport = &ud->uh_sport,
911 			.dport = &ud->uh_dport,
912 			.maxpktsize = 0
913 		};
914 
915 		/* Save original destination address, if this is a proxy packet.
916 		 * Also modify packet to include destination encoding.  This may
917 		 * change the size of IP header. */
918 		if (proxy_type != 0) {
919 			SetProxyPort(lnk, dest_port);
920 			SetProxyAddress(lnk, dest_address);
921 			ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
922 			ud = (struct udphdr *)ip_next(pip);
923 		}
924 
925 		alias_address = GetAliasAddress(lnk);
926 		alias_port = GetAliasPort(lnk);
927 
928 		/* Walk out chain. */
929 		find_handler(OUT, UDP, la, pip, &ad);
930 
931 		/* If UDP checksum is not zero, adjust since source port is */
932 		/* being aliased and source address is being altered	*/
933 		if (ud->uh_sum != 0) {
934 			int accumulate;
935 
936 			accumulate = ud->uh_sport;
937 			accumulate -= alias_port;
938 			accumulate += twowords(&pip->ip_src);
939 			accumulate -= twowords(&alias_address);
940 			ADJUST_CHECKSUM(accumulate, ud->uh_sum);
941 		}
942 		/* Put alias port in UDP header */
943 		ud->uh_sport = alias_port;
944 
945 		/* Change source address */
946 		DifferentialChecksum(&pip->ip_sum,
947 		    &alias_address, &pip->ip_src, 2);
948 		pip->ip_src = alias_address;
949 
950 		return (PKT_ALIAS_OK);
951 	}
952 }
953 
954 static int
TcpAliasIn(struct libalias * la,struct ip * pip)955 TcpAliasIn(struct libalias *la, struct ip *pip)
956 {
957 	struct tcphdr *tc;
958 	struct alias_link *lnk;
959 	size_t dlen;
960 	int ret;
961 
962 	LIBALIAS_LOCK_ASSERT(la);
963 
964 	dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
965 	if (dlen < sizeof(struct tcphdr))
966 		return (PKT_ALIAS_IGNORED);
967 	tc = (struct tcphdr *)ip_next(pip);
968 
969 	ret = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
970 	    tc->th_sport, tc->th_dport,
971 	    IPPROTO_TCP,
972 	    !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY),
973 	    &lnk);
974 	if (ret == PKT_ALIAS_OK) {
975 		struct in_addr alias_address;
976 		struct in_addr original_address;
977 		struct in_addr proxy_address;
978 		u_short alias_port;
979 		u_short proxy_port;
980 		int accumulate;
981 
982 		/*
983 		 * The init of MANY vars is a bit below, but aliashandlepptpin
984 		 * seems to need the destination port that came within the
985 		 * packet and not the original one looks below [*].
986 		 */
987 
988 		struct alias_data ad = {
989 			.lnk = lnk,
990 			.oaddr = NULL,
991 			.aaddr = NULL,
992 			.aport = NULL,
993 			.sport = &tc->th_sport,
994 			.dport = &tc->th_dport,
995 			.maxpktsize = 0
996 		};
997 
998 		/* Walk out chain. */
999 		find_handler(IN, TCP, la, pip, &ad);
1000 
1001 		alias_address = GetAliasAddress(lnk);
1002 		original_address = GetOriginalAddress(lnk);
1003 		proxy_address = GetProxyAddress(lnk);
1004 		alias_port = tc->th_dport;
1005 		tc->th_dport = GetOriginalPort(lnk);
1006 		proxy_port = GetProxyPort(lnk);
1007 
1008 		/*
1009 		 * Look above, if anyone is going to add find_handler AFTER
1010 		 * this aliashandlepptpin/point, please redo alias_data too.
1011 		 * Uncommenting the piece here below should be enough.
1012 		 */
1013 #if 0
1014 				 struct alias_data ad = {
1015 					.lnk = lnk,
1016 					.oaddr = &original_address,
1017 					.aaddr = &alias_address,
1018 					.aport = &alias_port,
1019 					.sport = &ud->uh_sport,
1020 					.dport = &ud->uh_dport,
1021 					.maxpktsize = 0
1022 				};
1023 
1024 				/* Walk out chain. */
1025 				error = find_handler(la, pip, &ad);
1026 				if (error == EHDNOF)
1027 					printf("Protocol handler not found\n");
1028 #endif
1029 
1030 		/* Adjust TCP checksum since destination port is being
1031 		 * unaliased and destination port is being altered. */
1032 		accumulate = alias_port;
1033 		accumulate -= tc->th_dport;
1034 		accumulate += twowords(&alias_address);
1035 		accumulate -= twowords(&original_address);
1036 
1037 		/* If this is a proxy, then modify the TCP source port
1038 		 * and checksum accumulation */
1039 		if (proxy_port != 0) {
1040 			accumulate += tc->th_sport;
1041 			tc->th_sport = proxy_port;
1042 			accumulate -= tc->th_sport;
1043 			accumulate += twowords(&pip->ip_src);
1044 			accumulate -= twowords(&proxy_address);
1045 		}
1046 		/* See if ACK number needs to be modified */
1047 		if (GetAckModified(lnk) == 1) {
1048 			int delta;
1049 
1050 			tc = (struct tcphdr *)ip_next(pip);
1051 			delta = GetDeltaAckIn(tc->th_ack, lnk);
1052 			if (delta != 0) {
1053 				accumulate += twowords(&tc->th_ack);
1054 				tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
1055 				accumulate -= twowords(&tc->th_ack);
1056 			}
1057 		}
1058 		ADJUST_CHECKSUM(accumulate, tc->th_sum);
1059 
1060 		/* Restore original IP address */
1061 		accumulate = twowords(&pip->ip_dst);
1062 		pip->ip_dst = original_address;
1063 		accumulate -= twowords(&pip->ip_dst);
1064 
1065 		/* If this is a transparent proxy packet,
1066 		 * then modify the source address */
1067 		if (proxy_address.s_addr != 0) {
1068 			accumulate += twowords(&pip->ip_src);
1069 			pip->ip_src = proxy_address;
1070 			accumulate -= twowords(&pip->ip_src);
1071 		}
1072 		ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1073 
1074 		/* Monitor TCP connection state */
1075 		tc = (struct tcphdr *)ip_next(pip);
1076 		TcpMonitorIn(__tcp_get_flags(tc), lnk);
1077 
1078 		return (PKT_ALIAS_OK);
1079 	}
1080 	return (ret);
1081 }
1082 
1083 static int
TcpAliasOut(struct libalias * la,struct ip * pip,int maxpacketsize,int create)1084 TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
1085 {
1086 	int proxy_type, ret;
1087 	u_short dest_port;
1088 	u_short proxy_server_port;
1089 	size_t dlen;
1090 	struct in_addr dest_address;
1091 	struct in_addr proxy_server_address;
1092 	struct tcphdr *tc;
1093 	struct alias_link *lnk;
1094 
1095 	LIBALIAS_LOCK_ASSERT(la);
1096 
1097 	dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
1098 	if (dlen < sizeof(struct tcphdr))
1099 		return (PKT_ALIAS_IGNORED);
1100 	tc = (struct tcphdr *)ip_next(pip);
1101 
1102 	if (create)
1103 		proxy_type = ProxyCheck(la, &proxy_server_address,
1104 		    &proxy_server_port, pip->ip_src, pip->ip_dst,
1105 		    tc->th_dport, pip->ip_p);
1106 	else
1107 		proxy_type = 0;
1108 
1109 	if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
1110 		return (PKT_ALIAS_OK);
1111 
1112 	/* If this is a transparent proxy, save original destination,
1113 	 * then alter the destination and adjust checksums */
1114 	dest_port = tc->th_dport;
1115 	dest_address = pip->ip_dst;
1116 	if (proxy_type != 0) {
1117 		int accumulate;
1118 
1119 		accumulate = tc->th_dport;
1120 		tc->th_dport = proxy_server_port;
1121 		accumulate -= tc->th_dport;
1122 		accumulate += twowords(&pip->ip_dst);
1123 		accumulate -= twowords(&proxy_server_address);
1124 		ADJUST_CHECKSUM(accumulate, tc->th_sum);
1125 
1126 		accumulate = twowords(&pip->ip_dst);
1127 		pip->ip_dst = proxy_server_address;
1128 		accumulate -= twowords(&pip->ip_dst);
1129 		ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1130 	}
1131 	ret = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
1132 	    tc->th_sport, tc->th_dport,
1133 	    IPPROTO_TCP, create, &lnk);
1134 	if (ret != PKT_ALIAS_OK)
1135 		return (ret);
1136 	{
1137 		u_short alias_port;
1138 		struct in_addr alias_address;
1139 		int accumulate;
1140 		struct alias_data ad = {
1141 			.lnk = lnk,
1142 			.oaddr = NULL,
1143 			.aaddr = &alias_address,
1144 			.aport = &alias_port,
1145 			.sport = &tc->th_sport,
1146 			.dport = &tc->th_dport,
1147 			.maxpktsize = maxpacketsize
1148 		};
1149 
1150 		/* Save original destination address, if this is a proxy packet.
1151 		 * Also modify packet to include destination
1152 		 * encoding.  This may change the size of IP header. */
1153 		if (proxy_type != 0) {
1154 			SetProxyPort(lnk, dest_port);
1155 			SetProxyAddress(lnk, dest_address);
1156 			ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
1157 			tc = (struct tcphdr *)ip_next(pip);
1158 		}
1159 		/* Get alias address and port */
1160 		alias_port = GetAliasPort(lnk);
1161 		alias_address = GetAliasAddress(lnk);
1162 
1163 		/* Monitor TCP connection state */
1164 		tc = (struct tcphdr *)ip_next(pip);
1165 		TcpMonitorOut(__tcp_get_flags(tc), lnk);
1166 
1167 		/* Walk out chain. */
1168 		find_handler(OUT, TCP, la, pip, &ad);
1169 
1170 		/* Adjust TCP checksum since source port is being aliased
1171 		 * and source address is being altered */
1172 		accumulate = tc->th_sport;
1173 		tc->th_sport = alias_port;
1174 		accumulate -= tc->th_sport;
1175 		accumulate += twowords(&pip->ip_src);
1176 		accumulate -= twowords(&alias_address);
1177 
1178 		/* Modify sequence number if necessary */
1179 		if (GetAckModified(lnk) == 1) {
1180 			int delta;
1181 
1182 			tc = (struct tcphdr *)ip_next(pip);
1183 			delta = GetDeltaSeqOut(tc->th_seq, lnk);
1184 			if (delta != 0) {
1185 				accumulate += twowords(&tc->th_seq);
1186 				tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1187 				accumulate -= twowords(&tc->th_seq);
1188 			}
1189 		}
1190 		ADJUST_CHECKSUM(accumulate, tc->th_sum);
1191 
1192 		/* Change source address */
1193 		accumulate = twowords(&pip->ip_src);
1194 		pip->ip_src = alias_address;
1195 		accumulate -= twowords(&pip->ip_src);
1196 		ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1197 
1198 		return (PKT_ALIAS_OK);
1199 	}
1200 }
1201 
1202 /* Fragment Handling
1203 
1204     FragmentIn()
1205     FragmentOut()
1206 
1207 The packet aliasing module has a limited ability for handling IP
1208 fragments.  If the ICMP, TCP or UDP header is in the first fragment
1209 received, then the ID number of the IP packet is saved, and other
1210 fragments are identified according to their ID number and IP address
1211 they were sent from.  Pointers to unresolved fragments can also be
1212 saved and recalled when a header fragment is seen.
1213 */
1214 
1215 /* Local prototypes */
1216 static int	FragmentIn(struct libalias *la, struct in_addr ip_src,
1217 		    struct ip *pip, u_short ip_id, u_short *ip_sum);
1218 static int	FragmentOut(struct libalias *, struct ip *pip,
1219 		    u_short *ip_sum);
1220 
1221 static int
FragmentIn(struct libalias * la,struct in_addr ip_src,struct ip * pip,u_short ip_id,u_short * ip_sum)1222 FragmentIn(struct libalias *la, struct in_addr ip_src, struct ip *pip,
1223     u_short ip_id, u_short *ip_sum)
1224 {
1225 	struct alias_link *lnk;
1226 
1227 	LIBALIAS_LOCK_ASSERT(la);
1228 	lnk = FindFragmentIn2(la, ip_src, pip->ip_dst, ip_id);
1229 	if (lnk != NULL) {
1230 		struct in_addr original_address;
1231 
1232 		GetFragmentAddr(lnk, &original_address);
1233 		DifferentialChecksum(ip_sum,
1234 		    &original_address, &pip->ip_dst, 2);
1235 		pip->ip_dst = original_address;
1236 
1237 		return (PKT_ALIAS_OK);
1238 	}
1239 	return (PKT_ALIAS_UNRESOLVED_FRAGMENT);
1240 }
1241 
1242 static int
FragmentOut(struct libalias * la,struct ip * pip,u_short * ip_sum)1243 FragmentOut(struct libalias *la, struct ip *pip, u_short *ip_sum)
1244 {
1245 	struct in_addr alias_address;
1246 
1247 	LIBALIAS_LOCK_ASSERT(la);
1248 	alias_address = FindAliasAddress(la, pip->ip_src);
1249 	DifferentialChecksum(ip_sum,
1250 	    &alias_address, &pip->ip_src, 2);
1251 	pip->ip_src = alias_address;
1252 
1253 	return (PKT_ALIAS_OK);
1254 }
1255 
1256 /* Outside World Access
1257 
1258 	PacketAliasSaveFragment()
1259 	PacketAliasGetFragment()
1260 	PacketAliasFragmentIn()
1261 	PacketAliasIn()
1262 	PacketAliasOut()
1263 	PacketUnaliasOut()
1264 
1265 (prototypes in alias.h)
1266 */
1267 
1268 int
LibAliasSaveFragment(struct libalias * la,void * ptr)1269 LibAliasSaveFragment(struct libalias *la, void *ptr)
1270 {
1271 	int iresult;
1272 	struct alias_link *lnk;
1273 	struct ip *pip;
1274 
1275 	LIBALIAS_LOCK(la);
1276 	pip = (struct ip *)ptr;
1277 	lnk = AddFragmentPtrLink(la, pip->ip_src, pip->ip_id);
1278 	iresult = PKT_ALIAS_ERROR;
1279 	if (lnk != NULL) {
1280 		SetFragmentPtr(lnk, ptr);
1281 		iresult = PKT_ALIAS_OK;
1282 	}
1283 	LIBALIAS_UNLOCK(la);
1284 	return (iresult);
1285 }
1286 
1287 void *
LibAliasGetFragment(struct libalias * la,void * ptr)1288 LibAliasGetFragment(struct libalias *la, void *ptr)
1289 {
1290 	struct alias_link *lnk;
1291 	void *fptr;
1292 	struct ip *pip;
1293 
1294 	LIBALIAS_LOCK(la);
1295 	pip = (struct ip *)ptr;
1296 	lnk = FindFragmentPtr(la, pip->ip_src, pip->ip_id);
1297 	if (lnk != NULL) {
1298 		GetFragmentPtr(lnk, &fptr);
1299 		SetFragmentPtr(lnk, NULL);
1300 		SetExpire(lnk, 0);	/* Deletes link */
1301 	} else
1302 		fptr = NULL;
1303 
1304 	LIBALIAS_UNLOCK(la);
1305 	return (fptr);
1306 }
1307 
1308 void
LibAliasFragmentIn(struct libalias * la,void * ptr,void * ptr_fragment)1309 LibAliasFragmentIn(struct libalias *la,
1310     void *ptr,	/* Points to correctly de-aliased header fragment */
1311     void *ptr_fragment	/* fragment which must be de-aliased   */
1312 )
1313 {
1314 	struct ip *pip;
1315 	struct ip *fpip;
1316 
1317 	LIBALIAS_LOCK(la);
1318 	(void)la;
1319 	pip = (struct ip *)ptr;
1320 	fpip = (struct ip *)ptr_fragment;
1321 
1322 	DifferentialChecksum(&fpip->ip_sum,
1323 	    &pip->ip_dst, &fpip->ip_dst, 2);
1324 	fpip->ip_dst = pip->ip_dst;
1325 	LIBALIAS_UNLOCK(la);
1326 }
1327 
1328 /* Local prototypes */
1329 static int
1330 LibAliasOutLocked(struct libalias *la, struct ip *pip,
1331     int maxpacketsize, int create);
1332 static int
1333 LibAliasInLocked(struct libalias *la, struct ip *pip,
1334     int maxpacketsize);
1335 
1336 int
LibAliasIn(struct libalias * la,void * ptr,int maxpacketsize)1337 LibAliasIn(struct libalias *la, void *ptr, int maxpacketsize)
1338 {
1339 	int res;
1340 
1341 	LIBALIAS_LOCK(la);
1342 	res = LibAliasInLocked(la, (struct ip *)ptr, maxpacketsize);
1343 	LIBALIAS_UNLOCK(la);
1344 	return (res);
1345 }
1346 
1347 static int
LibAliasInLocked(struct libalias * la,struct ip * pip,int maxpacketsize)1348 LibAliasInLocked(struct libalias *la, struct ip *pip, int maxpacketsize)
1349 {
1350 	struct in_addr alias_addr;
1351 	int iresult;
1352 
1353 	if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1354 		la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1355 		iresult = LibAliasOutLocked(la, pip, maxpacketsize, 1);
1356 		la->packetAliasMode |= PKT_ALIAS_REVERSE;
1357 		goto getout;
1358 	}
1359 	HouseKeeping(la);
1360 	alias_addr = pip->ip_dst;
1361 
1362 	/* Defense against mangled packets */
1363 	if (ntohs(pip->ip_len) > maxpacketsize
1364 	    || (pip->ip_hl << 2) > maxpacketsize) {
1365 		iresult = PKT_ALIAS_IGNORED;
1366 		goto getout;
1367 	}
1368 
1369 	if (FRAG_NO_HDR(pip)) {
1370 		iresult = FragmentIn(la, pip->ip_src, pip, pip->ip_id,
1371 		    &pip->ip_sum);
1372 		goto getout;
1373 	}
1374 
1375 	iresult = PKT_ALIAS_IGNORED;
1376 	switch (pip->ip_p) {
1377 	case IPPROTO_ICMP:
1378 		iresult = IcmpAliasIn(la, pip);
1379 		break;
1380 	case IPPROTO_UDP:
1381 		iresult = UdpAliasIn(la, pip);
1382 		break;
1383 	case IPPROTO_TCP:
1384 		iresult = TcpAliasIn(la, pip);
1385 		break;
1386 #ifdef _KERNEL
1387 	case IPPROTO_SCTP:
1388 		iresult = SctpAlias(la, pip, SN_TO_LOCAL);
1389 		break;
1390 #endif
1391 	case IPPROTO_GRE: {
1392 		int error;
1393 		struct alias_data ad = {
1394 			.lnk = NULL,
1395 			.oaddr = NULL,
1396 			.aaddr = NULL,
1397 			.aport = NULL,
1398 			.sport = NULL,
1399 			.dport = NULL,
1400 			.maxpktsize = 0
1401 		};
1402 
1403 		/* Walk out chain. */
1404 		error = find_handler(IN, IP, la, pip, &ad);
1405 		if (error == 0)
1406 			iresult = PKT_ALIAS_OK;
1407 		else
1408 			iresult = ProtoAliasIn(la, pip->ip_src,
1409 			    pip, pip->ip_p, &pip->ip_sum);
1410 		break;
1411 	}
1412 	default:
1413 		iresult = ProtoAliasIn(la, pip->ip_src, pip,
1414 		    pip->ip_p, &pip->ip_sum);
1415 		break;
1416 	}
1417 
1418 	if (MF_ISSET(pip)) {
1419 		struct alias_link *lnk;
1420 
1421 		lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id);
1422 		if (lnk != NULL) {
1423 			iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1424 			SetFragmentAddr(lnk, pip->ip_dst);
1425 		} else {
1426 			iresult = PKT_ALIAS_ERROR;
1427 		}
1428 	}
1429 
1430 getout:
1431 	return (iresult);
1432 }
1433 
1434 /* Unregistered address ranges */
1435 
1436 /* 10.0.0.0   ->   10.255.255.255 */
1437 #define UNREG_ADDR_A_LOWER 0x0a000000
1438 #define UNREG_ADDR_A_UPPER 0x0affffff
1439 
1440 /* 172.16.0.0  ->  172.31.255.255 */
1441 #define UNREG_ADDR_B_LOWER 0xac100000
1442 #define UNREG_ADDR_B_UPPER 0xac1fffff
1443 
1444 /* 192.168.0.0 -> 192.168.255.255 */
1445 #define UNREG_ADDR_C_LOWER 0xc0a80000
1446 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1447 
1448 /* 100.64.0.0  -> 100.127.255.255 (RFC 6598 - Carrier Grade NAT) */
1449 #define UNREG_ADDR_CGN_LOWER 0x64400000
1450 #define UNREG_ADDR_CGN_UPPER 0x647fffff
1451 
1452 int
LibAliasOut(struct libalias * la,void * ptr,int maxpacketsize)1453 LibAliasOut(struct libalias *la, void *ptr, int maxpacketsize)
1454 {
1455 	int res;
1456 
1457 	LIBALIAS_LOCK(la);
1458 	res = LibAliasOutLocked(la, (struct ip *)ptr, maxpacketsize, 1);
1459 	LIBALIAS_UNLOCK(la);
1460 	return (res);
1461 }
1462 
1463 int
LibAliasOutTry(struct libalias * la,void * ptr,int maxpacketsize,int create)1464 LibAliasOutTry(struct libalias *la, void *ptr, int maxpacketsize, int create)
1465 {
1466 	int res;
1467 
1468 	LIBALIAS_LOCK(la);
1469 	res = LibAliasOutLocked(la, (struct ip *)ptr, maxpacketsize, create);
1470 	LIBALIAS_UNLOCK(la);
1471 	return (res);
1472 }
1473 
1474 static int
LibAliasOutLocked(struct libalias * la,struct ip * pip,int maxpacketsize,int create)1475 LibAliasOutLocked(struct libalias *la,
1476     struct ip *pip,	/* valid IP packet */
1477     int maxpacketsize,	/* How much the packet data may grow (FTP and IRC inline changes) */
1478     int create		/* Create new entries ? */
1479 )
1480 {
1481 	int iresult;
1482 	struct in_addr addr_save;
1483 
1484 	if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1485 		la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1486 		iresult = LibAliasInLocked(la, pip, maxpacketsize);
1487 		la->packetAliasMode |= PKT_ALIAS_REVERSE;
1488 		goto getout;
1489 	}
1490 	HouseKeeping(la);
1491 
1492 	/* Defense against mangled packets */
1493 	if (ntohs(pip->ip_len) > maxpacketsize
1494 	    || (pip->ip_hl << 2) > maxpacketsize) {
1495 		iresult = PKT_ALIAS_IGNORED;
1496 		goto getout;
1497 	}
1498 
1499 	addr_save = GetDefaultAliasAddress(la);
1500 	if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY ||
1501 	    la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN) {
1502 		u_long addr;
1503 		int iclass;
1504 
1505 		iclass = 0;
1506 		addr = ntohl(pip->ip_src.s_addr);
1507 		if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1508 			iclass = 3;
1509 		else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1510 			iclass = 2;
1511 		else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1512 			iclass = 1;
1513 		else if (addr >= UNREG_ADDR_CGN_LOWER && addr <= UNREG_ADDR_CGN_UPPER &&
1514 		    la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN)
1515 			iclass = 4;
1516 
1517 		if (iclass == 0) {
1518 			SetDefaultAliasAddress(la, pip->ip_src);
1519 		}
1520 	} else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) {
1521 		SetDefaultAliasAddress(la, pip->ip_src);
1522 	}
1523 
1524 	if (FRAG_NO_HDR(pip)) {
1525 		iresult = FragmentOut(la, pip, &pip->ip_sum);
1526 		goto getout_restore;
1527 	}
1528 
1529 	iresult = PKT_ALIAS_IGNORED;
1530 	switch (pip->ip_p) {
1531 	case IPPROTO_ICMP:
1532 		iresult = IcmpAliasOut(la, pip, create);
1533 		break;
1534 	case IPPROTO_UDP:
1535 		iresult = UdpAliasOut(la, pip, maxpacketsize, create);
1536 		break;
1537 	case IPPROTO_TCP:
1538 		iresult = TcpAliasOut(la, pip, maxpacketsize, create);
1539 		break;
1540 #ifdef _KERNEL
1541 	case IPPROTO_SCTP:
1542 		iresult = SctpAlias(la, pip, SN_TO_GLOBAL);
1543 		break;
1544 #endif
1545 	case IPPROTO_GRE: {
1546 		int error;
1547 		struct alias_data ad = {
1548 			.lnk = NULL,
1549 			.oaddr = NULL,
1550 			.aaddr = NULL,
1551 			.aport = NULL,
1552 			.sport = NULL,
1553 			.dport = NULL,
1554 			.maxpktsize = 0
1555 		};
1556 		/* Walk out chain. */
1557 		error = find_handler(OUT, IP, la, pip, &ad);
1558 		if (error == 0)
1559 			iresult = PKT_ALIAS_OK;
1560 		else
1561 			iresult = ProtoAliasOut(la, pip,
1562 			    pip->ip_dst, pip->ip_p, &pip->ip_sum, create);
1563 		break;
1564 		}
1565 	default:
1566 		iresult = ProtoAliasOut(la, pip,
1567 		    pip->ip_dst, pip->ip_p, &pip->ip_sum, create);
1568 		break;
1569 	}
1570 
1571 getout_restore:
1572 	SetDefaultAliasAddress(la, addr_save);
1573 getout:
1574 	return (iresult);
1575 }
1576 
1577 int
LibAliasUnaliasOut(struct libalias * la,void * ptr,int maxpacketsize)1578 LibAliasUnaliasOut(struct libalias *la,
1579     void *ptr,		/* valid IP packet */
1580     int maxpacketsize	/* for error checking */
1581 )
1582 {
1583 	struct ip *pip;
1584 	struct icmp *ic;
1585 	struct udphdr *ud;
1586 	struct tcphdr *tc;
1587 	struct alias_link *lnk;
1588 	int iresult = PKT_ALIAS_IGNORED;
1589 
1590 	LIBALIAS_LOCK(la);
1591 	pip = (struct ip *)ptr;
1592 
1593 	/* Defense against mangled packets */
1594 	if (ntohs(pip->ip_len) > maxpacketsize
1595 	    || (pip->ip_hl << 2) > maxpacketsize)
1596 		goto getout;
1597 
1598 	ud = (struct udphdr *)ip_next(pip);
1599 	tc = (struct tcphdr *)ip_next(pip);
1600 	ic = (struct icmp *)ip_next(pip);
1601 
1602 	/* Find a link */
1603 	if (pip->ip_p == IPPROTO_UDP) {
1604 		iresult = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1605 		    ud->uh_dport, ud->uh_sport,
1606 		    IPPROTO_UDP, 0, &lnk);
1607 		if (iresult != PKT_ALIAS_OK)
1608 			goto getout;
1609 	} else if (pip->ip_p == IPPROTO_TCP) {
1610 		iresult = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1611 		    tc->th_dport, tc->th_sport,
1612 		    IPPROTO_TCP, 0, &lnk);
1613 		if (iresult != PKT_ALIAS_OK)
1614 			goto getout;
1615 	} else if (pip->ip_p == IPPROTO_ICMP) {
1616 		iresult = FindIcmpIn(la, pip->ip_dst, pip->ip_src,
1617 		    ic->icmp_id, 0, &lnk);
1618 		if (iresult != PKT_ALIAS_OK)
1619 			goto getout;
1620 	} else
1621 		lnk = NULL;
1622 
1623 	/* Change it from an aliased packet to an unaliased packet */
1624 	if (lnk != NULL) {
1625 		if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) {
1626 			int accumulate;
1627 			struct in_addr original_address;
1628 			u_short original_port;
1629 
1630 			original_address = GetOriginalAddress(lnk);
1631 			original_port = GetOriginalPort(lnk);
1632 
1633 			/* Adjust TCP/UDP checksum */
1634 			accumulate = twowords(&pip->ip_src);
1635 			accumulate -= twowords(&original_address);
1636 
1637 			if (pip->ip_p == IPPROTO_UDP) {
1638 				accumulate += ud->uh_sport;
1639 				accumulate -= original_port;
1640 				ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1641 			} else {
1642 				accumulate += tc->th_sport;
1643 				accumulate -= original_port;
1644 				ADJUST_CHECKSUM(accumulate, tc->th_sum);
1645 			}
1646 
1647 			/* Adjust IP checksum */
1648 			DifferentialChecksum(&pip->ip_sum,
1649 			    &original_address, &pip->ip_src, 2);
1650 
1651 			/* Un-alias source address and port number */
1652 			pip->ip_src = original_address;
1653 			if (pip->ip_p == IPPROTO_UDP)
1654 				ud->uh_sport = original_port;
1655 			else
1656 				tc->th_sport = original_port;
1657 
1658 			iresult = PKT_ALIAS_OK;
1659 		} else if (pip->ip_p == IPPROTO_ICMP) {
1660 			int accumulate;
1661 			struct in_addr original_address;
1662 			u_short original_id;
1663 
1664 			original_address = GetOriginalAddress(lnk);
1665 			original_id = GetOriginalPort(lnk);
1666 
1667 			/* Adjust ICMP checksum */
1668 			accumulate = twowords(&pip->ip_src);
1669 			accumulate -= twowords(&original_address);
1670 			accumulate += ic->icmp_id;
1671 			accumulate -= original_id;
1672 			ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1673 
1674 			/* Adjust IP checksum */
1675 			DifferentialChecksum(&pip->ip_sum,
1676 			    &original_address, &pip->ip_src, 2);
1677 
1678 			/* Un-alias source address and port number */
1679 			pip->ip_src = original_address;
1680 			ic->icmp_id = original_id;
1681 
1682 			iresult = PKT_ALIAS_OK;
1683 		}
1684 	}
1685 getout:
1686 	LIBALIAS_UNLOCK(la);
1687 	return (iresult);
1688 }
1689 
1690 #ifndef _KERNEL
1691 
1692 int
LibAliasRefreshModules(void)1693 LibAliasRefreshModules(void)
1694 {
1695 	char buf[256], conf[] = "/etc/libalias.conf";
1696 	FILE *fd;
1697 	int i, len;
1698 
1699 	fd = fopen(conf, "r");
1700 	if (fd == NULL)
1701 		err(1, "fopen(%s)", conf);
1702 
1703 	LibAliasUnLoadAllModule();
1704 
1705 	for (;;) {
1706 		fgets(buf, 256, fd);
1707 		if (feof(fd))
1708 			break;
1709 		len = strlen(buf);
1710 		if (len > 1) {
1711 			for (i = 0; i < len; i++)
1712 				if (!isspace(buf[i]))
1713 					break;
1714 			if (buf[i] == '#')
1715 				continue;
1716 			buf[len - 1] = '\0';
1717 			LibAliasLoadModule(buf);
1718 		}
1719 	}
1720 	fclose(fd);
1721 	return (0);
1722 }
1723 
1724 int
LibAliasLoadModule(char * path)1725 LibAliasLoadModule(char *path)
1726 {
1727 	struct dll *t;
1728 	void *handle;
1729 	struct proto_handler *m;
1730 	const char *error;
1731 	moduledata_t *p;
1732 
1733 	handle = dlopen (path, RTLD_LAZY);
1734 	if (!handle) {
1735 		fprintf(stderr, "%s\n", dlerror());
1736 		return (EINVAL);
1737 	}
1738 
1739 	p = dlsym(handle, "alias_mod");
1740 	if ((error = dlerror()) != NULL)  {
1741 		fprintf(stderr, "%s\n", dlerror());
1742 		return (EINVAL);
1743 	}
1744 
1745 	t = malloc(sizeof(struct dll));
1746 	if (t == NULL)
1747 		return (ENOMEM);
1748 	strncpy(t->name, p->name, DLL_LEN);
1749 	t->handle = handle;
1750 	if (attach_dll(t) == EEXIST) {
1751 		free(t);
1752 		fprintf(stderr, "dll conflict\n");
1753 		return (EEXIST);
1754 	}
1755 
1756 	m = dlsym(t->handle, "handlers");
1757 	if ((error = dlerror()) != NULL)  {
1758 		fprintf(stderr, "%s\n", error);
1759 		return (EINVAL);
1760 	}
1761 
1762 	LibAliasAttachHandlers(m);
1763 	return (0);
1764 }
1765 
1766 int
LibAliasUnLoadAllModule(void)1767 LibAliasUnLoadAllModule(void)
1768 {
1769 	struct dll *t;
1770 	struct proto_handler *p;
1771 
1772 	/* Unload all modules then reload everything. */
1773 	while ((p = first_handler()) != NULL) {
1774 		LibAliasDetachHandlers(p);
1775 	}
1776 	while ((t = walk_dll_chain()) != NULL) {
1777 		dlclose(t->handle);
1778 		free(t);
1779 	}
1780 	return (1);
1781 }
1782 
1783 #endif
1784 
1785 #ifdef _KERNEL
1786 /*
1787  * m_megapullup() - this function is a big hack.
1788  * Thankfully, it's only used in ng_nat and ipfw+nat.
1789  *
1790  * It allocates an mbuf with cluster and copies the specified part of the chain
1791  * into cluster, so that it is all contiguous and can be accessed via a plain
1792  * (char *) pointer. This is required, because libalias doesn't know how to
1793  * handle mbuf chains.
1794  *
1795  * On success, m_megapullup returns an mbuf (possibly with cluster) containing
1796  * the input packet, on failure NULL. The input packet is always consumed.
1797  */
1798 struct mbuf *
m_megapullup(struct mbuf * m,int len)1799 m_megapullup(struct mbuf *m, int len)
1800 {
1801 	struct mbuf *mcl;
1802 
1803 	if (len > m->m_pkthdr.len)
1804 		goto bad;
1805 
1806 	if (m->m_next == NULL && M_WRITABLE(m))
1807 		return (m);
1808 
1809 	if (len <= MJUMPAGESIZE)
1810 		mcl = m_get2(len, M_NOWAIT, MT_DATA, M_PKTHDR);
1811 	else if (len <= MJUM9BYTES)
1812 		mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES);
1813 	else if (len <= MJUM16BYTES)
1814 		mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM16BYTES);
1815 	else
1816 		goto bad;
1817 	if (mcl == NULL)
1818 		goto bad;
1819 	m_align(mcl, len);
1820 	m_move_pkthdr(mcl, m);
1821 	m_copydata(m, 0, len, mtod(mcl, caddr_t));
1822 	mcl->m_len = mcl->m_pkthdr.len = len;
1823 	m_freem(m);
1824 
1825 	return (mcl);
1826 bad:
1827 	m_freem(m);
1828 	return (NULL);
1829 }
1830 #endif
1831