Commit 0039920a authored by Simon Kelley's avatar Simon Kelley

Severely fix code formating of contrib/lease-tools/dhcp_release6.c

parent 39d8550a
...@@ -46,7 +46,8 @@ typedef unsigned char u8; ...@@ -46,7 +46,8 @@ typedef unsigned char u8;
typedef unsigned short u16; typedef unsigned short u16;
typedef unsigned int u32; typedef unsigned int u32;
enum DHCP6_TYPES{ enum DHCP6_TYPES
{
SOLICIT = 1, SOLICIT = 1,
ADVERTISE = 2, ADVERTISE = 2,
REQUEST = 3, REQUEST = 3,
...@@ -61,8 +62,10 @@ enum DHCP6_TYPES{ ...@@ -61,8 +62,10 @@ enum DHCP6_TYPES{
RELAY_FORW = 12, RELAY_FORW = 12,
RELAY_REPL = 13 RELAY_REPL = 13
}; };
enum DHCP6_OPTIONS{
enum DHCP6_OPTIONS
{
CLIENTID = 1, CLIENTID = 1,
SERVERID = 2, SERVERID = 2,
IA_NA = 3, IA_NA = 3,
...@@ -82,25 +85,27 @@ enum DHCP6_OPTIONS{ ...@@ -82,25 +85,27 @@ enum DHCP6_OPTIONS{
INTERFACE_ID = 18, INTERFACE_ID = 18,
RECONF_MSG = 19, RECONF_MSG = 19,
RECONF_ACCEPT = 20, RECONF_ACCEPT = 20,
}; };
enum DHCP6_STATUSES{ enum DHCP6_STATUSES
{
SUCCESS = 0, SUCCESS = 0,
UNSPEC_FAIL = 1, UNSPEC_FAIL = 1,
NOADDR_AVAIL=2, NOADDR_AVAIL=2,
NO_BINDING = 3, NO_BINDING = 3,
NOT_ON_LINK = 4, NOT_ON_LINK = 4,
USE_MULTICAST =5 USE_MULTICAST =5
}; };
static struct option longopts[] = { static struct option longopts[] = {
{"ip", required_argument, 0, 'a'}, {"ip", required_argument, 0, 'a' },
{"server-id", required_argument, 0, 's'}, {"server-id", required_argument, 0, 's' },
{"client-id", required_argument, 0, 'c'}, {"client-id", required_argument, 0, 'c' },
{"iface", required_argument, 0, 'n'}, {"iface", required_argument, 0, 'n' },
{"iaid", required_argument, 0, 'i'}, {"iaid", required_argument, 0, 'i' },
{"dry-run", no_argument, 0, 'd'}, {"dry-run", no_argument, 0, 'd' },
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h' },
{0, 0, 0, 0} {0, 0, 0, 0 }
}; };
const short DHCP6_CLIENT_PORT = 546; const short DHCP6_CLIENT_PORT = 546;
...@@ -108,207 +113,227 @@ const short DHCP6_SERVER_PORT = 547; ...@@ -108,207 +113,227 @@ const short DHCP6_SERVER_PORT = 547;
const char* DHCP6_MULTICAST_ADDRESS = "ff02::1:2"; const char* DHCP6_MULTICAST_ADDRESS = "ff02::1:2";
struct dhcp6_option{ struct dhcp6_option {
uint16_t type; uint16_t type;
uint16_t len; uint16_t len;
char value[1024]; char value[1024];
}; };
struct dhcp6_iaaddr_option{ struct dhcp6_iaaddr_option {
uint16_t type; uint16_t type;
uint16_t len; uint16_t len;
struct in6_addr ip; struct in6_addr ip;
uint32_t preferred_lifetime; uint32_t preferred_lifetime;
uint32_t valid_lifetime; uint32_t valid_lifetime;
}; };
struct dhcp6_iana_option{ struct dhcp6_iana_option {
uint16_t type; uint16_t type;
uint16_t len; uint16_t len;
uint32_t iaid; uint32_t iaid;
uint32_t t1; uint32_t t1;
uint32_t t2; uint32_t t2;
char options[1024]; char options[1024];
}; };
struct dhcp6_packet{ struct dhcp6_packet {
size_t len; size_t len;
char buf[2048]; char buf[2048];
};
} ;
size_t pack_duid(const char* str, char* dst){ size_t pack_duid(const char* str, char* dst)
{
char* tmp = strdup(str); char* tmp = strdup(str);
char* tmp_to_free = tmp; char* tmp_to_free = tmp;
char *ptr; char *ptr;
uint8_t write_pos = 0; uint8_t write_pos = 0;
while ((ptr = strtok (tmp, ":"))) { while ((ptr = strtok (tmp, ":")))
dst[write_pos] = (uint8_t) strtol(ptr, NULL, 16); {
write_pos += 1; dst[write_pos] = (uint8_t) strtol(ptr, NULL, 16);
tmp = NULL; write_pos += 1;
tmp = NULL;
} }
free(tmp_to_free);
return write_pos; free(tmp_to_free);
return write_pos;
} }
struct dhcp6_option create_client_id_option(const char* duid){ struct dhcp6_option create_client_id_option(const char* duid)
struct dhcp6_option option; {
option.type = htons(CLIENTID); struct dhcp6_option option;
bzero(option.value, sizeof(option.value)); option.type = htons(CLIENTID);
option.len = htons(pack_duid(duid, option.value)); bzero(option.value, sizeof(option.value));
return option; option.len = htons(pack_duid(duid, option.value));
return option;
} }
struct dhcp6_option create_server_id_option(const char* duid){ struct dhcp6_option create_server_id_option(const char* duid)
struct dhcp6_option option; {
option.type = htons(SERVERID); struct dhcp6_option option;
bzero(option.value, sizeof(option.value)); option.type = htons(SERVERID);
option.len = htons(pack_duid(duid, option.value)); bzero(option.value, sizeof(option.value));
return option; option.len = htons(pack_duid(duid, option.value));
return option;
} }
struct dhcp6_iaaddr_option create_iaadr_option(const char* ip){ struct dhcp6_iaaddr_option create_iaadr_option(const char* ip)
struct dhcp6_iaaddr_option result; {
result.type =htons(IAADDR); struct dhcp6_iaaddr_option result;
/* no suboptions needed here, so length is 24 */ result.type =htons(IAADDR);
result.len = htons(24); /* no suboptions needed here, so length is 24 */
result.preferred_lifetime = 0; result.len = htons(24);
result.valid_lifetime = 0; result.preferred_lifetime = 0;
int s = inet_pton(AF_INET6, ip, &(result.ip)); result.valid_lifetime = 0;
if (s <= 0) { int s = inet_pton(AF_INET6, ip, &(result.ip));
if (s == 0) if (s <= 0) {
fprintf(stderr, "Not in presentation format"); if (s == 0)
else fprintf(stderr, "Not in presentation format");
perror("inet_pton"); else
exit(EXIT_FAILURE); perror("inet_pton");
} exit(EXIT_FAILURE);
return result; }
return result;
} }
struct dhcp6_iana_option create_iana_option(const char * iaid, struct dhcp6_iaaddr_option ia_addr){
struct dhcp6_iana_option result; struct dhcp6_iana_option create_iana_option(const char * iaid, struct dhcp6_iaaddr_option ia_addr)
result.type = htons(IA_NA); {
result.iaid = htonl(atoi(iaid)); struct dhcp6_iana_option result;
result.t1 = 0; result.type = htons(IA_NA);
result.t2 = 0; result.iaid = htonl(atoi(iaid));
result.len = htons(12 + ntohs(ia_addr.len) + 2 * sizeof(uint16_t)); result.t1 = 0;
memcpy(result.options, &ia_addr, ntohs(ia_addr.len) + 2 * sizeof(uint16_t)); result.t2 = 0;
return result; result.len = htons(12 + ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
memcpy(result.options, &ia_addr, ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
return result;
} }
struct dhcp6_packet create_release_packet(const char* iaid, const char* ip, const char* client_id, const char* server_id){ struct dhcp6_packet create_release_packet(const char* iaid, const char* ip, const char* client_id, const char* server_id)
struct dhcp6_packet result; {
bzero(result.buf, sizeof(result.buf)); struct dhcp6_packet result;
/* message_type */ bzero(result.buf, sizeof(result.buf));
result.buf[0] = RELEASE; /* message_type */
/* tx_id */ result.buf[0] = RELEASE;
bzero(result.buf+1, 3); /* tx_id */
bzero(result.buf+1, 3);
struct dhcp6_option client_option = create_client_id_option(client_id);
struct dhcp6_option server_option = create_server_id_option(server_id); struct dhcp6_option client_option = create_client_id_option(client_id);
struct dhcp6_iaaddr_option iaaddr_option = create_iaadr_option(ip); struct dhcp6_option server_option = create_server_id_option(server_id);
struct dhcp6_iana_option iana_option = create_iana_option(iaid, iaaddr_option); struct dhcp6_iaaddr_option iaaddr_option = create_iaadr_option(ip);
int offset = 4; struct dhcp6_iana_option iana_option = create_iana_option(iaid, iaaddr_option);
memcpy(result.buf + offset, &client_option, ntohs(client_option.len) + 2*sizeof(uint16_t)); int offset = 4;
offset += (ntohs(client_option.len)+ 2 *sizeof(uint16_t) ); memcpy(result.buf + offset, &client_option, ntohs(client_option.len) + 2*sizeof(uint16_t));
memcpy(result.buf + offset, &server_option, ntohs(server_option.len) + 2*sizeof(uint16_t) ); offset += (ntohs(client_option.len)+ 2 *sizeof(uint16_t) );
offset += (ntohs(server_option.len)+ 2* sizeof(uint16_t)); memcpy(result.buf + offset, &server_option, ntohs(server_option.len) + 2*sizeof(uint16_t) );
memcpy(result.buf + offset, &iana_option, ntohs(iana_option.len) + 2*sizeof(uint16_t) ); offset += (ntohs(server_option.len)+ 2* sizeof(uint16_t));
offset += (ntohs(iana_option.len)+ 2* sizeof(uint16_t)); memcpy(result.buf + offset, &iana_option, ntohs(iana_option.len) + 2*sizeof(uint16_t) );
result.len = offset; offset += (ntohs(iana_option.len)+ 2* sizeof(uint16_t));
return result; result.len = offset;
return result;
} }
uint16_t parse_iana_suboption(char* buf, size_t len){ uint16_t parse_iana_suboption(char* buf, size_t len)
size_t current_pos = 0; {
char option_value[1024]; size_t current_pos = 0;
while (current_pos < len) { char option_value[1024];
uint16_t option_type, option_len; while (current_pos < len)
memcpy(&option_type,buf + current_pos, sizeof(uint16_t)); {
memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t)); uint16_t option_type, option_len;
option_type = ntohs(option_type); memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
option_len = ntohs(option_len); memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
current_pos += 2 * sizeof(uint16_t); option_type = ntohs(option_type);
if (option_type == STATUS_CODE){ option_len = ntohs(option_len);
uint16_t status; current_pos += 2 * sizeof(uint16_t);
memcpy(&status, buf + current_pos, sizeof(uint16_t)); if (option_type == STATUS_CODE)
status = ntohs(status); {
if (status != SUCCESS){ uint16_t status;
memcpy(option_value, buf + current_pos + sizeof(uint16_t) , option_len - sizeof(uint16_t)); memcpy(&status, buf + current_pos, sizeof(uint16_t));
option_value[option_len-sizeof(uint16_t)] ='\0'; status = ntohs(status);
fprintf(stderr, "Error: %s\n", option_value); if (status != SUCCESS)
{
memcpy(option_value, buf + current_pos + sizeof(uint16_t) , option_len - sizeof(uint16_t));
option_value[option_len-sizeof(uint16_t)] ='\0';
fprintf(stderr, "Error: %s\n", option_value);
} }
return status; return status;
} }
} }
return -2;
return -2;
} }
int16_t parse_packet(char* buf, size_t len){ int16_t parse_packet(char* buf, size_t len)
uint8_t type = buf[0]; {
/*skipping tx id. you need it, uncomment following line uint8_t type = buf[0];
uint16_t tx_id = ntohs((buf[1] <<16) + (buf[2] <<8) + buf[3]); /*skipping tx id. you need it, uncomment following line
*/ uint16_t tx_id = ntohs((buf[1] <<16) + (buf[2] <<8) + buf[3]);
size_t current_pos = 4; */
if (type != REPLY ){ size_t current_pos = 4;
return NOT_REPLY_CODE; if (type != REPLY )
} return NOT_REPLY_CODE;
char option_value[1024];
while (current_pos < len) { char option_value[1024];
uint16_t option_type, option_len; while (current_pos < len)
memcpy(&option_type,buf + current_pos, sizeof(uint16_t)); {
memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t)); uint16_t option_type, option_len;
option_type = ntohs(option_type); memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
option_len = ntohs(option_len); memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
current_pos += 2 * sizeof(uint16_t); option_type = ntohs(option_type);
if (option_type == STATUS_CODE){ option_len = ntohs(option_len);
uint16_t status; current_pos += 2 * sizeof(uint16_t);
memcpy(&status, buf + current_pos, sizeof(uint16_t)); if (option_type == STATUS_CODE)
status = ntohs(status); {
if (status != SUCCESS){ uint16_t status;
memcpy(option_value, buf + current_pos +sizeof(uint16_t) , option_len -sizeof(uint16_t)); memcpy(&status, buf + current_pos, sizeof(uint16_t));
fprintf(stderr, "Error: %d %s\n", status, option_value); status = ntohs(status);
return status; if (status != SUCCESS)
} {
memcpy(option_value, buf + current_pos +sizeof(uint16_t) , option_len -sizeof(uint16_t));
fprintf(stderr, "Error: %d %s\n", status, option_value);
return status;
}
} }
if (option_type == IA_NA ){
uint16_t result = parse_iana_suboption(buf + current_pos +24, option_len -24);
if (result){
return result;
}
}
current_pos += option_len;
if (option_type == IA_NA )
{
uint16_t result = parse_iana_suboption(buf + current_pos +24, option_len -24);
if (result)
return result;
}
current_pos += option_len;
} }
return -1;
return -1;
} }
void usage(const char* arg, FILE* stream){ void usage(const char* arg, FILE* stream)
const char* usage_string ="--ip IPv6 --iface IFACE --server-id SERVER_ID --client-id CLIENT_ID --iaid IAID [--dry-run] | --help"; {
fprintf (stream, "Usage: %s %s\n", arg, usage_string); const char* usage_string ="--ip IPv6 --iface IFACE --server-id SERVER_ID --client-id CLIENT_ID --iaid IAID [--dry-run] | --help";
fprintf (stream, "Usage: %s %s\n", arg, usage_string);
} }
int send_release_packet(const char* iface, struct dhcp6_packet* packet){ int send_release_packet(const char* iface, struct dhcp6_packet* packet)
{
struct sockaddr_in6 server_addr, client_addr; struct sockaddr_in6 server_addr, client_addr;
char response[1400]; char response[1400];
int sock = socket(PF_INET6, SOCK_DGRAM, 0); int sock = socket(PF_INET6, SOCK_DGRAM, 0);
int i = 0; int i = 0;
if (sock < 0) { if (sock < 0)
perror("creating socket"); {
return -1; perror("creating socket");
return -1;
} }
if (setsockopt(sock, SOL_SOCKET, 25, iface, strlen(iface)) == -1) {
if (setsockopt(sock, SOL_SOCKET, 25, iface, strlen(iface)) == -1)
{
perror("SO_BINDTODEVICE"); perror("SO_BINDTODEVICE");
close(sock); close(sock);
return -1; return -1;
} }
memset(&server_addr, 0, sizeof(server_addr)); memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin6_family = AF_INET6; server_addr.sin6_family = AF_INET6;
client_addr.sin6_family = AF_INET6; client_addr.sin6_family = AF_INET6;
...@@ -320,126 +345,149 @@ int send_release_packet(const char* iface, struct dhcp6_packet* packet){ ...@@ -320,126 +345,149 @@ int send_release_packet(const char* iface, struct dhcp6_packet* packet){
inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr); inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr);
server_addr.sin6_port = htons(DHCP6_SERVER_PORT); server_addr.sin6_port = htons(DHCP6_SERVER_PORT);
int16_t recv_size = 0; int16_t recv_size = 0;
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++)
if (sendto(sock, packet->buf, packet->len, 0, {
(struct sockaddr *)&server_addr, if (sendto(sock, packet->buf, packet->len, 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
sizeof(server_addr)) < 0) { {
perror("sendto failed"); perror("sendto failed");
exit(4); exit(4);
} }
recv_size = recvfrom(sock, response, sizeof(response), MSG_DONTWAIT, NULL, 0); recv_size = recvfrom(sock, response, sizeof(response), MSG_DONTWAIT, NULL, 0);
if (recv_size == -1){ if (recv_size == -1)
if (errno == EAGAIN){ {
sleep(1); if (errno == EAGAIN)
continue; {
}else { sleep(1);
continue;
}
else
{
perror("recvfrom"); perror("recvfrom");
} }
} }
int16_t result = parse_packet(response, recv_size); int16_t result = parse_packet(response, recv_size);
if (result == NOT_REPLY_CODE){ if (result == NOT_REPLY_CODE)
{
sleep(1); sleep(1);
continue; continue;
} }
return result; return result;
} }
fprintf(stderr, "Response timed out\n");
return -1;
fprintf(stderr, "Response timed out\n");
return -1;
} }
int main(int argc, char * const argv[]) { int main(int argc, char * const argv[])
const char* UNINITIALIZED = ""; {
const char* iface = UNINITIALIZED; const char* UNINITIALIZED = "";
const char* ip = UNINITIALIZED; const char* iface = UNINITIALIZED;
const char* client_id = UNINITIALIZED; const char* ip = UNINITIALIZED;
const char* server_id = UNINITIALIZED; const char* client_id = UNINITIALIZED;
const char* iaid = UNINITIALIZED; const char* server_id = UNINITIALIZED;
int dry_run = 0; const char* iaid = UNINITIALIZED;
while (1) { int dry_run = 0;
int option_index = 0; while (1)
int c = getopt_long(argc, argv, "a:s:c:n:i:hd", longopts, &option_index); {
if (c == -1){ int option_index = 0;
break; int c = getopt_long(argc, argv, "a:s:c:n:i:hd", longopts, &option_index);
} if (c == -1)
switch(c){ break;
case 0:
if (longopts[option_index].flag !=0){
break;
}
printf ("option %s", longopts[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 'i':
iaid = optarg;
break;
case 'n':
iface = optarg;
break;
case 'a':
ip = optarg;
break;
case 'c':
client_id = optarg;
break;
case 'd':
dry_run = 1;
break;
case 's':
server_id = optarg;
break;
case 'h':
usage(argv[0], stdout);
return 0;
case '?':
usage(argv[0], stderr);
return -1;
default:
abort();
}
switch(c)
{
case 0:
if (longopts[option_index].flag !=0)
break;
printf ("option %s", longopts[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 'i':
iaid = optarg;
break;
case 'n':
iface = optarg;
break;
case 'a':
ip = optarg;
break;
case 'c':
client_id = optarg;
break;
case 'd':
dry_run = 1;
break;
case 's':
server_id = optarg;
break;
case 'h':
usage(argv[0], stdout);
return 0;
case '?':
usage(argv[0], stderr);
return -1;
default:
abort();
}
} }
if (iaid == UNINITIALIZED){
fprintf(stderr, "Missing required iaid parameter\n"); if (iaid == UNINITIALIZED)
usage(argv[0], stderr); {
return -1; fprintf(stderr, "Missing required iaid parameter\n");
usage(argv[0], stderr);
return -1;
} }
if (server_id == UNINITIALIZED){
if (server_id == UNINITIALIZED)
{
fprintf(stderr, "Missing required server-id parameter\n"); fprintf(stderr, "Missing required server-id parameter\n");
usage(argv[0], stderr); usage(argv[0], stderr);
return -1; return -1;
} }
if (client_id == UNINITIALIZED){
if (client_id == UNINITIALIZED)
{
fprintf(stderr, "Missing required client-id parameter\n"); fprintf(stderr, "Missing required client-id parameter\n");
usage(argv[0], stderr); usage(argv[0], stderr);
return -1; return -1;
} }
if (ip == UNINITIALIZED){
if (ip == UNINITIALIZED)
{
fprintf(stderr, "Missing required ip parameter\n"); fprintf(stderr, "Missing required ip parameter\n");
usage(argv[0], stderr); usage(argv[0], stderr);
return -1; return -1;
} }
if (iface == UNINITIALIZED){
fprintf(stderr, "Missing required iface parameter\n"); if (iface == UNINITIALIZED)
{
fprintf(stderr, "Missing required iface parameter\n");
usage(argv[0], stderr); usage(argv[0], stderr);
return -1; return -1;
} }
struct dhcp6_packet packet = create_release_packet(iaid, ip, client_id, server_id); struct dhcp6_packet packet = create_release_packet(iaid, ip, client_id, server_id);
if (dry_run){
if (dry_run)
{
uint16_t i; uint16_t i;
for(i=0;i<packet.len;i++){
printf("%hhx", packet.buf[i]); for(i=0; i<packet.len; i++)
} printf("%hhx", packet.buf[i]);
printf("\n"); printf("\n");
return 0; return 0;
} }
return send_release_packet(iface, &packet); return send_release_packet(iface, &packet);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment