2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 #include <sys/types.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <errno.h>
33 #include <stdarg.h>
34 #include <limits.h>
35 #include <ctype.h>
36 #include <libgen.h>
37 #include <sys/isa_defs.h>
38 #include <sys/socket.h>
39 #include <net/if_arp.h>
40 #include <netinet/in.h>
41 #include <arpa/inet.h>
42 #include <sys/sysmacros.h>
43 #include <libinetutil.h>
44 #include <libdlpi.h>
45 #include <netinet/dhcp6.h>
46
47 #include "dhcp_symbol.h"
48 #include "dhcp_inittab.h"
49
50 static uint64_t dhcp_htonll(uint64_t);
51 static uint64_t dhcp_ntohll(uint64_t);
52 static void inittab_msg(const char *, ...);
53 static uchar_t category_to_code(const char *);
54 static boolean_t encode_number(uint8_t, uint8_t, boolean_t, uint8_t,
55 const char *, uint8_t *, int *);
56 static boolean_t decode_number(uint8_t, uint8_t, boolean_t, uint8_t,
57 const uint8_t *, char *, int *);
58 static dhcp_symbol_t *inittab_lookup(uchar_t, char, const char *, int32_t,
59 size_t *);
60 static dsym_category_t itabcode_to_dsymcode(uchar_t);
61 static boolean_t parse_entry(char *, char **);
62
63 /*
64 * forward declaration of our internal inittab_table[]. too bulky to put
65 * up front -- check the end of this file for its definition.
66 *
67 * Note: we have only an IPv4 version here. The inittab_verify() function is
68 * used by the DHCP server and manager. We'll need a new function if the
69 * server is extended to DHCPv6.
70 */
71 static dhcp_symbol_t inittab_table[];
1461 to += sprintf(to, is_signed ? "%hd" : "%hu",
1462 ntohs(uint16));
1463 break;
1464
1465 case 3:
1466 uint32 = 0;
1467 (void) memcpy((uchar_t *)&uint32 + 1, from, 3);
1468 to += sprintf(to, is_signed ? "%ld" : "%lu",
1469 ntohl(uint32));
1470 break;
1471
1472 case 4:
1473 (void) memcpy(&uint32, from, 4);
1474 to += sprintf(to, is_signed ? "%ld" : "%lu",
1475 ntohl(uint32));
1476 break;
1477
1478 case 8:
1479 (void) memcpy(&uint64, from, 8);
1480 to += sprintf(to, is_signed ? "%lld" : "%llu",
1481 dhcp_ntohll(uint64));
1482 break;
1483
1484 default:
1485 *ierrnop = ITAB_BAD_NUMBER;
1486 inittab_msg("decode_number: unknown integer size `%d'",
1487 size);
1488 return (B_FALSE);
1489 }
1490 if (n_entries > 0)
1491 *to++ = ' ';
1492 }
1493
1494 *to = '\0';
1495 return (B_TRUE);
1496 }
1497
1498 /*
1499 * encode_number(): encodes a sequence of numbers from ascii into binary;
1500 * number will end up on the wire so it needs to be in nbo
1501 *
1557 (void) memcpy(to, &uint16, 2);
1558 break;
1559
1560 case 3:
1561 uint32 = htonl(strtoul(from, &endptr, 0));
1562 if (errno != 0 || from == endptr) {
1563 goto error;
1564 }
1565 (void) memcpy(to, (uchar_t *)&uint32 + 1, 3);
1566 break;
1567
1568 case 4:
1569 uint32 = htonl(strtoul(from, &endptr, 0));
1570 if (errno != 0 || from == endptr) {
1571 goto error;
1572 }
1573 (void) memcpy(to, &uint32, 4);
1574 break;
1575
1576 case 8:
1577 uint64 = dhcp_htonll(strtoull(from, &endptr, 0));
1578 if (errno != 0 || from == endptr) {
1579 goto error;
1580 }
1581 (void) memcpy(to, &uint64, 8);
1582 break;
1583
1584 default:
1585 inittab_msg("encode_number: unsupported integer "
1586 "size `%d'", size);
1587 return (B_FALSE);
1588 }
1589
1590 from = strchr(from, ' ');
1591 if (from == NULL)
1592 break;
1593 }
1594
1595 return (B_TRUE);
1596
1597 error:
1677
1678 /*
1679 * category_to_code(): maps a category name to its numeric representation
1680 *
1681 * input: const char *: the category name
1682 * output: uchar_t: its internal code (numeric representation)
1683 */
1684
1685 static uchar_t
1686 category_to_code(const char *category)
1687 {
1688 unsigned int i;
1689
1690 for (i = 0; i < ITAB_CAT_COUNT; i++)
1691 if (strcasecmp(category_map[i].cme_name, category) == 0)
1692 return (category_map[i].cme_itabcode);
1693
1694 return (0);
1695 }
1696
1697 /*
1698 * dhcp_htonll(): converts a 64-bit number from host to network byte order
1699 *
1700 * input: uint64_t: the number to convert
1701 * output: uint64_t: its value in network byte order
1702 */
1703
1704 static uint64_t
1705 dhcp_htonll(uint64_t uint64_hbo)
1706 {
1707 return (dhcp_ntohll(uint64_hbo));
1708 }
1709
1710 /*
1711 * dhcp_ntohll(): converts a 64-bit number from network to host byte order
1712 *
1713 * input: uint64_t: the number to convert
1714 * output: uint64_t: its value in host byte order
1715 */
1716
1717 static uint64_t
1718 dhcp_ntohll(uint64_t uint64_nbo)
1719 {
1720 #ifdef _LITTLE_ENDIAN
1721 return ((uint64_t)ntohl(uint64_nbo & 0xffffffff) << 32 |
1722 ntohl(uint64_nbo >> 32));
1723 #else
1724 return (uint64_nbo);
1725 #endif
1726 }
1727
1728 /*
1729 * our internal table of DHCP option values, used by inittab_verify()
1730 */
1731 static dhcp_symbol_t inittab_table[] =
1732 {
1733 { DSYM_INTERNAL, 1024, "Hostname", DSYM_BOOL, 0, 0 },
1734 { DSYM_INTERNAL, 1025, "LeaseNeg", DSYM_BOOL, 0, 0 },
1735 { DSYM_INTERNAL, 1026, "EchoVC", DSYM_BOOL, 0, 0 },
1736 { DSYM_INTERNAL, 1027, "BootPath", DSYM_ASCII, 1, 128 },
1737 { DSYM_FIELD, 0, "Opcode", DSYM_UNUMBER8, 1, 1 },
1738 { DSYM_FIELD, 1, "Htype", DSYM_UNUMBER8, 1, 1 },
1739 { DSYM_FIELD, 2, "HLen", DSYM_UNUMBER8, 1, 1 },
1740 { DSYM_FIELD, 3, "Hops", DSYM_UNUMBER8, 1, 1 },
1741 { DSYM_FIELD, 4, "Xid", DSYM_UNUMBER32, 1, 1 },
1742 { DSYM_FIELD, 8, "Secs", DSYM_UNUMBER16, 1, 1 },
1743 { DSYM_FIELD, 10, "Flags", DSYM_OCTET, 1, 2 },
1744 { DSYM_FIELD, 12, "Ciaddr", DSYM_IP, 1, 1 },
1745 { DSYM_FIELD, 16, "Yiaddr", DSYM_IP, 1, 1 },
1746 { DSYM_FIELD, 20, "BootSrvA", DSYM_IP, 1, 1 },
1747 { DSYM_FIELD, 24, "Giaddr", DSYM_IP, 1, 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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/types.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <errno.h>
31 #include <stdarg.h>
32 #include <limits.h>
33 #include <ctype.h>
34 #include <libgen.h>
35 #include <sys/isa_defs.h>
36 #include <sys/socket.h>
37 #include <net/if_arp.h>
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
40 #include <sys/sysmacros.h>
41 #include <libinetutil.h>
42 #include <libdlpi.h>
43 #include <netinet/dhcp6.h>
44
45 #include "dhcp_symbol.h"
46 #include "dhcp_inittab.h"
47
48 static void inittab_msg(const char *, ...);
49 static uchar_t category_to_code(const char *);
50 static boolean_t encode_number(uint8_t, uint8_t, boolean_t, uint8_t,
51 const char *, uint8_t *, int *);
52 static boolean_t decode_number(uint8_t, uint8_t, boolean_t, uint8_t,
53 const uint8_t *, char *, int *);
54 static dhcp_symbol_t *inittab_lookup(uchar_t, char, const char *, int32_t,
55 size_t *);
56 static dsym_category_t itabcode_to_dsymcode(uchar_t);
57 static boolean_t parse_entry(char *, char **);
58
59 /*
60 * forward declaration of our internal inittab_table[]. too bulky to put
61 * up front -- check the end of this file for its definition.
62 *
63 * Note: we have only an IPv4 version here. The inittab_verify() function is
64 * used by the DHCP server and manager. We'll need a new function if the
65 * server is extended to DHCPv6.
66 */
67 static dhcp_symbol_t inittab_table[];
1457 to += sprintf(to, is_signed ? "%hd" : "%hu",
1458 ntohs(uint16));
1459 break;
1460
1461 case 3:
1462 uint32 = 0;
1463 (void) memcpy((uchar_t *)&uint32 + 1, from, 3);
1464 to += sprintf(to, is_signed ? "%ld" : "%lu",
1465 ntohl(uint32));
1466 break;
1467
1468 case 4:
1469 (void) memcpy(&uint32, from, 4);
1470 to += sprintf(to, is_signed ? "%ld" : "%lu",
1471 ntohl(uint32));
1472 break;
1473
1474 case 8:
1475 (void) memcpy(&uint64, from, 8);
1476 to += sprintf(to, is_signed ? "%lld" : "%llu",
1477 ntohll(uint64));
1478 break;
1479
1480 default:
1481 *ierrnop = ITAB_BAD_NUMBER;
1482 inittab_msg("decode_number: unknown integer size `%d'",
1483 size);
1484 return (B_FALSE);
1485 }
1486 if (n_entries > 0)
1487 *to++ = ' ';
1488 }
1489
1490 *to = '\0';
1491 return (B_TRUE);
1492 }
1493
1494 /*
1495 * encode_number(): encodes a sequence of numbers from ascii into binary;
1496 * number will end up on the wire so it needs to be in nbo
1497 *
1553 (void) memcpy(to, &uint16, 2);
1554 break;
1555
1556 case 3:
1557 uint32 = htonl(strtoul(from, &endptr, 0));
1558 if (errno != 0 || from == endptr) {
1559 goto error;
1560 }
1561 (void) memcpy(to, (uchar_t *)&uint32 + 1, 3);
1562 break;
1563
1564 case 4:
1565 uint32 = htonl(strtoul(from, &endptr, 0));
1566 if (errno != 0 || from == endptr) {
1567 goto error;
1568 }
1569 (void) memcpy(to, &uint32, 4);
1570 break;
1571
1572 case 8:
1573 uint64 = htonll(strtoull(from, &endptr, 0));
1574 if (errno != 0 || from == endptr) {
1575 goto error;
1576 }
1577 (void) memcpy(to, &uint64, 8);
1578 break;
1579
1580 default:
1581 inittab_msg("encode_number: unsupported integer "
1582 "size `%d'", size);
1583 return (B_FALSE);
1584 }
1585
1586 from = strchr(from, ' ');
1587 if (from == NULL)
1588 break;
1589 }
1590
1591 return (B_TRUE);
1592
1593 error:
1673
1674 /*
1675 * category_to_code(): maps a category name to its numeric representation
1676 *
1677 * input: const char *: the category name
1678 * output: uchar_t: its internal code (numeric representation)
1679 */
1680
1681 static uchar_t
1682 category_to_code(const char *category)
1683 {
1684 unsigned int i;
1685
1686 for (i = 0; i < ITAB_CAT_COUNT; i++)
1687 if (strcasecmp(category_map[i].cme_name, category) == 0)
1688 return (category_map[i].cme_itabcode);
1689
1690 return (0);
1691 }
1692
1693 /*
1694 * our internal table of DHCP option values, used by inittab_verify()
1695 */
1696 static dhcp_symbol_t inittab_table[] =
1697 {
1698 { DSYM_INTERNAL, 1024, "Hostname", DSYM_BOOL, 0, 0 },
1699 { DSYM_INTERNAL, 1025, "LeaseNeg", DSYM_BOOL, 0, 0 },
1700 { DSYM_INTERNAL, 1026, "EchoVC", DSYM_BOOL, 0, 0 },
1701 { DSYM_INTERNAL, 1027, "BootPath", DSYM_ASCII, 1, 128 },
1702 { DSYM_FIELD, 0, "Opcode", DSYM_UNUMBER8, 1, 1 },
1703 { DSYM_FIELD, 1, "Htype", DSYM_UNUMBER8, 1, 1 },
1704 { DSYM_FIELD, 2, "HLen", DSYM_UNUMBER8, 1, 1 },
1705 { DSYM_FIELD, 3, "Hops", DSYM_UNUMBER8, 1, 1 },
1706 { DSYM_FIELD, 4, "Xid", DSYM_UNUMBER32, 1, 1 },
1707 { DSYM_FIELD, 8, "Secs", DSYM_UNUMBER16, 1, 1 },
1708 { DSYM_FIELD, 10, "Flags", DSYM_OCTET, 1, 2 },
1709 { DSYM_FIELD, 12, "Ciaddr", DSYM_IP, 1, 1 },
1710 { DSYM_FIELD, 16, "Yiaddr", DSYM_IP, 1, 1 },
1711 { DSYM_FIELD, 20, "BootSrvA", DSYM_IP, 1, 1 },
1712 { DSYM_FIELD, 24, "Giaddr", DSYM_IP, 1, 1 },
|