#include <stdlib.h>
#include <net.h>
#include <acess/sys.h>
+#include <errno.h>
+
+enum {
+ UDP_IOCTL_GETSETLPORT = 4,
+ UDP_IOCTL_GETSETRPORT,
+ UDP_IOCTL_GETSETRMASK,
+ UDP_IOCTL_SETRADDR,
+};
#define FILENAME_MAX 255
// --- Translation functions ---
uint32_t TransactionID;
char HWAddr[6];
-
+
+ int64_t StartTime;
int64_t Timeout;
int nTimeouts;
} tInterface;
// === CODE ===
int main(int argc, char *argv[])
{
- tInterface *ifaces = NULL, *i;
+ tInterface *ifaces = NULL;
if( argc > 2 ) {
fprintf(stderr, "Usage: %s <interface>\n", argv[0]);
Scan_Dir( &ifaces, "/Devices/ip/adapters" );
}
- for( i = ifaces; i; i = i->Next )
+ for( tInterface *i = ifaces; i; i = i->Next )
{
if( Start_Interface(i) < 0 ) {
return -1;
}
i->State = STATE_PREINIT;
+ i->StartTime = _SysTimestamp();
// Send request
Send_DHCPDISCOVER(i);
{
int maxfd;
fd_set fds;
- tInterface *p;
int64_t timeout = 1000;
maxfd = 0;
FD_ZERO(&fds);
- for( i = ifaces; i; i = i->Next )
+ for( tInterface *i = ifaces; i; i = i->Next )
{
FD_SET(i->SocketFD, &fds);
if(maxfd < i->SocketFD) maxfd = i->SocketFD;
_SysDebug("select() returned");
// Check for changes (with magic to allow inline deletion)
- for( p = (void*)&ifaces, i = ifaces; i; p=i,i = i->Next )
+ for( tInterface *p = (void*)&ifaces, *i = ifaces; i; p=i,i = i->Next )
{
if( FD_ISSET(i->SocketFD, &fds) )
{
{
if( Handle_Timeout(i) )
{
- fprintf(stderr, "%s timed out\n", i->Adapter);
+ fprintf(stderr, "DHCP on %s timed out\n", i->Adapter);
goto _remove;
}
}
fprintf(stderr, "ERROR: Unable to open '%s'\n", path);
return -1;
}
- tmp = 68; _SysIOCtl(fd, 4, &tmp); // Local port
- tmp = 67; _SysIOCtl(fd, 5, &tmp); // Remote port
- tmp = 0; _SysIOCtl(fd, 7, &tmp); // Remote addr mask bits - we don't care where the reply comes from
+ tmp = 68; _SysIOCtl(fd, UDP_IOCTL_GETSETLPORT, &tmp); // Local port
+ tmp = 67; _SysIOCtl(fd, UDP_IOCTL_GETSETRPORT, &tmp); // Remote port
+ tmp = 0; _SysIOCtl(fd, UDP_IOCTL_GETSETRMASK, &tmp); // Remote addr mask bits - don't care source
addr[0] = addr[1] = addr[2] = addr[3] = 255; // 255.255.255.255
- _SysIOCtl(fd, 8, addr); // Remote address
+ _SysIOCtl(fd, UDP_IOCTL_SETRADDR, addr); // Remote address
return 0;
}
msg->siaddr = htonl(0); // siaddr - Zero? maybe -1
msg->giaddr = htonl(0); // giaddr - Zero?
memcpy(msg->chaddr, Iface->HWAddr, 6);
+ memset(msg->chaddr+6, 0, sizeof(msg->chaddr)-6);
memset(msg->sname, 0, sizeof(msg->sname)); // Nuke the rest
memset(msg->file, 0, sizeof(msg->file)); // Nuke the rest
msg->options[i++] = 53; // DHCP Message Type
msg->options[i++] = 1;
msg->options[i++] = 1; // - DHCPDISCOVER
- msg->options[i++] = 255; // End of list
+ msg->options[i ] = 255; // End of list
+ // UDP Header
data[0] = 67; data[1] = 0; // Port
data[2] = 4; data[3] = 0; // AddrType
data[4] = 255; data[5] = 255; data[6] = 255; data[7] = 255;
i = _SysWrite(Iface->SocketFD, data, sizeof(data));
if( i != sizeof(data) ) {
- _SysDebug("_SysWrite failed (%i != %i)", i, sizeof(data));
+ _SysDebug("_SysWrite failed (%i != %i): %s", i, sizeof(data),
+ strerror(errno));
}
Update_State(Iface, STATE_DISCOVER_SENT);
}
int i;
msg = (void*) ((char*)OfferPacket) + 8;
+ if( msg->xid != htonl(Iface->TransactionID) ) {
+ _SysDebug("DHCPREQUEST: Transaction ID mismatch");
+ return ;
+ }
+
// Reuses old data :)
- msg->op = 1;
- msg->htype = 1;
- msg->hlen = 6;
- msg->hops = 0;
- msg->xid = msg->xid;
- msg->secs = htons(0); // TODO: Maintain times
- msg->flags = htons(0);
+ msg->op = htonb(1);
+ msg->htype = htonb(1);
+ msg->hlen = htonb(6);
+ msg->hops = htonb(0);
+ msg->xid = htonl(Iface->TransactionID);
+ msg->secs = htons( (_SysTimestamp()-Iface->StartTime+499)/1000 ); // TODO: Maintain times
+ msg->flags = htons(0x0000);
memcpy(msg->chaddr, Iface->HWAddr, 6);
memset(msg->sname, 0, sizeof(msg->sname)); // Nuke the rest
memset(msg->file, 0, sizeof(msg->file)); // Nuke the rest
void *router = NULL;
void *subnet_mask = NULL;
- _SysDebug("Doing read on %i", Iface->SocketFD);
+ _SysDebug("Doing read on %s %i", Iface->Adapter, Iface->SocketFD);
len = _SysRead(Iface->SocketFD, data, sizeof(data));
_SysDebug("len = %i", len);
switch(Iface->State)
{
case STATE_DISCOVER_SENT:
+ fprintf(stderr, "DHCPDISCOVER timeout on %s, trying again\n", Iface->Adapter);
Send_DHCPDISCOVER(Iface);
break;
+ case STATE_REQUEST_SENT:
+ fprintf(stderr, "DHCPREQUEST timeout on %s\n", Iface->Adapter);
+ return 1;
default:
- _SysDebug("Timeout with state = %i", Iface->State);
- break;
+ _SysDebug("Timeout with state = %i (%s)", Iface->State, Iface->Adapter);
+ return 1;
}
return 0;
}
// TODO: Exponential backoff
Iface->Timeout = _SysTimestamp() + 3000;
Iface->nTimeouts ++;
- _SysDebug("State %i repeated, timeout is 3000ms now", newState);
+ _SysDebug("%s: State %i repeated, timeout is 3000ms now",
+ Iface->Adapter,
+ newState);
}
}