📄 bootp_support.c
字号:
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_t
get_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 BOOTP
cyg_bool_t
init_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 INET6
extern const struct in6_addr in6mask128;
cyg_bool_t
init_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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -