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