⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dhcp_prot.c

📁 Mavell 无线模块原厂IC AP32源代码。DHCP客户端与服务端源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
                *pstate = DHCPSTATE_RENEWING;                break;            }            // Check for well-formed packet with correct termination (not truncated)            length = dhcp_size( received );#ifdef CYGDBG_NET_DHCP_CHATTER            diag_printf( "---------DHCPSTATE_RENEW_RECV received:\n" );            if ( length <= 0 )                diag_printf( "WARNING! malformed or truncated packet\n" );            diag_printf( "...rx_addr is family %d, addr %08x, port %d\n",                         rx_addr.sin_family,                         rx_addr.sin_addr.s_addr,                         rx_addr.sin_port );            show_bootp( intf, received );#endif            if ( length <= 0 )                break;            if ( CHECK_XID() )          // not the same transaction;                break;                  // listen again...            if ( 0 == received->bp_siaddr.s_addr )            {                // then fill in from the options...                length = sizeof(received->bp_siaddr.s_addr);                get_bootp_option( received, TAG_DHCP_SERVER_ID,                                  &received->bp_siaddr.s_addr);            }            // check it was a DHCP reply            length = sizeof(msgtype);            if ( get_bootp_option( received, TAG_DHCP_MESS_TYPE, &msgtype) )            {                if ( DHCPACK == msgtype  // Same offer?                        && received->bp_yiaddr.s_addr == xmit->bp_yiaddr.s_addr)                {                    // we like the packet, so reset the timeout for next time                    reset_timeout( &tv, &timeout_scratch );                    // Record the new lease and set up timers &c                    new_lease( received, lease );                    *pstate = DHCPSTATE_BOUND;                    break;                }                if ( DHCPNAK == msgtype )                { // we're bounced!                    *pstate = DHCPSTATE_NOTBOUND;  // So quit out.                    break;                }                // otherwise it's something else, maybe another offer.                // Just listen again, which implicitly discards it.            }            break;        case DHCPSTATE_REBINDING:            // Just send what you got with a DHCPREQUEST in the message type.            // Then wait for an ACK.  This one is BROADCAST.            // Fill in the BOOTP request - DHCPREQUEST packet            xmit->bp_xid = xid;            xmit->bp_op = BOOTREQUEST;            xmit->bp_flags = htons(0); // no BROADCAST FLAG            // Use the *client* address here:            xmit->bp_ciaddr.s_addr = xmit->bp_yiaddr.s_addr;            set_fixed_tag( xmit, TAG_DHCP_MESS_TYPE, DHCPREQUEST, 1 );            // These must not be set in this context            unset_tag( xmit, TAG_DHCP_REQ_IP );            unset_tag( xmit, TAG_DHCP_SERVER_ID );            // Set all the tags we want to use when sending a packet            set_default_dhcp_tags( xmit );#ifdef CYGDBG_NET_DHCP_CHATTER            diag_printf( "---------DHCPSTATE_REBINDING sending:\n" );            show_bootp( intf, xmit );#endif            // Send back a [modified] copy.  Note that some fields are explicitly            // cleared, as per the RFC.  We need the copy because these fields are            // still useful to us (and currently stored in the 'result' structure)            xlen = dhcp_size_for_send( xmit );            bcopy( xmit, &xmit2, xlen );            xmit2.bp_yiaddr.s_addr = xmit2.bp_siaddr.s_addr = xmit2.bp_giaddr.s_addr = 0;            xmit2.bp_hops = 0;#ifdef ORIG_DHCP_CODE            if (sendto(s, &xmit2, xlen, 0,                       (struct sockaddr *)&broadcast_addr, sizeof(broadcast_addr)) < 0)#else            if(dhcp_send_broadcast_to_driver(xlen,(cyg_uint8 *) &xmit2,ifr.ifr_hwaddr.sa_data) < 0 )#endif            {                *pstate = DHCPSTATE_FAILED;                break;            }            *pstate = DHCPSTATE_REBIND_RECV;            break;        case DHCPSTATE_REBIND_RECV:            // wait for an ACK or a NACK - retry by going back to            // DHCPSTATE_REBINDING; NACK means go to NOTBOUND.            // No answer means just wait for expiry; we tried!            setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));            addrlen = sizeof(rx_addr);            if (recvfrom(s, received, sizeof(struct bootp), 0,                         (struct sockaddr *)&rx_addr, &addrlen) < 0)            {                // No packet arrived                // go to the next larger timeout and re-send:                if ( ! next_timeout( &tv, &timeout_scratch ) )                {                    // If we timed out completely, just give up until EX                    // expires - retain the lease meanwhile.  The normal                    // lease mechanism will invoke NOTBOUND state as and                    // when necessary.                    *pstate = DHCPSTATE_BOUND;                    break;                }                *pstate = DHCPSTATE_REBINDING;                break;            }            // Check for well-formed packet with correct termination (not truncated)            length = dhcp_size( received );#ifdef CYGDBG_NET_DHCP_CHATTER            diag_printf( "---------DHCPSTATE_REBIND_RECV received:\n" );            if ( length <= 0 )                diag_printf( "WARNING! malformed or truncated packet\n" );            diag_printf( "...rx_addr is family %d, addr %08x, port %d\n",                         rx_addr.sin_family,                         rx_addr.sin_addr.s_addr,                         rx_addr.sin_port );            show_bootp( intf, received );#endif            if ( length <= 0 )                break;            if ( CHECK_XID() )          // not the same transaction;                break;                  // listen again...            if ( 0 == received->bp_siaddr.s_addr )            {                // then fill in from the options...                //int length = sizeof(received->bp_siaddr.s_addr );                get_bootp_option( received, TAG_DHCP_SERVER_ID,                                  &received->bp_siaddr.s_addr);            }            // check it was a DHCP reply            length = sizeof(msgtype);            if ( get_bootp_option( received, TAG_DHCP_MESS_TYPE, &msgtype) )            {                if ( DHCPACK == msgtype  // Same offer?                        && received->bp_yiaddr.s_addr == xmit->bp_yiaddr.s_addr)                {                    // we like the packet, so reset the timeout for next time                    reset_timeout( &tv, &timeout_scratch );                    // Record the new lease and set up timers &c                    new_lease( received, lease );                    *pstate = DHCPSTATE_BOUND;                    break;                }                else if ( DHCPNAK == msgtype )                { // we're bounced!                    *pstate = DHCPSTATE_NOTBOUND;  // So back the start of the rigmarole.                    break;                }                // otherwise it's something else, maybe another offer.                // Just listen again, which implicitly discards it.            }            break;        case DHCPSTATE_BOOTP_FALLBACK:            // All done with socket            close(s);            // And no lease should have become active, but JIC            no_lease( lease );            // Re-initialize the interface with the new state            if ( DHCPSTATE_BOOTP_FALLBACK != oldstate )            {                // Then need to go down and up                do_dhcp_down_net( intf, res, &oldstate, lease ); // oldstate used                if ( 0 != oldstate )                {                    // Then not called from init_all_network_interfaces()                    // so we must initialize the interface ourselves                    if (!init_net(intf, res))                    {                        do_dhcp_down_net( intf, res, pstate, lease );                        *pstate = DHCPSTATE_FAILED;                        return false;                    }                }            }            // Otherwise, nothing whatsoever to do...            return true;        case DHCPSTATE_NOTBOUND:            // All done with socket            close(s);            // No lease active            no_lease( lease );            // Leave interface up so app can tidy.            return false;        case DHCPSTATE_FAILED:            // All done with socket            close(s);            // No lease active            no_lease( lease );            // Unconditionally down the interface.            do_dhcp_down_net( intf, res, &oldstate, lease );            return false;        case DHCPSTATE_DO_RELEASE:            // We have been forced here by external means, to release the            // lease for graceful shutdown.            // Just send what you got with a DHCPRELEASE in the message            // type UNICAST straight to the server.  No ACK.  Then go to            // NOTBOUND state.            NEW_XID( xid );            xmit->bp_xid = xid;            xmit->bp_op = BOOTREQUEST;            xmit->bp_flags = htons(0); // no BROADCAST FLAG            // Use the *client* address here:            xmit->bp_ciaddr.s_addr = xmit->bp_yiaddr.s_addr;            set_fixed_tag( xmit, TAG_DHCP_MESS_TYPE, DHCPRELEASE, 1 );            // Set unicast address to *server*            server_addr.sin_addr.s_addr = res->bp_siaddr.s_addr;#ifdef CYGDBG_NET_DHCP_CHATTER            diag_printf( "---------DHCPSTATE_DO_RELEASE sending:\n" );            diag_printf( "UNICAST to family %d, addr %08x, port %d\n",                         server_addr.sin_family,                         server_addr.sin_addr.s_addr,                         server_addr.sin_port );            show_bootp( intf, xmit );#endif            // Send back a [modified] copy.  Note that some fields are explicitly            // cleared, as per the RFC.  We need the copy because these fields are            // still useful to us (and currently stored in the 'result' structure)            xlen = dhcp_size_for_send( xmit );            bcopy( xmit, &xmit2, xlen );            xmit2.bp_yiaddr.s_addr = xmit2.bp_siaddr.s_addr = xmit2.bp_giaddr.s_addr = 0;            xmit2.bp_hops = 0;            if (sendto(s, &xmit2, xlen, 0,                       // UNICAST address of the server:                       (struct sockaddr *)&server_addr,                       sizeof(server_addr)) < 0)            {                *pstate = DHCPSTATE_FAILED;                break;            }            *pstate = DHCPSTATE_NOTBOUND;            break;        default:            no_lease( lease );            close(s);            return false;        }    }    /* NOTREACHED */    return false;}// ------------------------------------------------------------------------// Bring an interface down, failed to initialize it or lease is expired// Also part of normal startup, bring down for proper reinitializationint do_dhcp_down_net(const char *intf, struct bootp *res,                 cyg_uint8 *pstate, struct dhcp_lease *lease){    struct sockaddr_in *addrp;    struct ifreq ifr;    int s;#ifdef CYGDBG_NET_DHCP_CHATTER     diag_printf("do_dhcp_down_net:  on interface %s, state %d\n",intf, *pstate);#endif    // Ensure clean slate/* Nimrod S removed route_reinit call - cleans also LAN side configuration *///    route_reinit();  // Force any existing routes to be forgotten    s = socket(AF_INET, SOCK_DGRAM, 0);    if (s < 0)    {        perror("socket");        return false;    }    addrp = (struct sockaddr_in *) &ifr.ifr_addr;    // Remove any existing address    if ( DHCPSTATE_FAILED == *pstate            || DHCPSTATE_INIT == *pstate            || 0 == *pstate )    {        // it was configured for broadcast only, "half-up"        memset(addrp, 0, sizeof(*addrp));        addrp->sin_family = AF_INET;        addrp->sin_len = sizeof(*addrp);        addrp->sin_port = 0;        addrp->sin_addr.s_addr = INADDR_ANY;    }    else    {        // get the specific address that was used        strcpy(ifr.ifr_name, intf);        if (ioctl(s, SIOCGIFADDR, &ifr))        {            perror("SIOCGIFADDR 1");            close(s);            return false;        }    }    strcpy(ifr.ifr_name, intf);    if (ioctl(s, SIOCDIFADDR, &ifr))    { /* delete IF addr */        perror("SIOCDIFADDR1");    }#ifdef INET6    {        int s6;        s6 = socket(AF_INET6, SOCK_DGRAM, 0);        if (s6 < 0)        {            perror("socket AF_INET6");            return false;        }        // Now delete the ipv6 addr        strcpy(ifr.ifr_name, intf);        if (ioctl(s6, SIOCGLIFADDR, &ifr))        {            perror("SIOCGIFADDR_IN6 1");            return false;        }        strcpy(ifr.ifr_name, intf);        if (ioctl(s6, SIOCDLIFADDR, &ifr))        { /* delete IF addr */            perror("SIOCDIFADDR_IN61");        }        close(s6);    }#endif /* IP6 */    // Shut down interface so it can be reinitialized    ifr.ifr_flags &= ~(IFF_UP | IFF_RUNNING);    if (ioctl(s, SIOCSIFFLAGS, &ifr))    { /* set ifnet flags */        perror("SIOCSIFFLAGS down");        close(s);        return false;    }    // All done with socket    close(s);    if ( 0 != *pstate ) // preserve initial state        *pstate = DHCPSTATE_INIT;    return true;}// ------------------------------------------------------------------------// Release (relinquish) a leased address - if we have one - and bring down// the interface.int do_dhcp_release(const char *intf, struct bootp *res,                cyg_uint8 *pstate, struct dhcp_lease *lease){#ifdef CYGDBG_NET_DHCP_CHATTER     diag_printf("do_dhcp_release:  on interface %s\n",intf);#endif    if ( 0 != *pstate            && DHCPSTATE_INIT != *pstate            && DHCPSTATE_NOTBOUND != *pstate            && DHCPSTATE_FAILED != *pstate            && DHCPSTATE_BOOTP_FALLBACK != *pstate )    {        *pstate = DHCPSTATE_DO_RELEASE;        do_dhcp( intf, res, pstate, lease ); // to send the release packet        cyg_thread_delay( 100 );             // to let it leave the building    }    return true;}// ------------------------------------------------------------------------#endif // CYGPKG_NET_DHCP// EOF dhcp_prot.c

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -