📄 dhcpc.c
字号:
} optptr += optptr[1] + 2; } return type;}/**************************************************************************** * Name: dhcpc_parsemsg ****************************************************************************/static uint8 dhcpc_parsemsg(struct dhcpc_state_s *pdhcpc, int buflen, struct dhcpc_state *presult){ if (pdhcpc->packet.op == DHCP_REPLY && memcmp(pdhcpc->packet.xid, xid, sizeof(xid)) == 0 && memcmp(pdhcpc->packet.chaddr, pdhcpc->ds_macaddr, pdhcpc->ds_maclen) == 0) { memcpy(&presult->ipaddr.s_addr, pdhcpc->packet.yiaddr, 4); return dhcpc_parseoptions(presult, &pdhcpc->packet.options[4], buflen); } return 0;}/**************************************************************************** * Global Functions ****************************************************************************//**************************************************************************** * Name: dhcpc_open ****************************************************************************/void *dhcpc_open(const void *macaddr, int maclen){ struct dhcpc_state_s *pdhcpc; struct sockaddr_in addr; struct timeval tv; dbg("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", ((uint8*)macaddr)[0], ((uint8*)macaddr)[1], ((uint8*)macaddr)[2], ((uint8*)macaddr)[3], ((uint8*)macaddr)[4], ((uint8*)macaddr)[5]); /* Allocate an internal DHCP structure */ pdhcpc = (struct dhcpc_state_s *)malloc(sizeof(struct dhcpc_state_s)); if (pdhcpc) { /* Initialize the allocated structure */ memset(pdhcpc, 0, sizeof(struct dhcpc_state_s)); pdhcpc->ds_macaddr = macaddr; pdhcpc->ds_maclen = maclen; /* Create a UDP socket */ pdhcpc->sockfd = socket(PF_INET, SOCK_DGRAM, 0); if (pdhcpc->sockfd < 0) { free(pdhcpc); return NULL; } /* bind the socket */ addr.sin_family = AF_INET; addr.sin_port = HTONS(DHCPC_CLIENT_PORT); addr.sin_addr.s_addr = INADDR_ANY; if (bind(pdhcpc->sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0) { close(pdhcpc->sockfd); free(pdhcpc); return NULL; } /* Configure for read timeouts */ tv.tv_sec = 10; tv.tv_usec = 0; if (setsockopt(pdhcpc->sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)) < 0) { close(pdhcpc->sockfd); free(pdhcpc); return NULL; } } return (void*)pdhcpc;}/**************************************************************************** * Name: dhcpc_close ****************************************************************************/void dhcpc_close(void *handle){ struct dchcpc_state_internal *pdhcpc = (struct dchcpc_state_internal *)handle; if (pdhcpc) { free(pdhcpc); }}/**************************************************************************** * Name: dhcpc_request ****************************************************************************/int dhcpc_request(void *handle, struct dhcpc_state *presult){ struct dhcpc_state_s *pdhcpc = (struct dhcpc_state_s *)handle; struct in_addr oldaddr; struct in_addr newaddr; ssize_t result; uint8 msgtype; int retries; int state; /* Save the currently assigned IP address (should be INADDR_ANY) */ oldaddr.s_addr = 0; uip_gethostaddr("eth0", &oldaddr); /* Loop until we receive the lease (or an error occurs) */ do { /* Set the IP address to INADDR_ANY. */ newaddr.s_addr = INADDR_ANY; (void)uip_sethostaddr("eth0", &newaddr); /* Loop sending DISCOVER until we receive an OFFER from a DHCP * server. We will lock on to the first OFFER and decline any * subsequent offers (which will happen if there are more than one * DHCP servers on the network. */ state = STATE_INITIAL; do { /* Send the DISCOVER command */ dbg("Broadcast DISCOVER\n"); if (dhcpc_sendmsg(pdhcpc, presult, DHCPDISCOVER) < 0) { return ERROR; } /* Get the DHCPOFFER response */ result = recv(pdhcpc->sockfd, &pdhcpc->packet, sizeof(struct dhcp_msg), 0); if (result >= 0) { msgtype = dhcpc_parsemsg(pdhcpc, result, presult); if (msgtype == DHCPOFFER) { /* Save the servid from the presult so that it is not clobbered * by a new OFFER. */ dbg("Received OFFER from %08x\n", ntohl(presult->serverid.s_addr)); pdhcpc->ipaddr.s_addr = presult->ipaddr.s_addr; pdhcpc->serverid.s_addr = presult->serverid.s_addr; /* Temporarily use the address offered by the server and break * out of the loop. */ (void)uip_sethostaddr("eth0", &presult->ipaddr); state = STATE_HAVE_OFFER; } } /* An error has occurred. If this was a timeout error (meaning that * nothing was received on this socket for a long period of time). * Then loop and send the DISCOVER command again. */ else if (*get_errno_ptr() != EAGAIN) { /* An error other than a timeout was received -- error out */ return ERROR; } } while (state == STATE_INITIAL); /* Loop sending the REQUEST up to three times (if there is no response) */ retries = 0; do { /* Send the REQUEST message to obtain the lease that was offered to us. */ dbg("Send REQUEST\n"); if (dhcpc_sendmsg(pdhcpc, presult, DHCPREQUEST) < 0) { return ERROR; } retries++; /* Get the ACK/NAK response to the REQUEST (or timeout) */ result = recv(pdhcpc->sockfd, &pdhcpc->packet, sizeof(struct dhcp_msg), 0); if (result >= 0) { /* Parse the response */ msgtype = dhcpc_parsemsg(pdhcpc, result, presult); /* The ACK response means that the server has accepted our request * and we have the lease. */ if (msgtype == DHCPACK) { dbg("Received ACK\n"); state = STATE_HAVE_LEASE; } /* NAK means the the server has refused our request. Break out of * this loop with state == STATE_HAVE_OFFER and send DISCOVER again */ else if (msgtype == DHCPNAK) { dbg("Received NAK\n"); break; } /* If we get any OFFERs from other servers, then decline them now * and continue waiting for the ACK from the server that we * requested from. */ else if (msgtype == DHCPOFFER) { dbg("Received another OFFER, send DECLINE\n"); (void)dhcpc_sendmsg(pdhcpc, presult, DHCPDECLINE); } /* Otherwise, it is something that we do not recognize */ else { dbg("Ignoring msgtype=%d\n", msgtype); } } /* An error has occurred. If this was a timeout error (meaning * that nothing was received on this socket for a long period of time). * Then break out and send the DISCOVER command again (at most * 3 times). */ else if (*get_errno_ptr() != EAGAIN) { /* An error other than a timeout was received */ (void)uip_sethostaddr("eth0", &oldaddr); return ERROR; } } while (state == STATE_HAVE_OFFER && retries < 3); } while (state != STATE_HAVE_LEASE); dbg("Got IP address %d.%d.%d.%d\n", (presult->ipaddr.s_addr >> 24 ) & 0xff, (presult->ipaddr.s_addr >> 16 ) & 0xff, (presult->ipaddr.s_addr >> 8 ) & 0xff, (presult->ipaddr.s_addr ) & 0xff); dbg("Got netmask %d.%d.%d.%d\n", (presult->netmask.s_addr >> 24 ) & 0xff, (presult->netmask.s_addr >> 16 ) & 0xff, (presult->netmask.s_addr >> 8 ) & 0xff, (presult->netmask.s_addr ) & 0xff); dbg("Got DNS server %d.%d.%d.%d\n", (presult->dnsaddr.s_addr >> 24 ) & 0xff, (presult->dnsaddr.s_addr >> 16 ) & 0xff, (presult->dnsaddr.s_addr >> 8 ) & 0xff, (presult->dnsaddr.s_addr ) & 0xff); dbg("Got default router %d.%d.%d.%d\n", (presult->default_router.s_addr >> 24 ) & 0xff, (presult->default_router.s_addr >> 16 ) & 0xff, (presult->default_router.s_addr >> 8 ) & 0xff, (presult->default_router.s_addr ) & 0xff); dbg("Lease expires in %ld seconds\n", ntohs(presult->lease_time[0])*65536ul + ntohs(presult->lease_time[1])); return OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -