📄 bootp_support.c
字号:
switch (*op) { 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: 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; 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; \ } \ 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; int one = 1; struct ecos_rtentry route; struct in_addr netmask, gateway; unsigned int length; 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 = 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"); return false; } 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"); return false; } // 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"); return false; } } length = sizeof(addrp->sin_addr); if (get_bootp_option(bp, TAG_IP_BROADCAST, &addrp->sin_addr,&length)) { if (ioctl(s, SIOCSIFBRDADDR, &ifr)) { perror("SIOCSIFBRDADDR"); return false; } // 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"); return false; } // 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"); return false; } } } } close(s);#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 return true;}#ifdef INET6extern const struct in6_addr in6mask128;cyg_bool_tinit_net_IPv6(const char *intf, struct bootp *bp, char *prefix){ int s; struct in6_aliasreq in6_addr; char in6_ip[128]; // Set up non link-layer address s = socket(AF_INET6, SOCK_DGRAM, 0); if (s < 0) { perror("socket IPv6"); return false; } 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); return false; } 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"); return false; } close(s); return true;}#endif// EOF bootp_support.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -