1 /* 2 * Copyright 2006, 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 "Settings.h" 11 12 #include <Alert.h> 13 #include <Application.h> 14 #include <Directory.h> 15 #include <Entry.h> 16 #include <NodeMonitor.h> 17 #include <Path.h> 18 #include <TextView.h> 19 20 #include <arpa/inet.h> 21 #include <net/if.h> 22 #include <net/if_dl.h> 23 #include <net/if_types.h> 24 #include <netinet/in.h> 25 #include <sys/socket.h> 26 #include <sys/sockio.h> 27 28 #include <errno.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <unistd.h> 33 34 35 class NetServer : public BApplication { 36 public: 37 NetServer(); 38 39 virtual void AboutRequested(); 40 virtual void ReadyToRun(); 41 virtual void MessageReceived(BMessage* message); 42 43 private: 44 bool _PrepareRequest(ifreq& request, const char* name); 45 bool _TestForInterface(int socket, const char* name); 46 status_t _ConfigureInterface(int socket, BMessage& interface); 47 status_t _ConfigureDevice(int socket, const char* path); 48 void _ConfigureDevices(int socket, const char* path); 49 void _ConfigureInterfaces(int socket); 50 void _BringUpInterfaces(); 51 52 Settings fSettings; 53 }; 54 55 56 struct address_family { 57 int family; 58 const char* name; 59 const char* identifiers[4]; 60 bool (*parse_address)(const char* string, sockaddr* _address); 61 }; 62 63 // AF_INET family 64 static bool inet_parse_address(const char* string, sockaddr* address); 65 66 static const address_family kFamilies[] = { 67 { 68 AF_INET, 69 "inet", 70 {"AF_INET", "inet", "ipv4", NULL}, 71 inet_parse_address 72 }, 73 { -1, NULL, {NULL}, NULL } 74 }; 75 76 77 static bool 78 inet_parse_address(const char* string, sockaddr* _address) 79 { 80 in_addr inetAddress; 81 82 if (inet_aton(string, &inetAddress) != 1) 83 return false; 84 85 sockaddr_in& address = *(sockaddr_in *)_address; 86 address.sin_family = AF_INET; 87 address.sin_len = sizeof(struct sockaddr_in); 88 address.sin_port = 0; 89 address.sin_addr = inetAddress; 90 memset(&address.sin_zero[0], 0, sizeof(address.sin_zero)); 91 92 return true; 93 } 94 95 96 // #pragma mark - 97 98 99 static bool 100 get_family_index(const char* name, int32& familyIndex) 101 { 102 for (int32 i = 0; kFamilies[i].family >= 0; i++) { 103 for (int32 j = 0; kFamilies[i].identifiers[j]; j++) { 104 if (!strcmp(name, kFamilies[i].identifiers[j])) { 105 // found a match 106 familyIndex = i; 107 return true; 108 } 109 } 110 } 111 112 // defaults to AF_INET 113 familyIndex = 0; 114 return false; 115 } 116 117 118 static bool 119 parse_address(int32 familyIndex, const char* argument, struct sockaddr& address) 120 { 121 if (argument == NULL) 122 return false; 123 124 return kFamilies[familyIndex].parse_address(argument, &address); 125 } 126 127 128 // #pragma mark - 129 130 131 NetServer::NetServer() 132 : BApplication("application/x-vnd.haiku-net_server") 133 { 134 } 135 136 137 void 138 NetServer::AboutRequested() 139 { 140 BAlert *alert = new BAlert("about", "Networking Server\n" 141 "\tCopyright " B_UTF8_COPYRIGHT "2006, Haiku.\n", "Ok"); 142 BTextView *view = alert->TextView(); 143 BFont font; 144 145 view->SetStylable(true); 146 147 view->GetFont(&font); 148 font.SetSize(18); 149 font.SetFace(B_BOLD_FACE); 150 view->SetFontAndColor(0, 17, &font); 151 152 alert->Go(NULL); 153 } 154 155 156 void 157 NetServer::ReadyToRun() 158 { 159 fSettings.StartMonitoring(this); 160 _BringUpInterfaces(); 161 } 162 163 164 void 165 NetServer::MessageReceived(BMessage* message) 166 { 167 switch (message->what) { 168 case B_NODE_MONITOR: 169 fSettings.Update(message); 170 break; 171 172 case kMsgInterfaceSettingsUpdated: 173 { 174 // we need a socket to talk to the networking stack 175 int socket = ::socket(AF_INET, SOCK_DGRAM, 0); 176 if (socket < 0) 177 break; 178 179 _ConfigureInterfaces(socket); 180 close(socket); 181 break; 182 } 183 184 default: 185 BApplication::MessageReceived(message); 186 return; 187 } 188 } 189 190 191 bool 192 NetServer::_PrepareRequest(ifreq& request, const char* name) 193 { 194 if (strlen(name) > IF_NAMESIZE) { 195 fprintf(stderr, "%s: interface name \"%s\" is too long.\n", Name(), name); 196 return false; 197 } 198 199 strcpy(request.ifr_name, name); 200 return true; 201 } 202 203 204 bool 205 NetServer::_TestForInterface(int socket, const char* name) 206 { 207 // get a list of all interfaces 208 209 ifconf config; 210 config.ifc_len = sizeof(config.ifc_value); 211 if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0) 212 return false; 213 214 uint32 count = (uint32)config.ifc_value; 215 if (count == 0) { 216 // there are no interfaces yet 217 return false; 218 } 219 220 void *buffer = malloc(count * sizeof(struct ifreq)); 221 if (buffer == NULL) { 222 fprintf(stderr, "%s: Out of memory.\n", Name()); 223 return false; 224 } 225 226 config.ifc_len = count * sizeof(struct ifreq); 227 config.ifc_buf = buffer; 228 if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) 229 return false; 230 231 ifreq *interface = (ifreq *)buffer; 232 int32 nameLength = strlen(name); 233 bool success = false; 234 235 for (uint32 i = 0; i < count; i++) { 236 if (!strncmp(interface->ifr_name, name, nameLength)) { 237 success = true; 238 break; 239 } 240 241 interface = (ifreq *)((addr_t)interface + IF_NAMESIZE + interface->ifr_addr.sa_len); 242 } 243 244 free(buffer); 245 return success; 246 } 247 248 249 status_t 250 NetServer::_ConfigureInterface(int socket, BMessage& interface) 251 { 252 const char *device; 253 if (interface.FindString("device", &device) != B_OK) 254 return B_BAD_VALUE; 255 256 ifreq request; 257 if (!_PrepareRequest(request, device)) 258 return B_ERROR; 259 260 int32 flags; 261 if (interface.FindInt32("flags", &flags) < B_OK) 262 flags = IFF_UP; 263 264 int32 mtu; 265 if (interface.FindInt32("mtu", &mtu) < B_OK) 266 mtu = -1; 267 268 int32 metric; 269 if (interface.FindInt32("metric", &metric) < B_OK) 270 metric = -1; 271 272 BMessage addressMessage; 273 for (int32 index = 0; interface.FindMessage("address", index, &addressMessage) == B_OK; 274 index++) { 275 const char* family; 276 if (addressMessage.FindString("family", &family) < B_OK) 277 continue; 278 279 int32 familyIndex; 280 if (!get_family_index(family, familyIndex)) { 281 // we don't support this family 282 continue; 283 } 284 285 int familySocket = socket; 286 if (kFamilies[familyIndex].family != AF_INET) 287 socket = ::socket(kFamilies[familyIndex].family, SOCK_DGRAM, 0); 288 if (socket < 0) { 289 // the family is not available in this environment 290 continue; 291 } 292 293 uint32 interfaceIndex = 0; 294 if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) >= 0) 295 interfaceIndex = request.ifr_index; 296 297 if (interfaceIndex == 0) { 298 // we need to create the interface first 299 request.ifr_parameter.base_name[0] = '\0'; 300 request.ifr_parameter.device[0] = '\0'; 301 request.ifr_parameter.sub_type = 0; 302 // the default device is okay for us 303 304 if (ioctl(socket, SIOCAIFADDR, &request, sizeof(request)) < 0) { 305 fprintf(stderr, "%s: Could not add interface: %s\n", Name(), 306 strerror(errno)); 307 return errno; 308 } 309 } 310 311 // retrieve addresses 312 313 bool hasAddress = false, hasMask = false, hasPeer = false, hasBroadcast = false; 314 struct sockaddr address, mask, peer, broadcast, gateway; 315 316 const char* string; 317 if (addressMessage.FindString("address", &string) == B_OK 318 && parse_address(familyIndex, string, address)) { 319 hasAddress = true; 320 321 if (addressMessage.FindString("mask", &string) == B_OK 322 && parse_address(familyIndex, string, mask)) 323 hasMask = true; 324 } 325 if (addressMessage.FindString("peer", &string) == B_OK 326 && parse_address(familyIndex, string, peer)) 327 hasPeer = true; 328 if (addressMessage.FindString("broadcast", &string) == B_OK 329 && parse_address(familyIndex, string, broadcast)) 330 hasBroadcast = true; 331 332 // add gateway route, if we're asked for it 333 334 if (addressMessage.FindString("gateway", &string) == B_OK 335 && parse_address(familyIndex, string, gateway)) { 336 route_entry route; 337 memset(&route, 0, sizeof(route_entry)); 338 route.flags = RTF_STATIC | RTF_DEFAULT | RTF_GATEWAY; 339 route.gateway = &gateway; 340 341 request.ifr_route = route; 342 ioctl(socket, SIOCDELRT, &request, sizeof(request)); 343 // Try to remove a previous default route, doesn't matter 344 // if it fails. 345 346 if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) { 347 fprintf(stderr, "%s: Could not add route for %s: %s\n", 348 Name(), device, strerror(errno)); 349 } 350 } 351 352 // set addresses 353 354 if (hasAddress) { 355 memcpy(&request.ifr_addr, &address, address.sa_len); 356 357 if (ioctl(familySocket, SIOCSIFADDR, &request, sizeof(struct ifreq)) < 0) { 358 fprintf(stderr, "%s: Setting address failed: %s\n", Name(), strerror(errno)); 359 continue; 360 } 361 } 362 363 if (ioctl(familySocket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) < 0) { 364 fprintf(stderr, "%s: Getting flags failed: %s\n", Name(), strerror(errno)); 365 continue; 366 } 367 int32 currentFlags = request.ifr_flags; 368 369 if (!hasMask && hasAddress && kFamilies[familyIndex].family == AF_INET 370 && ioctl(familySocket, SIOCGIFNETMASK, &request, sizeof(struct ifreq)) == 0 371 && request.ifr_mask.sa_family == AF_UNSPEC) { 372 // generate standard netmask if it doesn't have one yet 373 sockaddr_in *netmask = (sockaddr_in *)&mask; 374 netmask->sin_len = sizeof(sockaddr_in); 375 netmask->sin_family = AF_INET; 376 377 // choose default netmask depending on the class of the address 378 in_addr_t net = ((sockaddr_in *)&address)->sin_addr.s_addr; 379 if (IN_CLASSA(net) 380 || (ntohl(net) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) { 381 // class A, or loopback 382 netmask->sin_addr.s_addr = IN_CLASSA_NET; 383 } if (IN_CLASSB(net)) { 384 // class B 385 netmask->sin_addr.s_addr = IN_CLASSB_NET; 386 } else { 387 // class C and rest 388 netmask->sin_addr.s_addr = IN_CLASSC_NET; 389 } 390 391 hasMask = true; 392 } 393 if (hasMask) { 394 memcpy(&request.ifr_mask, &mask, mask.sa_len); 395 396 if (ioctl(familySocket, SIOCSIFNETMASK, &request, sizeof(struct ifreq)) < 0) { 397 fprintf(stderr, "%s: Setting subnet mask failed: %s\n", Name(), strerror(errno)); 398 continue; 399 } 400 } 401 402 if (!hasBroadcast && hasAddress && (currentFlags & IFF_BROADCAST) 403 && kFamilies[familyIndex].family == AF_INET 404 && ioctl(familySocket, SIOCGIFBRDADDR, &request, sizeof(struct ifreq)) == 0 405 && request.ifr_mask.sa_family == AF_UNSPEC) { 406 // generate standard broadcast address if it doesn't have one yet 407 sockaddr_in *broadcastAddr = (sockaddr_in *)&broadcast; 408 uint32 maskValue = ((sockaddr_in *)&mask)->sin_addr.s_addr; 409 uint32 broadcastValue = ((sockaddr_in *)&address)->sin_addr.s_addr; 410 broadcastValue = (broadcastValue & maskValue) | ~maskValue; 411 broadcastAddr->sin_len = sizeof(sockaddr_in); 412 broadcastAddr->sin_family = AF_INET; 413 broadcastAddr->sin_addr.s_addr = broadcastValue; 414 hasBroadcast = true; 415 } 416 if (hasBroadcast) { 417 memcpy(&request.ifr_broadaddr, &broadcast, broadcast.sa_len); 418 419 if (ioctl(familySocket, SIOCSIFBRDADDR, &request, sizeof(struct ifreq)) < 0) { 420 fprintf(stderr, "%s: Setting broadcast address failed: %s\n", Name(), strerror(errno)); 421 continue; 422 } 423 } 424 425 if (hasPeer) { 426 memcpy(&request.ifr_dstaddr, &peer, peer.sa_len); 427 428 if (ioctl(familySocket, SIOCSIFDSTADDR, &request, sizeof(struct ifreq)) < 0) { 429 fprintf(stderr, "%s: Setting peer address failed: %s\n", Name(), strerror(errno)); 430 continue; 431 } 432 } 433 434 // set flags 435 436 if (flags != 0) { 437 request.ifr_flags = currentFlags | flags; 438 if (ioctl(familySocket, SIOCSIFFLAGS, &request, sizeof(struct ifreq)) < 0) 439 fprintf(stderr, "%s: Setting flags failed: %s\n", Name(), strerror(errno)); 440 } 441 442 // set options 443 444 if (mtu != -1) { 445 request.ifr_mtu = mtu; 446 if (ioctl(familySocket, SIOCSIFMTU, &request, sizeof(struct ifreq)) < 0) 447 fprintf(stderr, "%s: Setting MTU failed: %s\n", Name(), strerror(errno)); 448 } 449 450 if (metric != -1) { 451 request.ifr_metric = metric; 452 if (ioctl(familySocket, SIOCSIFMETRIC, &request, sizeof(struct ifreq)) < 0) 453 fprintf(stderr, "%s: Setting metric failed: %s\n", Name(), strerror(errno)); 454 } 455 } 456 457 return B_OK; 458 } 459 460 461 status_t 462 NetServer::_ConfigureDevice(int socket, const char* path) 463 { 464 BMessage interface; 465 interface.AddString("device", path); 466 467 // TODO: enable DHCP instead 468 BMessage address; 469 address.AddString("family", "inet"); 470 address.AddString("address", "192.168.0.56"); 471 address.AddString("gateway", "192.168.0.254"); 472 interface.AddMessage("address", &address); 473 474 return _ConfigureInterface(socket, interface); 475 } 476 477 478 void 479 NetServer::_ConfigureDevices(int socket, const char* startPath) 480 { 481 BDirectory directory(startPath); 482 BEntry entry; 483 while (directory.GetNextEntry(&entry) == B_OK) { 484 char name[B_FILE_NAME_LENGTH]; 485 struct stat stat; 486 BPath path; 487 if (entry.GetName(name) != B_OK 488 || !strcmp(name, "stack") 489 || entry.GetPath(&path) != B_OK 490 || entry.GetStat(&stat) != B_OK) 491 continue; 492 493 if (S_ISBLK(stat.st_mode) || S_ISCHR(stat.st_mode)) 494 _ConfigureDevice(socket, path.Path()); 495 else if (entry.IsDirectory()) 496 _ConfigureDevices(socket, path.Path()); 497 } 498 } 499 500 501 void 502 NetServer::_ConfigureInterfaces(int socket) 503 { 504 BMessage interface; 505 uint32 cookie = 0; 506 while (fSettings.GetNextInterface(cookie, interface) == B_OK) { 507 const char *device; 508 if (interface.FindString("device", &device) != B_OK) 509 continue; 510 511 if (!strncmp(device, "/dev/net/", 9)) { 512 // it's a kernel device, check if it's present 513 BEntry entry(device); 514 if (!entry.Exists()) 515 continue; 516 } 517 518 _ConfigureInterface(socket, interface); 519 } 520 } 521 522 523 void 524 NetServer::_BringUpInterfaces() 525 { 526 // we need a socket to talk to the networking stack 527 int socket = ::socket(AF_INET, SOCK_DGRAM, 0); 528 if (socket < 0) { 529 fprintf(stderr, "%s: The networking stack doesn't seem to be available.\n", 530 Name()); 531 Quit(); 532 return; 533 } 534 535 // First, we look into the settings, and try to bring everything up from there 536 537 _ConfigureInterfaces(socket); 538 539 // check configuration 540 541 if (!_TestForInterface(socket, "loop")) { 542 // there is no loopback interface, create one 543 BMessage interface; 544 interface.AddString("device", "loop"); 545 BMessage address; 546 address.AddString("family", "inet"); 547 address.AddString("address", "127.0.0.1"); 548 interface.AddMessage("address", &address); 549 550 _ConfigureInterface(socket, interface); 551 } 552 553 if (!_TestForInterface(socket, "/dev/net/")) { 554 // there is no driver configured - see if there is one and try to use it 555 _ConfigureDevices(socket, "/dev/net"); 556 } 557 558 close(socket); 559 } 560 561 562 // #pragma mark - 563 564 565 int 566 main() 567 { 568 NetServer app; 569 app.Run(); 570 571 return 0; 572 } 573 574