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

📄 bootp_support.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
//==========================================================================
//
//      lib/bootp_support.c
//
//      Minimal BOOTP functions
//
//==========================================================================
//####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):    gthomas
// Contributors: gthomas
// Date:         2000-01-10
// Purpose:      
// Description:  
//              
//
//####DESCRIPTIONEND####
//
//==========================================================================

// BOOTP support (and a little DHCP support also)

#include <pkgconf/system.h>
#include <pkgconf/net.h>
#include <pkgconf/isoinfra.h>

#include <network.h>
#include <errno.h>
#ifdef CYGPKG_NET_FREEBSD_STACK  // New layout
#include <net/if_var.h>
#include <netinet/in_var.h>
#include <netinet6/nd6.h>
#endif

#ifdef CYGINT_ISO_DNS
#include <netdb.h>
#endif
#ifdef CYGPKG_NET_SNTP
#include <cyg/sntp/sntp.h>
#endif

#ifndef CYGPKG_LIBC_STDIO
#define perror(s) diag_printf(#s ": %s\n", strerror(errno))
#endif

// This function sets up the interface it the simplest configuration.
// Just enough to broadcast a BOOTP request and get a response.
// It returns 'true' if a response was obtained.
cyg_bool_t
do_bootp(const char *intf, struct bootp *recv)
{
    struct sockaddr_in *addrp;
    struct ifreq ifr;
    struct sockaddr_in cli_addr, serv_addr, bootp_server_addr;
    struct ecos_rtentry route;
    int s=-1, addrlen;
    int one = 1;
    struct bootp bootp_xmit;
    unsigned char mincookie[] = {99,130,83,99,255} ;
    struct timeval tv;
    cyg_bool_t retcode = false;

    // 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");
        goto out;
    }

    if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one))) {
        perror("setsockopt");
        goto out;
    }

    addrp = (struct sockaddr_in *) &ifr.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(ifr.ifr_name, intf);
    if (ioctl(s, SIOCSIFADDR, &ifr)) {
        perror("SIOCSIFADDR");
        goto out;
    }

    if (ioctl(s, SIOCSIFNETMASK, &ifr)) {
        perror("SIOCSIFNETMASK");
        goto out;
    }

    /* the broadcast address is 255.255.255.255 */
    memset(&addrp->sin_addr, 255, sizeof(addrp->sin_addr));
    if (ioctl(s, SIOCSIFBRDADDR, &ifr)) {
        perror("SIOCSIFBRDADDR");
        goto out;
    }

    ifr.ifr_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING;
    if (ioctl(s, SIOCSIFFLAGS, &ifr)) {
        perror("SIOCSIFFLAGS");
        goto out;
    }

    if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) {
        perror("SIOCGIFHWADDR");
        goto out;
    }

    // Set up routing
    /* 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_family = AF_INET;
    addrp->sin_port = 0;
    addrp->sin_addr.s_addr = INADDR_ANY;
    memcpy(&route.rt_dst, addrp, sizeof(*addrp));
    memcpy(&route.rt_genmask, addrp, sizeof(*addrp));

    route.rt_dev = ifr.ifr_name;
    route.rt_flags = RTF_UP|RTF_GATEWAY;
    route.rt_metric = 0;

    if (ioctl(s, SIOCADDRT, &route)) {
        if (errno != EEXIST) {
            perror("SIOCADDRT 3");
            goto out;
        }
    }

    memset((char *) &cli_addr, 0, sizeof(cli_addr));
    cli_addr.sin_family = AF_INET;
    cli_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    cli_addr.sin_port = htons(IPPORT_BOOTPC);
    
    if(bind(s, (struct sockaddr *) &cli_addr, sizeof(cli_addr)) < 0) {
        perror("bind error");
        goto out;
    }
    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
        perror("setsockopt SO_REUSEADDR");
        goto out;
    }
    if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one))) {
        perror("setsockopt SO_REUSEPORT");
        goto out;
    }
    
    memset((char *) &serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
    serv_addr.sin_port = htons(IPPORT_BOOTPS);

    // Fill in the BOOTP request
    bzero(&bootp_xmit, sizeof(bootp_xmit));
    if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) {
        perror("SIOCGIFHWADDR");
        goto out;
    }
    bootp_xmit.bp_htype = HTYPE_ETHERNET;
    bootp_xmit.bp_hlen = IFHWADDRLEN;
    bcopy(ifr.ifr_hwaddr.sa_data, &bootp_xmit.bp_chaddr, bootp_xmit.bp_hlen);

    bootp_xmit.bp_secs = 0;
    bcopy(mincookie, bootp_xmit.bp_vend, sizeof(mincookie));

    bootp_xmit.bp_op = BOOTREQUEST;

    if(sendto(s, &bootp_xmit, sizeof(struct bootp), 0, 
              (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        perror("sendto error");
        goto out;
    }

    tv.tv_sec = 5;
    tv.tv_usec = 0;
    setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
    
    // Everything passed here is a success.
    retcode = true;
    
    addrlen = sizeof(bootp_server_addr);
    if (recvfrom(s, recv, sizeof(struct bootp), 0,
                 (struct sockaddr *)&bootp_server_addr, &addrlen) < 0) {
        // This is an "acceptable" error, it means there is no server for
        // us: do not initialize the interface.
        retcode = false;
    }

    // Shut things down regardless of success of rx, otherwise other
    // interfaces cannot be initialised!
    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(ifr.ifr_name, intf);
    if (ioctl(s, SIOCDIFADDR, &ifr)) {
        perror("SIOCDIFADDR");
    }

    // Shut down interface so it can be reinitialized
    ifr.ifr_flags &= ~(IFF_UP | IFF_RUNNING);
    if (ioctl(s, SIOCSIFFLAGS, &ifr)) {
        perror("SIOCSIFFLAGS");
        retcode = false;
    }

 out:
    // All done with socket
    if (s != -1)
      close(s);
    return retcode;
}

static char *_bootp_op[] = {"", "REQUEST", "REPLY"};
static char *_bootp_hw_type[] = {"", "Ethernet", "Exp Ethernet", "AX25",
                                     "Pronet", "Chaos", "IEEE802", "Arcnet"};

static char *_dhcpmsgs[] = {"","DISCOVER", "OFFER", "REQUEST", "DECLINE",
                           "ACK", "NAK", "RELEASE" };

void
show_bootp(const char *intf, struct bootp *bp)
{
    int i, len;
    unsigned char *op, *ap = 0, optover;
    unsigned char name[128];
    struct in_addr addr[32];
    unsigned int length;
    
    diag_printf("BOOTP[%s] op: %s\n", intf, _bootp_op[bp->bp_op]);
    diag_printf("       htype: %s\n", _bootp_hw_type[bp->bp_htype]);
    diag_printf("        hlen: %d\n", bp->bp_hlen );
    diag_printf("        hops: %d\n", bp->bp_hops );
    diag_printf("         xid: 0x%x\n", bp->bp_xid );
    diag_printf("        secs: %d\n", bp->bp_secs );
    diag_printf("       flags: 0x%x\n", bp->bp_flags );
    diag_printf("       hw_addr: ");
    for (i = 0;  i < bp->bp_hlen;  i++) {
        diag_printf("%02x", bp->bp_chaddr[i]);
        if (i != (bp->bp_hlen-1)) diag_printf(":");
    }
    diag_printf("\n");
    diag_printf("     client IP: %s\n", inet_ntoa(bp->bp_ciaddr));
    diag_printf("         my IP: %s\n", inet_ntoa(bp->bp_yiaddr));
    diag_printf("     server IP: %s\n", inet_ntoa(bp->bp_siaddr));
    diag_printf("    gateway IP: %s\n", inet_ntoa(bp->bp_giaddr));

    optover = 0; // See whether sname and file are overridden for options
    length = sizeof(optover);
    (void)get_bootp_option( bp, TAG_DHCP_OPTOVER, &optover, &length );
    if ( !(1 & optover) && bp->bp_sname[0] )
        diag_printf("        server: %s\n", bp->bp_sname);
    if ( ! (2 & optover) && bp->bp_file[0] )
        diag_printf("          file: %s\n", bp->bp_file);
    if (bp->bp_vend[0]) {
        diag_printf("  options:\n");
        op = &bp->bp_vend[4];
        while (*op != TAG_END) {
            switch (*op) {
            case TAG_PAD:
                op++;
                continue;
            case TAG_SUBNET_MASK:
            case TAG_GATEWAY:
            case TAG_IP_BROADCAST:
            case TAG_DOMAIN_SERVER:
                ap = (unsigned char *)&addr[0];
                len = *(op+1);
                for (i = 0;  i < len;  i++) {
                    *ap++ = *(op+i+2);
                }
                if (*op == TAG_SUBNET_MASK)   ap =  "  subnet mask";
                if (*op == TAG_GATEWAY)       ap =  "      gateway";
                if (*op == TAG_IP_BROADCAST)  ap =  " IP broadcast";
                if (*op == TAG_DOMAIN_SERVER) ap =  "domain server";
                diag_printf("      %s: ", ap);
                ap = (unsigned char *)&addr[0];
                while (len > 0) {
                    diag_printf("%s", inet_ntoa(*(struct in_addr *)ap));
                    len -= sizeof(struct in_addr);
                    ap += sizeof(struct in_addr);
                    if (len) diag_printf(", ");
                }
                diag_printf("\n");
                break;
            case TAG_DOMAIN_NAME:

⌨️ 快捷键说明

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