bootp_support.c
来自「eCos操作系统源码」· C语言 代码 · 共 654 行 · 第 1/2 页
C
654 行
case TAG_HOST_NAME: for (i = 0; i < *(op+1); i++) { name[i] = *(op+i+2); } name[*(op+1)] = '\0'; if (*op == TAG_DOMAIN_NAME) ap = " domain name"; if (*op == TAG_HOST_NAME) ap = " host name"; diag_printf(" %s: %s\n", ap, name); break; case TAG_DHCP_MESS_TYPE: diag_printf(" DHCP message: %d %s\n", op[2], _dhcpmsgs[op[2]] ); break; case TAG_DHCP_REQ_IP: diag_printf(" DHCP requested ip: %d.%d.%d.%d\n", op[2], op[3], op[4], op[5] ); break; case TAG_DHCP_LEASE_TIME : case TAG_DHCP_RENEWAL_TIME : case TAG_DHCP_REBIND_TIME : diag_printf(" DHCP time %d: %d\n", *op, ((((((op[2]<<8)+op[3])<<8)+op[4])<<8)+op[5]) ); break; case TAG_DHCP_SERVER_ID : diag_printf(" DHCP server id: %d.%d.%d.%d\n", op[2], op[3], op[4], op[5] ); break; case TAG_DHCP_OPTOVER : case TAG_DHCP_PARM_REQ_LIST: case TAG_DHCP_TEXT_MESSAGE : case TAG_DHCP_MAX_MSGSZ : case TAG_DHCP_CLASSID : case TAG_DHCP_CLIENTID : diag_printf(" DHCP option: %x/%d.%d:", *op, *op, *(op+1)); if ( 1 == op[1] ) diag_printf( " %d", op[2] ); else if ( 2 == op[1] ) diag_printf( " %d", (op[2]<<8)+op[3] ); else if ( 4 == op[1] ) diag_printf( " %d", ((((((op[2]<<8)+op[3])<<8)+op[4])<<8)+op[5]) ); else for ( i = 2; i < 2 + op[1]; i++ ) diag_printf(" %d",op[i]); diag_printf("\n"); break; case TAG_NTP_SERVER: diag_printf(" NTP servers: "); for ( i = 0 ; i < op[1]/4 ; i++) { diag_printf("%d.%d.%d.%d ", op[1+i*4+1], op[1+i*4+2], op[1+i*4+3], op[1+i*4+4]); } diag_printf("\n"); break; default: diag_printf("Unknown option: %x/%d.%d:", *op, *op, *(op+1)); for ( i = 2; i < 2 + op[1]; i++ ) diag_printf(" %d",op[i]); diag_printf("\n"); break; } op += *(op+1)+2; } }}cyg_bool_tget_bootp_option(struct bootp *bp, unsigned char tag, void *opt, unsigned int *length){ unsigned char *val = (unsigned char *)opt; int i; cyg_uint8 optover; #define SCANTAG( ptr ) CYG_MACRO_START \ unsigned int max; \ unsigned char *op = (ptr); \ while (*op != TAG_END) { \ if (*op == tag) { \ max=(*(op+1)>*length ? *length : *(op+1)); \ for (i = 0; i < max; i++) { \ *val++ = *(op+i+2); \ } \ *length=max; \ return true; \ } \ if (*op == TAG_PAD) { \ op++; \ } else { \ op += *(op+1)+2; \ } \ } \CYG_MACRO_END SCANTAG( &bp->bp_vend[4] ); if ( TAG_DHCP_OPTOVER == tag ) // prevent recursion > once return false; // else, look for that tag to see if there's more... optover = 0; if ( ! get_bootp_option( bp, TAG_DHCP_OPTOVER, &optover, length) ) return false; if ( 1 & optover ) // then the file field also holds options SCANTAG( &bp->bp_file[0] ); if ( 2 & optover ) // then the sname field also holds options SCANTAG( &bp->bp_sname[0] ); return false;}// [Re]initialize the network interface with the info passed from BOOTPcyg_bool_tinit_net(const char *intf, struct bootp *bp){ struct sockaddr_in *addrp; struct ifreq ifr; int s=-1; int one = 1; struct ecos_rtentry route; struct in_addr netmask, gateway; unsigned int length; int retcode = false; 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 = bp->bp_yiaddr; // The address BOOTP gave us // Must do this temporarily with default route and netmask so that // [sub]netmask can be set. strcpy(ifr.ifr_name, intf); if (ioctl(s, SIOCSIFADDR, &ifr)) { perror("SIOCIFADDR"); goto out; } length = sizeof(addrp->sin_addr); if (get_bootp_option(bp, TAG_SUBNET_MASK, &addrp->sin_addr,&length)) { netmask = addrp->sin_addr; if (ioctl(s, SIOCSIFNETMASK, &ifr)) { perror("SIOCSIFNETMASK"); goto out; } // Must do this again so that [sub]netmask (and so default route) // is taken notice of. addrp->sin_addr = bp->bp_yiaddr; // The address BOOTP gave us if (ioctl(s, SIOCSIFADDR, &ifr)) { perror("SIOCIFADDR 2"); goto out; } } length = sizeof(addrp->sin_addr); if (get_bootp_option(bp, TAG_IP_BROADCAST, &addrp->sin_addr,&length)) { if (ioctl(s, SIOCSIFBRDADDR, &ifr)) { perror("SIOCSIFBRDADDR"); goto out; } // Do not re-set the IFADDR after this; doing *that* resets the // BRDADDR to the default! } ifr.ifr_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING; if (ioctl(s, SIOCSIFFLAGS, &ifr)) { perror("SIOCSIFFLAGS"); goto out; } // Set up routing length = sizeof(addrp->sin_addr); if (get_bootp_option(bp, TAG_GATEWAY, &gateway,&length)) { // ...and it's a nonzero address... if ( 0 != gateway.s_addr ) { memset(&route, 0, sizeof(route)); addrp->sin_family = AF_INET; addrp->sin_port = 0; addrp->sin_len = sizeof(*addrp); addrp->sin_addr.s_addr = 0; // Use 0,0,GATEWAY for the default route memcpy(&route.rt_dst, addrp, sizeof(*addrp)); addrp->sin_addr.s_addr = 0; memcpy(&route.rt_genmask, addrp, sizeof(*addrp)); addrp->sin_addr = gateway; memcpy(&route.rt_gateway, 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)) { diag_printf("Route - dst: %s", inet_ntoa(((struct sockaddr_in *)&route.rt_dst)->sin_addr)); diag_printf(", mask: %s", inet_ntoa(((struct sockaddr_in *)&route.rt_genmask)->sin_addr)); diag_printf(", gateway: %s\n", inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr)); if (errno != EEXIST) { perror("SIOCADDRT 3"); goto out; } } } } retcode = true; #ifdef CYGINT_ISO_DNS {#define MAX_IP_ADDR_LEN 16 char buf[BP_MAX_OPTION_LEN+1]; memset(buf,0,sizeof(buf)); length = sizeof(buf); if (get_bootp_option(bp, TAG_DOMAIN_NAME, buf, &length)) { setdomainname(buf, length); } length = sizeof(buf); if (get_bootp_option(bp, TAG_DOMAIN_SERVER, buf, &length)) { cyg_dns_res_init((struct in_addr *)buf); } }#endif#ifdef CYGNUM_NET_SNTP_UNICAST_MAXDHCP { struct in_addr dhcp_addrs[CYGNUM_NET_SNTP_UNICAST_MAXDHCP]; /* Removed any previously registered addresses */ cyg_sntp_set_servers(NULL, 0); /* See if we received any NTP servers from DHCP */ length = sizeof(dhcp_addrs); if (get_bootp_option(bp, TAG_NTP_SERVER, &dhcp_addrs[0], &length)) { static struct sockaddr ntp_servers[CYGNUM_NET_SNTP_UNICAST_MAXDHCP]; struct servent *service; cyg_uint32 num; /* See how many addresses we got. The length should always * be a multiple of 4, but cut off any extra bytes and * use what we got. */ length /= sizeof(struct in_addr); /* Fill out a sockaddr array for the NTP client */ service = getservbyname("ntp", "udp"); CYG_CHECK_DATA_PTR(service, "NTP service not found."); memset(&ntp_servers[0], 0, sizeof(ntp_servers)); for (num = 0; num < length; num++) { struct sockaddr_in *saddr = (struct sockaddr_in *)&ntp_servers[num]; saddr->sin_len = sizeof(*saddr); saddr->sin_family = AF_INET; saddr->sin_port = service->s_port; /* Already network-endian */ saddr->sin_addr = dhcp_addrs[num]; /* Already network-endian */ } /* Configure the client with the array */ cyg_sntp_set_servers(&ntp_servers[0], num); } }#endif /* CYGNUM_NET_SNTP_UNICAST_MAXDHCP */ out: if (s != -1) close(s); return retcode;}#ifdef INET6extern const struct in6_addr in6mask128;cyg_bool_tinit_net_IPv6(const char *intf, struct bootp *bp, char *prefix){ int s =-1 ; struct in6_aliasreq in6_addr; char in6_ip[128]; int retcode = false; // Set up non link-layer address s = socket(AF_INET6, SOCK_DGRAM, 0); if (s < 0) { perror("socket IPv6"); goto out; } bzero(&in6_addr, sizeof(in6_addr)); diag_sprintf(in6_ip, "%s::%s", prefix, inet_ntoa(bp->bp_yiaddr)); in6_addr.ifra_addr.sin6_len = sizeof(struct sockaddr_in6); in6_addr.ifra_addr.sin6_family = AF_INET6; if (!inet_pton(AF_INET6, in6_ip, (char *)&in6_addr.ifra_addr.sin6_addr)) { diag_printf("Can't set IPv6 address: %s\n", in6_ip); goto out; } in6_addr.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6); in6_addr.ifra_prefixmask.sin6_family = AF_INET6; in6_addr.ifra_prefixmask.sin6_addr = in6mask128; strcpy(in6_addr.ifra_name, intf); in6_addr.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; in6_addr.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; if (ioctl(s, SIOCAIFADDR_IN6, &in6_addr)) { perror("SIOCAIFADDR_IN6"); goto out; } retcode = true; out: if (s != -1) close(s); return retcode;}#endif// EOF bootp_support.c
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?