static int handle_v4_route( enum monitor_opp opp, orc_options_t * options, struct nlmsghdr * nl_msg) { int err; char buf[BUFLEN]; char intfnam[IFNAMSIZ]; l3_next_hop_id_t next_hop; u32 netmask; orc_v4_route_t entry; int success = parse_v4_route(options, nl_msg, &entry); if (success == 0) { orc_trace("Ignoring irrelevant(?) route update\n"); return 0; } else if (success == -1) { orc_warn("Error parsing v4 route update - ignoring\n"); return -1; } if (entry.gateway_valid) snprintf(buf, BUFLEN, "via gateway "IPV4_FORMAT, IPV4_ADDR_PRINT(entry.gateway)); else snprintf(buf, BUFLEN, "direct"); orc_info("%s IPv4 Route: " IPV4_FORMAT "/%d %s on intf %s (%d)\n", ((opp == OP_ADD)? "Adding" : "Deleting"), IPV4_ADDR_PRINT(entry.dst_ip), entry.dst_mask_len, buf, interface_index_to_name(entry.dst_if_index, intfnam, IFNAMSIZ), entry.dst_if_index); netmask = ~((1<<(32-entry.dst_mask_len))-1); if (next_hop_lookup( Next_Hop_DB, entry.gateway, &next_hop)) { orc_debug("Found next_hop_id=%d for gateway " IPV4_FORMAT "\n", next_hop, IPV4_ADDR_PRINT(entry.gateway)); } else next_hop = NEXT_HOP_KERNEL; /** software forward until we learn * next_hop via ARP **/ if (opp == OP_ADD) { /* Call the driver to actually add the route IF it has a gateway */ if (entry.gateway_valid) { /** even if we know the next hop, register * as pending anyway because the next hop could * expire and we need to be able to look it up for the lifetime of * the route */ if ((err = pending_next_hop_add_gateway( Next_Hop_DB, entry.gateway, entry.dst_ip, netmask)) != 0) { orc_debug("pending_next_hop_add_gateway() failed: %d\n", err); } call_add_l3_v4_route(options, entry.dst_ip, netmask, next_hop ); } else { if ((err = pending_next_hop_add_direct( Next_Hop_DB, entry.dst_ip, netmask)) != 0) { orc_debug("pending_next_hop_add_direct() failed: %d\n", err); } } } else /* opp == OP_DEL */ { if (entry.gateway_valid) { orc_debug("Calling drv->del_l3_v4_route(" IPV4_FORMAT "/" IPV4_FORMAT",next_hop=%d)\n", IPV4_ADDR_PRINT(entry.dst_ip), IPV4_ADDR_PRINT(netmask), next_hop ); /* call the driver to delete the route */ options->drv->del_l3_v4_route( entry.dst_ip, netmask, next_hop ); /* delete the pending next_hop */ if ((err = pending_next_hop_del_gateway( Next_Hop_DB, entry.gateway, entry.dst_ip, netmask)) != 0) { orc_debug("pending_next_hop_del_gateway() failed: %d\n", err); } } else { /* direct route */ if ((err = pending_next_hop_del_direct( Next_Hop_DB, entry.dst_ip, netmask)) != 0) { orc_debug("pending_next_hop_del_gateway() failed: %d\n", err); } } } return success; }
int options_parse( orc_options_t * options, char * argv[], int argc) { int c; int opt_index = 0; int done = 0; while ( !done ) { c = getopt_long(argc, argv, OPT_STRING, long_options, &opt_index); switch (c) { case 'd': options->driver = optarg; orc_log("Setting driver to \"%s\"\n", options->driver); break; case 'D': if (optarg != NULL) { int debug = atoi(optarg); if (debug >= ORC_LOG_MAX) usage("--debug: value out of range:", optarg); options->debug = atoi(optarg); } else { options->debug = ORC_LOG_DEBUG; } DEBUG_THRESHOLD = options->debug; orc_log("Setting Debug level to %s\n", orc_log_threshold()); break; case 'M': options->daemon = 1; break; case 'p': if (options->num_driver_paths >= MAX_DRIVER_PATHS) usage("Too many driver paths specified", NULL); options->driver_paths[options->num_driver_paths++] = optarg; orc_log("Adding to driver search path: \"%s\"\n", optarg); break; case 'P': options->ports_only = 1; break; case 'V': options->verbose = 1; break; case 'h': usage("Help requested", NULL); break; case 'i': if (optarg == NULL) usage("option missing interface prefix",NULL); options->ifnam_prefix = strdup(optarg); orc_info("Setting interface prefix to \"%s\"\n", options->ifnam_prefix); break; case '?': usage("Invalid option", argv[optind]); break; case -1: done = 1; break; }; } return opt_index + 1; }