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