📄 bootp_support.c
字号:
//==========================================================================//// 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#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_tdo_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, addrlen; int one = 1; struct bootp bootp_xmit; unsigned char mincookie[] = {99,130,83,99,255} ; struct timeval tv; cyg_bool_t retcode = true; // 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 *) &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"); return false; } if (ioctl(s, SIOCSIFNETMASK, &ifr)) { 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, &ifr)) { perror("SIOCSIFBRDADDR"); return false; } ifr.ifr_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING; if (ioctl(s, SIOCSIFFLAGS, &ifr)) { perror("SIOCSIFFLAGS"); return false; } if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) { perror("SIOCGIFHWADDR"); return false; } // 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"); return false; } } 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"); return false; } if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) { perror("setsockopt SO_REUSEADDR"); return false; } if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one))) { perror("setsockopt SO_REUSEPORT"); return false; } 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"); return false; } 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"); return false; } tv.tv_sec = 5; tv.tv_usec = 0; setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); 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"); return false; } // All done with socket 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" };voidshow_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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -