Milos RTOS v0.3.4a
Real Time Operating System
Private functions
Collaboration diagram for Private functions:

Functions

__STATIC __VOID __dhcpSetState (__PDHCP dhcp, u8 state)
 Sets a new state for the internal DHCP state machine.
__STATIC __BOOL __dhcpOpenSocket (__PDHCP dhcp)
 Creates a socket for communicating with the the DHCP server.
__STATIC __VOID __dhcpCloseSocket (__PDHCP dhcp)
 Closes the DHCP socket.
__STATIC i32 __dhcpSendBootp (__PSOCKET sock, u32 addr, __PDHCP_BOOTP bootp, u16 opt_len)
 Sends a BOOTP packet through UDP socket sock.
__STATIC u16 __dhcpPrepareBootp (__PDHCP_BOOTP bootp, u8 msgtype, u32 xid, u8 *mac, u32 ciaddr, u16 sec)
 Prepares a __DHCP_BOOTP structure for transmission.
__STATIC i32 __dhcpSendDiscover (__PNETIF netif)
 Broadcasts a discover packet from the Network Interface netif.
__STATIC __VOID __dhcpWait (__PDHCP dhcp, u8 next_state, u8 wait)
 Moves the DHCP state machine to the wait state and waits there for a timeout.
__STATIC i32 __dhcpRecvBootp (__PDHCP dhcp)
 Reads a BOOTP packet from the dhcp structure socket.
__STATIC u8 __dhcpGetMsgIdFromBootp (__PDHCP_BOOTP bootp)
 Retrieves the message ID from a received BOOTP structure.
__STATIC __BOOL __dhcpProcessAck (__PNETIF netif, __PDHCP dhcp)
 Processes an incoming ACK message.
__STATIC __BOOL __dhcpProcessOffer (__PNETIF netif, __PDHCP dhcp)
 Process an incoming DHCP offer message.
__STATIC __BOOL __dhcpRenew (__PNETIF netif, __PDHCP dhcp, u32 serv_addr)
 Sends a request message intended to renew the DHCP leasing.
__STATIC __VOID __dhcpReceiveAck (__PNETIF netif, __PDHCP dhcp, u8 success_state, u8 fail_state)
 Receives for an ACK response from the DHCP server.

Function Documentation

__STATIC __VOID __dhcpSetState ( __PDHCP  dhcp,
u8  state 
)

Sets a new state for the internal DHCP state machine.

Other than setting the new state, this function can output the new state to the debug terminal. Depends on the debug constants in the net.h file.

Parameters:
dhcpPointer to a __DHCP structure.
stateThe new state. A list can be found at States.
Returns:
Nothing.

Definition at line 234 of file dhcp.c.

{
    dhcp->state = state;

#if __NET_DEBUG_DHCP
    NETOUT(__NET_DEBUG_DHCP, ("[DHCP] new state: "));

    switch (state)
    {
        case __DHCP_STATE_IDLE:
            NETMSG(__NET_DEBUG_DHCP, ("IDLE"));
            break;
        case __DHCP_STATE_INIT:
            NETMSG(__NET_DEBUG_DHCP, ("INIT"));
            break;
        case __DHCP_STATE_SELECTING:
            NETMSG(__NET_DEBUG_DHCP, ("SELECTING"));
            break;
        case __DHCP_STATE_REQUESTING:
            NETMSG(__NET_DEBUG_DHCP, ("REQUESTING"));
            break;
        case __DHCP_STATE_INIT_REBOOT:
            NETMSG(__NET_DEBUG_DHCP, ("REBOOT"));
            break;
        case __DHCP_STATE_REBOOTING:
            NETMSG(__NET_DEBUG_DHCP, ("REBOOTING"));
            break;
        case __DHCP_STATE_BOUND:
            NETMSG(__NET_DEBUG_DHCP, ("BOUND"));
            break;
        case __DHCP_STATE_RENEWING:
            NETMSG(__NET_DEBUG_DHCP, ("RENEWING"));
            break;
        case __DHCP_STATE_REBINDING:
            NETMSG(__NET_DEBUG_DHCP, ("REBINDING"));
            break;
        case __DHCP_STATE_WAIT:
            NETMSG(__NET_DEBUG_DHCP, ("WAIT"));
            break;
    }
#endif /* __NET_DEBUG_DHCP */

}

