From 0ce7725e1ce38e95260696fd94feb958b0e8abd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 12 Dec 2006 01:16:28 +0000 Subject: [PATCH] * An interface can now also be configured to be "auto config" (which means DHCP for now). * Some minor cleanup in the DHCP client. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19465 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/net/DHCPClient.cpp | 166 +++++++++++++++++---------------- src/servers/net/DHCPClient.h | 3 + src/servers/net/NetServer.cpp | 111 +++++++++++----------- 3 files changed, 150 insertions(+), 130 deletions(-) diff --git a/src/servers/net/DHCPClient.cpp b/src/servers/net/DHCPClient.cpp index 6182a57f70..a7c5cf7ba6 100644 --- a/src/servers/net/DHCPClient.cpp +++ b/src/servers/net/DHCPClient.cpp @@ -296,16 +296,13 @@ DHCPClient::DHCPClient(BMessenger target, const char* device) { fTransactionID = system_time(); - dhcp_message discover(DHCP_DISCOVER); - discover.opcode = BOOT_REQUEST; - discover.hardware_type = ARP_HARDWARE_TYPE_ETHER; - discover.hardware_address_length = 6; - discover.transaction_id = htonl(fTransactionID); - discover.seconds_since_boot = htons(max_c(system_time() / 1000000LL, 65535)); - fStatus = get_mac_address(device, discover.mac_address); + fStatus = get_mac_address(device, fMAC); if (fStatus < B_OK) return; + dhcp_message discover(DHCP_DISCOVER); + _PrepareMessage(discover); + int socket = ::socket(AF_INET, SOCK_DGRAM, 0); if (socket < 0) { fStatus = errno; @@ -418,48 +415,7 @@ DHCPClient::DHCPClient(BMessenger target, const char* device) BMessage address; address.AddString("family", "inet"); address.AddString("address", _ToString(fAssignedAddress)); - - dhcp_option_cookie cookie; - message_option option; - const uint8 *data; - size_t size; - while (message->NextOption(cookie, option, data, size)) { - // iterate through all options - switch (option) { - case OPTION_ROUTER_ADDRESS: - address.AddString("gateway", _ToString(data)); - break; - case OPTION_SUBNET_MASK: - address.AddString("mask", _ToString(data)); - break; - case OPTION_DOMAIN_NAME_SERVER: - // TODO: for now, write it out to /etc/resolv.conf - for (uint32 i = 0; i < size / 4; i++) { - printf("DNS: %s\n", _ToString(&data[i*4]).String()); - } - break; - case OPTION_SERVER_ADDRESS: - fServer.sin_addr.s_addr = *(in_addr_t*)data; - break; - case OPTION_ADDRESS_LEASE_TIME: - printf("lease time of %lu seconds\n", htonl(*(uint32*)data)); - break; - - case OPTION_HOST_NAME: - char name[256]; - memcpy(name, data, size); - name[size] = '\0'; - printf("DHCP host name: \"%s\"\n", name); - break; - - case OPTION_MESSAGE_TYPE: - break; - - default: - printf("unknown option %lu\n", (uint32)option); - break; - } - } + _ParseOptions(*message, address); configure.AddMessage("address", &address); @@ -472,24 +428,9 @@ DHCPClient::DHCPClient(BMessenger target, const char* device) && status == B_OK) { // configuration succeeded, request it from the server _ResetTimeout(socket); + state = REQUESTING; - - request.opcode = BOOT_REQUEST; - request.hardware_type = ARP_HARDWARE_TYPE_ETHER; - request.hardware_address_length = 6; - request.transaction_id = htonl(fTransactionID); - request.seconds_since_boot = htons(max_c(system_time() / 1000000LL, 65535)); - memcpy(request.mac_address, discover.mac_address, 6); - - // add server identifier option - uint8* next = request.options; - next = request.PutOption(next, OPTION_MESSAGE_TYPE, (uint8)DHCP_REQUEST); - next = request.PutOption(next, OPTION_MESSAGE_SIZE, - (uint16)sizeof(dhcp_message)); - next = request.PutOption(next, OPTION_SERVER_ADDRESS, - (uint32)fServer.sin_addr.s_addr); - next = request.PutOption(next, OPTION_REQUEST_IP_ADDRESS, fAssignedAddress); - next = request.PutOption(next, OPTION_END); + _PrepareMessage(request); fStatus = _SendMessage(socket, request, broadcast); // we're sending a broadcast so that all offers get an answer @@ -533,24 +474,93 @@ DHCPClient::~DHCPClient() // release lease dhcp_message release(DHCP_RELEASE); - release.opcode = BOOT_REQUEST; - release.hardware_type = ARP_HARDWARE_TYPE_ETHER; - release.hardware_address_length = 6; - release.transaction_id = htonl(fTransactionID); - release.seconds_since_boot = htons(max_c(system_time() / 1000000LL, 65535)); - get_mac_address(fDevice.String(), release.mac_address); - - // add server identifier option - uint8* next = const_cast(release.LastOption()); - next = release.PutOption(next, OPTION_SERVER_ADDRESS, (uint32)fServer.sin_addr.s_addr); - next = release.PutOption(next, OPTION_REQUEST_IP_ADDRESS, fAssignedAddress); - next = release.PutOption(next, OPTION_END); + _PrepareMessage(release); _SendMessage(socket, release, fServer); close(socket); } +void +DHCPClient::_ParseOptions(dhcp_message& message, BMessage& address) +{ + dhcp_option_cookie cookie; + message_option option; + const uint8 *data; + size_t size; + while (message.NextOption(cookie, option, data, size)) { + // iterate through all options + switch (option) { + case OPTION_ROUTER_ADDRESS: + address.AddString("gateway", _ToString(data)); + break; + case OPTION_SUBNET_MASK: + address.AddString("mask", _ToString(data)); + break; + case OPTION_DOMAIN_NAME_SERVER: + // TODO: for now, write it out to /etc/resolv.conf + for (uint32 i = 0; i < size / 4; i++) { + printf("DNS: %s\n", _ToString(&data[i*4]).String()); + } + break; + case OPTION_SERVER_ADDRESS: + fServer.sin_addr.s_addr = *(in_addr_t*)data; + break; + case OPTION_ADDRESS_LEASE_TIME: + printf("lease time of %lu seconds\n", htonl(*(uint32*)data)); + break; + + case OPTION_HOST_NAME: + char name[256]; + memcpy(name, data, size); + name[size] = '\0'; + printf("DHCP host name: \"%s\"\n", name); + break; + + case OPTION_MESSAGE_TYPE: + break; + + default: + printf("unknown option %lu\n", (uint32)option); + break; + } + } +} + + +void +DHCPClient::_PrepareMessage(dhcp_message& message) +{ + message.opcode = BOOT_REQUEST; + message.hardware_type = ARP_HARDWARE_TYPE_ETHER; + message.hardware_address_length = 6; + message.transaction_id = htonl(fTransactionID); + message.seconds_since_boot = htons(max_c(system_time() / 1000000LL, 65535)); + memcpy(message.mac_address, fMAC, 6); + + switch (message.Type()) { + case DHCP_REQUEST: + case DHCP_RELEASE: + { + // add server identifier option + uint8* next = message.options; + next = message.PutOption(next, OPTION_MESSAGE_TYPE, (uint8)DHCP_REQUEST); + next = message.PutOption(next, OPTION_MESSAGE_SIZE, + (uint16)sizeof(dhcp_message)); + next = message.PutOption(next, OPTION_SERVER_ADDRESS, + (uint32)fServer.sin_addr.s_addr); + next = message.PutOption(next, OPTION_REQUEST_IP_ADDRESS, fAssignedAddress); + next = message.PutOption(next, OPTION_END); + break; + } + + default: + // the default options are fine + break; + } +} + + void DHCPClient::_ResetTimeout(int socket) { diff --git a/src/servers/net/DHCPClient.h b/src/servers/net/DHCPClient.h index d15d7e7053..e101ed9282 100644 --- a/src/servers/net/DHCPClient.h +++ b/src/servers/net/DHCPClient.h @@ -29,6 +29,8 @@ class DHCPClient : public BHandler { virtual void MessageReceived(BMessage* message); private: + void _ParseOptions(dhcp_message& message, BMessage& address); + void _PrepareMessage(dhcp_message& message); status_t _SendMessage(int socket, dhcp_message& message, sockaddr_in& address) const; void _ResetTimeout(int socket); bool _TimeoutShift(int socket); @@ -37,6 +39,7 @@ class DHCPClient : public BHandler { BString fDevice; BMessageRunner* fRunner; + uint8 fMAC[6]; uint32 fTransactionID; in_addr_t fAssignedAddress; sockaddr_in fServer; diff --git a/src/servers/net/NetServer.cpp b/src/servers/net/NetServer.cpp index ae58891b51..a96f989562 100644 --- a/src/servers/net/NetServer.cpp +++ b/src/servers/net/NetServer.cpp @@ -48,7 +48,8 @@ class NetServer : public BApplication { private: bool _TestForInterface(int socket, const char* name); - status_t _ConfigureInterface(int socket, BMessage& interface); + status_t _ConfigureInterface(int socket, BMessage& interface, + bool fromMessage = false); bool _QuitLooperForDevice(const char* device); BLooper* _LooperForDevice(const char* device); status_t _ConfigureDevice(int socket, const char* path); @@ -246,8 +247,8 @@ NetServer::MessageReceived(BMessage* message) if (socket < 0) break; - status_t status = _ConfigureInterface(socket, *message); - + status_t status = _ConfigureInterface(socket, *message, true); + BMessage reply(B_REPLY); reply.AddInt32("status", status); message->SendReply(&reply); @@ -309,7 +310,7 @@ NetServer::_TestForInterface(int socket, const char* name) status_t -NetServer::_ConfigureInterface(int socket, BMessage& interface) +NetServer::_ConfigureInterface(int socket, BMessage& interface, bool fromMessage) { const char *device; if (interface.FindString("device", &device) != B_OK) @@ -319,6 +320,8 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface) if (!prepare_request(request, device)) return B_ERROR; + bool startAutoConfig = false; + int32 flags; if (interface.FindInt32("flags", &flags) < B_OK) flags = IFF_UP; @@ -372,39 +375,59 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface) // retrieve addresses + bool autoConfig; + if (addressMessage.FindBool("auto config", &autoConfig) != B_OK) + autoConfig = false; + if (autoConfig && fromMessage) { + // we don't accept auto-config messages this way + continue; + } + bool hasAddress = false, hasMask = false, hasPeer = false, hasBroadcast = false; struct sockaddr address, mask, peer, broadcast, gateway; - const char* string; - if (addressMessage.FindString("address", &string) == B_OK - && parse_address(familyIndex, string, address)) { - hasAddress = true; - if (addressMessage.FindString("mask", &string) == B_OK - && parse_address(familyIndex, string, mask)) - hasMask = true; + if (!autoConfig) { + if (addressMessage.FindString("address", &string) == B_OK + && parse_address(familyIndex, string, address)) { + hasAddress = true; + + if (addressMessage.FindString("mask", &string) == B_OK + && parse_address(familyIndex, string, mask)) + hasMask = true; + } + if (addressMessage.FindString("peer", &string) == B_OK + && parse_address(familyIndex, string, peer)) + hasPeer = true; + if (addressMessage.FindString("broadcast", &string) == B_OK + && parse_address(familyIndex, string, broadcast)) + hasBroadcast = true; } - if (addressMessage.FindString("peer", &string) == B_OK - && parse_address(familyIndex, string, peer)) - hasPeer = true; - if (addressMessage.FindString("broadcast", &string) == B_OK - && parse_address(familyIndex, string, broadcast)) - hasBroadcast = true; - // add gateway route, if we're asked for it + route_entry route; + memset(&route, 0, sizeof(route_entry)); + route.flags = RTF_STATIC | RTF_DEFAULT; - if (addressMessage.FindString("gateway", &string) == B_OK + request.ifr_route = route; + ioctl(socket, SIOCDELRT, &request, sizeof(request)); + // Try to remove a previous default route, doesn't matter + // if it fails. + + if (autoConfig) { + // add a default route to make the interface accessible, even without an address + if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) { + fprintf(stderr, "%s: Could not add route for %s: %s\n", + Name(), device, strerror(errno)); + } else { + _QuitLooperForDevice(device); + startAutoConfig = true; + } + } else if (addressMessage.FindString("gateway", &string) == B_OK && parse_address(familyIndex, string, gateway)) { - route_entry route; - memset(&route, 0, sizeof(route_entry)); + // add gateway route, if we're asked for it route.flags = RTF_STATIC | RTF_DEFAULT | RTF_GATEWAY; route.gateway = &gateway; - request.ifr_route = route; - ioctl(socket, SIOCDELRT, &request, sizeof(request)); - // Try to remove a previous default route, doesn't matter - // if it fails. - if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) { fprintf(stderr, "%s: Could not add route for %s: %s\n", Name(), device, strerror(errno)); @@ -516,6 +539,14 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface) } } + if (startAutoConfig) { + // start auto configuration + AutoconfigLooper* looper = new AutoconfigLooper(this, device); + looper->Run(); + + fDeviceMap[device] = looper; + } + return B_OK; } @@ -550,40 +581,16 @@ NetServer::_LooperForDevice(const char* device) status_t NetServer::_ConfigureDevice(int socket, const char* path) { - _QuitLooperForDevice(path); // bring interface up, but don't configure it just yet BMessage interface; interface.AddString("device", path); BMessage address; address.AddString("family", "inet"); + address.AddBool("auto config", true); interface.AddMessage("address", &address); - status_t status = _ConfigureInterface(socket, interface); - if (status < B_OK) - return status; - - // add a default route to make the interface accessible, even without an address - route_entry route; - memset(&route, 0, sizeof(route_entry)); - route.flags = RTF_STATIC | RTF_DEFAULT; - - ifreq request; - if (!prepare_request(request, path)) - return B_ERROR; - - request.ifr_route = route; - if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) { - fprintf(stderr, "%s: Could not add route for %s: %s\n", - Name(), path, strerror(errno)); - } - - AutoconfigLooper* looper = new AutoconfigLooper(this, path); - looper->Run(); - - fDeviceMap[path] = looper; - - return B_OK; + return _ConfigureInterface(socket, interface); }