1145519Sdarrenr/*	$FreeBSD$	*/
2145510Sdarrenr
3145510Sdarrenr/*
4255332Scy * Copyright (C) 2012 by Darren Reed.
5145510Sdarrenr *
6145510Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
7145510Sdarrenr *
8255332Scy * $Id$
9145510Sdarrenr */
10145510Sdarrenr#if !defined(lint)
11145510Sdarrenrstatic const char sccsid[] = "@(#)ipft_tx.c	1.7 6/5/96 (C) 1993 Darren Reed";
12255332Scystatic const char rcsid[] = "@(#)$Id$";
13145510Sdarrenr#endif
14145510Sdarrenr
15145510Sdarrenr#include <ctype.h>
16145510Sdarrenr
17145510Sdarrenr#include "ipf.h"
18145510Sdarrenr#include "ipt.h"
19145510Sdarrenr
20145510Sdarrenrextern	int	opts;
21145510Sdarrenr
22145510Sdarrenrstatic	char	*tx_proto = "";
23145510Sdarrenr
24145510Sdarrenrstatic	int	text_open __P((char *)), text_close __P((void));
25255332Scystatic	int	text_readip __P((mb_t *, char **, int *));
26145510Sdarrenrstatic	int	parseline __P((char *, ip_t *, char **, int *));
27145510Sdarrenr
28145547Sdarrenrstatic	char	myflagset[] = "FSRPAUEC";
29145547Sdarrenrstatic	u_char	myflags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH,
30145510Sdarrenr				TH_ACK, TH_URG, TH_ECN, TH_CWR };
31145510Sdarrenr
32145510Sdarrenrstruct	ipread	iptext = { text_open, text_close, text_readip, R_DO_CKSUM };
33145510Sdarrenrstatic	FILE	*tfp = NULL;
34145510Sdarrenrstatic	int	tfd = -1;
35145510Sdarrenr
36145510Sdarrenrstatic	u_32_t	tx_hostnum __P((char *, int *));
37145510Sdarrenrstatic	u_short	tx_portnum __P((char *));
38145510Sdarrenr
39255332Scy#ifdef USE_INET6
40255332Scyint parseipv6 __P((char **, ip6_t *, char **, int *));
41255332Scy#endif
42145510Sdarrenr
43145510Sdarrenr/*
44145510Sdarrenr * returns an ip address as a long var as a result of either a DNS lookup or
45145510Sdarrenr * straight inet_addr() call
46145510Sdarrenr */
47145510Sdarrenrstatic	u_32_t	tx_hostnum(host, resolved)
48255332Scy	char	*host;
49255332Scy	int	*resolved;
50145510Sdarrenr{
51255332Scy	i6addr_t	ipa;
52145510Sdarrenr
53145510Sdarrenr	*resolved = 0;
54145510Sdarrenr	if (!strcasecmp("any", host))
55145510Sdarrenr		return 0L;
56145510Sdarrenr	if (ISDIGIT(*host))
57145510Sdarrenr		return inet_addr(host);
58145510Sdarrenr
59255332Scy	if (gethost(AF_INET, host, &ipa) == -1) {
60145510Sdarrenr		*resolved = -1;
61145510Sdarrenr		fprintf(stderr, "can't resolve hostname: %s\n", host);
62145510Sdarrenr		return 0;
63145510Sdarrenr	}
64255332Scy	return ipa.in4.s_addr;
65145510Sdarrenr}
66145510Sdarrenr
67145510Sdarrenr
68145510Sdarrenr/*
69145510Sdarrenr * find the port number given by the name, either from getservbyname() or
70145510Sdarrenr * straight atoi()
71145510Sdarrenr */
72145510Sdarrenrstatic	u_short	tx_portnum(name)
73255332Scy	char	*name;
74145510Sdarrenr{
75161357Sguido	struct	servent	*sp;
76145510Sdarrenr
77145510Sdarrenr	if (ISDIGIT(*name))
78145510Sdarrenr		return (u_short)atoi(name);
79161357Sguido	sp = getservbyname(name, tx_proto);
80145510Sdarrenr	if (sp)
81161357Sguido		return ntohs(sp->s_port);
82161357Sguido	(void) fprintf(stderr, "unknown service \"%s\".\n", name);
83161357Sguido	return 0;
84145510Sdarrenr}
85145510Sdarrenr
86145510Sdarrenr
87145510Sdarrenrstatic	int	text_open(fname)
88255332Scy	char	*fname;
89145510Sdarrenr{
90145510Sdarrenr	if (tfp && tfd != -1) {
91145510Sdarrenr		rewind(tfp);
92145510Sdarrenr		return tfd;
93145510Sdarrenr	}
94145510Sdarrenr
95145510Sdarrenr	if (!strcmp(fname, "-")) {
96145510Sdarrenr		tfd = 0;
97145510Sdarrenr		tfp = stdin;
98145510Sdarrenr	} else {
99145510Sdarrenr		tfd = open(fname, O_RDONLY);
100145510Sdarrenr		if (tfd != -1)
101145510Sdarrenr			tfp = fdopen(tfd, "r");
102145510Sdarrenr	}
103145510Sdarrenr	return tfd;
104145510Sdarrenr}
105145510Sdarrenr
106145510Sdarrenr
107145510Sdarrenrstatic	int	text_close()
108145510Sdarrenr{
109145510Sdarrenr	int	cfd = tfd;
110145510Sdarrenr
111145510Sdarrenr	tfd = -1;
112145510Sdarrenr	return close(cfd);
113145510Sdarrenr}
114145510Sdarrenr
115145510Sdarrenr
116255332Scystatic	int	text_readip(mb, ifn, dir)
117255332Scy	mb_t	*mb;
118255332Scy	char	**ifn;
119255332Scy	int	*dir;
120145510Sdarrenr{
121145510Sdarrenr	register char *s;
122145510Sdarrenr	char	line[513];
123170268Sdarrenr	ip_t	*ip;
124255332Scy	char	*buf;
125255332Scy	int	cnt;
126145510Sdarrenr
127255332Scy	buf = (char *)mb->mb_buf;
128255332Scy	cnt = sizeof(mb->mb_buf);
129255332Scy
130145510Sdarrenr	*ifn = NULL;
131145510Sdarrenr	while (fgets(line, sizeof(line)-1, tfp)) {
132145510Sdarrenr		if ((s = strchr(line, '\n')))
133145510Sdarrenr			*s = '\0';
134145510Sdarrenr		if ((s = strchr(line, '\r')))
135145510Sdarrenr			*s = '\0';
136145510Sdarrenr		if ((s = strchr(line, '#')))
137145510Sdarrenr			*s = '\0';
138145510Sdarrenr		if (!*line)
139145510Sdarrenr			continue;
140153881Sguido		if ((opts & OPT_DEBUG) != 0)
141145510Sdarrenr			printf("input: %s\n", line);
142145510Sdarrenr		*ifn = NULL;
143145510Sdarrenr		*dir = 0;
144170268Sdarrenr		if (!parseline(line, (ip_t *)buf, ifn, dir)) {
145170268Sdarrenr			ip = (ip_t *)buf;
146255332Scy			if (IP_V(ip) == 6) {
147255332Scy#ifdef USE_INET6
148255332Scy				mb->mb_len = ntohs(((ip6_t *)ip)->ip6_plen) +
149255332Scy				       sizeof(ip6_t);
150255332Scy#else
151255332Scy				mb->mb_len = 0;
152255332Scy#endif
153255332Scy			} else {
154255332Scy				mb->mb_len = ntohs(ip->ip_len);
155255332Scy			}
156255332Scy			return mb->mb_len;
157170268Sdarrenr		}
158145510Sdarrenr	}
159153881Sguido	if (feof(tfp))
160153881Sguido		return 0;
161145510Sdarrenr	return -1;
162145510Sdarrenr}
163145510Sdarrenr
164145510Sdarrenrstatic	int	parseline(line, ip, ifn, out)
165255332Scy	char	*line;
166255332Scy	ip_t	*ip;
167255332Scy	char	**ifn;
168255332Scy	int	*out;
169145510Sdarrenr{
170145510Sdarrenr	tcphdr_t	th, *tcp = &th;
171145510Sdarrenr	struct	icmp	icmp, *ic = &icmp;
172145510Sdarrenr	char	*cps[20], **cpp, c, ipopts[68];
173145510Sdarrenr	int	i, r;
174145510Sdarrenr
175145510Sdarrenr	if (*ifn)
176145510Sdarrenr		free(*ifn);
177145510Sdarrenr	bzero((char *)ip, MAX(sizeof(*tcp), sizeof(*ic)) + sizeof(*ip));
178145510Sdarrenr	bzero((char *)tcp, sizeof(*tcp));
179145510Sdarrenr	bzero((char *)ic, sizeof(*ic));
180145510Sdarrenr	bzero(ipopts, sizeof(ipopts));
181145510Sdarrenr	IP_HL_A(ip, sizeof(*ip) >> 2);
182145510Sdarrenr	IP_V_A(ip, IPVERSION);
183255332Scy	ip->ip_ttl = 63;
184145510Sdarrenr	for (i = 0, cps[0] = strtok(line, " \b\t\r\n"); cps[i] && i < 19; )
185145510Sdarrenr		cps[++i] = strtok(NULL, " \b\t\r\n");
186145510Sdarrenr
187145510Sdarrenr	cpp = cps;
188145510Sdarrenr	if (!*cpp)
189145510Sdarrenr		return 1;
190145510Sdarrenr
191145510Sdarrenr	c = **cpp;
192145510Sdarrenr	if (!ISALPHA(c) || (TOLOWER(c) != 'o' && TOLOWER(c) != 'i')) {
193145510Sdarrenr		fprintf(stderr, "bad direction \"%s\"\n", *cpp);
194145510Sdarrenr		return 1;
195145510Sdarrenr	}
196255332Scy
197255332Scy#ifdef USE_INET6
198255332Scy	if (!strcasecmp(*cpp, "out6") || !strcasecmp(*cpp, "in6")) {
199255332Scy		return parseipv6(cpp, (ip6_t *)ip, ifn, out);
200255332Scy	}
201255332Scy#endif
202255332Scy
203145510Sdarrenr	*out = (TOLOWER(c) == 'o') ? 1 : 0;
204145510Sdarrenr	cpp++;
205145510Sdarrenr	if (!*cpp)
206145510Sdarrenr		return 1;
207145510Sdarrenr
208145510Sdarrenr	if (!strcasecmp(*cpp, "on")) {
209145510Sdarrenr		cpp++;
210145510Sdarrenr		if (!*cpp)
211145510Sdarrenr			return 1;
212145510Sdarrenr		*ifn = strdup(*cpp++);
213145510Sdarrenr		if (!*cpp)
214145510Sdarrenr			return 1;
215145510Sdarrenr	}
216145510Sdarrenr
217145510Sdarrenr	c = **cpp;
218145510Sdarrenr	ip->ip_len = sizeof(ip_t);
219145510Sdarrenr	if (!strcasecmp(*cpp, "tcp") || !strcasecmp(*cpp, "udp") ||
220145510Sdarrenr	    !strcasecmp(*cpp, "icmp")) {
221145510Sdarrenr		if (c == 't') {
222145510Sdarrenr			ip->ip_p = IPPROTO_TCP;
223145510Sdarrenr			ip->ip_len += sizeof(struct tcphdr);
224145510Sdarrenr			tx_proto = "tcp";
225145510Sdarrenr		} else if (c == 'u') {
226145510Sdarrenr			ip->ip_p = IPPROTO_UDP;
227145510Sdarrenr			ip->ip_len += sizeof(struct udphdr);
228145510Sdarrenr			tx_proto = "udp";
229145510Sdarrenr		} else {
230145510Sdarrenr			ip->ip_p = IPPROTO_ICMP;
231145510Sdarrenr			ip->ip_len += ICMPERR_IPICMPHLEN;
232145510Sdarrenr			tx_proto = "icmp";
233145510Sdarrenr		}
234145510Sdarrenr		cpp++;
235145510Sdarrenr	} else if (ISDIGIT(**cpp) && !index(*cpp, '.')) {
236145510Sdarrenr		ip->ip_p = atoi(*cpp);
237145510Sdarrenr		cpp++;
238145510Sdarrenr	} else
239145510Sdarrenr		ip->ip_p = IPPROTO_IP;
240145510Sdarrenr
241145510Sdarrenr	if (!*cpp)
242145510Sdarrenr		return 1;
243145510Sdarrenr	if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) {
244145510Sdarrenr		char	*last;
245145510Sdarrenr
246145510Sdarrenr		last = strchr(*cpp, ',');
247145510Sdarrenr		if (!last) {
248145510Sdarrenr			fprintf(stderr, "tcp/udp with no source port\n");
249145510Sdarrenr			return 1;
250145510Sdarrenr		}
251145510Sdarrenr		*last++ = '\0';
252145510Sdarrenr		tcp->th_sport = htons(tx_portnum(last));
253145510Sdarrenr		if (ip->ip_p == IPPROTO_TCP) {
254145510Sdarrenr			tcp->th_win = htons(4096);
255145510Sdarrenr			TCP_OFF_A(tcp, sizeof(*tcp) >> 2);
256145510Sdarrenr		}
257145510Sdarrenr	}
258145510Sdarrenr	ip->ip_src.s_addr = tx_hostnum(*cpp, &r);
259145510Sdarrenr	cpp++;
260145510Sdarrenr	if (!*cpp)
261145510Sdarrenr		return 1;
262145510Sdarrenr
263145510Sdarrenr	if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) {
264145510Sdarrenr		char	*last;
265145510Sdarrenr
266145510Sdarrenr		last = strchr(*cpp, ',');
267145510Sdarrenr		if (!last) {
268145510Sdarrenr			fprintf(stderr, "tcp/udp with no destination port\n");
269145510Sdarrenr			return 1;
270145510Sdarrenr		}
271145510Sdarrenr		*last++ = '\0';
272145510Sdarrenr		tcp->th_dport = htons(tx_portnum(last));
273145510Sdarrenr	}
274145510Sdarrenr	ip->ip_dst.s_addr = tx_hostnum(*cpp, &r);
275145510Sdarrenr	cpp++;
276172776Sdarrenr	if (ip->ip_p == IPPROTO_TCP) {
277172776Sdarrenr		if (*cpp != NULL) {
278172776Sdarrenr			char	*s, *t;
279145510Sdarrenr
280172776Sdarrenr			tcp->th_flags = 0;
281172776Sdarrenr			for (s = *cpp; *s; s++)
282172776Sdarrenr				if ((t  = strchr(myflagset, *s)))
283172776Sdarrenr					tcp->th_flags |= myflags[t-myflagset];
284172776Sdarrenr			if (tcp->th_flags)
285172776Sdarrenr				cpp++;
286172776Sdarrenr		}
287172776Sdarrenr
288145510Sdarrenr		if (tcp->th_flags & TH_URG)
289145510Sdarrenr			tcp->th_urp = htons(1);
290172776Sdarrenr
291172776Sdarrenr		if (*cpp && !strncasecmp(*cpp, "seq=", 4)) {
292172776Sdarrenr			tcp->th_seq = htonl(atoi(*cpp + 4));
293172776Sdarrenr			cpp++;
294172776Sdarrenr		}
295172776Sdarrenr
296172776Sdarrenr		if (*cpp && !strncasecmp(*cpp, "ack=", 4)) {
297172776Sdarrenr			tcp->th_ack = htonl(atoi(*cpp + 4));
298172776Sdarrenr			cpp++;
299172776Sdarrenr		}
300145510Sdarrenr	} else if (*cpp && ip->ip_p == IPPROTO_ICMP) {
301255332Scy		char	*t;
302145510Sdarrenr
303153881Sguido		t = strchr(*cpp, ',');
304153881Sguido		if (t != NULL)
305153881Sguido			*t = '\0';
306153881Sguido
307255332Scy		ic->icmp_type = geticmptype(AF_INET, *cpp);
308153881Sguido		if (t != NULL)
309255332Scy			ic->icmp_code = atoi(t + 1);
310255332Scy		cpp++;
311255332Scy
312255332Scy		if (ic->icmp_type == ICMP_ECHO ||
313255332Scy		    ic->icmp_type == ICMP_ECHOREPLY)
314255332Scy			ic->icmp_id = htons(getpid());
315255332Scy		if (t != NULL)
316153881Sguido			*t = ',';
317145510Sdarrenr	}
318145510Sdarrenr
319145510Sdarrenr	if (*cpp && !strcasecmp(*cpp, "opt")) {
320145510Sdarrenr		u_long	olen;
321145510Sdarrenr
322145510Sdarrenr		cpp++;
323145510Sdarrenr		olen = buildopts(*cpp, ipopts, (IP_HL(ip) - 5) << 2);
324145510Sdarrenr		if (olen) {
325145510Sdarrenr			bcopy(ipopts, (char *)(ip + 1), olen);
326145510Sdarrenr			IP_HL_A(ip, IP_HL(ip) + (olen >> 2));
327255332Scy			ip->ip_len += olen;
328145510Sdarrenr		}
329145510Sdarrenr	}
330145510Sdarrenr	if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
331145510Sdarrenr		bcopy((char *)tcp, ((char *)ip) + (IP_HL(ip) << 2),
332145510Sdarrenr			sizeof(*tcp));
333145510Sdarrenr	else if (ip->ip_p == IPPROTO_ICMP)
334145510Sdarrenr		bcopy((char *)ic, ((char *)ip) + (IP_HL(ip) << 2),
335145510Sdarrenr			sizeof(*ic));
336145510Sdarrenr	ip->ip_len = htons(ip->ip_len);
337145510Sdarrenr	return 0;
338145510Sdarrenr}
339255332Scy
340255332Scy
341255332Scy#ifdef USE_INET6
342255332Scyint parseipv6(cpp, ip6, ifn, out)
343255332Scy	char **cpp;
344255332Scy	ip6_t *ip6;
345255332Scy	char **ifn;
346255332Scy	int *out;
347255332Scy{
348255332Scy	tcphdr_t th, *tcp = &th;
349255332Scy	struct icmp6_hdr icmp, *ic6 = &icmp;
350255332Scy
351255332Scy	bzero((char *)ip6, MAX(sizeof(*tcp), sizeof(*ic6)) + sizeof(*ip6));
352255332Scy	bzero((char *)tcp, sizeof(*tcp));
353255332Scy	bzero((char *)ic6, sizeof(*ic6));
354255332Scy	ip6->ip6_vfc = 0x60;
355255332Scy
356255332Scy	*out = (**cpp == 'o') ? 1 : 0;
357255332Scy	cpp++;
358255332Scy	if (!*cpp)
359255332Scy		return 1;
360255332Scy
361255332Scy	if (!strcasecmp(*cpp, "on")) {
362255332Scy		cpp++;
363255332Scy		if (!*cpp)
364255332Scy			return 1;
365255332Scy		*ifn = strdup(*cpp++);
366255332Scy		if (!*cpp)
367255332Scy			return 1;
368255332Scy	}
369255332Scy
370255332Scy	if (!strcasecmp(*cpp, "tcp")) {
371255332Scy		ip6->ip6_nxt = IPPROTO_TCP;
372255332Scy		tx_proto = "tcp";
373255332Scy		cpp++;
374255332Scy	} else if (!strcasecmp(*cpp, "udp")) {
375255332Scy		ip6->ip6_nxt = IPPROTO_UDP;
376255332Scy		tx_proto = "udp";
377255332Scy		cpp++;
378255332Scy	} else if (!strcasecmp(*cpp, "icmpv6")) {
379255332Scy		ip6->ip6_nxt = IPPROTO_ICMPV6;
380255332Scy		tx_proto = "icmpv6";
381255332Scy		cpp++;
382255332Scy	} else if (ISDIGIT(**cpp) && !index(*cpp, ':')) {
383255332Scy		ip6->ip6_nxt = atoi(*cpp);
384255332Scy		cpp++;
385255332Scy	} else
386255332Scy		ip6->ip6_nxt = IPPROTO_IPV6;
387255332Scy
388255332Scy	if (!*cpp)
389255332Scy		return 1;
390255332Scy
391255332Scy	switch (ip6->ip6_nxt)
392255332Scy	{
393255332Scy	case IPPROTO_TCP :
394255332Scy		ip6->ip6_plen = sizeof(struct tcphdr);
395255332Scy		break;
396255332Scy	case IPPROTO_UDP :
397255332Scy		ip6->ip6_plen = sizeof(struct udphdr);
398255332Scy		break;
399255332Scy	case IPPROTO_ICMPV6 :
400255332Scy		ip6->ip6_plen = ICMP6ERR_IPICMPHLEN;
401255332Scy		break;
402255332Scy	default :
403255332Scy		break;
404255332Scy	}
405255332Scy
406255332Scy	if (ip6->ip6_nxt == IPPROTO_TCP || ip6->ip6_nxt == IPPROTO_UDP) {
407255332Scy		char *last;
408255332Scy
409255332Scy		last = strchr(*cpp, ',');
410255332Scy		if (!last) {
411255332Scy			fprintf(stderr, "tcp/udp with no source port\n");
412255332Scy			return 1;
413255332Scy		}
414255332Scy		*last++ = '\0';
415255332Scy		tcp->th_sport = htons(tx_portnum(last));
416255332Scy		if (ip6->ip6_nxt == IPPROTO_TCP) {
417255332Scy			tcp->th_win = htons(4096);
418255332Scy			TCP_OFF_A(tcp, sizeof(*tcp) >> 2);
419255332Scy		}
420255332Scy	}
421255332Scy
422255332Scy	if (inet_pton(AF_INET6, *cpp, &ip6->ip6_src) != 1) {
423255332Scy		fprintf(stderr, "cannot parse source address '%s'\n", *cpp);
424255332Scy		return 1;
425255332Scy	}
426255332Scy
427255332Scy	cpp++;
428255332Scy	if (!*cpp)
429255332Scy		return 1;
430255332Scy
431255332Scy	if (ip6->ip6_nxt == IPPROTO_TCP || ip6->ip6_nxt == IPPROTO_UDP) {
432255332Scy		char *last;
433255332Scy
434255332Scy		last = strchr(*cpp, ',');
435255332Scy		if (!last) {
436255332Scy			fprintf(stderr, "tcp/udp with no destination port\n");
437255332Scy			return 1;
438255332Scy		}
439255332Scy		*last++ = '\0';
440255332Scy		tcp->th_dport = htons(tx_portnum(last));
441255332Scy	}
442255332Scy
443255332Scy	if (inet_pton(AF_INET6, *cpp, &ip6->ip6_dst) != 1) {
444255332Scy		fprintf(stderr, "cannot parse destination address '%s'\n",
445255332Scy			*cpp);
446255332Scy		return 1;
447255332Scy	}
448255332Scy
449255332Scy	cpp++;
450255332Scy	if (ip6->ip6_nxt == IPPROTO_TCP) {
451255332Scy		if (*cpp != NULL) {
452255332Scy			char *s, *t;
453255332Scy
454255332Scy			tcp->th_flags = 0;
455255332Scy			for (s = *cpp; *s; s++)
456255332Scy				if ((t  = strchr(myflagset, *s)))
457255332Scy					tcp->th_flags |= myflags[t-myflagset];
458255332Scy			if (tcp->th_flags)
459255332Scy				cpp++;
460255332Scy		}
461255332Scy
462255332Scy		if (tcp->th_flags & TH_URG)
463255332Scy			tcp->th_urp = htons(1);
464255332Scy
465255332Scy		if (*cpp && !strncasecmp(*cpp, "seq=", 4)) {
466255332Scy			tcp->th_seq = htonl(atoi(*cpp + 4));
467255332Scy			cpp++;
468255332Scy		}
469255332Scy
470255332Scy		if (*cpp && !strncasecmp(*cpp, "ack=", 4)) {
471255332Scy			tcp->th_ack = htonl(atoi(*cpp + 4));
472255332Scy			cpp++;
473255332Scy		}
474255332Scy	} else if (*cpp && ip6->ip6_nxt == IPPROTO_ICMPV6) {
475255332Scy		char *t;
476255332Scy
477255332Scy		t = strchr(*cpp, ',');
478255332Scy		if (t != NULL)
479255332Scy			*t = '\0';
480255332Scy
481255332Scy		ic6->icmp6_type = geticmptype(AF_INET6, *cpp);
482255332Scy		if (t != NULL)
483255332Scy			ic6->icmp6_code = atoi(t + 1);
484255332Scy
485255332Scy		if (ic6->icmp6_type == ICMP6_ECHO_REQUEST ||
486255332Scy		    ic6->icmp6_type == ICMP6_ECHO_REPLY)
487255332Scy			ic6->icmp6_id = htons(getpid());
488255332Scy
489255332Scy		if (t != NULL)
490255332Scy			*t = ',';
491255332Scy	}
492255332Scy
493255332Scy	if (ip6->ip6_nxt == IPPROTO_TCP || ip6->ip6_nxt == IPPROTO_UDP) {
494255332Scy		bcopy((char *)tcp, (char *)ip6 + sizeof(*ip6),
495255332Scy			sizeof(*tcp));
496255332Scy	} else if (ip6->ip6_nxt == IPPROTO_ICMPV6) {
497255332Scy		bcopy((char *)ic6, (char *)ip6 + sizeof(*ip6),
498255332Scy			sizeof(*ic6));
499255332Scy	}
500255332Scy
501255332Scy	/*
502255332Scy	 * Because a length of 0 == jumbo gram...
503255332Scy	 */
504255332Scy	if (ip6->ip6_plen == 0) {
505255332Scy		ip6->ip6_plen++;
506255332Scy	}
507255332Scy	ip6->ip6_plen = htons(ip6->ip6_plen);
508255332Scy	return 0;
509255332Scy}
510255332Scy#endif
511