Home | History | Annotate | Download | only in dhc
      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