Creates a socket for communicating with the the DHCP server.

The socket will only be created if the sock member of the __DHCP structure is __NULL.

Parameters:
dhcpPointer to a __DHCP structure.
Returns:
__TRUE on success, otherwise __FALSE.

Definition at line 289 of file dhcp.c.

{
    if (!dhcp->sock)
    {
        dhcp->sock = __socketCreate(__SOCK_TYPE_UDP, __DHCP_CLIENT_PORT);
        if (!dhcp->sock) return __FALSE;
    }

    return __TRUE;
}

Here is the call graph for this function:

Closes the DHCP socket.

This function will also destroy the socket.

Parameters:
dhcpPointer to a __DHCP structure.
Returns:
Nothing.

Definition at line 310 of file dhcp.c.

{
    __socketClose(dhcp->sock);
    __socketDestroy(dhcp->sock);
    dhcp->sock = __NULL;
}

Here is the call graph for this function:

__STATIC i32 __dhcpSendBootp ( __PSOCKET  sock,
u32  addr,
__PDHCP_BOOTP  bootp,
u16  opt_len 
)

Sends a BOOTP packet through UDP socket sock.

Parameters:
sockSocket used for the transmission.
addrDHCP server address (in NBO).
bootpPointer to a __DHCP_BOOTP structure to be sent.
opt_lenThe length of the options field of the bootp structure.
Returns:
Zero on success, otherwise non-zero.

Definition at line 328 of file dhcp.c.

{
    u16 len;
    bootp->options[opt_len++] = 0xFF;

    len = sizeof(__DHCP_BOOTP) - sizeof(bootp->options) + opt_len;

    if (len < 300) len = 300;

    if (__socketSendTo(sock, addr, __DHCP_SERVER_PORT, bootp, len) == len)
    {
        return 0;
    }

    return -1;
}

Here is the call graph for this function:

__STATIC u16 __dhcpPrepareBootp ( __PDHCP_BOOTP  bootp,
u8  msgtype,
u32  xid,
u8 *  mac,
u32  ciaddr,
u16  sec 
)

Prepares a __DHCP_BOOTP structure for transmission.

Parameters:
bootpPointer to a __DHCP_BOOTP structure to be filled.
msgtypeType of message (parameter in the options field).
xidTransaction ID to be used.
mac6 bytes length MAC address of the source (local network interface MAC address).
ciaddrClient address (local address) in NBO.
secSeconds from the start of the leasing.
Returns:
The final length of the options field of the __DHCP_BOOTP structure.

Definition at line 358 of file dhcp.c.

{
    u8 values[3] = {1,3,6};
    u8* options;
    u16 len = 0;
    u16 val;

    bootp->op = 1;
    bootp->hw_addr_type = 1;
    bootp->hw_addr_len = 6;
    bootp->hops = 0;
    bootp->xid = xid;
    bootp->secs = sec;
    bootp->flags = __htons(0x8000); /* TODO check if needed */
    __memCpy(bootp->chaddr, mac, 6);

    options = bootp->options;

    /* Magic cookie */
    *(options++) = 0x63;
    *(options++) = 0x82;
    *(options++) = 0x53;
    *(options++) = 0x63;

    len = 4;

    /* Message type */
    __dhcpAdd8bitOption(options, __DHCP_OPT_MSGTYPE, msgtype, len);

    /* Data requested from DHCP server */
    __dhcpAddOption(options, __DHCP_OPT_PARAMSREQUEST, 3, values, len);

    /* Hostname TODO take the value from somewhere else */
    __dhcpAddOption(options, __DHCP_OPT_HOSTNAME, 5, (u8*) "milos", len);

    /* Max. DHCP message size we will accept */
    val = 576;
    __dhcpAdd16bitOption(options, __DHCP_OPT_MAXMSGSIZE, val, len);

    return len;
}

