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

📄 dhcp_prot.c

📁 ecos实时嵌入式操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
/*==========================================================================////      dhcp_prot.c////      DHCP protocol implementation for DHCP client////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):   hmt// Contributors: gthomas// Date:        2000-07-01// Purpose:     DHCP support// Description: ////####DESCRIPTIONEND####////========================================================================*/#include <pkgconf/system.h>#include <pkgconf/net.h>#ifdef CYGPKG_NET_DHCP#if 0#define perror( txt ) // nothing#endif#include <network.h>#include <dhcp.h>#include <errno.h>#include <cyg/infra/cyg_ass.h>#ifdef INET6#include <net/if_var.h>#include <netinet6/in6_var.h>#endif// ------------------------------------------------------------------------// Returns a pointer to the end of dhcp message (or NULL if invalid)// meaning the address of the byte *after* the TAG_END token in the vendor// data.static unsigned char *scan_dhcp_size( struct bootp *ppkt ){    unsigned char *op;        op = &ppkt->bp_vend[0];    // First check for the cookie!    if ( op[0] !=  99 ||         op[1] != 130 ||         op[2] !=  83 ||         op[3] !=  99 ) {        CYG_FAIL( "Bad DHCP cookie" );        return NULL;    }    op += 4;    while (*op != TAG_END) {        op += *(op+1)+2;        if ( op > &ppkt->bp_vend[BP_VEND_LEN-1] ) {            CYG_FAIL( "Oversize DHCP packet in dhcp_size" );            return NULL;        }    }    // Check op has not gone wild    CYG_ASSERT( op > (unsigned char *)(&ppkt[0]), "op pointer underflow!" );    // Compare op with non-existent "next" struct bootp in the array.    CYG_ASSERT( op < (unsigned char *)(&ppkt[1]), "op pointer overflow!" );    return op + 1; // Address of first invalid byte}// ------------------------------------------------------------------------// Get the actual packet size of an initialized bufferstatic intdhcp_size( struct bootp *ppkt ){    unsigned char *op;    op = scan_dhcp_size( ppkt );    if ( !op ) return 0;    return (op - (unsigned char *)ppkt);}// ------------------------------------------------------------------------// Get the actual packet size of an initialized buffer// This will also pad the packet with 0 if length is less// than BP_STD_TX_MINPKTSZ.static intdhcp_size_for_send( struct bootp *ppkt ){    unsigned char *op;    op = scan_dhcp_size( ppkt );    if ( !op ) return 0; // Better not scribble!    // Zero extra bytes until the packet is large enough.    for ( ; op < (((unsigned char *)ppkt) + BP_STD_TX_MINPKTSZ); op++ )        *op = 0;    return (op - (unsigned char *)ppkt);}// ------------------------------------------------------------------------// Insert/set an option value in an initialized bufferstatic intset_fixed_tag( struct bootp *ppkt,               unsigned char tag,               cyg_uint32 value,               int len){    unsigned char *op;    // Initially this will only scan the options field.        op = &ppkt->bp_vend[4];    while (*op != TAG_END) {        if ( op > &ppkt->bp_vend[BP_VEND_LEN-1] ) {            CYG_FAIL( "Oversize DHCP packet in set_fixed_tag" );            return false;        }        if (*op == tag)                 // Found it...            break;        op += *(op+1)+2;    }        if (*op == tag) { // Found it...        if ( *(op+1) != len ) {            CYG_FAIL( "Wrong size in set_fixed_tag" );            return false;           // wrong size        }    }    else { // overwrite the end tag and install a new one        if ( op + len + 2 > &ppkt->bp_vend[BP_VEND_LEN-1] ) {            CYG_FAIL( "Oversize DHCP packet in set_fixed_tag append" );            return false;        }        *op = tag;        *(op+1) = len;        *(op + len + 2) = TAG_END;    }    // and insert the value.  Net order is BE.    op += len + 2 - 1;              // point to end of value    while ( len-- > 0 ) {        *op-- = (unsigned char)(value & 255);        value >>= 8;    }    return true;}// Note that this does not permit changing the size of an extant tag.static intset_variable_tag( struct bootp *ppkt,               unsigned char tag,               cyg_uint8 *pvalue,               int len){    unsigned char *op;    // Initially this will only scan the options field.    op = &ppkt->bp_vend[4];    while (*op != TAG_END) {        if ( op > &ppkt->bp_vend[BP_VEND_LEN-1] ) {            CYG_FAIL( "Oversize DHCP packet in set_variable_tag" );            return false;        }        if (*op == tag)                 // Found it...            break;        op += *(op+1)+2;    }        if (*op == tag) { // Found it...        if ( *(op+1) != len ) {            CYG_FAIL( "Wrong size in set_variable_tag" );            return false;           // wrong size        }    }    else { // overwrite the end tag and install a new one        if ( op + len + 2 > &ppkt->bp_vend[BP_VEND_LEN-1] ) {            CYG_FAIL( "Oversize DHCP packet in set_variable_tag append" );            return false;        }        *op = tag;        *(op+1) = len;        *(op + len + 2) = TAG_END;    }    // and insert the value.  No order is implied.    op += 2;               // point to start of value    while ( len-- > 0 ) {        *op++ = *pvalue++;    }    return true;}static intunset_tag( struct bootp *ppkt,           unsigned char tag ){    unsigned char *op, *nextp = 0, *killp = 0;    // Initially this will only scan the options field.        op = &ppkt->bp_vend[4];    while (*op != TAG_END) {        if ( op > &ppkt->bp_vend[BP_VEND_LEN-1] ) {            CYG_FAIL( "Oversize DHCP packet in unset_tag" );            return false;        }        if (*op == tag) {               // Found it...            killp = op;                 // item to kill            nextp = op + *(op+1)+2;     // next item address        }        op += *(op+1)+2;                // scan to the end    }    if ( !killp )        return false;    // Obliterate the found op by copying down: *op is the end.    while( nextp <= op )                // <= to copy the TAG_END too.        *killp++ = *nextp++;        return true;}// ------------------------------------------------------------------------// Bring up an interface enough to broadcast, before we know who we arestatic intbring_half_up(const char *intf, struct ifreq *ifrp ){    int s;    int one = 1;    struct sockaddr_in *addrp;    struct ecos_rtentry route;    // Ensure clean slate    cyg_route_reinit();  // Force any existing routes to be forgotten    s = socket(AF_INET, SOCK_DGRAM, 0);    if (s < 0) {        perror("socket");        return false;    }    if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one))) {        perror("setsockopt");        return false;    }    addrp = (struct sockaddr_in *) &ifrp->ifr_addr;    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;    strcpy(ifrp->ifr_name, intf);    if (ioctl(s, SIOCSIFADDR, ifrp)) { /* set ifnet address */        perror("SIOCSIFADDR");        return false;    }    if (ioctl(s, SIOCSIFNETMASK, ifrp)) { /* set net addr mask */        perror("SIOCSIFNETMASK");        return false;    }    /* the broadcast address is 255.255.255.255 */    memset(&addrp->sin_addr, 255, sizeof(addrp->sin_addr));    if (ioctl(s, SIOCSIFBRDADDR, ifrp)) { /* set broadcast addr */        perror("SIOCSIFBRDADDR");        return false;    }    ifrp->ifr_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING;    if (ioctl(s, SIOCSIFFLAGS, ifrp)) { /* set ifnet flags */        perror("SIOCSIFFLAGS up");        return false;    }    if (ioctl(s, SIOCGIFHWADDR, ifrp) < 0) { /* get MAC address */        perror("SIOCGIFHWADDR 1");        return false;    }    // Set up routing    addrp->sin_family = AF_INET;    addrp->sin_port = 0;    addrp->sin_len = sizeof(*addrp);  // Size of address    /* the broadcast address is 255.255.255.255 */    memset(&addrp->sin_addr, 255, sizeof(addrp->sin_addr));    memset(&route, 0, sizeof(route));    memcpy(&route.rt_gateway, addrp, sizeof(*addrp));    addrp->sin_addr.s_addr = INADDR_ANY;    memcpy(&route.rt_dst, addrp, sizeof(*addrp));    memcpy(&route.rt_genmask, addrp, sizeof(*addrp));    route.rt_dev = ifrp->ifr_name;    route.rt_flags = RTF_UP|RTF_GATEWAY;    route.rt_metric = 0;    if (ioctl(s, SIOCADDRT, &route)) { /* add route */

⌨️ 快捷键说明

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