xref: /freebsd/crypto/openssh/misc.c (revision 9336e0699bda8a301cd2bfa37106b6ec5e32012e)
1 /* $OpenBSD: misc.c,v 1.64 2006/08/03 03:34:42 deraadt Exp $ */
2 /*
3  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
4  * Copyright (c) 2005,2006 Damien Miller.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include "includes.h"
28 
29 #include <sys/types.h>
30 #include <sys/ioctl.h>
31 #include <sys/socket.h>
32 #include <sys/param.h>
33 
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <unistd.h>
39 
40 #include <netinet/in.h>
41 #include <netinet/tcp.h>
42 
43 #include <errno.h>
44 #include <fcntl.h>
45 #ifdef HAVE_PATHS_H
46 # include <paths.h>
47 #include <pwd.h>
48 #endif
49 #ifdef SSH_TUN_OPENBSD
50 #include <net/if.h>
51 #endif
52 
53 #include "xmalloc.h"
54 #include "misc.h"
55 #include "log.h"
56 #include "ssh.h"
57 
58 /* remove newline at end of string */
59 char *
60 chop(char *s)
61 {
62 	char *t = s;
63 	while (*t) {
64 		if (*t == '\n' || *t == '\r') {
65 			*t = '\0';
66 			return s;
67 		}
68 		t++;
69 	}
70 	return s;
71 
72 }
73 
74 /* set/unset filedescriptor to non-blocking */
75 int
76 set_nonblock(int fd)
77 {
78 	int val;
79 
80 	val = fcntl(fd, F_GETFL, 0);
81 	if (val < 0) {
82 		error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
83 		return (-1);
84 	}
85 	if (val & O_NONBLOCK) {
86 		debug3("fd %d is O_NONBLOCK", fd);
87 		return (0);
88 	}
89 	debug2("fd %d setting O_NONBLOCK", fd);
90 	val |= O_NONBLOCK;
91 	if (fcntl(fd, F_SETFL, val) == -1) {
92 		debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd,
93 		    strerror(errno));
94 		return (-1);
95 	}
96 	return (0);
97 }
98 
99 int
100 unset_nonblock(int fd)
101 {
102 	int val;
103 
104 	val = fcntl(fd, F_GETFL, 0);
105 	if (val < 0) {
106 		error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
107 		return (-1);
108 	}
109 	if (!(val & O_NONBLOCK)) {
110 		debug3("fd %d is not O_NONBLOCK", fd);
111 		return (0);
112 	}
113 	debug("fd %d clearing O_NONBLOCK", fd);
114 	val &= ~O_NONBLOCK;
115 	if (fcntl(fd, F_SETFL, val) == -1) {
116 		debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s",
117 		    fd, strerror(errno));
118 		return (-1);
119 	}
120 	return (0);
121 }
122 
123 /* disable nagle on socket */
124 void
125 set_nodelay(int fd)
126 {
127 	int opt;
128 	socklen_t optlen;
129 
130 	optlen = sizeof opt;
131 	if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) {
132 		debug("getsockopt TCP_NODELAY: %.100s", strerror(errno));
133 		return;
134 	}
135 	if (opt == 1) {
136 		debug2("fd %d is TCP_NODELAY", fd);
137 		return;
138 	}
139 	opt = 1;
140 	debug2("fd %d setting TCP_NODELAY", fd);
141 	if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1)
142 		error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
143 }
144 
145 /* Characters considered whitespace in strsep calls. */
146 #define WHITESPACE " \t\r\n"
147 #define QUOTE	"\""
148 
149 /* return next token in configuration line */
150 char *
151 strdelim(char **s)
152 {
153 	char *old;
154 	int wspace = 0;
155 
156 	if (*s == NULL)
157 		return NULL;
158 
159 	old = *s;
160 
161 	*s = strpbrk(*s, WHITESPACE QUOTE "=");
162 	if (*s == NULL)
163 		return (old);
164 
165 	if (*s[0] == '\"') {
166 		memmove(*s, *s + 1, strlen(*s)); /* move nul too */
167 		/* Find matching quote */
168 		if ((*s = strpbrk(*s, QUOTE)) == NULL) {
169 			return (NULL);		/* no matching quote */
170 		} else {
171 			*s[0] = '\0';
172 			return (old);
173 		}
174 	}
175 
176 	/* Allow only one '=' to be skipped */
177 	if (*s[0] == '=')
178 		wspace = 1;
179 	*s[0] = '\0';
180 
181 	/* Skip any extra whitespace after first token */
182 	*s += strspn(*s + 1, WHITESPACE) + 1;
183 	if (*s[0] == '=' && !wspace)
184 		*s += strspn(*s + 1, WHITESPACE) + 1;
185 
186 	return (old);
187 }
188 
189 struct passwd *
190 pwcopy(struct passwd *pw)
191 {
192 	struct passwd *copy = xcalloc(1, sizeof(*copy));
193 
194 	copy->pw_name = xstrdup(pw->pw_name);
195 	copy->pw_passwd = xstrdup(pw->pw_passwd);
196 	copy->pw_gecos = xstrdup(pw->pw_gecos);
197 	copy->pw_uid = pw->pw_uid;
198 	copy->pw_gid = pw->pw_gid;
199 #ifdef HAVE_PW_EXPIRE_IN_PASSWD
200 	copy->pw_expire = pw->pw_expire;
201 #endif
202 #ifdef HAVE_PW_CHANGE_IN_PASSWD
203 	copy->pw_change = pw->pw_change;
204 #endif
205 #ifdef HAVE_PW_CLASS_IN_PASSWD
206 	copy->pw_class = xstrdup(pw->pw_class);
207 #endif
208 	copy->pw_dir = xstrdup(pw->pw_dir);
209 	copy->pw_shell = xstrdup(pw->pw_shell);
210 	return copy;
211 }
212 
213 /*
214  * Convert ASCII string to TCP/IP port number.
215  * Port must be >0 and <=65535.
216  * Return 0 if invalid.
217  */
218 int
219 a2port(const char *s)
220 {
221 	long port;
222 	char *endp;
223 
224 	errno = 0;
225 	port = strtol(s, &endp, 0);
226 	if (s == endp || *endp != '\0' ||
227 	    (errno == ERANGE && (port == LONG_MIN || port == LONG_MAX)) ||
228 	    port <= 0 || port > 65535)
229 		return 0;
230 
231 	return port;
232 }
233 
234 int
235 a2tun(const char *s, int *remote)
236 {
237 	const char *errstr = NULL;
238 	char *sp, *ep;
239 	int tun;
240 
241 	if (remote != NULL) {
242 		*remote = SSH_TUNID_ANY;
243 		sp = xstrdup(s);
244 		if ((ep = strchr(sp, ':')) == NULL) {
245 			xfree(sp);
246 			return (a2tun(s, NULL));
247 		}
248 		ep[0] = '\0'; ep++;
249 		*remote = a2tun(ep, NULL);
250 		tun = a2tun(sp, NULL);
251 		xfree(sp);
252 		return (*remote == SSH_TUNID_ERR ? *remote : tun);
253 	}
254 
255 	if (strcasecmp(s, "any") == 0)
256 		return (SSH_TUNID_ANY);
257 
258 	tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr);
259 	if (errstr != NULL)
260 		return (SSH_TUNID_ERR);
261 
262 	return (tun);
263 }
264 
265 #define SECONDS		1
266 #define MINUTES		(SECONDS * 60)
267 #define HOURS		(MINUTES * 60)
268 #define DAYS		(HOURS * 24)
269 #define WEEKS		(DAYS * 7)
270 
271 /*
272  * Convert a time string into seconds; format is
273  * a sequence of:
274  *      time[qualifier]
275  *
276  * Valid time qualifiers are:
277  *      <none>  seconds
278  *      s|S     seconds
279  *      m|M     minutes
280  *      h|H     hours
281  *      d|D     days
282  *      w|W     weeks
283  *
284  * Examples:
285  *      90m     90 minutes
286  *      1h30m   90 minutes
287  *      2d      2 days
288  *      1w      1 week
289  *
290  * Return -1 if time string is invalid.
291  */
292 long
293 convtime(const char *s)
294 {
295 	long total, secs;
296 	const char *p;
297 	char *endp;
298 
299 	errno = 0;
300 	total = 0;
301 	p = s;
302 
303 	if (p == NULL || *p == '\0')
304 		return -1;
305 
306 	while (*p) {
307 		secs = strtol(p, &endp, 10);
308 		if (p == endp ||
309 		    (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) ||
310 		    secs < 0)
311 			return -1;
312 
313 		switch (*endp++) {
314 		case '\0':
315 			endp--;
316 			break;
317 		case 's':
318 		case 'S':
319 			break;
320 		case 'm':
321 		case 'M':
322 			secs *= MINUTES;
323 			break;
324 		case 'h':
325 		case 'H':
326 			secs *= HOURS;
327 			break;
328 		case 'd':
329 		case 'D':
330 			secs *= DAYS;
331 			break;
332 		case 'w':
333 		case 'W':
334 			secs *= WEEKS;
335 			break;
336 		default:
337 			return -1;
338 		}
339 		total += secs;
340 		if (total < 0)
341 			return -1;
342 		p = endp;
343 	}
344 
345 	return total;
346 }
347 
348 /*
349  * Returns a standardized host+port identifier string.
350  * Caller must free returned string.
351  */
352 char *
353 put_host_port(const char *host, u_short port)
354 {
355 	char *hoststr;
356 
357 	if (port == 0 || port == SSH_DEFAULT_PORT)
358 		return(xstrdup(host));
359 	if (asprintf(&hoststr, "[%s]:%d", host, (int)port) < 0)
360 		fatal("put_host_port: asprintf: %s", strerror(errno));
361 	debug3("put_host_port: %s", hoststr);
362 	return hoststr;
363 }
364 
365 /*
366  * Search for next delimiter between hostnames/addresses and ports.
367  * Argument may be modified (for termination).
368  * Returns *cp if parsing succeeds.
369  * *cp is set to the start of the next delimiter, if one was found.
370  * If this is the last field, *cp is set to NULL.
371  */
372 char *
373 hpdelim(char **cp)
374 {
375 	char *s, *old;
376 
377 	if (cp == NULL || *cp == NULL)
378 		return NULL;
379 
380 	old = s = *cp;
381 	if (*s == '[') {
382 		if ((s = strchr(s, ']')) == NULL)
383 			return NULL;
384 		else
385 			s++;
386 	} else if ((s = strpbrk(s, ":/")) == NULL)
387 		s = *cp + strlen(*cp); /* skip to end (see first case below) */
388 
389 	switch (*s) {
390 	case '\0':
391 		*cp = NULL;	/* no more fields*/
392 		break;
393 
394 	case ':':
395 	case '/':
396 		*s = '\0';	/* terminate */
397 		*cp = s + 1;
398 		break;
399 
400 	default:
401 		return NULL;
402 	}
403 
404 	return old;
405 }
406 
407 char *
408 cleanhostname(char *host)
409 {
410 	if (*host == '[' && host[strlen(host) - 1] == ']') {
411 		host[strlen(host) - 1] = '\0';
412 		return (host + 1);
413 	} else
414 		return host;
415 }
416 
417 char *
418 colon(char *cp)
419 {
420 	int flag = 0;
421 
422 	if (*cp == ':')		/* Leading colon is part of file name. */
423 		return (0);
424 	if (*cp == '[')
425 		flag = 1;
426 
427 	for (; *cp; ++cp) {
428 		if (*cp == '@' && *(cp+1) == '[')
429 			flag = 1;
430 		if (*cp == ']' && *(cp+1) == ':' && flag)
431 			return (cp+1);
432 		if (*cp == ':' && !flag)
433 			return (cp);
434 		if (*cp == '/')
435 			return (0);
436 	}
437 	return (0);
438 }
439 
440 /* function to assist building execv() arguments */
441 void
442 addargs(arglist *args, char *fmt, ...)
443 {
444 	va_list ap;
445 	char *cp;
446 	u_int nalloc;
447 	int r;
448 
449 	va_start(ap, fmt);
450 	r = vasprintf(&cp, fmt, ap);
451 	va_end(ap);
452 	if (r == -1)
453 		fatal("addargs: argument too long");
454 
455 	nalloc = args->nalloc;
456 	if (args->list == NULL) {
457 		nalloc = 32;
458 		args->num = 0;
459 	} else if (args->num+2 >= nalloc)
460 		nalloc *= 2;
461 
462 	args->list = xrealloc(args->list, nalloc, sizeof(char *));
463 	args->nalloc = nalloc;
464 	args->list[args->num++] = cp;
465 	args->list[args->num] = NULL;
466 }
467 
468 void
469 replacearg(arglist *args, u_int which, char *fmt, ...)
470 {
471 	va_list ap;
472 	char *cp;
473 	int r;
474 
475 	va_start(ap, fmt);
476 	r = vasprintf(&cp, fmt, ap);
477 	va_end(ap);
478 	if (r == -1)
479 		fatal("replacearg: argument too long");
480 
481 	if (which >= args->num)
482 		fatal("replacearg: tried to replace invalid arg %d >= %d",
483 		    which, args->num);
484 	xfree(args->list[which]);
485 	args->list[which] = cp;
486 }
487 
488 void
489 freeargs(arglist *args)
490 {
491 	u_int i;
492 
493 	if (args->list != NULL) {
494 		for (i = 0; i < args->num; i++)
495 			xfree(args->list[i]);
496 		xfree(args->list);
497 		args->nalloc = args->num = 0;
498 		args->list = NULL;
499 	}
500 }
501 
502 /*
503  * Expands tildes in the file name.  Returns data allocated by xmalloc.
504  * Warning: this calls getpw*.
505  */
506 char *
507 tilde_expand_filename(const char *filename, uid_t uid)
508 {
509 	const char *path;
510 	char user[128], ret[MAXPATHLEN];
511 	struct passwd *pw;
512 	u_int len, slash;
513 
514 	if (*filename != '~')
515 		return (xstrdup(filename));
516 	filename++;
517 
518 	path = strchr(filename, '/');
519 	if (path != NULL && path > filename) {		/* ~user/path */
520 		slash = path - filename;
521 		if (slash > sizeof(user) - 1)
522 			fatal("tilde_expand_filename: ~username too long");
523 		memcpy(user, filename, slash);
524 		user[slash] = '\0';
525 		if ((pw = getpwnam(user)) == NULL)
526 			fatal("tilde_expand_filename: No such user %s", user);
527 	} else if ((pw = getpwuid(uid)) == NULL)	/* ~/path */
528 		fatal("tilde_expand_filename: No such uid %d", uid);
529 
530 	if (strlcpy(ret, pw->pw_dir, sizeof(ret)) >= sizeof(ret))
531 		fatal("tilde_expand_filename: Path too long");
532 
533 	/* Make sure directory has a trailing '/' */
534 	len = strlen(pw->pw_dir);
535 	if ((len == 0 || pw->pw_dir[len - 1] != '/') &&
536 	    strlcat(ret, "/", sizeof(ret)) >= sizeof(ret))
537 		fatal("tilde_expand_filename: Path too long");
538 
539 	/* Skip leading '/' from specified path */
540 	if (path != NULL)
541 		filename = path + 1;
542 	if (strlcat(ret, filename, sizeof(ret)) >= sizeof(ret))
543 		fatal("tilde_expand_filename: Path too long");
544 
545 	return (xstrdup(ret));
546 }
547 
548 /*
549  * Expand a string with a set of %[char] escapes. A number of escapes may be
550  * specified as (char *escape_chars, char *replacement) pairs. The list must
551  * be terminated by a NULL escape_char. Returns replaced string in memory
552  * allocated by xmalloc.
553  */
554 char *
555 percent_expand(const char *string, ...)
556 {
557 #define EXPAND_MAX_KEYS	16
558 	struct {
559 		const char *key;
560 		const char *repl;
561 	} keys[EXPAND_MAX_KEYS];
562 	u_int num_keys, i, j;
563 	char buf[4096];
564 	va_list ap;
565 
566 	/* Gather keys */
567 	va_start(ap, string);
568 	for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) {
569 		keys[num_keys].key = va_arg(ap, char *);
570 		if (keys[num_keys].key == NULL)
571 			break;
572 		keys[num_keys].repl = va_arg(ap, char *);
573 		if (keys[num_keys].repl == NULL)
574 			fatal("percent_expand: NULL replacement");
575 	}
576 	va_end(ap);
577 
578 	if (num_keys >= EXPAND_MAX_KEYS)
579 		fatal("percent_expand: too many keys");
580 
581 	/* Expand string */
582 	*buf = '\0';
583 	for (i = 0; *string != '\0'; string++) {
584 		if (*string != '%') {
585  append:
586 			buf[i++] = *string;
587 			if (i >= sizeof(buf))
588 				fatal("percent_expand: string too long");
589 			buf[i] = '\0';
590 			continue;
591 		}
592 		string++;
593 		if (*string == '%')
594 			goto append;
595 		for (j = 0; j < num_keys; j++) {
596 			if (strchr(keys[j].key, *string) != NULL) {
597 				i = strlcat(buf, keys[j].repl, sizeof(buf));
598 				if (i >= sizeof(buf))
599 					fatal("percent_expand: string too long");
600 				break;
601 			}
602 		}
603 		if (j >= num_keys)
604 			fatal("percent_expand: unknown key %%%c", *string);
605 	}
606 	return (xstrdup(buf));
607 #undef EXPAND_MAX_KEYS
608 }
609 
610 /*
611  * Read an entire line from a public key file into a static buffer, discarding
612  * lines that exceed the buffer size.  Returns 0 on success, -1 on failure.
613  */
614 int
615 read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz,
616    u_long *lineno)
617 {
618 	while (fgets(buf, bufsz, f) != NULL) {
619 		(*lineno)++;
620 		if (buf[strlen(buf) - 1] == '\n' || feof(f)) {
621 			return 0;
622 		} else {
623 			debug("%s: %s line %lu exceeds size limit", __func__,
624 			    filename, *lineno);
625 			/* discard remainder of line */
626 			while (fgetc(f) != '\n' && !feof(f))
627 				;	/* nothing */
628 		}
629 	}
630 	return -1;
631 }
632 
633 int
634 tun_open(int tun, int mode)
635 {
636 #if defined(CUSTOM_SYS_TUN_OPEN)
637 	return (sys_tun_open(tun, mode));
638 #elif defined(SSH_TUN_OPENBSD)
639 	struct ifreq ifr;
640 	char name[100];
641 	int fd = -1, sock;
642 
643 	/* Open the tunnel device */
644 	if (tun <= SSH_TUNID_MAX) {
645 		snprintf(name, sizeof(name), "/dev/tun%d", tun);
646 		fd = open(name, O_RDWR);
647 	} else if (tun == SSH_TUNID_ANY) {
648 		for (tun = 100; tun >= 0; tun--) {
649 			snprintf(name, sizeof(name), "/dev/tun%d", tun);
650 			if ((fd = open(name, O_RDWR)) >= 0)
651 				break;
652 		}
653 	} else {
654 		debug("%s: invalid tunnel %u", __func__, tun);
655 		return (-1);
656 	}
657 
658 	if (fd < 0) {
659 		debug("%s: %s open failed: %s", __func__, name, strerror(errno));
660 		return (-1);
661 	}
662 
663 	debug("%s: %s mode %d fd %d", __func__, name, mode, fd);
664 
665 	/* Set the tunnel device operation mode */
666 	snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tun%d", tun);
667 	if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
668 		goto failed;
669 
670 	if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)
671 		goto failed;
672 
673 	/* Set interface mode */
674 	ifr.ifr_flags &= ~IFF_UP;
675 	if (mode == SSH_TUNMODE_ETHERNET)
676 		ifr.ifr_flags |= IFF_LINK0;
677 	else
678 		ifr.ifr_flags &= ~IFF_LINK0;
679 	if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
680 		goto failed;
681 
682 	/* Bring interface up */
683 	ifr.ifr_flags |= IFF_UP;
684 	if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
685 		goto failed;
686 
687 	close(sock);
688 	return (fd);
689 
690  failed:
691 	if (fd >= 0)
692 		close(fd);
693 	if (sock >= 0)
694 		close(sock);
695 	debug("%s: failed to set %s mode %d: %s", __func__, name,
696 	    mode, strerror(errno));
697 	return (-1);
698 #else
699 	error("Tunnel interfaces are not supported on this platform");
700 	return (-1);
701 #endif
702 }
703 
704 void
705 sanitise_stdfd(void)
706 {
707 	int nullfd, dupfd;
708 
709 	if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
710 		fprintf(stderr, "Couldn't open /dev/null: %s", strerror(errno));
711 		exit(1);
712 	}
713 	while (++dupfd <= 2) {
714 		/* Only clobber closed fds */
715 		if (fcntl(dupfd, F_GETFL, 0) >= 0)
716 			continue;
717 		if (dup2(nullfd, dupfd) == -1) {
718 			fprintf(stderr, "dup2: %s", strerror(errno));
719 			exit(1);
720 		}
721 	}
722 	if (nullfd > 2)
723 		close(nullfd);
724 }
725 
726 char *
727 tohex(const void *vp, size_t l)
728 {
729 	const u_char *p = (const u_char *)vp;
730 	char b[3], *r;
731 	size_t i, hl;
732 
733 	if (l > 65536)
734 		return xstrdup("tohex: length > 65536");
735 
736 	hl = l * 2 + 1;
737 	r = xcalloc(1, hl);
738 	for (i = 0; i < l; i++) {
739 		snprintf(b, sizeof(b), "%02x", p[i]);
740 		strlcat(r, b, hl);
741 	}
742 	return (r);
743 }
744 
745 u_int64_t
746 get_u64(const void *vp)
747 {
748 	const u_char *p = (const u_char *)vp;
749 	u_int64_t v;
750 
751 	v  = (u_int64_t)p[0] << 56;
752 	v |= (u_int64_t)p[1] << 48;
753 	v |= (u_int64_t)p[2] << 40;
754 	v |= (u_int64_t)p[3] << 32;
755 	v |= (u_int64_t)p[4] << 24;
756 	v |= (u_int64_t)p[5] << 16;
757 	v |= (u_int64_t)p[6] << 8;
758 	v |= (u_int64_t)p[7];
759 
760 	return (v);
761 }
762 
763 u_int32_t
764 get_u32(const void *vp)
765 {
766 	const u_char *p = (const u_char *)vp;
767 	u_int32_t v;
768 
769 	v  = (u_int32_t)p[0] << 24;
770 	v |= (u_int32_t)p[1] << 16;
771 	v |= (u_int32_t)p[2] << 8;
772 	v |= (u_int32_t)p[3];
773 
774 	return (v);
775 }
776 
777 u_int16_t
778 get_u16(const void *vp)
779 {
780 	const u_char *p = (const u_char *)vp;
781 	u_int16_t v;
782 
783 	v  = (u_int16_t)p[0] << 8;
784 	v |= (u_int16_t)p[1];
785 
786 	return (v);
787 }
788 
789 void
790 put_u64(void *vp, u_int64_t v)
791 {
792 	u_char *p = (u_char *)vp;
793 
794 	p[0] = (u_char)(v >> 56) & 0xff;
795 	p[1] = (u_char)(v >> 48) & 0xff;
796 	p[2] = (u_char)(v >> 40) & 0xff;
797 	p[3] = (u_char)(v >> 32) & 0xff;
798 	p[4] = (u_char)(v >> 24) & 0xff;
799 	p[5] = (u_char)(v >> 16) & 0xff;
800 	p[6] = (u_char)(v >> 8) & 0xff;
801 	p[7] = (u_char)v & 0xff;
802 }
803 
804 void
805 put_u32(void *vp, u_int32_t v)
806 {
807 	u_char *p = (u_char *)vp;
808 
809 	p[0] = (u_char)(v >> 24) & 0xff;
810 	p[1] = (u_char)(v >> 16) & 0xff;
811 	p[2] = (u_char)(v >> 8) & 0xff;
812 	p[3] = (u_char)v & 0xff;
813 }
814 
815 
816 void
817 put_u16(void *vp, u_int16_t v)
818 {
819 	u_char *p = (u_char *)vp;
820 
821 	p[0] = (u_char)(v >> 8) & 0xff;
822 	p[1] = (u_char)v & 0xff;
823 }
824