Here is the call graph for this function:

Broadcasts a discover packet from the Network Interface netif.

Parameters:
netifPointer to a Network Interface.
Returns:
Zero on success, otherwise non-zero.

Definition at line 407 of file dhcp.c.

{
    __PDHCP dhcp = (__PDHCP) netif->dhcp;
    __PDHCP_BOOTP bootp;
    u16 len = 0;

    if (!__dhcpOpenSocket(dhcp)) return -1;

    if (dhcp->bootp == __NULL)
    {
        dhcp->bootp = __heapAlloc(sizeof(__DHCP_BOOTP));
        if (!dhcp->bootp)
        {
            __dhcpCloseSocket(dhcp);
            return -1;
        }
    }

    __memSet(dhcp->bootp, 0, sizeof(__DHCP_BOOTP));

    __dhcpRenewXid(dhcp);
    bootp = dhcp->bootp;

    len = __dhcpPrepareBootp(bootp, __DHCP_MSGTYPE_DISCOVER, dhcp->xid, netif->addr.type.mac, 0, 0);

    return __dhcpSendBootp(dhcp->sock, 0xFFFFFFFF, bootp, len);
}

Here is the call graph for this function:

__STATIC __VOID __dhcpWait ( __PDHCP  dhcp,
u8  next_state,
u8  wait 
)

Moves the DHCP state machine to the wait state and waits there for a timeout.

Parameters:
dhcpPointer to a __DHCP structure.
next_stateState to transit after the waiting time expires.
waitTime to wait (in seconds).
Returns:
Nothing.

Definition at line 445 of file dhcp.c.

{
    __dhcpSetState(dhcp, __DHCP_STATE_WAIT);
    dhcp->next_state = next_state;
    dhcp->timer = __systemGetSecondsCount();
    dhcp->wait = wait;
}

Here is the call graph for this function:

Reads a BOOTP packet from the dhcp structure socket.

Parameters:
dhcpPointer to a dhcp structure containing a socket to read the BOOTP packet from.
Returns:
Zero on success, otherwise non-zero.

Definition at line 462 of file dhcp.c.

{
    u32 addr;
    u16 port;
    i32 ret;

    if (!__dhcpOpenSocket(dhcp)) return -1;

    if (dhcp->bootp == __NULL)
    {
        dhcp->bootp = __heapAlloc(sizeof(__DHCP_BOOTP));
        if (!dhcp->bootp) return -1;
    }

    __memSet(dhcp->bootp, 0, sizeof(__DHCP_BOOTP));

    ret = __socketRecvFrom(dhcp->sock, &addr, &port, dhcp->bootp, sizeof(__DHCP_BOOTP));

    if (ret > 0)
    {
        /* Check for (at least) the size of a BOOTP structure plus 4 byte for
         * the magic cookie plus 1 byte for the termination 0xFF */
        if (ret > sizeof(__DHCP_BOOTP) - sizeof(dhcp->bootp->options) + 4 + 1)
        {
            /* Packet should be OK */
            return 0;
        }
    }

    return -1;
}

Here is the call graph for this function:

Retrieves the message ID from a received BOOTP structure.

Parameters:
bootpPointer to a __DHCP_BOOTP structure.
Returns:
The value of the message ID from the options field.

Definition at line 501 of file dhcp.c.

