1 /* 2 * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 */ 8 9 10 #include "AutoconfigLooper.h" 11 #include "DHCPClient.h" 12 #include "NetServer.h" 13 14 #include <errno.h> 15 #include <net/if_dl.h> 16 #include <net/if_types.h> 17 #include <stdio.h> 18 #include <sys/socket.h> 19 #include <sys/sockio.h> 20 21 22 static const uint32 kMsgReadyToRun = 'rdyr'; 23 24 25 AutoconfigLooper::AutoconfigLooper(BMessenger target, const char* device) 26 : BLooper(device), 27 fTarget(target), 28 fDevice(device) 29 { 30 BMessage ready(kMsgReadyToRun); 31 PostMessage(&ready); 32 } 33 34 35 AutoconfigLooper::~AutoconfigLooper() 36 { 37 } 38 39 40 void 41 AutoconfigLooper::_ReadyToRun() 42 { 43 ifreq request; 44 if (!prepare_request(request, fDevice.String())) 45 return; 46 47 // set IFF_CONFIGURING flag on interface 48 49 int socket = ::socket(AF_LINK, SOCK_DGRAM, 0); 50 if (socket < 0) 51 return; 52 53 if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) == 0) { 54 request.ifr_flags |= IFF_CONFIGURING; 55 ioctl(socket, SIOCSIFFLAGS, &request, sizeof(struct ifreq)); 56 } 57 58 close(socket); 59 60 // start with DHCP 61 62 DHCPClient* client = new DHCPClient(fTarget, fDevice.String()); 63 AddHandler(client); 64 65 if (client->Initialize() == B_OK) 66 return; 67 68 RemoveHandler(client); 69 delete client; 70 71 puts("DHCP failed miserably!"); 72 73 // DHCP obviously didn't work out, take some default values for now 74 // TODO: have a look at zeroconf 75 // TODO: this could also be done add-on based 76 77 BMessage interface(kMsgConfigureInterface); 78 interface.AddString("device", fDevice.String()); 79 interface.AddBool("auto", true); 80 81 uint8 mac[6]; 82 uint8 last = 56; 83 if (get_mac_address(fDevice.String(), mac) == B_OK) { 84 // choose IP address depending on the MAC address, if available 85 last = mac[0] ^ mac[1] ^ mac[2] ^ mac[3] ^ mac[4] ^ mac[5]; 86 if (last > 253) 87 last = 253; 88 else if (last == 0) 89 last = 1; 90 } 91 92 char string[64]; 93 // IANA defined the default autoconfig network (for when a DHCP request 94 // fails for some reason) as being 169.254.0.0/255.255.0.0. We are only 95 // generating the last octet but we could also use the 2 last octets if 96 // wanted. 97 snprintf(string, sizeof(string), "169.254.0.%u", last); 98 99 BMessage address; 100 address.AddString("family", "inet"); 101 address.AddString("address", string); 102 interface.AddMessage("address", &address); 103 104 fTarget.SendMessage(&interface); 105 } 106 107 108 void 109 AutoconfigLooper::MessageReceived(BMessage* message) 110 { 111 switch (message->what) { 112 case kMsgReadyToRun: 113 _ReadyToRun(); 114 break; 115 116 default: 117 BLooper::MessageReceived(message); 118 break; 119 } 120 } 121 122