Esempio n. 1
0
/*
 * Function: dhcpol_parse_packet
 *
 * Purpose:
 *    Parse the option areas in the DHCP packet.
 *    Verifies that the packet has the right magic number,
 *    then parses and accumulates the option areas.
 *    First the pkt->dp_options is parsed.  If that contains
 *    the overload option, it parses pkt->dp_file if specified,
 *    then parses pkt->dp_sname if specified.
 */
boolean_t
dhcpol_parse_packet(dhcpol_t * options, struct dhcp * pkt, int len,
		    unsigned char * err)
{
    char		rfc_magic[4] = RFC_OPTIONS_MAGIC;

    dhcpol_init(options);	/* make sure it's empty */

    if (err)
	err[0] = '\0';

    if (len < (sizeof(*pkt) + RFC_MAGIC_SIZE)) {
	if (err) {
	    sprintf(err, "packet is too short: %d < %d",
		    len, (int)sizeof(*pkt) + RFC_MAGIC_SIZE);
	}
	return (FALSE);
    }
    if (bcmp(pkt->dp_options, rfc_magic, RFC_MAGIC_SIZE)) {
	if (err)
	    sprintf(err, "missing magic number");
	return (FALSE);
    }
    if (dhcpol_parse_buffer(options, pkt->dp_options + RFC_MAGIC_SIZE,
			    len - sizeof(*pkt) - RFC_MAGIC_SIZE, err) == FALSE)
	return (FALSE);
    { /* get overloaded options */
	unsigned char *	overload;
	int		overload_len;

	overload = (unsigned char *)
	    dhcpol_find(options, dhcptag_option_overload_e, 
				&overload_len, NULL);
	if (overload && overload_len == 1) { /* has overloaded options */
	    dhcpol_t	extra;

	    dhcpol_init(&extra);
	    if (*overload == DHCP_OVERLOAD_FILE
		|| *overload == DHCP_OVERLOAD_BOTH) {
		if (dhcpol_parse_buffer(&extra, pkt->dp_file, 
					 sizeof(pkt->dp_file), NULL)) {
		    dhcpol_concat(options, &extra);
		    dhcpol_free(&extra);
		}
	    }
	    if (*overload == DHCP_OVERLOAD_SNAME
		|| *overload == DHCP_OVERLOAD_BOTH) {
		if (dhcpol_parse_buffer(&extra, pkt->dp_sname, 
					 sizeof(pkt->dp_sname), NULL)) {
		    dhcpol_concat(options, &extra);
		    dhcpol_free(&extra);
		}
	    }
	}
    }
    return (TRUE);
}
Esempio n. 2
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);
}
Esempio n. 3
0
/*
 * Function: dhcpol_parse_vendor
 *
 * Purpose:
 *   Given a set of options, find the vendor specific option(s)
 *   and parse all of them into a single option list.
 *  
 * Return value:
 *   TRUE if vendor specific options existed and were parsed succesfully,
 *   FALSE otherwise.
 */
boolean_t
dhcpol_parse_vendor(dhcpol_t * vendor, dhcpol_t * options,
		    unsigned char * err)
{
    dhcpol_t		extra;
    boolean_t		ret = FALSE;
    int 		start = 0;

    if (err)
	err[0] = '\0';

    dhcpol_init(vendor);
    dhcpol_init(&extra);

    for (;;) {
	void *		data;
	int		len;

	data = dhcpol_find(options, dhcptag_vendor_specific_e, &len, &start);
	if (data == NULL) {
	    break; /* out of for */
	}

	if (dhcpol_parse_buffer(&extra, data, len, err) == FALSE) {
	    goto failed;
	}

	if (dhcpol_concat(vendor, &extra) == FALSE) {
	    if (err)
		sprintf(err, "dhcpol_concat() failed at %d\n", start);
	    goto failed;
	}
	dhcpol_free(&extra);
	ret = TRUE;
    }
    if (ret == FALSE) {
	if (err)
	    strcpy(err, "missing vendor specific options");
    }
    return (ret);

 failed:
    dhcpol_free(vendor);
    dhcpol_free(&extra);
    return (FALSE);
}
Esempio n. 4
0
File: bsdplib.c Progetto: 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;
}
Esempio n. 5
0
/*
 * Function: dhcpol_parse_buffer
 *
 * Purpose:
 *   Parse the given buffer into DHCP options, returning the
 *   list of option pointers in the given dhcpol_t.
 *   Parsing continues until we hit the end of the buffer or
 *   the end tag.
 */
boolean_t
dhcpol_parse_buffer(dhcpol_t * list, void * buffer, int length,
		    unsigned char * err)
{
    int			len;
    unsigned char *	scan;
    unsigned char	tag;

    if (err)
	err[0] = '\0';

    dhcpol_init(list);

    len = length;
    tag = dhcptag_pad_e;
    for (scan = (unsigned char *)buffer; tag != dhcptag_end_e && len > 0; ) {

	tag = scan[DHCP_TAG_OFFSET];

	switch (tag) {
	  case dhcptag_end_e:
	      dhcpol_add(list, scan); /* remember that it was terminated */
	      scan++;
	      len--;
	      break;
	  case dhcptag_pad_e: /* ignore pad */
	      scan++;
	      len--;
	      break;
	  default: {
	      unsigned char	option_len = scan[DHCP_LEN_OFFSET];
	    
	      dhcpol_add(list, scan);
	      len -= (option_len + 2);
	      scan += (option_len + 2);
	      break;
	  }
	}
    }
    if (len < 0) {
	/* ran off the end */
	if (err)
	    sprintf(err, "parse failed near tag %d", tag);
	dhcpol_free(list);
	return (FALSE);
    }
    return (TRUE);
}
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;
}