コード例 #1
0
int
main()
{
    int 	i;
    dhcpol_t 	options;
    char	error[256];
    struct dhcp * pkt = (struct dhcp *)buf;

    dhcpol_init(&options);

    for (i = 0; tests[i].name; i++) {
	printf("\nTest %d: ", i);
	bcopy(tests[i].data, pkt->dp_options, tests[i].len);
	if (dhcpol_parse_packet(&options, pkt, 
				sizeof(*pkt) + tests[i].len,
				error) != tests[i].result) {
	    printf("test '%s' FAILED\n", tests[i].name);
	    if (tests[i].result == TRUE) {
		printf("error message returned was %s\n", error);
	    }
	}
	else {
	    printf("test '%s' PASSED\n", tests[i].name);
	    if (tests[i].result == FALSE) {
		printf("error message returned was %s\n", error);
	    }
	}
	dhcpol_free(&options);
    }
    exit(0);
}
コード例 #2
0
ファイル: netboot.c プロジェクト: Prajna/xnu
static boolean_t
get_ip_parameters(struct in_addr * iaddr_p, struct in_addr * netmask_p, 
		   struct in_addr * router_p)
{
    void *		entry;
    const void *	pkt;
    int			pkt_len;


    entry = IOBSDRegistryEntryForDeviceTree("/chosen");
    if (entry == NULL) {
	return (FALSE);
    }
    pkt = IOBSDRegistryEntryGetData(entry, DHCP_RESPONSE, &pkt_len);
    if (pkt != NULL && pkt_len >= (int)sizeof(struct dhcp)) {
	printf("netboot: retrieving IP information from DHCP response\n");
    }
    else {
	pkt = IOBSDRegistryEntryGetData(entry, BOOTP_RESPONSE, &pkt_len);
	if (pkt != NULL && pkt_len >= (int)sizeof(struct dhcp)) {
	    printf("netboot: retrieving IP information from BOOTP response\n");
	}
    }
    if (pkt != NULL) {
	const struct in_addr *	ip;
	int			len;
	dhcpol_t 		options;
	const struct dhcp *	reply;

	reply = (const struct dhcp *)pkt;
	(void)dhcpol_parse_packet(&options, reply, pkt_len);
	*iaddr_p = reply->dp_yiaddr;
	ip = (const struct in_addr *)
	    dhcpol_find(&options, 
			dhcptag_subnet_mask_e, &len, NULL);
	if (ip) {
	    *netmask_p = *ip;
	}
	ip = (const struct in_addr *)
	    dhcpol_find(&options, dhcptag_router_e, &len, NULL);
	if (ip) {
	    *router_p = *ip;
	}
    }
    IOBSDRegistryEntryRelease(entry);
    return (pkt != NULL);
}
コード例 #3
0
ファイル: bsdplib.c プロジェクト: aosm/bootp
PRIVATE_EXTERN void
bsdp_print_packet(struct dhcp * pkt, int length, int options_only)
{
    dhcpo_err_str_t	err;
    int 	i;
    dhcpol_t	options;
    dhcpol_t	vendor_options;

    dhcpol_init(&options);
    dhcpol_init(&vendor_options);
    if (options_only == 0) {
	dhcp_packet_print(pkt, length);
    }
    if (dhcpol_parse_packet(&options, pkt, length, &err) == FALSE) {
	fprintf(stderr, "packet did not parse, %s\n", err.str);
	return;
    }
    if (dhcpol_parse_vendor(&vendor_options, &options, &err) == FALSE) {
	fprintf(stderr, "vendor options did not parse, %s\n", err.str);
	goto done;
    }
    printf("BSDP Options count is %d\n", dhcpol_count(&vendor_options));
    for (i = 0; i < dhcpol_count(&vendor_options); i++) {
	u_int8_t	code;
	u_int8_t *	opt = dhcpol_element(&vendor_options, i);
	u_int8_t	len;

	code = opt[TAG_OFFSET];
	len = opt[LEN_OFFSET];
	printf("%s: ", bsdptag_name(code));
	if (code == bsdptag_message_type_e) {
	    printf("%s (", bsdp_msgtype_names(opt[OPTION_OFFSET]));
	    dhcptype_print(bsdptag_type(code), opt + OPTION_OFFSET, len);
	    printf(")\n");
	}
	else {
	    dhcptype_print(bsdptag_type(code), opt + OPTION_OFFSET, len);
	    printf("\n");
	}
    }
 done:
    dhcpol_free(&options);
    dhcpol_free(&vendor_options);
    return;
}
コード例 #4
0
ファイル: netboot.c プロジェクト: Prajna/xnu
static boolean_t
get_root_path(char * root_path)
{
    void *		entry;
    boolean_t		found = FALSE;
    const void *	pkt;
    int			pkt_len;
    
    entry = IOBSDRegistryEntryForDeviceTree("/chosen");
    if (entry == NULL) {
	return (FALSE);
    }
    pkt = IOBSDRegistryEntryGetData(entry, BSDP_RESPONSE, &pkt_len);
    if (pkt != NULL && pkt_len >= (int)sizeof(struct dhcp)) {
	printf("netboot: retrieving root path from BSDP response\n");
    }
    else {
	pkt = IOBSDRegistryEntryGetData(entry, BOOTP_RESPONSE, 
					&pkt_len);
	if (pkt != NULL && pkt_len >= (int)sizeof(struct dhcp)) {
	    printf("netboot: retrieving root path from BOOTP response\n");
	}
    }
    if (pkt != NULL) {
	int			len;
	dhcpol_t 		options;
	const char *		path;
	const struct dhcp *	reply;

	reply = (const struct dhcp *)pkt;
	(void)dhcpol_parse_packet(&options, reply, pkt_len);

	path = (const char *)dhcpol_find(&options, 
					 dhcptag_root_path_e, &len, NULL);
	if (path) {
	    memcpy(root_path, path, len);
	    root_path[len] = '\0';
	    found = TRUE;
	}
    }
    IOBSDRegistryEntryRelease(entry);
    return (found);

}
コード例 #5
0
ファイル: client.c プロジェクト: aosm/bootp
static int
S_bsdp_option(mach_port_t server, int argc, char * argv[])
{
    CFDictionaryRef	chosen = NULL;
    void *		data = NULL;
    int			data_len;
    struct dhcp *	dhcp;
    int			length;
    dhcpol_t		options;
    CFDataRef		response = NULL;
    int			ret = 1;
    int			tag = 0;
    dhcpol_t		vendor_options;
    int			vendor_tag = 0;

    if (getuid() != 0) {
	return (EX_NOPERM);
    }

    chosen = myIORegistryEntryCopyValue("IODeviceTree:/chosen");
    if (chosen == NULL) {
	goto done;
    }
    response = CFDictionaryGetValue(chosen, CFSTR("bsdp-response"));
    if (isA_CFData(response) == NULL) {
	response = CFDictionaryGetValue(chosen, CFSTR("bootp-response"));
	if (isA_CFData(response) == NULL) {
	    goto done;
	}
    }

    /* ALIGN: CFDataGetBytePtr is aligned to at least sizeof(uint64) */
    dhcp = (struct dhcp *)(void *)CFDataGetBytePtr(response);
    length = (int)CFDataGetLength(response);
    if (dhcpol_parse_packet(&options, dhcp, length, NULL) == FALSE) {
	goto done;
    }
    if (strcmp(argv[0], SHADOW_MOUNT_PATH_COMMAND) == 0) {
	tag = dhcptag_vendor_specific_e;
	vendor_tag = bsdptag_shadow_mount_path_e;
    }
    else if (strcmp(argv[0], SHADOW_FILE_PATH_COMMAND) == 0) {
	tag = dhcptag_vendor_specific_e;
	vendor_tag = bsdptag_shadow_file_path_e;
    }
    else if (strcmp(argv[0], MACHINE_NAME_COMMAND) == 0) {
	tag = dhcptag_vendor_specific_e;
	vendor_tag = bsdptag_machine_name_e;
    }
    else {
	tag = atoi(argv[0]);
	if (argc == 2) {
	    vendor_tag = atoi(argv[1]);
	}
    }
    if (tag == dhcptag_vendor_specific_e && vendor_tag != 0) {
	if (dhcpol_parse_vendor(&vendor_options, &options, NULL) == FALSE) {
	    goto done;
	}
	data = dhcpol_option_copy(&vendor_options, vendor_tag, &data_len);
	if (data != NULL) {
	    dhcptype_print(bsdptag_type(vendor_tag), data, data_len);
	    ret = 0;
	}
	dhcpol_free(&vendor_options);
    }
    else {
	const dhcptag_info_t * entry;

	entry = dhcptag_info(tag);
	if (entry == NULL) {
	    goto done;
	}
	data = dhcpol_option_copy(&options, tag, &data_len);
	if (data != NULL) {
	    dhcptype_print(entry->type, data, data_len);
	    ret = 0;
	}
    }
 done:
    if (data != NULL) {
	free(data);
    }
    if (chosen != NULL) {
	CFRelease(chosen);
    }
    return (ret);
}
コード例 #6
0
ファイル: DHCPLease.c プロジェクト: aosm/bootp
/*
 * Function: DHCPLeaseCreateWithDictionary
 * Purpose:
 *   Instantiate a new DHCPLease structure corresponding to the given
 *   dictionary.  Validates that required properties are present,
 *   returns NULL if those checks fail.
 */