{
    u8* options;
    u32 len;

    options = bootp->options;
    options += 4;
    len = sizeof(bootp->options);

    while (*options != __DHCP_OPT_END && len--)
    {
        if (*(options+1) > len) return __FALSE;

        switch (*options)
        {
            /* Message type */
            case __DHCP_OPT_MSGTYPE:
                /* Check size */
                if (*(++options) != 1) return __FALSE;
                return (*(++options));
        }
    }

    return 0;
}

Processes an incoming ACK message.

Parameters:
netifPointer to a Network Interface.
dhcpPointer to a __DHCP structure.
Returns:
__TRUE if the data in the ACK packet is valid, otherwise __FALSE.

Definition at line 535 of file dhcp.c.

{
    u32 ip = dhcp->bootp->yiaddr;
    u32 gw;
    u32 dns;
    u32 mask;
    u8* options;
    u32 len;

    dns = gw = mask = 0;

    options = dhcp->bootp->options;
    options += 4;
    len = sizeof(dhcp->bootp->options);

    __memSet(&dhcp->lease, 0, sizeof(__DHCP_LEASE));

    while (*options != __DHCP_OPT_END && len--)
    {
        if (*(options+1) > len) return __FALSE;

        switch (*options)
        {
            /* DNS */
            case __DHCP_OPT_DNS:
                /* Check size */
                if (*(++options) != 4) return __FALSE;
                __memCpy(&dns, ++options, 4);
                options += 4;
                break;

            /* Gateway */
            case __DHCP_OPT_GATEWAY:
                /* Check size */
                if (*(++options) != 4) return __FALSE;
                __memCpy(&gw, ++options, 4);
                options += 4;
                break;

            /* Network mask */
            case __DHCP_OPT_NETMASK:
                /* Check size */
                if (*(++options) != 4) return __FALSE;
                __memCpy(&mask, ++options, 4);
                options += 4;
                break;

            case __DHCP_OPT_LEASETIME:
                /* Check size */
                if (*(++options) != 4) return __FALSE;
                __memCpy(&dhcp->lease.lease, ++options, 4);
                options += 4;

                dhcp->lease.lease = __ntohl(dhcp->lease.lease);
                break;

            case __DHCP_OPT_RENEWALTIME:
                if (*(++options) != 4) return __FALSE;
                __memCpy(&dhcp->lease.renewal, ++options, 4);
                options += 4;

                dhcp->lease.renewal = __ntohl(dhcp->lease.renewal);
                break;

            case __DHCP_OPT_REBINDTIME:
                if (*(++options) != 4) return __FALSE;
                __memCpy(&dhcp->lease.rebind, ++options, 4);
                options += 4;

                dhcp->lease.rebind = __ntohl(dhcp->lease.rebind);
                break;

            default:
                ++options;
                options += *options;
                ++options;
                break;
        }
    }

    if (dhcp->lease.lease == 0)
        dhcp->lease.lease = __DHCP_DEFAULT_LEASE_TIME;

    if (dhcp->lease.renewal == 0)
        dhcp->lease.renewal = dhcp->lease.lease / 2;

    if (dhcp->lease.rebind == 0)
        dhcp->lease.rebind = (dhcp->lease.lease - ((dhcp->lease.renewal / 2) / 2));

    dhcp->lease.curr_timer = __systemGetSecondsCount();

    netif->ip = ip;
    netif->mask = mask;
    netif->dns1 = dns;
    netif->gateway = gw;

    __routeAdd(netif, 0, 0, netif->gateway);
    __routeAdd(netif, netif->ip, netif->mask, 0);

    __dhcpCloseSocket(dhcp);
    __heapFree(dhcp->bootp);
    dhcp->bootp = __NULL;

    return __TRUE;
}

Here is the call graph for this function:

Process an incoming DHCP offer message.

This function will send a request packet to the DHCP server if the offer is valid.

Parameters:
netifPointer to a Network Interface.
dhcpPointer to a __DHCP structure.
Returns:
__TRUE if the offer is valid and was successfully processed, otherwise __FALSE.

Definition at line 652 of file dhcp.c.

