|
@@ -36,27 +36,27 @@ struct duid {
|
|
|
unsigned char hwaddr[6];
|
|
|
};
|
|
|
|
|
|
-struct addrinfo *getaddr(int addr_fam, const char *hostname, const char *port);
|
|
|
-char *addrName(const struct sockaddr_storage *addr, char *buf, size_t bufsize);
|
|
|
+struct addrinfo* getaddr(int addr_fam, const char* hostname, const char* port);
|
|
|
+char* addrName(const struct sockaddr_storage* addr, char* buf, size_t bufsize);
|
|
|
void add_option(int v6, unsigned optnum, unsigned count,
|
|
|
- size_t size, int direct, unsigned char options[], size_t *buffer_used,
|
|
|
- ...);
|
|
|
-int get_linklocal_addr(const char if_name[], struct sockaddr_storage *addr);
|
|
|
-const char *optionName(int v6, unsigned optnum);
|
|
|
-const unsigned char *find_option(const struct dhcp_packet *pkt, int search_opt);
|
|
|
-int socket_setup(int addr_fam, const char *localAddr, const char *port,
|
|
|
- const char *type, struct sockaddr_storage *l_addr);
|
|
|
-void gen_discover(struct dhcp_packet *discover_pkt, const struct in_addr *giaddr);
|
|
|
-void gen_request(struct dhcp_packet *dhcp_pkt, const struct in_addr *giaddr,
|
|
|
- const struct in_addr *yiaddr, const unsigned char *server_id);
|
|
|
-void dhcp_recv(int v6, void *msg, int recv_fd, const struct sockaddr_storage *recv_laddr);
|
|
|
-void dora(const char *server, const char *localAddr);
|
|
|
-void sarr(const char *server, const char *if_name);
|
|
|
-void print_addrinfo(FILE *f, const struct addrinfo *addr);
|
|
|
-void print_sa6_info(FILE *f, const struct sockaddr_in6 *sa);
|
|
|
-void gen_solicit(struct dhcpv6_packet *dhcp_pkt, const struct duid *client_id);
|
|
|
-void dhcp_send(int v6, const unsigned char *msg, int send_fd, const struct
|
|
|
- sockaddr *r_addr, const struct sockaddr_storage *send_laddr);
|
|
|
+ size_t size, int direct, unsigned char options[], size_t* buffer_used,
|
|
|
+ ...);
|
|
|
+int get_linklocal_addr(const char if_name[], struct sockaddr_storage* addr);
|
|
|
+const char* optionName(int v6, unsigned optnum);
|
|
|
+const unsigned char* find_option(const struct dhcp_packet* pkt, int search_opt);
|
|
|
+int socket_setup(int addr_fam, const char* localAddr, const char* port,
|
|
|
+ const char* type, struct sockaddr_storage* l_addr);
|
|
|
+void gen_discover(struct dhcp_packet* discover_pkt, const struct in_addr* giaddr);
|
|
|
+void gen_request(struct dhcp_packet* dhcp_pkt, const struct in_addr* giaddr,
|
|
|
+ const struct in_addr* yiaddr, const unsigned char* server_id);
|
|
|
+void dhcp_recv(int v6, void* msg, int recv_fd, const struct sockaddr_storage* recv_laddr);
|
|
|
+void dora(const char* server, const char* localAddr);
|
|
|
+void sarr(const char* server, const char* if_name);
|
|
|
+void print_addrinfo(FILE* f, const struct addrinfo* addr);
|
|
|
+void print_sa6_info(FILE* f, const struct sockaddr_in6* sa);
|
|
|
+void gen_solicit(struct dhcpv6_packet* dhcp_pkt, const struct duid* client_id);
|
|
|
+void dhcp_send(int v6, const unsigned char* msg, int send_fd, const struct
|
|
|
+ sockaddr* r_addr, const struct sockaddr_storage* send_laddr);
|
|
|
|
|
|
static const struct dkdesc diagLetters[] = {
|
|
|
{ 's', DK_SOCK },
|
|
@@ -67,32 +67,35 @@ static const struct dkdesc diagLetters[] = {
|
|
|
};
|
|
|
|
|
|
int
|
|
|
-main(int argc, const char *argv[])
|
|
|
-{
|
|
|
+main(int argc, const char* argv[]) {
|
|
|
int ret;
|
|
|
int v6;
|
|
|
// int initialOnly;
|
|
|
- const char *localName = NULL;
|
|
|
+ const char* localName = NULL;
|
|
|
// unsigned rate;
|
|
|
// unsigned numRequest;
|
|
|
- const char *server;
|
|
|
- const char *diagSelector = "";
|
|
|
+ const char* server;
|
|
|
+ const char* diagSelector = "";
|
|
|
confdata_t confdata;
|
|
|
|
|
|
- if ((ret = procArgs(argc, argv, &confdata, &server)) != 1)
|
|
|
- exit(ret);
|
|
|
+ if ((ret = procArgs(argc, argv, &confdata, &server)) != 1) {
|
|
|
+ exit(ret);
|
|
|
+ }
|
|
|
|
|
|
v6 = confdata.map['6']->num > 0;
|
|
|
- if (confdata.map['l']->num > 0)
|
|
|
+ if (confdata.map['l']->num > 0) {
|
|
|
localName = confdata.map['l']->values[0]->value.string;
|
|
|
- if (confdata.map['x']->num > 0)
|
|
|
+ }
|
|
|
+ if (confdata.map['x']->num > 0) {
|
|
|
diagSelector = confdata.map['x']->values[0]->value.string;
|
|
|
+ }
|
|
|
|
|
|
srand(time(NULL));
|
|
|
- if (v6)
|
|
|
- sarr(server, localName);
|
|
|
- else
|
|
|
- dora(server, localName);
|
|
|
+ if (v6) {
|
|
|
+ sarr(server, localName);
|
|
|
+ } else {
|
|
|
+ dora(server, localName);
|
|
|
+ }
|
|
|
dk_setup(diagSelector, diagLetters);
|
|
|
|
|
|
exit(0);
|
|
@@ -116,34 +119,33 @@ main(int argc, const char *argv[])
|
|
|
* Return value: The network fd.
|
|
|
*/
|
|
|
int
|
|
|
-socket_setup(int addr_fam, const char *localAddr, const char *port,
|
|
|
- const char *type, struct sockaddr_storage *l_addr)
|
|
|
-{
|
|
|
+socket_setup(int addr_fam, const char* localAddr, const char* port,
|
|
|
+ const char* type, struct sockaddr_storage* l_addr) {
|
|
|
char addrbuf[ADDR_NAME_BUFSIZE];
|
|
|
int net_fd;
|
|
|
- struct addrinfo *addrs;
|
|
|
+ struct addrinfo* addrs;
|
|
|
|
|
|
if ((addrs = getaddr(addr_fam, localAddr, port)) == NULL) {
|
|
|
- fprintf(stderr, "No addresses for %s\n", localAddr);
|
|
|
- exit(1);
|
|
|
+ fprintf(stderr, "No addresses for %s\n", localAddr);
|
|
|
+ exit(1);
|
|
|
}
|
|
|
if (localAddr == NULL) {
|
|
|
- if (dk_set(DK_SOCK)) {
|
|
|
- fprintf(stderr, "local address:\n");
|
|
|
- print_sa6_info(stderr, (struct sockaddr_in6 *)l_addr);
|
|
|
- }
|
|
|
- memcpy(&((struct sockaddr_in6 *)addrs->ai_addr)->sin6_addr,
|
|
|
- &((struct sockaddr_in6 *)l_addr)->sin6_addr,
|
|
|
- sizeof(struct in6_addr));
|
|
|
- ((struct sockaddr_in6 *)addrs->ai_addr)->sin6_flowinfo =
|
|
|
- ((struct sockaddr_in6 *)l_addr)->sin6_flowinfo;
|
|
|
- ((struct sockaddr_in6 *)addrs->ai_addr)->sin6_scope_id =
|
|
|
- ((struct sockaddr_in6 *)l_addr)->sin6_scope_id;
|
|
|
+ if (dk_set(DK_SOCK)) {
|
|
|
+ fprintf(stderr, "local address:\n");
|
|
|
+ print_sa6_info(stderr, (struct sockaddr_in6*)l_addr);
|
|
|
+ }
|
|
|
+ memcpy(&((struct sockaddr_in6*)addrs->ai_addr)->sin6_addr,
|
|
|
+ &((struct sockaddr_in6*)l_addr)->sin6_addr,
|
|
|
+ sizeof(struct in6_addr));
|
|
|
+ ((struct sockaddr_in6*)addrs->ai_addr)->sin6_flowinfo =
|
|
|
+ ((struct sockaddr_in6*)l_addr)->sin6_flowinfo;
|
|
|
+ ((struct sockaddr_in6*)addrs->ai_addr)->sin6_scope_id =
|
|
|
+ ((struct sockaddr_in6*)l_addr)->sin6_scope_id;
|
|
|
}
|
|
|
if (dk_set(DK_SOCK)) {
|
|
|
- print_addrinfo(stderr, addrs);
|
|
|
- fprintf(stderr, "Creating socket from addrinfo:\n");
|
|
|
- print_addrinfo(stderr, addrs);
|
|
|
+ print_addrinfo(stderr, addrs);
|
|
|
+ fprintf(stderr, "Creating socket from addrinfo:\n");
|
|
|
+ print_addrinfo(stderr, addrs);
|
|
|
}
|
|
|
net_fd = socket(addrs->ai_family, addrs->ai_socktype, addrs->ai_protocol);
|
|
|
if (net_fd < 0) {
|
|
@@ -151,13 +153,13 @@ socket_setup(int addr_fam, const char *localAddr, const char *port,
|
|
|
exit(1);
|
|
|
}
|
|
|
if (bind(net_fd, addrs->ai_addr, addrs->ai_addrlen) == -1) {
|
|
|
- int s_errno = errno;
|
|
|
- fprintf(stderr, "Could not bind to %s: %s\n",
|
|
|
- addrName((struct sockaddr_storage *)addrs->ai_addr, addrbuf,
|
|
|
- sizeof(addrbuf)), strerror(s_errno));
|
|
|
- exit(1);
|
|
|
+ int s_errno = errno;
|
|
|
+ fprintf(stderr, "Could not bind to %s: %s\n",
|
|
|
+ addrName((struct sockaddr_storage*)addrs->ai_addr, addrbuf,
|
|
|
+ sizeof(addrbuf)), strerror(s_errno));
|
|
|
+ exit(1);
|
|
|
}
|
|
|
- dkprintf(DK_SOCK, "%s fd %d bound to %s\n", type, net_fd, addrName((struct sockaddr_storage *)addrs->ai_addr, addrbuf, sizeof(addrbuf)));
|
|
|
+ dkprintf(DK_SOCK, "%s fd %d bound to %s\n", type, net_fd, addrName((struct sockaddr_storage*)addrs->ai_addr, addrbuf, sizeof(addrbuf)));
|
|
|
memcpy(l_addr, addrs->ai_addr, sizeof(struct sockaddr_storage));
|
|
|
freeaddrinfo(addrs);
|
|
|
return net_fd;
|
|
@@ -173,38 +175,38 @@ socket_setup(int addr_fam, const char *localAddr, const char *port,
|
|
|
* discover_packet is a pointer to storage for the packet to be generated.
|
|
|
*/
|
|
|
void
|
|
|
-gen_discover(struct dhcp_packet *discover_pkt, const struct in_addr *giaddr)
|
|
|
-{
|
|
|
+gen_discover(struct dhcp_packet* discover_pkt, const struct in_addr* giaddr) {
|
|
|
size_t options_len;
|
|
|
|
|
|
- bzero((char *) discover_pkt, sizeof(struct dhcp_packet));
|
|
|
+ bzero((char*) discover_pkt, sizeof(struct dhcp_packet));
|
|
|
discover_pkt->op = BOOTREQUEST;
|
|
|
discover_pkt->htype = HTYPE_ETHER;
|
|
|
discover_pkt->hlen = 6;
|
|
|
discover_pkt->hops = 1;
|
|
|
- discover_pkt->xid = 0x12345678; /* transaction id - fix */
|
|
|
+ discover_pkt->xid = 0x12345678; /* transaction id - fix */
|
|
|
discover_pkt->secs = 0;
|
|
|
discover_pkt->flags = 0;
|
|
|
memcpy(&discover_pkt->giaddr, giaddr, sizeof((*discover_pkt).giaddr));
|
|
|
- strncpy((char *)discover_pkt->chaddr, "\x12\x34\x56\x78\x9a\xbc", 6); /* client hardware addr - fix */
|
|
|
+ strncpy((char*)discover_pkt->chaddr, "\x12\x34\x56\x78\x9a\xbc", 6); /* client hardware addr - fix */
|
|
|
memset(discover_pkt->options, DHO_PAD, DHCP_MAX_OPTION_LEN);
|
|
|
- strncpy((char *)discover_pkt->options, "\x63\x82\x53\x63", 4); /* magic cookie */
|
|
|
+ strncpy((char*)discover_pkt->options, "\x63\x82\x53\x63", 4); /* magic cookie */
|
|
|
options_len = 4;
|
|
|
add_option(0, DHO_DHCP_MESSAGE_TYPE, 1, 1, 1, discover_pkt->options, &options_len,
|
|
|
- DHCPDISCOVER);
|
|
|
+ DHCPDISCOVER);
|
|
|
add_option(0, DHO_DHCP_PARAMETER_REQUEST_LIST, 4, 1, 1, discover_pkt->options,
|
|
|
- &options_len, DHO_SUBNET_MASK, DHO_ROUTERS, DHO_DOMAIN_NAME,
|
|
|
- DHO_DOMAIN_NAME_SERVERS);
|
|
|
+ &options_len, DHO_SUBNET_MASK, DHO_ROUTERS, DHO_DOMAIN_NAME,
|
|
|
+ DHO_DOMAIN_NAME_SERVERS);
|
|
|
add_option(0, DHO_DHCP_LEASE_TIME, 1, 4, 1, discover_pkt->options, &options_len,
|
|
|
- htonl(60));
|
|
|
+ htonl(60));
|
|
|
|
|
|
- if (options_len < DHCP_MAX_OPTION_LEN)
|
|
|
- discover_pkt->options[options_len++] = DHO_END;
|
|
|
+ if (options_len < DHCP_MAX_OPTION_LEN) {
|
|
|
+ discover_pkt->options[options_len++] = DHO_END;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* gen_request(): Generate a DHCPv4 request packet.
|
|
|
- *
|
|
|
+ *
|
|
|
* Input variables
|
|
|
* giaddr is the address to copy into the giaddr element.
|
|
|
* yiaddr is the address to store in the DHO_DHCP_REQUESTED_ADDRESS option.
|
|
@@ -214,36 +216,36 @@ gen_discover(struct dhcp_packet *discover_pkt, const struct in_addr *giaddr)
|
|
|
* dhcp_pkt points to storage for the packet to be generated.
|
|
|
*/
|
|
|
void
|
|
|
-gen_request(struct dhcp_packet *dhcp_pkt, const struct in_addr *giaddr,
|
|
|
- const struct in_addr *yiaddr, const unsigned char *server_id)
|
|
|
-{
|
|
|
+gen_request(struct dhcp_packet* dhcp_pkt, const struct in_addr* giaddr,
|
|
|
+ const struct in_addr* yiaddr, const unsigned char* server_id) {
|
|
|
size_t options_len;
|
|
|
|
|
|
- bzero((char *) dhcp_pkt, sizeof(struct dhcp_packet));
|
|
|
+ bzero((char*) dhcp_pkt, sizeof(struct dhcp_packet));
|
|
|
dhcp_pkt->op = BOOTREQUEST;
|
|
|
dhcp_pkt->htype = HTYPE_ETHER;
|
|
|
dhcp_pkt->hlen = 6;
|
|
|
dhcp_pkt->hops = 1;
|
|
|
- dhcp_pkt->xid = 0x12345678; /* transaction id - fix */
|
|
|
+ dhcp_pkt->xid = 0x12345678; /* transaction id - fix */
|
|
|
dhcp_pkt->secs = 0;
|
|
|
dhcp_pkt->flags = 0;
|
|
|
memcpy(&dhcp_pkt->giaddr, giaddr, sizeof((*dhcp_pkt).giaddr));
|
|
|
/*memcpy(&dhcp_pkt->yiaddr, yiaddr, sizeof((*dhcp_pkt).yiaddr));*/
|
|
|
- strncpy((char *)dhcp_pkt->chaddr, "\x12\x34\x56\x78\x9a\xbc", 6); /* client hardware addr - fix */
|
|
|
+ strncpy((char*)dhcp_pkt->chaddr, "\x12\x34\x56\x78\x9a\xbc", 6); /* client hardware addr - fix */
|
|
|
memset(dhcp_pkt->options, DHO_PAD, DHCP_MAX_OPTION_LEN);
|
|
|
- strncpy((char *)dhcp_pkt->options, "\x63\x82\x53\x63", 4); /* magic cookie */
|
|
|
+ strncpy((char*)dhcp_pkt->options, "\x63\x82\x53\x63", 4); /* magic cookie */
|
|
|
options_len = 4;
|
|
|
add_option(0, DHO_DHCP_MESSAGE_TYPE, 1, 1, 1, dhcp_pkt->options, &options_len,
|
|
|
- DHCPREQUEST);
|
|
|
+ DHCPREQUEST);
|
|
|
add_option(0, DHO_DHCP_SERVER_IDENTIFIER, 1, 4, 0, dhcp_pkt->options,
|
|
|
- &options_len, server_id);
|
|
|
+ &options_len, server_id);
|
|
|
add_option(0, DHO_DHCP_REQUESTED_ADDRESS, 1, 4, 1, dhcp_pkt->options,
|
|
|
- &options_len, *yiaddr);
|
|
|
+ &options_len, *yiaddr);
|
|
|
add_option(0, DHO_DHCP_LEASE_TIME, 1, 4, 1, dhcp_pkt->options, &options_len,
|
|
|
- htonl(60));
|
|
|
+ htonl(60));
|
|
|
|
|
|
- if (options_len < DHCP_MAX_OPTION_LEN)
|
|
|
- dhcp_pkt->options[options_len++] = DHO_END;
|
|
|
+ if (options_len < DHCP_MAX_OPTION_LEN) {
|
|
|
+ dhcp_pkt->options[options_len++] = DHO_END;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -257,9 +259,9 @@ gen_request(struct dhcp_packet *dhcp_pkt, const struct in_addr *giaddr,
|
|
|
* send_laddr: Local address of socket, for informational messages only.
|
|
|
*/
|
|
|
void
|
|
|
-dhcp_send(int v6, const unsigned char *msg, int send_fd, const struct sockaddr *r_addr,
|
|
|
- const struct sockaddr_storage *send_laddr) {
|
|
|
-
|
|
|
+dhcp_send(int v6, const unsigned char* msg, int send_fd, const struct sockaddr* r_addr,
|
|
|
+ const struct sockaddr_storage* send_laddr) {
|
|
|
+
|
|
|
size_t num_octets;
|
|
|
ssize_t num_written;
|
|
|
char addrbuf[ADDR_NAME_BUFSIZE];
|
|
@@ -267,22 +269,22 @@ dhcp_send(int v6, const unsigned char *msg, int send_fd, const struct sockaddr *
|
|
|
|
|
|
num_octets = v6 ? sizeof(struct dhcpv6_packet) : sizeof(struct dhcp_packet);
|
|
|
if (dk_set(DK_MSG)) {
|
|
|
- fprintf(stderr, "Sending %zu octets to socket fd %u, local %s remote %s",
|
|
|
- num_octets, send_fd,
|
|
|
- addrName((struct sockaddr_storage *)send_laddr, addrbuf, sizeof(addrbuf)),
|
|
|
- addrName((struct sockaddr_storage *)r_addr, addrbuf2, sizeof(addrbuf2)));
|
|
|
- fprintf(stderr, "Packet contents:\n");
|
|
|
- print_dhcp_packet(v6, msg, num_octets);
|
|
|
+ fprintf(stderr, "Sending %zu octets to socket fd %u, local %s remote %s",
|
|
|
+ num_octets, send_fd,
|
|
|
+ addrName((struct sockaddr_storage*)send_laddr, addrbuf, sizeof(addrbuf)),
|
|
|
+ addrName((struct sockaddr_storage*)r_addr, addrbuf2, sizeof(addrbuf2)));
|
|
|
+ fprintf(stderr, "Packet contents:\n");
|
|
|
+ print_dhcp_packet(v6, msg, num_octets);
|
|
|
}
|
|
|
num_written = sendto(send_fd, msg, num_octets, 0,
|
|
|
- r_addr, sizeof(struct sockaddr_storage));
|
|
|
+ r_addr, sizeof(struct sockaddr_storage));
|
|
|
if (num_written < 0) {
|
|
|
- int s_errno = errno;
|
|
|
- fprintf(stderr, "Send failed: %s\n", strerror(s_errno));
|
|
|
- exit(1);
|
|
|
+ int s_errno = errno;
|
|
|
+ fprintf(stderr, "Send failed: %s\n", strerror(s_errno));
|
|
|
+ exit(1);
|
|
|
}
|
|
|
if ((size_t) num_written != num_octets) {
|
|
|
- fprintf(stderr, "Only %d of %u octets written\n", (int) num_written, (unsigned) num_octets);
|
|
|
+ fprintf(stderr, "Only %d of %u octets written\n", (int) num_written, (unsigned) num_octets);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -297,71 +299,70 @@ dhcp_send(int v6, const unsigned char *msg, int send_fd, const struct sockaddr *
|
|
|
* msg points to storage for the received message.
|
|
|
*/
|
|
|
void
|
|
|
-dhcp_recv(int v6, void *msg, int recv_fd,
|
|
|
- const struct sockaddr_storage *recv_laddr) {
|
|
|
-
|
|
|
+dhcp_recv(int v6, void* msg, int recv_fd,
|
|
|
+ const struct sockaddr_storage* recv_laddr) {
|
|
|
+
|
|
|
ssize_t num_octets;
|
|
|
struct sockaddr_storage sourceAddr;
|
|
|
socklen_t addrSize;
|
|
|
char addrbuf[ADDR_NAME_BUFSIZE];
|
|
|
|
|
|
dkprintf(DK_SOCK, "Waiting for response on socket fd %u, %s",
|
|
|
- recv_fd,
|
|
|
- addrName(recv_laddr, addrbuf, sizeof(addrbuf)));
|
|
|
+ recv_fd,
|
|
|
+ addrName(recv_laddr, addrbuf, sizeof(addrbuf)));
|
|
|
addrSize = sizeof(sourceAddr);
|
|
|
- num_octets = recvfrom(recv_fd, msg, v6 ? sizeof(struct dhcpv6_packet) : sizeof(struct dhcp_packet), 0, (struct sockaddr *)&sourceAddr, &addrSize);
|
|
|
+ num_octets = recvfrom(recv_fd, msg, v6 ? sizeof(struct dhcpv6_packet) : sizeof(struct dhcp_packet), 0, (struct sockaddr*)&sourceAddr, &addrSize);
|
|
|
/* TODO: check for recvfrom failure status here */
|
|
|
if (dk_set(DK_MSG)) {
|
|
|
- fprintf(stderr, "Got %zd octets from fd %u, %s", num_octets, recv_fd,
|
|
|
- addrName(&sourceAddr, addrbuf, sizeof(addrbuf)));
|
|
|
- fprintf(stderr, "Received packet contents:\n");
|
|
|
- print_dhcp_packet(v6, msg, num_octets);
|
|
|
+ fprintf(stderr, "Got %zd octets from fd %u, %s", num_octets, recv_fd,
|
|
|
+ addrName(&sourceAddr, addrbuf, sizeof(addrbuf)));
|
|
|
+ fprintf(stderr, "Received packet contents:\n");
|
|
|
+ print_dhcp_packet(v6, msg, num_octets);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void
|
|
|
-dora(const char *server, const char *localAddr)
|
|
|
-{
|
|
|
+dora(const char* server, const char* localAddr) {
|
|
|
struct sockaddr_storage send_laddr, recv_laddr;
|
|
|
struct dhcp_packet discover_pkt, offer_pkt, request_pkt, ack_pkt;
|
|
|
int send_fd, recv_fd;
|
|
|
- const unsigned char *type, *server_id;
|
|
|
+ const unsigned char* type, *server_id;
|
|
|
aaddr_buf a_yiaddr;
|
|
|
- struct addrinfo *remote;
|
|
|
- struct in_addr *local_address;
|
|
|
+ struct addrinfo* remote;
|
|
|
+ struct in_addr* local_address;
|
|
|
|
|
|
send_fd = socket_setup(AF_INET, localAddr, "bootpc", "Send", &send_laddr);
|
|
|
recv_fd = socket_setup(AF_INET, localAddr, "bootps", "Recv", &recv_laddr);
|
|
|
|
|
|
if ((remote = getaddr(AF_INET, server, "bootps")) == NULL) {
|
|
|
- fprintf(stderr, "No addresses for %s\n", server);
|
|
|
- exit(1);
|
|
|
+ fprintf(stderr, "No addresses for %s\n", server);
|
|
|
+ exit(1);
|
|
|
}
|
|
|
|
|
|
- local_address = &((struct sockaddr_in *)&send_laddr)->sin_addr;
|
|
|
+ local_address = &((struct sockaddr_in*)&send_laddr)->sin_addr;
|
|
|
gen_discover(&discover_pkt, local_address);
|
|
|
|
|
|
- dhcp_send(0, (unsigned char *)&discover_pkt, send_fd, remote->ai_addr, &send_laddr);
|
|
|
+ dhcp_send(0, (unsigned char*)&discover_pkt, send_fd, remote->ai_addr, &send_laddr);
|
|
|
dhcp_recv(0, &offer_pkt, recv_fd, &recv_laddr);
|
|
|
type = find_option(&offer_pkt, DHO_DHCP_MESSAGE_TYPE);
|
|
|
if (type == NULL) {
|
|
|
- fprintf(stderr, "DHCP reponse did not include message type option\n");
|
|
|
- exit(1);
|
|
|
+ fprintf(stderr, "DHCP reponse did not include message type option\n");
|
|
|
+ exit(1);
|
|
|
}
|
|
|
if (type[2] != DHCPOFFER) {
|
|
|
- fprintf(stderr, "DHCP reponse had message type %d; expecting DHCPOFFER\n", type[2]);
|
|
|
- exit(1);
|
|
|
+ fprintf(stderr, "DHCP reponse had message type %d; expecting DHCPOFFER\n", type[2]);
|
|
|
+ exit(1);
|
|
|
}
|
|
|
server_id = find_option(&offer_pkt, DHO_DHCP_SERVER_IDENTIFIER);
|
|
|
if (type == NULL) {
|
|
|
- fprintf(stderr, "DHCP reponse did not include server identifier option\n");
|
|
|
- exit(1);
|
|
|
+ fprintf(stderr, "DHCP reponse did not include server identifier option\n");
|
|
|
+ exit(1);
|
|
|
}
|
|
|
server_id += 2;
|
|
|
- printf("Server identifier: %08x\n", ntohl(*(int *)server_id));
|
|
|
+ printf("Server identifier: %08x\n", ntohl(*(int*)server_id));
|
|
|
printf("Offered address: %s\n", addrtoa(AF_INET, &offer_pkt.yiaddr, a_yiaddr));
|
|
|
gen_request(&request_pkt, local_address, &offer_pkt.yiaddr, server_id);
|
|
|
- dhcp_send(0, (unsigned char *)&request_pkt, send_fd, remote->ai_addr, &send_laddr);
|
|
|
+ dhcp_send(0, (unsigned char*)&request_pkt, send_fd, remote->ai_addr, &send_laddr);
|
|
|
dhcp_recv(0, &ack_pkt, recv_fd, &recv_laddr);
|
|
|
}
|
|
|
|
|
@@ -382,13 +383,12 @@ Discard REPLY messsages in whhich the "transaction-id" field in the message does
|
|
|
used in the original message.
|
|
|
*/
|
|
|
void
|
|
|
-sarr(const char *server, const char *if_name)
|
|
|
-{
|
|
|
+sarr(const char* server, const char* if_name) {
|
|
|
struct sockaddr_storage send_laddr, recv_laddr;
|
|
|
struct dhcpv6_packet solicit_pkt, advertise_pkt;
|
|
|
int send_fd, recv_fd;
|
|
|
- struct in6_addr *local_address;
|
|
|
- struct addrinfo *remote;
|
|
|
+ struct in6_addr* local_address;
|
|
|
+ struct addrinfo* remote;
|
|
|
struct duid client_id;
|
|
|
|
|
|
get_linklocal_addr(if_name, &send_laddr);
|
|
@@ -400,48 +400,49 @@ sarr(const char *server, const char *if_name)
|
|
|
recv_fd = send_fd;
|
|
|
|
|
|
if (server != NULL) {
|
|
|
- if (strcmp(server, "all"))
|
|
|
- server = All_DHCP_Relay_Agents_and_Servers;
|
|
|
- else if (strcmp(server, "server"))
|
|
|
- server = All_DHCP_Servers;
|
|
|
+ if (strcmp(server, "all")) {
|
|
|
+ server = All_DHCP_Relay_Agents_and_Servers;
|
|
|
+ } else if (strcmp(server, "server")) {
|
|
|
+ server = All_DHCP_Servers;
|
|
|
+ }
|
|
|
}
|
|
|
if ((remote = getaddr(AF_INET6, server, "547")) == NULL) {
|
|
|
- fprintf(stderr, "Conversion failed for %s\n", server);
|
|
|
- exit(1);
|
|
|
+ fprintf(stderr, "Conversion failed for %s\n", server);
|
|
|
+ exit(1);
|
|
|
}
|
|
|
|
|
|
- local_address = &((struct sockaddr_in6 *)&send_laddr)->sin6_addr;
|
|
|
+ local_address = &((struct sockaddr_in6*)&send_laddr)->sin6_addr;
|
|
|
|
|
|
client_id.duid_type = htons(DUID_LL);
|
|
|
client_id.htype = htons(HTYPE_ETHER);
|
|
|
- memset(client_id.hwaddr, 0xA, 6); /* TEMPORARY - FIX */
|
|
|
+ memset(client_id.hwaddr, 0xA, 6); /* TEMPORARY - FIX */
|
|
|
|
|
|
gen_solicit(&solicit_pkt, &client_id);
|
|
|
- dhcp_send(1, (unsigned char *)&solicit_pkt, send_fd, remote->ai_addr, &send_laddr);
|
|
|
+ dhcp_send(1, (unsigned char*)&solicit_pkt, send_fd, remote->ai_addr, &send_laddr);
|
|
|
dhcp_recv(1, &advertise_pkt, recv_fd, &recv_laddr);
|
|
|
-/*
|
|
|
- *
|
|
|
- * type = find_option(&offer_pkt, DHO_DHCP_MESSAGE_TYPE);
|
|
|
- * if (type == NULL) {
|
|
|
- * fprintf(stderr, "DHCP reponse did not include message type option\n");
|
|
|
- * exit(1);
|
|
|
- * }
|
|
|
- * if (type[2] != DHCPOFFER) {
|
|
|
- * fprintf(stderr, "DHCP reponse had message type %d; expecting DHCPOFFER\n", type[2]);
|
|
|
- * exit(1);
|
|
|
- * }
|
|
|
- * server_id = find_option(&offer_pkt, DHO_DHCP_SERVER_IDENTIFIER);
|
|
|
- * if (type == NULL) {
|
|
|
- * fprintf(stderr, "DHCP reponse did not include server identifier option\n");
|
|
|
- * exit(1);
|
|
|
- * }
|
|
|
- * server_id += 2;
|
|
|
- * printf("Server identifier: %08x\n", ntohl(*(int *)server_id));
|
|
|
- * printf("Offered address: %s\n", addrtoa(AF_INET, &offer_pkt.yiaddr, a_yiaddr));
|
|
|
- * gen_request(&request_pkt, local_address, &offer_pkt.yiaddr, server_id);
|
|
|
- * dhcp_send(&request_pkt, send_fd, remote->ai_addr, &send_laddr);
|
|
|
- * dhcp_recv(&ack_pkt, recv_fd, &recv_laddr);
|
|
|
- */
|
|
|
+ /*
|
|
|
+ *
|
|
|
+ * type = find_option(&offer_pkt, DHO_DHCP_MESSAGE_TYPE);
|
|
|
+ * if (type == NULL) {
|
|
|
+ * fprintf(stderr, "DHCP reponse did not include message type option\n");
|
|
|
+ * exit(1);
|
|
|
+ * }
|
|
|
+ * if (type[2] != DHCPOFFER) {
|
|
|
+ * fprintf(stderr, "DHCP reponse had message type %d; expecting DHCPOFFER\n", type[2]);
|
|
|
+ * exit(1);
|
|
|
+ * }
|
|
|
+ * server_id = find_option(&offer_pkt, DHO_DHCP_SERVER_IDENTIFIER);
|
|
|
+ * if (type == NULL) {
|
|
|
+ * fprintf(stderr, "DHCP reponse did not include server identifier option\n");
|
|
|
+ * exit(1);
|
|
|
+ * }
|
|
|
+ * server_id += 2;
|
|
|
+ * printf("Server identifier: %08x\n", ntohl(*(int *)server_id));
|
|
|
+ * printf("Offered address: %s\n", addrtoa(AF_INET, &offer_pkt.yiaddr, a_yiaddr));
|
|
|
+ * gen_request(&request_pkt, local_address, &offer_pkt.yiaddr, server_id);
|
|
|
+ * dhcp_send(&request_pkt, send_fd, remote->ai_addr, &send_laddr);
|
|
|
+ * dhcp_recv(&ack_pkt, recv_fd, &recv_laddr);
|
|
|
+ */
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -451,26 +452,25 @@ sarr(const char *server, const char *if_name)
|
|
|
* Use IA_TA to request temporary addresses
|
|
|
*/
|
|
|
void
|
|
|
-gen_solicit(struct dhcpv6_packet *dhcp_pkt, const struct duid *client_id)
|
|
|
-{
|
|
|
+gen_solicit(struct dhcpv6_packet* dhcp_pkt, const struct duid* client_id) {
|
|
|
int tid;
|
|
|
int i;
|
|
|
size_t options_len = 0;
|
|
|
|
|
|
- bzero((char *) dhcp_pkt, sizeof(struct dhcpv6_packet));
|
|
|
+ bzero((char*) dhcp_pkt, sizeof(struct dhcpv6_packet));
|
|
|
dhcp_pkt->msg_type = DHCPV6_SOLICIT;
|
|
|
tid = rand();
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
- dhcp_pkt->transaction_id[i] = (unsigned char)tid;
|
|
|
- tid >>= 8;
|
|
|
+ dhcp_pkt->transaction_id[i] = (unsigned char)tid;
|
|
|
+ tid >>= 8;
|
|
|
}
|
|
|
add_option(1, D6O_CLIENTID, 1, sizeof(struct duid), 0, dhcp_pkt->options,
|
|
|
- &options_len, client_id);
|
|
|
+ &options_len, client_id);
|
|
|
add_option(1, D6O_IA_TA, 1, 4, 1, dhcp_pkt->options,
|
|
|
- &options_len, "0xabcd"); /* Temporary - FIX */
|
|
|
+ &options_len, "0xabcd"); /* Temporary - FIX */
|
|
|
/* D60_ORO: Option Request Option */
|
|
|
add_option(1, D6O_ORO, 1, 2, 1, dhcp_pkt->options,
|
|
|
- &options_len, D6O_NAME_SERVERS);
|
|
|
+ &options_len, D6O_NAME_SERVERS);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -494,37 +494,34 @@ gen_solicit(struct dhcpv6_packet *dhcp_pkt, const struct duid *client_id)
|
|
|
*/
|
|
|
void
|
|
|
add_option(int v6, unsigned optnum, unsigned count, size_t size,
|
|
|
- int direct, unsigned char options[], size_t *buffer_used, ...)
|
|
|
-{
|
|
|
+ int direct, unsigned char options[], size_t* buffer_used, ...) {
|
|
|
va_list ap;
|
|
|
unsigned i;
|
|
|
size_t buffer_size = v6 ? sizeof(struct dhcpv6_packet) : DHCP_MAX_OPTION_LEN;
|
|
|
|
|
|
if ((*buffer_used + (v6 ? 4 : 2) + count * size) > buffer_size) {
|
|
|
- fprintf(stderr, "%s: Insufficient option space\n", progName);
|
|
|
- exit(1);
|
|
|
+ fprintf(stderr, "%s: Insufficient option space\n", progName);
|
|
|
+ exit(1);
|
|
|
}
|
|
|
if (v6) {
|
|
|
- struct v6_option *opt = (struct v6_option *)&options[(*buffer_used)];
|
|
|
- opt->code = htons(optnum);
|
|
|
- opt->len = htons(count * size);
|
|
|
- *buffer_used += 4;
|
|
|
- }
|
|
|
- else {
|
|
|
- options[(*buffer_used)++] = optnum;
|
|
|
- options[(*buffer_used)++] = count * size;
|
|
|
+ struct v6_option* opt = (struct v6_option*)&options[(*buffer_used)];
|
|
|
+ opt->code = htons(optnum);
|
|
|
+ opt->len = htons(count * size);
|
|
|
+ *buffer_used += 4;
|
|
|
+ } else {
|
|
|
+ options[(*buffer_used)++] = optnum;
|
|
|
+ options[(*buffer_used)++] = count * size;
|
|
|
}
|
|
|
va_start(ap,buffer_used);
|
|
|
for (i = 1; i <= count; i++) {
|
|
|
- if (direct) {
|
|
|
- int value = va_arg(ap, int);
|
|
|
- memcpy(&options[*buffer_used], (char *)&value, size);
|
|
|
- }
|
|
|
- else {
|
|
|
- char *p = va_arg(ap, char *);
|
|
|
- memcpy(&options[*buffer_used], p, size);
|
|
|
- }
|
|
|
- (*buffer_used) += size;
|
|
|
+ if (direct) {
|
|
|
+ int value = va_arg(ap, int);
|
|
|
+ memcpy(&options[*buffer_used], (char*)&value, size);
|
|
|
+ } else {
|
|
|
+ char* p = va_arg(ap, char*);
|
|
|
+ memcpy(&options[*buffer_used], p, size);
|
|
|
+ }
|
|
|
+ (*buffer_used) += size;
|
|
|
}
|
|
|
/* ap */
|
|
|
va_end(ap);
|
|
@@ -534,11 +531,11 @@ add_option(int v6, unsigned optnum, unsigned count, size_t size,
|
|
|
* Return value:
|
|
|
* buf is returned.
|
|
|
*/
|
|
|
-char *
|
|
|
-addrtoa(int addr_fam, const struct in_addr *addr, aaddr_buf buf)
|
|
|
-{
|
|
|
- if (inet_ntop(addr_fam, addr, buf, ADDR_NAME_BUFSIZE) == NULL)
|
|
|
- strcpy(buf, "untranslatable");
|
|
|
+char*
|
|
|
+addrtoa(int addr_fam, const struct in_addr* addr, aaddr_buf buf) {
|
|
|
+ if (inet_ntop(addr_fam, addr, buf, ADDR_NAME_BUFSIZE) == NULL) {
|
|
|
+ strcpy(buf, "untranslatable");
|
|
|
+ }
|
|
|
return buf;
|
|
|
}
|
|
|
|
|
@@ -548,7 +545,7 @@ addrtoa(int addr_fam, const struct in_addr *addr, aaddr_buf buf)
|
|
|
* is printed and the program exits with status 2.
|
|
|
*
|
|
|
* Input variables:
|
|
|
- * hostname: The host name to look up. This can be either a name or an IPv4
|
|
|
+ * hostname: The host name to look up. This can be either a name or an IPv4
|
|
|
* dotted-quad address, or null to not fill in the address.
|
|
|
* port: The port to include in addrinfo. This can be either a service name or
|
|
|
* an ASCII decimal number, or null to not fill in the port number.
|
|
@@ -560,10 +557,9 @@ addrtoa(int addr_fam, const struct in_addr *addr, aaddr_buf buf)
|
|
|
* A pointer to the addrinfo list. This must be freed by the caller with
|
|
|
* freeaddrinfo().
|
|
|
*/
|
|
|
-struct addrinfo *
|
|
|
-getaddr(int addr_fam, const char *hostname, const char *port)
|
|
|
-{
|
|
|
- struct addrinfo *ai;
|
|
|
+struct addrinfo*
|
|
|
+getaddr(int addr_fam, const char* hostname, const char* port) {
|
|
|
+ struct addrinfo* ai;
|
|
|
struct addrinfo hints;
|
|
|
int ret;
|
|
|
|
|
@@ -573,9 +569,9 @@ getaddr(int addr_fam, const char *hostname, const char *port)
|
|
|
hints.ai_protocol = IPPROTO_UDP;
|
|
|
|
|
|
if ((ret = getaddrinfo(hostname, port, &hints, &ai)) != 0) {
|
|
|
- fprintf(stderr, "%s: %s: getaddrinfo: %s/%s\n", progName,
|
|
|
- hostname == NULL ? "" : hostname, port == NULL ? "" : port, gai_strerror(ret));
|
|
|
- exit(2);
|
|
|
+ fprintf(stderr, "%s: %s: getaddrinfo: %s/%s\n", progName,
|
|
|
+ hostname == NULL ? "" : hostname, port == NULL ? "" : port, gai_strerror(ret));
|
|
|
+ exit(2);
|
|
|
}
|
|
|
return ai;
|
|
|
}
|
|
@@ -594,19 +590,19 @@ getaddr(int addr_fam, const char *hostname, const char *port)
|
|
|
* Return value:
|
|
|
* buf is returned.
|
|
|
*/
|
|
|
-char *
|
|
|
-addrName(const struct sockaddr_storage *addr, char *name, size_t bufsize)
|
|
|
-{
|
|
|
- char *buf = name;
|
|
|
+char*
|
|
|
+addrName(const struct sockaddr_storage* addr, char* name, size_t bufsize) {
|
|
|
+ char* buf = name;
|
|
|
char servbuf[30];
|
|
|
|
|
|
- if (getnameinfo((struct sockaddr *)addr, sizeof(struct sockaddr_storage),
|
|
|
- name, bufsize, servbuf, 30, 0) != 0)
|
|
|
- strncpy(buf, "untranslatable", bufsize-1);
|
|
|
- else {
|
|
|
- size_t len = strlen(buf);
|
|
|
- if (len < bufsize)
|
|
|
- snprintf(name + len, bufsize - len, " port %s", servbuf);
|
|
|
+ if (getnameinfo((struct sockaddr*)addr, sizeof(struct sockaddr_storage),
|
|
|
+ name, bufsize, servbuf, 30, 0) != 0) {
|
|
|
+ strncpy(buf, "untranslatable", bufsize-1);
|
|
|
+ } else {
|
|
|
+ size_t len = strlen(buf);
|
|
|
+ if (len < bufsize) {
|
|
|
+ snprintf(name + len, bufsize - len, " port %s", servbuf);
|
|
|
+ }
|
|
|
}
|
|
|
return buf;
|
|
|
}
|
|
@@ -618,7 +614,7 @@ addrName(const struct sockaddr_storage *addr, char *name, size_t bufsize)
|
|
|
*
|
|
|
* Output variables:
|
|
|
* The link-local address for the interface is stored in addr.
|
|
|
- *
|
|
|
+ *
|
|
|
* Return value:
|
|
|
* 1 on success, 0 if no link-local address is found.
|
|
|
*
|
|
@@ -626,49 +622,49 @@ addrName(const struct sockaddr_storage *addr, char *name, size_t bufsize)
|
|
|
* printed and the program is exited with status 2.
|
|
|
*/
|
|
|
int
|
|
|
-get_linklocal_addr(const char if_name[], struct sockaddr_storage *addr)
|
|
|
-{
|
|
|
+get_linklocal_addr(const char if_name[], struct sockaddr_storage* addr) {
|
|
|
+
|
|
|
+ struct ifaddrs* ifaddr, *ifa;
|
|
|
|
|
|
- struct ifaddrs *ifaddr, *ifa;
|
|
|
-
|
|
|
if (getifaddrs(&ifaddr) == -1) {
|
|
|
- fprintf(stderr, "%s: Could not get interface addresses: %s\n",
|
|
|
- progName, strerror(errno));
|
|
|
+ fprintf(stderr, "%s: Could not get interface addresses: %s\n",
|
|
|
+ progName, strerror(errno));
|
|
|
exit(2);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
|
|
|
- if (ifa->ifa_addr->sa_family == AF_INET6 && strcmp(ifa->ifa_name, if_name) == 0 &&
|
|
|
- (ntohs(((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr.__in6_u.__u6_addr16[0]) & 0xffc0) == 0xfe80)
|
|
|
- break;
|
|
|
+ if (ifa->ifa_addr->sa_family == AF_INET6 && strcmp(ifa->ifa_name, if_name) == 0 &&
|
|
|
+ (ntohs(((struct sockaddr_in6*)ifa->ifa_addr)->sin6_addr.__in6_u.__u6_addr16[0]) & 0xffc0) == 0xfe80) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (ifa != NULL) {
|
|
|
+ memcpy(addr, ifa->ifa_addr, sizeof(struct sockaddr_storage));
|
|
|
}
|
|
|
- if (ifa != NULL)
|
|
|
- memcpy(addr, ifa->ifa_addr, sizeof(struct sockaddr_storage));
|
|
|
freeifaddrs(ifaddr);
|
|
|
return ifa != NULL;
|
|
|
}
|
|
|
|
|
|
void
|
|
|
-print_addrinfo(FILE *f, const struct addrinfo *addr)
|
|
|
-{
|
|
|
+print_addrinfo(FILE* f, const struct addrinfo* addr) {
|
|
|
fprintf(f, "Addrinfo:\n");
|
|
|
fprintf(f, "flags: 0x%x; family: %d; socktype: %d; proto: %d;\n",
|
|
|
- addr->ai_flags, addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
|
|
+ addr->ai_flags, addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
|
|
fprintf(f, "addrlen: %u; addr: %p; canonname: %s; next: %p\n",
|
|
|
- addr->ai_addrlen, addr->ai_addr, addr->ai_canonname, addr->ai_next);
|
|
|
- if (addr->ai_family == AF_INET6)
|
|
|
- print_sa6_info(f, (struct sockaddr_in6 *)addr->ai_addr);
|
|
|
+ addr->ai_addrlen, addr->ai_addr, addr->ai_canonname, addr->ai_next);
|
|
|
+ if (addr->ai_family == AF_INET6) {
|
|
|
+ print_sa6_info(f, (struct sockaddr_in6*)addr->ai_addr);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void
|
|
|
-print_sa6_info(FILE *f, const struct sockaddr_in6 *sa)
|
|
|
-{
|
|
|
+print_sa6_info(FILE* f, const struct sockaddr_in6* sa) {
|
|
|
char addrbuf[ADDR_NAME_BUFSIZE];
|
|
|
|
|
|
fprintf(f, "IPv6 sockaddr info:\n");
|
|
|
fprintf(f, "family: %u; flowinfo: 0x%x; scope-id: %u addr: %s\n",
|
|
|
- sa->sin6_family, sa->sin6_flowinfo, sa->sin6_scope_id,
|
|
|
- addrName((struct sockaddr_storage *)sa, addrbuf, sizeof(addrbuf)));
|
|
|
+ sa->sin6_family, sa->sin6_flowinfo, sa->sin6_scope_id,
|
|
|
+ addrName((struct sockaddr_storage*)sa, addrbuf, sizeof(addrbuf)));
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -682,21 +678,20 @@ print_sa6_info(FILE *f, const struct sockaddr_in6 *sa)
|
|
|
* If the packet contains the option, a pointer to its start (the option
|
|
|
* number) is returned. If not, NULL is returned.
|
|
|
*/
|
|
|
-const unsigned char *
|
|
|
-find_option(const struct dhcp_packet *pkt, int search_opt)
|
|
|
-{
|
|
|
- const unsigned char *p;
|
|
|
+const unsigned char*
|
|
|
+find_option(const struct dhcp_packet* pkt, int search_opt) {
|
|
|
+ const unsigned char* p;
|
|
|
|
|
|
p = &pkt->options[4];
|
|
|
while ((p - pkt->options) < DHCP_MAX_OPTION_LEN && *p != DHO_END) {
|
|
|
- if (*p == search_opt)
|
|
|
- return p;
|
|
|
- else if (*p == DHO_PAD)
|
|
|
- p++;
|
|
|
- else {
|
|
|
- size_t len = p[1];
|
|
|
- p += 2 + len;
|
|
|
- }
|
|
|
+ if (*p == search_opt) {
|
|
|
+ return p;
|
|
|
+ } else if (*p == DHO_PAD) {
|
|
|
+ p++;
|
|
|
+ } else {
|
|
|
+ size_t len = p[1];
|
|
|
+ p += 2 + len;
|
|
|
+ }
|
|
|
}
|
|
|
return NULL;
|
|
|
}
|