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/CDDL.txt 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/CDDL.txt. 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 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 */ 27 28 #pragma ident "@(#)dhcp.c 1.6 07/06/06 SMI" 29 30 #include <sys/socket.h> 31 #include <sys/fcntl.h> 32 #include <sys/types.h> 33 #include <netinet/in.h> 34 #include <inttypes.h> 35 #include <string.h> 36 #include <unistd.h> 37 #include <fcntl.h> 38 #include <time.h> 39 40 #include "dhcp.h" 41 42 void 43 vDHCPBuildDiscover(struct dhcpmsg *pdhcpm, unsigned char *macaddr, char *clase) 44 { 45 unsigned char *p = pdhcpm->options + 4; 46 unsigned long ulMagicCookie = htonl(0x63825363); 47 unsigned short dhcpMsgSize = htons(sizeof (struct dhcpmsg)); 48 49 (void) memset(pdhcpm, 0, sizeof (struct dhcpmsg)); 50 pdhcpm->op = 1; /* BOOTREQUEST */ 51 pdhcpm->htype = 1; /* ethernet */ 52 pdhcpm->hlen = 6; /* ethernet */ 53 pdhcpm->xid = (unsigned long) time(NULL); 54 pdhcpm->secs = 0; 55 /* to request server response in broadcast */ 56 pdhcpm->flags = htons(0x8000); 57 (void) memcpy(pdhcpm->chaddr, macaddr, 6); 58 (void) memcpy(pdhcpm->options, &ulMagicCookie, 4); 59 60 *p++ = dhcpMessageType; 61 *p++ = 1; 62 *p++ = 1; /* DHCP_DISCOVER */ 63 64 if (clase) 65 if (strlen(clase)) { 66 *p++ = dhcpClassIdentifier; 67 *p++ = (unsigned char) strlen(clase); 68 (void) memcpy(p, clase, strlen(clase)); 69 p += strlen(clase); 70 } 71 72 *p++ = dhcpParamRequest; 73 *p++ = 4; 74 *p++ = subnetMask; 75 *p++ = routersOnSubnet; 76 *p++ = hostName; 77 *p++ = vendorSpecificInfo; 78 79 *p++ = dhcpMaxMsgSize; 80 *p++ = 2; 81 (void) memcpy(p, &dhcpMsgSize, 2); 82 p += 2; 83 84 *p = endOption; 85 } 86 87 int 88 iDHCPStart(struct in_addr *padd, int raw, int reuse) 89 { 90 int res; 91 int true; 92 struct sockaddr_in clientaddr; 93 int udpsocket; 94 95 int type, protocol; 96 97 if (raw) { 98 type = SOCK_RAW; 99 protocol = IPPROTO_RAW; 100 } else { 101 type = SOCK_DGRAM; 102 protocol = IPPROTO_UDP; 103 } 104 105 udpsocket = socket(AF_INET, type, protocol); 106 if (udpsocket < 0) 107 return (ERR_SOCKET); 108 109 true = 1; 110 if (raw) 111 if (setsockopt(udpsocket, IPPROTO_IP, IP_HDRINCL, &true, 112 sizeof (true))) { 113 (void) close(udpsocket); 114 return (ERR_IOCTL); 115 } 116 117 true = 1; 118 if (reuse) 119 if (setsockopt(udpsocket, SOL_SOCKET, SO_REUSEADDR, &true, 120 sizeof (true))) { 121 (void) close(udpsocket); 122 return (ERR_IOCTL); 123 } 124 125 true = 1; 126 if (setsockopt(udpsocket, SOL_SOCKET, SO_BROADCAST, &true, 127 sizeof (true))) { 128 (void) close(udpsocket); 129 return (ERR_IOCTL); 130 } 131 132 (void) memset(&clientaddr, 0, sizeof (clientaddr)); 133 clientaddr.sin_family = AF_INET; 134 clientaddr.sin_port = htons(68); 135 if (padd == NULL) 136 clientaddr.sin_addr.s_addr = htonl(INADDR_ANY); 137 else 138 clientaddr.sin_addr = *padd; 139 140 res = bind(udpsocket, (struct sockaddr *)&clientaddr, 141 sizeof (clientaddr)); 142 if (res == -1) { 143 (void) close(udpsocket); 144 return (ERR_BIND); 145 } 146 147 return (udpsocket); 148 } 149