int main(int argc, char **argv) { char *p; int c; char const *radius_dir = RADDBDIR; char const *dict_dir = DICTDIR; char const *filename = NULL; DICT_ATTR const *da; fr_debug_lvl = 0; while ((c = getopt(argc, argv, "d:D:f:hr:t:vxi:" )) != EOF) switch(c) { case 'D': dict_dir = optarg; break; case 'd': radius_dir = optarg; break; case 'f': filename = optarg; break; case 'i': iface = optarg; break; case 'r': if (!isdigit((int) *optarg)) usage(); retries = atoi(optarg); if ((retries == 0) || (retries > 1000)) usage(); break; case 't': if (!isdigit((int) *optarg)) usage(); timeout = atof(optarg); break; case 'v': printf("%s\n", dhcpclient_version); exit(0); case 'x': fr_debug_lvl++; fr_log_fp = stdout; break; case 'h': default: usage(); } argc -= (optind - 1); argv += (optind - 1); if (argc < 2) usage(); /* convert timeout to a struct timeval */ #define USEC 1000000 tv_timeout.tv_sec = timeout; tv_timeout.tv_usec = ((timeout - (float) tv_timeout.tv_sec) * USEC); if (dict_init(dict_dir, RADIUS_DICTIONARY) < 0) { fr_perror("radclient"); return 1; } if (dict_read(radius_dir, RADIUS_DICTIONARY) == -1) { fr_perror("radclient"); return 1; } fr_strerror(); /* Clear the error buffer */ /* * Ensure that dictionary.dhcp is loaded. */ da = dict_attrbyname("DHCP-Message-Type"); if (!da) { if (dict_read(dict_dir, "dictionary.dhcp") < 0) { fprintf(stderr, "Failed reading dictionary.dhcp: %s\n", fr_strerror()); return -1; } } /* * Resolve hostname. */ server_ipaddr.af = AF_INET; if (strcmp(argv[1], "-") != 0) { char const *hostname = argv[1]; char const *portname = argv[1]; char buffer[256]; if (*argv[1] == '[') { /* IPv6 URL encoded */ p = strchr(argv[1], ']'); if ((size_t) (p - argv[1]) >= sizeof(buffer)) { usage(); } memcpy(buffer, argv[1] + 1, p - argv[1] - 1); buffer[p - argv[1] - 1] = '\0'; hostname = buffer; portname = p + 1; } p = strchr(portname, ':'); if (p && (strchr(p + 1, ':') == NULL)) { *p = '\0'; portname = p + 1; } else { portname = NULL; } if (ip_hton(&server_ipaddr, AF_INET, hostname, false) < 0) { fprintf(stderr, "dhcpclient: Failed to find IP address for host %s: %s\n", hostname, fr_syserror(errno)); fr_exit_now(1); } /* * Strip port from hostname if needed. */ if (portname) server_port = atoi(portname); } /* * See what kind of request we want to send. */ if (argc >= 3) { if (!isdigit((int) argv[2][0])) { packet_code = fr_str2int(request_types, argv[2], -2); if (packet_code == -2) { fprintf(stderr, "Unknown packet type: %s\n", argv[2]); usage(); } } else { packet_code = atoi(argv[2]); } } if (server_port == 0) server_port = 67; request_init(filename); /* * No data read. Die. */ if (!request || !request->vps) { fprintf(stderr, "dhcpclient: Nothing to send.\n"); fr_exit_now(1); } /* * Sanity check. */ if (!request->code) { fprintf(stderr, "dhcpclient: Command was %s, and request did not contain DHCP-Message-Type nor Packet-Type.\n", (argc >= 3) ? "'auto'" : "unspecified"); exit(1); } if ((request->code == PW_DHCP_RELEASE) || (request->code == PW_DHCP_DECLINE)) { /* These kind of packets do not get a reply, so don't wait for one. */ reply_expected = false; } /* * Bind to the first specified IP address and port. * This means we ignore later ones. */ if (request->src_ipaddr.af == AF_UNSPEC) { memset(&client_ipaddr, 0, sizeof(client_ipaddr)); client_ipaddr.af = server_ipaddr.af; client_port = 0; } else { client_ipaddr = request->src_ipaddr; client_port = request->src_port; } /* set "raw mode" if an interface is specified and if destination IP address is the broadcast address. */ if (iface) { iface_ind = if_nametoindex(iface); if (iface_ind <= 0) { fprintf(stderr, "dhcpclient: unknown interface: %s\n", iface); fr_exit_now(1); } if (server_ipaddr.ipaddr.ip4addr.s_addr == 0xFFFFFFFF) { fprintf(stderr, "dhcpclient: Using interface: %s (index: %d) in raw packet mode\n", iface, iface_ind); raw_mode = true; } } if (request->src_ipaddr.af == AF_UNSPEC) { request->src_ipaddr = client_ipaddr; request->src_port = client_port; } if (request->dst_ipaddr.af == AF_UNSPEC) { request->dst_ipaddr = server_ipaddr; request->dst_port = server_port; } /* * Encode the packet */ if (fr_dhcp_encode(request) < 0) { fprintf(stderr, "dhcpclient: failed encoding: %s\n", fr_strerror()); fr_exit_now(1); } if (fr_debug_lvl) print_hex(request); #ifdef HAVE_LIBPCAP if (raw_mode) { send_with_pcap(); } else #endif { send_with_socket(); } if (reply && fr_debug_lvl) print_hex(reply); if (reply && fr_dhcp_decode(reply) < 0) { fprintf(stderr, "dhcpclient: failed decoding\n"); return 1; } dict_free(); if (success) return 0; return 1; }
int main(int argc, char **argv) { static uint16_t server_port = 0; static int packet_code = 0; static fr_ipaddr_t server_ipaddr; static fr_ipaddr_t client_ipaddr; int c; char const *raddb_dir = RADDBDIR; char const *dict_dir = DICTDIR; char const *filename = NULL; RADIUS_PACKET *request = NULL; RADIUS_PACKET *reply = NULL; TALLOC_CTX *autofree = talloc_autofree_context(); int ret; fr_debug_lvl = 1; fr_log_fp = stdout; while ((c = getopt(argc, argv, "d:D:f:hr:t:vxi:")) != -1) switch(c) { case 'D': dict_dir = optarg; break; case 'd': raddb_dir = optarg; break; case 'f': filename = optarg; break; case 'i': iface = optarg; break; case 'r': if (!isdigit((int) *optarg)) usage(); retries = atoi(optarg); if ((retries == 0) || (retries > 1000)) usage(); break; case 't': if (!isdigit((int) *optarg)) usage(); timeout = atof(optarg); break; case 'v': DEBUG("%s", dhcpclient_version); exit(0); case 'x': fr_debug_lvl++; break; case 'h': default: usage(); } argc -= (optind - 1); argv += (optind - 1); if (argc < 2) usage(); /* convert timeout to a struct timeval */ #define USEC 1000000 tv_timeout.tv_sec = timeout; tv_timeout.tv_usec = ((timeout - (float) tv_timeout.tv_sec) * USEC); if (fr_dict_global_init(autofree, dict_dir) < 0) { fr_perror("dhcpclient"); exit(EXIT_FAILURE); } if (fr_dict_autoload(dhcpclient_dict) < 0) { fr_perror("dhcpclient"); exit(EXIT_FAILURE); } if (fr_dict_attr_autoload(dhcpclient_dict_attr) < 0) { fr_perror("dhcpclient"); exit(EXIT_FAILURE); } if (fr_dict_read(dict_freeradius, raddb_dir, FR_DICTIONARY_FILE) == -1) { fr_perror("dhcpclient"); exit(EXIT_FAILURE); } fr_strerror(); /* Clear the error buffer */ /* * Initialise the DHCPv4 library */ fr_dhcpv4_global_init(); /* * Resolve hostname. */ server_ipaddr.af = AF_INET; if (strcmp(argv[1], "-") != 0) { if (fr_inet_pton_port(&server_ipaddr, &server_port, argv[1], strlen(argv[1]), AF_UNSPEC, true, true) < 0) { fr_perror("dhcpclient"); fr_exit_now(1); } client_ipaddr.af = server_ipaddr.af; } /* * See what kind of request we want to send. */ if (argc >= 3) { if (!isdigit((int) argv[2][0])) { packet_code = fr_str2int(request_types, argv[2], -2); if (packet_code == -2) { ERROR("Unknown packet type: %s", argv[2]); usage(); } } else { packet_code = atoi(argv[2]); } } if (!server_port) server_port = 67; /* * set "raw mode" if an interface is specified and if destination * IP address is the broadcast address. */ if (iface) { iface_ind = if_nametoindex(iface); if (iface_ind <= 0) { ERROR("Unknown interface: %s", iface); exit(EXIT_FAILURE); } if (server_ipaddr.addr.v4.s_addr == 0xFFFFFFFF) { ERROR("Using interface: %s (index: %d) in raw packet mode", iface, iface_ind); raw_mode = true; } } request = request_init(filename); if (!request || !request->vps) { ERROR("Nothing to send"); exit(EXIT_FAILURE); } /* * Set defaults if they weren't specified via pairs */ if (request->src_port == 0) request->src_port = server_port + 1; if (request->dst_port == 0) request->dst_port = server_port; if (request->src_ipaddr.af == AF_UNSPEC) request->src_ipaddr = client_ipaddr; if (request->dst_ipaddr.af == AF_UNSPEC) request->dst_ipaddr = server_ipaddr; if (!request->code) request->code = packet_code; /* * Sanity check. */ if (!request->code) { ERROR("Command was %s, and request did not contain DHCP-Message-Type nor Packet-Type", (argc >= 3) ? "'auto'" : "unspecified"); exit(EXIT_FAILURE); } /* * These kind of packets do not get a reply, so don't wait for one. */ if ((request->code == FR_DHCP_RELEASE) || (request->code == FR_DHCP_DECLINE)) { reply_expected = false; } /* * Encode the packet */ if (fr_dhcpv4_packet_encode(request) < 0) { ERROR("Failed encoding packet"); exit(EXIT_FAILURE); } /* * Decode to produce VALUE_PAIRs from the default field */ if (fr_debug_lvl) { fr_dhcpv4_packet_decode(request); dhcp_packet_debug(request, false); } #ifdef HAVE_LIBPCAP if (raw_mode) { ret = send_with_pcap(&reply, request); } else #endif { ret = send_with_socket(&reply, request); } if (reply) { if (fr_dhcpv4_packet_decode(reply) < 0) { ERROR("Failed decoding packet"); ret = -1; } dhcp_packet_debug(reply, true); } fr_dhcpv4_global_free(); fr_dict_autofree(dhcpclient_dict); return ret < 0 ? 1 : 0; }