static DHCPLeaseRef
DHCPLeaseCreateWithDictionary(CFDictionaryRef dict, bool is_wifi)
{
    CFDataRef			hwaddr_data;
    dhcp_lease_time_t		lease_time;
    DHCPLeaseRef		lease_p;
    CFDataRef			pkt_data;
    CFRange			pkt_data_range;
    struct in_addr *		router_p;
    CFStringRef			ssid = NULL;
    CFDateRef			start_date;
    dhcp_lease_time_t		t1_time;
    dhcp_lease_time_t		t2_time;

    /* get the lease start time */
    start_date = CFDictionaryGetValue(dict, kLeaseStartDate);
    if (isA_CFDate(start_date) == NULL) {
	goto failed;
    }
    /* get the packet data */
    pkt_data = CFDictionaryGetValue(dict, kPacketData);
    if (isA_CFData(pkt_data) == NULL) {
	goto failed;
    }
    /* if Wi-Fi, get the SSID */
    if (is_wifi) {
	ssid = CFDictionaryGetValue(dict, kSSID);
	if (isA_CFString(ssid) == NULL) {
	    goto failed;
	}
    }

    pkt_data_range.location = 0;
    pkt_data_range.length = CFDataGetLength(pkt_data);
    if (pkt_data_range.length < sizeof(struct dhcp)) {
	goto failed;
    }
    lease_p = (DHCPLeaseRef)
	malloc(offsetof(DHCPLease, pkt) + pkt_data_range.length);
    bzero(lease_p, offsetof(DHCPLease, pkt));

    /* copy the packet data */
    CFDataGetBytes(pkt_data, pkt_data_range, lease_p->pkt);
    lease_p->pkt_length = (int)pkt_data_range.length;

    /* get the lease information and router IP address */
    lease_p->lease_start = (absolute_time_t)CFDateGetAbsoluteTime(start_date);
    { /* parse/retrieve options */
	dhcpol_t			options;
	
	(void)dhcpol_parse_packet(&options, (void *)lease_p->pkt,
				  (int)pkt_data_range.length, NULL);
	dhcp_get_lease_from_options(&options, &lease_time, &t1_time, &t2_time);
	router_p = dhcp_get_router_from_options(&options, lease_p->our_ip);
	dhcpol_free(&options);
    }
    lease_p->lease_length = lease_time;

    /* get the IP address */
    /* ALIGN: lease_p->pkt is aligned, cast ok. */
    lease_p->our_ip = ((struct dhcp *)(void *)lease_p->pkt)->dp_yiaddr;

    /* get the router information */
    if (router_p != NULL) {
	CFRange		hwaddr_range;

	lease_p->router_ip = *router_p;
	/* get the router hardware address */
	hwaddr_data = CFDictionaryGetValue(dict, kRouterHardwareAddress);
	hwaddr_range.length = 0;
	if (isA_CFData(hwaddr_data) != NULL) {
	    hwaddr_range.length = CFDataGetLength(hwaddr_data);
	}
	if (hwaddr_range.length > 0) {
	    hwaddr_range.location = 0;
	    if (hwaddr_range.length > sizeof(lease_p->router_hwaddr)) {
		hwaddr_range.length = sizeof(lease_p->router_hwaddr);
	    }
	    lease_p->router_hwaddr_length = (int)hwaddr_range.length;
	    CFDataGetBytes(hwaddr_data, hwaddr_range, lease_p->router_hwaddr);
	}
    }
    if (ssid != NULL) {
	CFRetain(ssid);
	lease_p->ssid = ssid;
    }
    return (lease_p);

 failed:
    return (NULL);
}
コード例 #7
0
void
dhcp_packet_print_cfstr(CFMutableStringRef str, struct dhcp * dp, int pkt_len)
{
    int 		i;
    int			j;
    int			len;

    if (pkt_len < sizeof(struct dhcp)) {
	STRING_APPEND(str, "Packet is too short %d < %d\n", pkt_len,
		(int)sizeof(struct dhcp));
	return;
    }
    STRING_APPEND(str, "op = ");
    if (dp->dp_op == BOOTREQUEST) {
	STRING_APPEND(str, "BOOTREQUEST\n");
    }
    else if (dp->dp_op == BOOTREPLY) {
	STRING_APPEND(str, "BOOTREPLY\n");
    }
    else {
	i = dp->dp_op;
	STRING_APPEND(str, "OP(%d)\n", i);
    }
    
    i = dp->dp_htype;
    STRING_APPEND(str, "htype = %d\n", i);
    
    STRING_APPEND(str, "flags = %x\n", ntohs(dp->dp_flags));
    len = dp->dp_hlen;
    STRING_APPEND(str, "hlen = %d\n", len);
    
    i = dp->dp_hops;
    STRING_APPEND(str, "hops = %d\n", i);
    
    STRING_APPEND(str, "xid = %lu\n", (u_long)ntohl(dp->dp_xid));
    
    STRING_APPEND(str, "secs = %hu\n", ntohs(dp->dp_secs));
    
    STRING_APPEND(str, "ciaddr = %s\n", inet_ntoa(dp->dp_ciaddr));
    STRING_APPEND(str, "yiaddr = %s\n", inet_ntoa(dp->dp_yiaddr));
    STRING_APPEND(str, "siaddr = %s\n", inet_ntoa(dp->dp_siaddr));
    STRING_APPEND(str, "giaddr = %s\n", inet_ntoa(dp->dp_giaddr));
    
    STRING_APPEND(str, "chaddr = ");
    for (j = 0; j < len; j++) {
	i = dp->dp_chaddr[j];
	STRING_APPEND(str, "%0x", i);
	if (j < (len - 1)) STRING_APPEND(str, ":");
    }
    STRING_APPEND(str, "\n");
    
    STRING_APPEND(str, "sname = %s\n", dp->dp_sname);
    STRING_APPEND(str, "file = %s\n", dp->dp_file);
    
    {
	dhcpol_t t;
	
	dhcpol_init(&t);
	if (dhcpol_parse_packet(&t, dp, pkt_len, NULL)) {
	    STRING_APPEND(str, "options:\n");
	    dhcpol_print_cfstr(str, &t);
	}
	dhcpol_free(&t);
    }
    return;
}
コード例 #8
0
ファイル: in_dhcp.c プロジェクト: Prajna/xnu
static int
dhcp_get_offer(struct dhcp_context * context, int wait_ticks)
{
    int				error = 0;
    int	 			gather_count = 0;
    const struct in_addr * 	ip;
    int				last_rating = 0;
    int				len;
    int				n;
    int 			rating;
    struct dhcp *		reply;
    struct in_addr		server_id;
    struct socket * 		timer_arg;

    timer_arg = context->so;
    reply = dhcp_context_reply(context);
    timeout((timeout_fcn_t)dhcp_timeout, &timer_arg, wait_ticks);
    while (1) {
	error = receive_packet(context->so, context->reply,
			       sizeof(context->reply), &n);
	if (error == 0) {
	    dhcpol_t		options;

	    dprintf(("\ndhcp: received packet length %d\n", n));
	    if (n < (int)sizeof(struct dhcp)) {
		dprintf(("dhcp: packet is too short %d < %d\n",
			 n, (int)sizeof(struct dhcp)));
		continue;
	    }
	    if (ntohl(reply->dp_xid) != context->xid
		|| reply->dp_yiaddr.s_addr == 0
		|| reply->dp_yiaddr.s_addr == INADDR_BROADCAST
		|| bcmp(reply->dp_chaddr,
			link_address(context->dl_p), 
			link_address_length(context->dl_p)) != 0) {
		/* not for us */
		continue;
	    }
	    (void)dhcpol_parse_packet(&options, reply, n);
	    if (get_dhcp_msgtype(&options) != dhcp_msgtype_offer_e) {
		/* not an offer */
		goto next_packet;
	    }
	    ip = (const struct in_addr *)
		dhcpol_find(&options, 
			    dhcptag_server_identifier_e, &len, NULL);
	    if (ip == NULL || len < (int)sizeof(*ip)) {
		/* missing/invalid server identifier */
		goto next_packet;
	    }
	    printf("dhcp: received OFFER: server " IP_FORMAT
		   " IP address "  IP_FORMAT "\n",
		   IP_LIST(ip), IP_LIST(&reply->dp_yiaddr));
	    server_id = *ip;
	    rating = rate_packet(&options);
	    if (rating > last_rating) {
		context->iaddr = reply->dp_yiaddr;
		ip = (const struct in_addr *)
		    dhcpol_find(&options, 
				dhcptag_subnet_mask_e, &len, NULL);
		if (ip != NULL && len >= (int)sizeof(*ip)) {
		    context->netmask = *ip;
		}
		ip = (const struct in_addr *)
		    dhcpol_find(&options, dhcptag_router_e, &len, NULL);
		if (ip != NULL && len >= (int)sizeof(*ip)) {
		    context->router = *ip;
		}
		context->server_id = server_id;
	    }
	    if (rating >= GOOD_RATING) {
		dhcpol_free(&options);
		/* packet is good enough */
		untimeout((timeout_fcn_t)dhcp_timeout, &timer_arg);
		break;
	    }
	    if (gather_count == 0) {
		untimeout((timeout_fcn_t)dhcp_timeout, &timer_arg);
		timer_arg = context->so;
		timeout((timeout_fcn_t)dhcp_timeout, &timer_arg, 
			hz * GATHER_TIME_SECS);
	    }
	    gather_count = 1;
	next_packet:
	    dhcpol_free(&options);
	}
	else if ((error != EWOULDBLOCK)) {
	    untimeout((timeout_fcn_t)dhcp_timeout, &timer_arg);
	    break;
	}
	else if (timer_arg == NULL) { /* timed out */
	    if (gather_count != 0) {
		dprintf(("dhcp: gathering time has expired\n"));
		error = 0;
	    }
	    break;
	}
	else {
	    socket_lock(context->so, 1);
	    error = sbwait(&context->so->so_rcv);
	    socket_unlock(context->so, 1);
	}
    }
    return (error);
}
コード例 #9
0
ファイル: in_dhcp.c プロジェクト: Prajna/xnu
static int
dhcp_get_ack(struct dhcp_context * context, int wait_ticks)
{
    int				error = 0;
    const struct in_addr * 	ip;
    int				len;
    int				n;
    struct dhcp *		reply;
    struct in_addr		server_id;
    struct socket * 		timer_arg;

    timer_arg = context->so;
    reply = dhcp_context_reply(context);
    timeout((timeout_fcn_t)dhcp_timeout, &timer_arg, wait_ticks);
    while (1) {
	error = receive_packet(context->so, context->reply,
			       sizeof(context->reply), &n);
	if (error == 0) {
	    dhcp_msgtype_t	msg;
	    dhcpol_t		options;

	    dprintf(("\ndhcp: received packet length %d\n", n));
	    if (n < (int)sizeof(struct dhcp)) {
		dprintf(("dhcp: packet is too short %d < %d\n",
			 n, (int)sizeof(struct dhcp)));
		continue;
	    }
	    if (ntohl(reply->dp_xid) != context->xid
		|| bcmp(reply->dp_chaddr, link_address(context->dl_p), 
			link_address_length(context->dl_p)) != 0) {
		/* not for us */
		continue;
	    }
	    (void)dhcpol_parse_packet(&options, reply, n);
	    server_id.s_addr = 0;
	    ip = (const struct in_addr *)
		dhcpol_find(&options, 
			    dhcptag_server_identifier_e, &len, NULL);
	    if (ip != NULL && len >= (int)sizeof(*ip)) {
		server_id = *ip;
	    }
	    msg = get_dhcp_msgtype(&options);
	    if (msg == dhcp_msgtype_nak_e
		&& server_id.s_addr == context->server_id.s_addr) {
		/* server NAK'd us, start over */
		dhcpol_free(&options);
		error = EPROTO;
		untimeout((timeout_fcn_t)dhcp_timeout, &timer_arg);
		break;
	    }
	    if (msg != dhcp_msgtype_ack_e
		|| reply->dp_yiaddr.s_addr == 0
		|| reply->dp_yiaddr.s_addr == INADDR_BROADCAST) {
		/* ignore the packet */
		goto next_packet;
	    }
	    printf("dhcp: received ACK: server " IP_FORMAT
		   " IP address "  IP_FORMAT "\n",
		   IP_LIST(&server_id), IP_LIST(&reply->dp_yiaddr));
	    context->iaddr = reply->dp_yiaddr;
	    ip = (const struct in_addr *)
		dhcpol_find(&options, 
			    dhcptag_subnet_mask_e, &len, NULL);
	    if (ip != NULL && len >= (int)sizeof(*ip)) {
		context->netmask = *ip;
	    }
	    ip = (const struct in_addr *)
		dhcpol_find(&options, dhcptag_router_e, &len, NULL);
	    if (ip != NULL && len >= (int)sizeof(*ip)) {
		context->router = *ip;
	    }
	    dhcpol_free(&options);
	    untimeout((timeout_fcn_t)dhcp_timeout, &timer_arg);
	    break;

	next_packet:
	    dhcpol_free(&options);
	}
	else if ((error != EWOULDBLOCK)) {
	    /* if some other error occurred, we're done */
	    untimeout((timeout_fcn_t)dhcp_timeout, &timer_arg);
	    break;
	}
	else if (timer_arg == NULL) { 
	    /* timed out */
	    break;
	}
	else {
	    /* wait for a wait to arrive, or a timeout to occur */
	    socket_lock(context->so, 1);
	    error = sbwait(&context->so->so_rcv);
	    socket_unlock(context->so, 1);
	}
    }
    return (error);
}