xref: /illumos-gate/usr/src/common/net/dhcp/octet.c (revision 4c28a617e3922d92a58e813a5b955eb526b9c386)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1996-2002 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /* LINTLIBRARY */
28 
29 #if !defined(_BOOT) && !defined(_KERNEL)
30 #include <stdio.h>
31 #include <ctype.h>
32 #include <stdlib.h>
33 #endif	/* _BOOT && _KERNEL */
34 #include <sys/types.h>
35 #include <sys/null.h>
36 #include <sys/errno.h>
37 
38 #if	defined(_BOOT) || defined(_KERNEL)
39 #define	isdigit(c)	((c) >= '0' && c <= '9')
40 #define	isxdigit(c)	(isdigit(c) || (((c) >= 'a') && ((c) <= 'f')) || \
41 			(((c) >= 'A') && ((c) <= 'F')))
42 #endif	/* _BOOT || _KERNEL */
43 
44 /*
45  * Converts an octet string into an ASCII string. The string returned is
46  * NULL-terminated, and the length recorded in blen does *not* include the
47  * null terminator (in other words, octet_to_hexascii() returns the length a'la
48  * strlen()).
49  *
50  * Returns 0 for Success, errno otherwise.
51  */
52 int
53 octet_to_hexascii(const void *nump, uint_t nlen, char *bufp, uint_t *blen)
54 {
55 	int		i;
56 	char		*bp;
57 	const uchar_t	*np;
58 	static char	ascii_conv[] = "0123456789ABCDEF";
59 
60 	if (nump == NULL || bufp == NULL || blen == NULL)
61 		return (EINVAL);
62 
63 	if ((nlen * 2) >= *blen) {
64 		*blen = 0;
65 		return (E2BIG);
66 	}
67 	for (i = 0, bp = bufp, np = (const uchar_t *)nump; i < nlen; i++) {
68 		*bp++ = ascii_conv[(np[i] >> 4) & 0x0f];
69 		*bp++ = ascii_conv[np[i] & 0x0f];
70 	}
71 	*bp = '\0';
72 	*blen = i * 2;
73 	return (0);
74 }
75 
76 /*
77  * Converts an ASCII string into an octet string.
78  *
79  * Returns 0 for success, errno otherwise.
80  */
81 int
82 hexascii_to_octet(const char *asp, uint_t alen, void *bufp, uint_t *blen)
83 {
84 	int		i, j, k;
85 	const char	*tp;
86 	uchar_t		*u_tp;
87 
88 	if (asp == NULL || bufp == NULL || blen == NULL)
89 		return (EINVAL);
90 
91 	if (alen > (*blen * 2))
92 		return (E2BIG);
93 
94 	k = ((alen % 2) == 0) ? alen / 2 : (alen / 2) + 1;
95 	for (tp = asp, u_tp = (uchar_t *)bufp, i = 0; i < k; i++, u_tp++) {
96 		/* one nibble at a time */
97 		for (*u_tp = 0, j = 0; j < 2; j++, tp++) {
98 			if (isdigit(*tp))
99 				*u_tp |= *tp - '0';
100 			else if (isxdigit(*tp))
101 				*u_tp |= (*tp & ~0x20) + 10 - 'A';
102 			else
103 				return (EINVAL);
104 			if ((j % 2) == 0)
105 				*u_tp <<= 4;
106 		}
107 	}
108 	*blen = k;
109 	return (0);
110 }
111