static int client_message_init(sd_dhcp_client *client, DHCPMessage *message, uint8_t type, uint16_t secs, uint8_t **opt, size_t *optlen) { int r; assert(secs); r = dhcp_message_init(message, BOOTREQUEST, client->xid, type, opt, optlen); if (r < 0) return r; /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers refuse to issue an DHCP lease if 'secs' is set to zero */ message->secs = htobe16(secs); memcpy(&message->chaddr, &client->mac_addr, ETH_ALEN); if (client->state == DHCP_STATE_RENEWING || client->state == DHCP_STATE_REBINDING) message->ciaddr = client->lease->address; /* Some DHCP servers will refuse to issue an DHCP lease if the Client Identifier option is not set */ r = dhcp_option_append(opt, optlen, DHCP_OPTION_CLIENT_IDENTIFIER, ETH_ALEN, &client->mac_addr); if (r < 0) return r; if (type == DHCP_DISCOVER || type == DHCP_REQUEST) { be16_t max_size; r = dhcp_option_append(opt, optlen, DHCP_OPTION_PARAMETER_REQUEST_LIST, client->req_opts_size, client->req_opts); if (r < 0) return r; /* Some DHCP servers will send bigger DHCP packets than the defined default size unless the Maximum Messge Size option is explicitely set */ max_size = htobe16(DHCP_IP_UDP_SIZE + DHCP_MESSAGE_SIZE + DHCP_MIN_OPTIONS_SIZE); r = dhcp_option_append(opt, optlen, DHCP_OPTION_MAXIMUM_MESSAGE_SIZE, 2, &max_size); if (r < 0) return r; } return 0; }
static void test_message_init(void) { _cleanup_free_ DHCPMessage *message = NULL; size_t optlen = 4, optoffset; size_t len = sizeof(DHCPMessage) + optlen; uint8_t *magic; message = malloc0(len); assert_se(dhcp_message_init(message, BOOTREQUEST, 0x12345678, DHCP_DISCOVER, optlen, &optoffset) >= 0); assert_se(message->xid == htobe32(0x12345678)); assert_se(message->op == BOOTREQUEST); magic = (uint8_t*)&message->magic; assert_se(magic[0] == 99); assert_se(magic[1] == 130); assert_se(magic[2] == 83); assert_se(magic[3] == 99); assert_se(dhcp_option_parse(message, len, NULL, NULL) >= 0); }
static int client_message_init(sd_dhcp_client *client, DHCPMessage *message, uint8_t type, uint8_t **opt, size_t *optlen) { be16_t max_size; int r; assert(client); assert(client->secs); assert(message); assert(opt); assert(optlen); assert(type == DHCP_DISCOVER || type == DHCP_REQUEST); r = dhcp_message_init(message, BOOTREQUEST, client->xid, type, opt, optlen); if (r < 0) return r; /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers refuse to issue an DHCP lease if 'secs' is set to zero */ message->secs = htobe16(client->secs); /* RFC2132 section 4.1.1: The client MUST include its hardware address in the ’chaddr’ field, if necessary for delivery of DHCP reply messages. */ memcpy(&message->chaddr, &client->client_id.mac_addr, ETH_ALEN); /* Some DHCP servers will refuse to issue an DHCP lease if the Client Identifier option is not set */ r = dhcp_option_append(opt, optlen, DHCP_OPTION_CLIENT_IDENTIFIER, sizeof(client->client_id), &client->client_id); if (r < 0) return r; /* RFC2131 section 3.5: in its initial DHCPDISCOVER or DHCPREQUEST message, a client may provide the server with a list of specific parameters the client is interested in. If the client includes a list of parameters in a DHCPDISCOVER message, it MUST include that list in any subsequent DHCPREQUEST messages. */ r = dhcp_option_append(opt, optlen, DHCP_OPTION_PARAMETER_REQUEST_LIST, client->req_opts_size, client->req_opts); if (r < 0) return r; /* RFC2131 section 3.5: The client SHOULD include the ’maximum DHCP message size’ option to let the server know how large the server may make its DHCP messages. Note (from ConnMan): Some DHCP servers will send bigger DHCP packets than the defined default size unless the Maximum Messge Size option is explicitely set */ max_size = htobe16(DHCP_IP_UDP_SIZE + DHCP_MESSAGE_SIZE + DHCP_MIN_OPTIONS_SIZE); r = dhcp_option_append(opt, optlen, DHCP_OPTION_MAXIMUM_MESSAGE_SIZE, 2, &max_size); if (r < 0) return r; return 0; }
static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret, uint8_t type, size_t *_optlen, size_t *_optoffset) { _cleanup_free_ DHCPPacket *packet; size_t optlen, optoffset, size; be16_t max_size; int r; assert(client); assert(client->secs); assert(ret); assert(_optlen); assert(_optoffset); assert(type == DHCP_DISCOVER || type == DHCP_REQUEST); optlen = DHCP_MIN_OPTIONS_SIZE; size = sizeof(DHCPPacket) + optlen; packet = malloc0(size); if (!packet) return -ENOMEM; r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type, optlen, &optoffset); if (r < 0) return r; /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers refuse to issue an DHCP lease if 'secs' is set to zero */ packet->dhcp.secs = htobe16(client->secs); /* RFC2132 section 4.1 A client that cannot receive unicast IP datagrams until its protocol software has been configured with an IP address SHOULD set the BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or DHCPREQUEST messages that client sends. The BROADCAST bit will provide a hint to the DHCP server and BOOTP relay agent to broadcast any messages to the client on the client's subnet. */ if (client->broadcast) packet->dhcp.flags = htobe16(0x8000); /* RFC2132 section 4.1.1: The client MUST include its hardware address in the ’chaddr’ field, if necessary for delivery of DHCP reply messages. */ memcpy(&packet->dhcp.chaddr, &client->client_id.mac_addr, ETH_ALEN); /* Some DHCP servers will refuse to issue an DHCP lease if the Client Identifier option is not set */ r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0, DHCP_OPTION_CLIENT_IDENTIFIER, sizeof(client->client_id), &client->client_id); if (r < 0) return r; /* RFC2131 section 3.5: in its initial DHCPDISCOVER or DHCPREQUEST message, a client may provide the server with a list of specific parameters the client is interested in. If the client includes a list of parameters in a DHCPDISCOVER message, it MUST include that list in any subsequent DHCPREQUEST messages. */ r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0, DHCP_OPTION_PARAMETER_REQUEST_LIST, client->req_opts_size, client->req_opts); if (r < 0) return r; /* RFC2131 section 3.5: The client SHOULD include the ’maximum DHCP message size’ option to let the server know how large the server may make its DHCP messages. Note (from ConnMan): Some DHCP servers will send bigger DHCP packets than the defined default size unless the Maximum Messge Size option is explicitely set */ max_size = htobe16(size); r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0, DHCP_OPTION_MAXIMUM_MESSAGE_SIZE, 2, &max_size); if (r < 0) return r; *_optlen = optlen; *_optoffset = optoffset; *ret = packet; packet = NULL; return 0; }