{
    u32 ouraddr = __ntohl(dhcp->bootp->yiaddr);
    u32 servaddr = __ntohl(dhcp->bootp->siaddr);
    u32 len;
    i32 ret;
    u8* options;

    /* Don't get too greedy. By now just accept the first offer. */
    __memSet(dhcp->bootp, 0, sizeof(__DHCP_BOOTP));

    len = __dhcpPrepareBootp(dhcp->bootp, __DHCP_MSGTYPE_REQUEST, dhcp->xid, netif->addr.type.mac, 0, 0);

    options = dhcp->bootp->options + len;

    __dhcpAdd32bitOption(options, __DHCP_OPT_SID, servaddr, len);
    __dhcpAdd32bitOption(options, __DHCP_OPT_REQIP, ouraddr, len);

    ret = __dhcpSendBootp(dhcp->sock, 0xFFFFFFFF, dhcp->bootp, len);

    return (ret == 0) ? __TRUE : __FALSE;
}

Here is the call graph for this function:

__STATIC __BOOL __dhcpRenew ( __PNETIF  netif,
__PDHCP  dhcp,
u32  serv_addr 
)

Sends a request message intended to renew the DHCP leasing.

Parameters:
netifPointer to a network interface.
dhcpPointer to a __DHCP structure.
serv_addrAddress of the DHCP server (in NBO).
Returns:
__TRUE if the message was sent, otherwise __FALSE.

Definition at line 684 of file dhcp.c.

{
    u32 ouraddr = netif->ip;
    u32 servaddr = serv_addr;
    u32 len;
    i32 ret;

    if (!__dhcpOpenSocket(dhcp)) return __FALSE;

    if (dhcp->bootp == __NULL)
    {
        dhcp->bootp = __heapAllocZero(sizeof(__DHCP_BOOTP));
        if (!dhcp->bootp) return __FALSE;
    }

    __dhcpRenewXid(dhcp);

    len = __dhcpPrepareBootp(dhcp->bootp, __DHCP_MSGTYPE_REQUEST, dhcp->xid, netif->addr.type.mac, 0, 0);

    dhcp->bootp->ciaddr = ouraddr;

    ret = __dhcpSendBootp(dhcp->sock, servaddr, dhcp->bootp, len);

    return (ret == 0) ? __TRUE : __FALSE;
}

Here is the call graph for this function:

__STATIC __VOID __dhcpReceiveAck ( __PNETIF  netif,
__PDHCP  dhcp,
u8  success_state,
u8  fail_state 
)

Receives for an ACK response from the DHCP server.

Parameters:
netifPointer to a network interface.
dhcpPointer to a __DHCP structure.
success_stateOn ACK, the state to transit after validation.
fail_stateOn NAK, the state to transit.
Returns:
Nothing.

Definition at line 720 of file dhcp.c.

{
    /* Read bootp from socket */
    if (__dhcpRecvBootp(dhcp) == 0)
    {
        /* Check for BOOTP == REPLY and same XID */
        if (dhcp->bootp->op == 2 && dhcp->bootp->xid == dhcp->xid)
        {
            /* If msg id == ACK */
            if (__dhcpGetMsgIdFromBootp(dhcp->bootp) == __DHCP_MSGTYPE_ACK)
            {
                NETMSG(__NET_DEBUG_DHCP, ("[DHCP] ACK received"));
                if (__dhcpProcessAck(netif, dhcp))
                {
                    __dhcpSetState(dhcp, success_state);
                }
            } else if (__dhcpGetMsgIdFromBootp(dhcp->bootp) == __DHCP_MSGTYPE_NAK)
            {
                NETMSG(__NET_DEBUG_DHCP, ("[DHCP] NAK received"));
                __dhcpWait(dhcp, fail_state, 1);
            }
        }
    }
}

Here is the call graph for this function:

 All Data Structures Files Functions Variables Typedefs Defines