mirror of
https://git.checksum.fail/alec/TOL.git
synced 2026-05-26 23:18:13 +00:00
143 lines
3.5 KiB
HolyC
143 lines
3.5 KiB
HolyC
|
|
#define CLIENT_START 0
|
|
#define CLIENT_DISCOVER 1
|
|
#define CLIENT_REQUEST 2
|
|
#define CLIENT_REQUEST_ACCEPTED 3
|
|
|
|
#define DHCP_TIMEOUT 3000
|
|
#define MAX_RETRIES 3
|
|
|
|
I64 DhcpConfigureInner(I64 sock, U32 *yiaddr_out, U32 *dns_ip_out,
|
|
U32 *router_ip_out, U32 *subnet_mask_out) {
|
|
I64 state = CLIENT_START;
|
|
I64 retries = 0;
|
|
|
|
I64 timeout = DHCP_TIMEOUT;
|
|
|
|
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO_MS, &timeout, sizeof(timeout)) <
|
|
0) {
|
|
"$FG,6$DhcpConfigure: setsockopt failed\n$FG$";
|
|
}
|
|
|
|
sockaddr_in addr;
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_port = htons(68);
|
|
addr.sin_addr.s_addr = INADDR_ANY;
|
|
|
|
if (bind(sock, &addr, sizeof(addr)) < 0) {
|
|
"$FG,4$DhcpConfigure: failed to bind\n$FG$";
|
|
return -1;
|
|
}
|
|
|
|
U32 xid = DhcpBeginTransaction();
|
|
|
|
I64 error = 0;
|
|
|
|
U32 dhcp_addr;
|
|
U8 buffer[2048];
|
|
|
|
I64 count;
|
|
sockaddr_in addr_in;
|
|
|
|
while (state != CLIENT_REQUEST_ACCEPTED) {
|
|
if (state == CLIENT_START) {
|
|
state = CLIENT_DISCOVER;
|
|
retries = 0;
|
|
} else if (state == CLIENT_DISCOVER) {
|
|
error = DhcpSendDiscover(xid);
|
|
if (error < 0)
|
|
return error;
|
|
|
|
count =
|
|
recvfrom(sock, buffer, sizeof(buffer), 0, &addr_in, sizeof(addr_in));
|
|
|
|
if (count > 0) {
|
|
//"Try parse Offer\n";
|
|
error = DhcpParseOffer(xid, buffer, count, yiaddr_out, dns_ip_out,
|
|
router_ip_out, subnet_mask_out);
|
|
|
|
if (error < 0) {
|
|
"$FG,6$DhcpParseOffer1: error %d\n$FG$", error;
|
|
}
|
|
}
|
|
|
|
if (count > 0 && error >= 0) {
|
|
dhcp_addr = ntohl(addr_in.sin_addr.s_addr);
|
|
//"DHCP Offer from %08X: YIAddr %08X,\n\tDNS %08X, Router %08X, Subnet
|
|
//%08X\n",
|
|
// dhcp_addr, *yiaddr_out, dns_ip, router_ip, subnet_mask;
|
|
|
|
state = CLIENT_REQUEST;
|
|
retries = 0;
|
|
} else if (++retries == MAX_RETRIES) {
|
|
"$FG,4$DhcpConfigure: max retries for DISCOVER\n$FG$";
|
|
return -1;
|
|
}
|
|
} else if (state == CLIENT_REQUEST) {
|
|
error = DhcpSendRequest(xid, *yiaddr_out, dhcp_addr);
|
|
if (error < 0)
|
|
return error;
|
|
|
|
count =
|
|
recvfrom(sock, buffer, sizeof(buffer), 0, &addr_in, sizeof(addr_in));
|
|
|
|
if (count > 0) {
|
|
//"Try parse Ack\n";
|
|
error = DhcpParseAck(xid, buffer, count);
|
|
|
|
if (error < 0) {
|
|
"$FG,6$DhcpParseOffer: error %d\n$FG$", error;
|
|
}
|
|
}
|
|
|
|
if (count > 0 && error >= 0) {
|
|
dhcp_addr = ntohl(addr_in.sin_addr.s_addr);
|
|
//"DHCP Ack from %08X\n", dhcp_addr;
|
|
|
|
state = CLIENT_REQUEST_ACCEPTED;
|
|
} else if (++retries == MAX_RETRIES) {
|
|
"$FG,4$DhcpConfigure: max retries for REQUEST\n$FG$";
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
I64 DhcpConfigure() {
|
|
I64 sock = socket(AF_INET, SOCK_DGRAM);
|
|
|
|
if (sock < 0)
|
|
return -1;
|
|
|
|
U32 yiaddr, dns_ip, router_ip, subnet_mask;
|
|
I64 state =
|
|
DhcpConfigureInner(sock, &yiaddr, &dns_ip, &router_ip, &subnet_mask);
|
|
|
|
close(sock);
|
|
|
|
if (state == CLIENT_REQUEST_ACCEPTED) {
|
|
in_addr in;
|
|
in.s_addr = htonl(yiaddr);
|
|
U8 buffer[INET_ADDRSTRLEN];
|
|
"$FG,2$Obtained IP address %s\n$FG$",
|
|
inet_ntop(AF_INET, &in.s_addr, buffer, sizeof(buffer));
|
|
IPv4SetAddress(yiaddr);
|
|
IPv4SetSubnet(router_ip, subnet_mask);
|
|
DnsSetResolverIPv4(dns_ip);
|
|
return 0;
|
|
} else
|
|
return -1;
|
|
}
|
|
|
|
U0 Netcfg() {
|
|
SocketInit();
|
|
|
|
"$FG,7$Netcfg: Configuring network...\n$FG$";
|
|
|
|
I64 error = DhcpConfigure();
|
|
if (error < 0)
|
|
"$FG,4$DhcpConfigure: error %d\n$FG$", error;
|
|
}
|