bool BNetworkAddress::Equals(const BNetworkAddress& other, bool includePort) const { if (IsEmpty() && other.IsEmpty()) return true; if (Family() != other.Family() || (includePort && Port() != other.Port())) { return false; } switch (fAddress.ss_family) { case AF_INET: { sockaddr_in& address = (sockaddr_in&)fAddress; sockaddr_in& otherAddress = (sockaddr_in&)other.fAddress; return memcmp(&address.sin_addr, &otherAddress.sin_addr, sizeof(address.sin_addr)) == 0; } case AF_INET6: { sockaddr_in6& address = (sockaddr_in6&)fAddress; sockaddr_in6& otherAddress = (sockaddr_in6&)other.fAddress; return memcmp(&address.sin6_addr, &otherAddress.sin6_addr, sizeof(address.sin6_addr)) == 0; } default: if (fAddress.ss_len != other.fAddress.ss_len) return false; return memcmp(&fAddress, &other.fAddress, fAddress.ss_len); } }
void configure_interface(const char* name, char* const* args, int32 argCount) { // try to parse address family int32 i = 0; int family = get_address_family(args[i]); if (family != AF_UNSPEC) i++; // try to parse address BNetworkAddress address; BNetworkAddress mask; if (parse_address(family, args[i], address)) { i++; if (parse_address(family, args[i], mask)) i++; } BNetworkInterface interface(name); if (!interface.Exists()) { // the interface does not exist yet, we have to add it first BNetworkRoster& roster = BNetworkRoster::Default(); status_t status = roster.AddInterface(interface); if (status != B_OK) { fprintf(stderr, "%s: Could not add interface: %s\n", kProgramName, strerror(status)); exit(1); } } BNetworkAddress broadcast; BNetworkAddress peer; int mtu = -1, metric = -1, media = -1; int addFlags = 0, currentFlags = 0, removeFlags = 0; bool doAutoConfig = false; // parse parameters and flags while (i < argCount) { if (!strcmp(args[i], "peer")) { if (!parse_address(family, args[i + 1], peer)) { fprintf(stderr, "%s: Option 'peer' needs valid address " "parameter\n", kProgramName); exit(1); } i++; } else if (!strcmp(args[i], "nm") || !strcmp(args[i], "netmask")) { if (!mask.IsEmpty()) { fprintf(stderr, "%s: Netmask or prefix length is specified " "twice\n", kProgramName); exit(1); } if (!parse_address(family, args[i + 1], mask)) { fprintf(stderr, "%s: Option 'netmask' needs valid address " "parameter\n", kProgramName); exit(1); } i++; } else if (!strcmp(args[i], "prefixlen") || !strcmp(args[i], "plen") || !strcmp(args[i], "prefix-length")) { if (!mask.IsEmpty()) { fprintf(stderr, "%s: Netmask or prefix length is specified " "twice\n", kProgramName); exit(1); } // default to AF_INET if no address family has been specified yet if (family == AF_UNSPEC) family = AF_INET; if (!prefix_length_to_mask(family, args[i + 1], mask)) { fprintf(stderr, "%s: Option 'prefix-length %s' is invalid for " "this address family\n", kProgramName, args[i + 1]); exit(1); } i++; } else if (!strcmp(args[i], "bc") || !strcmp(args[i], "broadcast")) { if (!broadcast.IsEmpty()) { fprintf(stderr, "%s: broadcast address is specified twice\n", kProgramName); exit(1); } if (!parse_address(family, args[i + 1], broadcast)) { fprintf(stderr, "%s: Option 'broadcast' needs valid address " "parameter\n", kProgramName); exit(1); } addFlags |= IFF_BROADCAST; i++; } else if (!strcmp(args[i], "mtu")) { mtu = args[i + 1] ? strtol(args[i + 1], NULL, 0) : 0; if (mtu <= 500) { fprintf(stderr, "%s: Option 'mtu' expected valid max transfer " "unit size\n", kProgramName); exit(1); } i++; } else if (!strcmp(args[i], "metric")) { if (i + 1 >= argCount) { fprintf(stderr, "%s: Option 'metric' expected parameter\n", kProgramName); exit(1); } metric = strtol(args[i + 1], NULL, 0); i++; } else if (!strcmp(args[i], "media")) { media = interface.Media(); if (media < 0) { fprintf(stderr, "%s: Unable to detect media type\n", kProgramName); exit(1); } if (i + 1 >= argCount) { fprintf(stderr, "%s: Option 'media' expected parameter\n", kProgramName); exit(1); } if (!media_parse_subtype(args[i + 1], IFM_TYPE(media), &media)) { fprintf(stderr, "%s: Invalid parameter for option 'media': " "'%s'\n", kProgramName, args[i + 1]); exit(1); } i++; } else if (!strcmp(args[i], "up") || !strcmp(args[i], "-down")) { addFlags |= IFF_UP; } else if (!strcmp(args[i], "down") || !strcmp(args[i], "-up")) { removeFlags |= IFF_UP; } else if (!strcmp(args[i], "bcast")) { addFlags |= IFF_BROADCAST; } else if (!strcmp(args[i], "-bcast")) { removeFlags |= IFF_BROADCAST; } else if (!strcmp(args[i], "promisc")) { addFlags |= IFF_PROMISC; } else if (!strcmp(args[i], "-promisc")) { removeFlags |= IFF_PROMISC; } else if (!strcmp(args[i], "allmulti")) { addFlags |= IFF_ALLMULTI; } else if (!strcmp(args[i], "-allmulti")) { removeFlags |= IFF_ALLMULTI; } else if (!strcmp(args[i], "loopback")) { addFlags |= IFF_LOOPBACK; } else if (!strcmp(args[i], "auto-config")) { doAutoConfig = true; } else usage(1); i++; } if ((addFlags & removeFlags) != 0) { fprintf(stderr, "%s: Contradicting flags specified\n", kProgramName); exit(1); } if (doAutoConfig && (!address.IsEmpty() || !mask.IsEmpty() || !broadcast.IsEmpty() || !peer.IsEmpty())) { fprintf(stderr, "%s: Contradicting changes specified\n", kProgramName); exit(1); } // set address/mask/broadcast/peer if (!address.IsEmpty() || !mask.IsEmpty() || !broadcast.IsEmpty()) { BNetworkInterfaceAddress interfaceAddress; interfaceAddress.SetAddress(address); interfaceAddress.SetMask(mask); if (!broadcast.IsEmpty()) interfaceAddress.SetBroadcast(broadcast); else if (!peer.IsEmpty()) interfaceAddress.SetDestination(peer); status_t status = interface.SetAddress(interfaceAddress); if (status != B_OK) { fprintf(stderr, "%s: Setting address failed: %s\n", kProgramName, strerror(status)); exit(1); } } currentFlags = interface.Flags(); // set flags if (!address.IsEmpty() || !mask.IsEmpty() || !broadcast.IsEmpty() || !peer.IsEmpty()) removeFlags = IFF_AUTO_CONFIGURED | IFF_CONFIGURING; if (addFlags || removeFlags) { status_t status = interface.SetFlags((currentFlags & ~removeFlags) | addFlags); if (status != B_OK) { fprintf(stderr, "%s: Setting flags failed: %s\n", kProgramName, strerror(status)); } } // set options if (mtu != -1) { status_t status = interface.SetMTU(mtu); if (status != B_OK) { fprintf(stderr, "%s: Setting MTU failed: %s\n", kProgramName, strerror(status)); } } if (metric != -1) { status_t status = interface.SetMetric(metric); if (status != B_OK) { fprintf(stderr, "%s: Setting metric failed: %s\n", kProgramName, strerror(status)); } } if (media != -1) { status_t status = interface.SetMedia(media); if (status != B_OK) { fprintf(stderr, "%s: Setting media failed: %s\n", kProgramName, strerror(status)); } } // start auto configuration, if asked for if (doAutoConfig) { status_t status = interface.AutoConfigure(family); if (status == B_BAD_PORT_ID) { fprintf(stderr, "%s: The net_server needs to run for the auto " "configuration!\n", kProgramName); } else if (status != B_OK) { fprintf(stderr, "%s: Auto-configuring failed: %s\n", kProgramName, strerror(status)); } } }
int main(int argc, char** argv) { if (argc > 1 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h"))) usage(0); int32 mode = RTM_LIST; if (argc > 1) { if (!strcmp(argv[1], "delete") || !strcmp(argv[1], "del") || !strcmp(argv[1], "-d")) { // delete route if (argc < 3) usage(1); mode = RTM_DELETE; } else if (!strcmp(argv[1], "add") || !strcmp(argv[1], "-a")) { // add route if (argc < 3) usage(1); mode = RTM_ADD; } else if (!strcmp(argv[1], "get")) { // get route for destination if (argc < 3) usage(1); mode = RTM_GET; } } int32 i = 2; int32 interfaceIndex = i; bool familySpecified = false; int32 familyIndex = 0; const char *interface = NULL; BNetworkAddress destination; BNetworkAddress mask; BNetworkAddress gateway; bool defaultRoute = false; route_entry route; memset(&route, 0, sizeof(route_entry)); while (i < argc && i < 5) { // try to parse address family if (i <= 3 && familySpecified == false && get_address_family(argv[i], familyIndex)) { familySpecified = true; if (i == 2) interfaceIndex = -1; } if (!strcmp(argv[i], "default")) { defaultRoute = true; route.flags = RTF_DEFAULT; i++; break; } else if (parse_address(familyIndex, argv[i], destination)) { i++; break; } i++; } if (!defaultRoute && destination.IsEmpty() && mode != RTM_LIST) usage(1); if (i == 3) interfaceIndex = -1; if (interfaceIndex != -1 && interfaceIndex < argc) interface = argv[interfaceIndex]; if (i < argc && parse_address(familyIndex, argv[i], mask)) i++; // parse options and flags while (i < argc) { if (!strcmp(argv[i], "gw") || !strcmp(argv[i], "gateway")) { if (!parse_address(familyIndex, argv[i + 1], gateway)) { fprintf(stderr, "%s: Option 'gw' needs valid address " "parameter\n", kProgramName); exit(1); } i++; } else if (!strcmp(argv[i], "nm") || !strcmp(argv[i], "netmask")) { if (!mask.IsEmpty()) { fprintf(stderr, "%s: Netmask or prefix length is specified " "twice\n", kProgramName); exit(1); } if (!parse_address(familyIndex, argv[i + 1], mask)) { fprintf(stderr, "%s: Option 'netmask' needs valid address " "parameter\n", kProgramName); exit(1); } i++; } else if (!strcmp(argv[i], "plen") || !strcmp(argv[i], "prefixlen") || !strcmp(argv[i], "prefix-length")) { if (!mask.IsEmpty()) { fprintf(stderr, "%s: Netmask or prefix length is specified " "twice\n", kProgramName); exit(1); } if (!prefix_length_to_mask(familyIndex, argv[i + 1], mask)) { fprintf(stderr, "%s: Option 'prefixlen' is invalid for this " "address family\n", kProgramName); exit(1); } i++; } else if (!strcmp(argv[i], "mtu")) { route.mtu = argv[i + 1] ? strtol(argv[i + 1], NULL, 0) : 0; if (route.mtu <= 500) { fprintf(stderr, "%s: Option 'mtu' exptected valid max transfer " "unit size\n", kProgramName); exit(1); } i++; } else if (!strcmp(argv[i], "host")) { route.flags |= RTF_HOST; } else if (!strcmp(argv[i], "local")) { route.flags |= RTF_LOCAL; } else if (!strcmp(argv[i], "reject")) { route.flags |= RTF_REJECT; } else usage(1); i++; } if (!destination.IsEmpty()) route.destination = (sockaddr*)destination; if (!mask.IsEmpty()) route.mask = (sockaddr*)mask; if (!gateway.IsEmpty()) { route.gateway = (sockaddr*)gateway; route.flags |= RTF_GATEWAY; } // we need a socket to talk to the networking stack int socket = ::socket(kFamilies[familyIndex].family, SOCK_DGRAM, 0); if (socket < 0) { fprintf(stderr, "%s: The requested address family is not available.\n", kProgramName); return 1; } switch (mode) { case RTM_ADD: if (interface == NULL) { fprintf(stderr, "%s: You need to specify an interface when " "adding a route.\n", kProgramName); usage(1); } add_route(socket, interface, route); break; case RTM_DELETE: if (interface == NULL) { fprintf(stderr, "%s: You need to specify an interface when " "removing a route.\n", kProgramName); usage(1); } delete_route(socket, interface, route); break; case RTM_LIST: if (familySpecified) list_routes(socket, interface, route); else { for (int32 i = 0; kFamilies[i].family >= 0; i++) { int socket = ::socket(kFamilies[i].family, SOCK_DGRAM, 0); if (socket < 0) continue; list_routes(socket, interface, route); close(socket); } } break; case RTM_GET: get_route(socket, route); break; } close(socket); return 0; }