📄 dhcpc_subr.c
字号:
/* insert message type */ dhcpcMsgOut.dhcp->options[offopt++] = _DHCP_MSGTYPE_TAG; dhcpcMsgOut.dhcp->options[offopt++] = 1; dhcpcMsgOut.dhcp->options[offopt++] = DHCPDECLINE; /* insert requested IP */ if (pReqSpec->ipaddr.s_addr == 0) return (0); dhcpcMsgOut.dhcp->options[offopt++] = _DHCP_REQUEST_IPADDR_TAG; dhcpcMsgOut.dhcp->options[offopt++] = 4; bcopy ((char *) &pReqSpec->ipaddr, &dhcpcMsgOut.dhcp->options[offopt], 4); offopt += 4; /* insert client identifier */ if (pReqSpec->clid != NULL) { dhcpcMsgOut.dhcp->options[offopt++] = _DHCP_CLIENT_ID_TAG; dhcpcMsgOut.dhcp->options[offopt++] = pReqSpec->clid->len; bcopy (pReqSpec->clid->id, &dhcpcMsgOut.dhcp->options[offopt], pReqSpec->clid->len); offopt += pReqSpec->clid->len; } /* insert server identifier */ dhcpcMsgOut.dhcp->options[offopt++] = _DHCP_SERVER_ID_TAG; dhcpcMsgOut.dhcp->options[offopt++] = 4; bcopy ((char *) &pReqSpec->srvaddr, &dhcpcMsgOut.dhcp->options[offopt], 4); offopt += 4; /* Insert error message, if available. */ if (pReqSpec->dhcp_errmsg != NULL) { dhcpcMsgOut.dhcp->options[offopt++] = _DHCP_ERRMSG_TAG; dhcpcMsgOut.dhcp->options[offopt++] = strlen (pReqSpec->dhcp_errmsg); bcopy (pReqSpec->dhcp_errmsg, &dhcpcMsgOut.dhcp->options[offopt], strlen (pReqSpec->dhcp_errmsg)); offopt += strlen (pReqSpec->dhcp_errmsg); } dhcpcMsgOut.dhcp->options[offopt] = _DHCP_END_TAG; /* * For backward compatibility with earlier DHCP servers, set the * reported message size to be at least as large as a BOOTP message. */ msgsize = (DFLTDHCPLEN - DFLTOPTLEN) + offopt + 1; if (msgsize < DFLTBOOTPLEN) msgsize = DFLTBOOTPLEN; /* construct udp part */ dhcpcMsgOut.udp->uh_sport = dhcpc_port; dhcpcMsgOut.udp->uh_dport = dhcps_port; dhcpcMsgOut.udp->uh_ulen = htons (msgsize + UDPHL); dhcpcMsgOut.udp->uh_sum = 0; /* fill pseudo udp header */ pudph.srcip.s_addr = 0; pudph.dstip.s_addr = pReqSpec->srvaddr.s_addr; pudph.zero = 0; pudph.prto = IPPROTO_UDP; pudph.ulen = dhcpcMsgOut.udp->uh_ulen; dhcpcMsgOut.udp->uh_sum = udp_cksum (&pudph, (char *) dhcpcMsgOut.udp, ntohs (pudph.ulen)); /* construct ip part */#if BSD<44 dhcpcMsgOut.ip->ip_v_hl = 0; dhcpcMsgOut.ip->ip_v_hl = IPVERSION << 4; dhcpcMsgOut.ip->ip_v_hl |= IPHL >> 2;#else dhcpcMsgOut.ip->ip_v = IPVERSION; dhcpcMsgOut.ip->ip_hl = IPHL >> 2;#endif dhcpcMsgOut.ip->ip_tos = 0; dhcpcMsgOut.ip->ip_len = htons (msgsize + UDPHL + IPHL); tmpul = generate_xid (pIfData); tmpul += (tmpul >> 16); dhcpcMsgOut.ip->ip_id = (u_short) (~tmpul); dhcpcMsgOut.ip->ip_off = htons (IP_DF); /* XXX */ dhcpcMsgOut.ip->ip_ttl = 0x20; /* XXX */ dhcpcMsgOut.ip->ip_p = IPPROTO_UDP; msgsize += UDPHL + IPHL; dhcpcMsgOut.ip->ip_src.s_addr = 0; dhcpcMsgOut.ip->ip_dst.s_addr = INADDR_BROADCAST; dhcpcMsgOut.ip->ip_sum = 0;#if BSD<44 dhcpcMsgOut.ip->ip_sum = checksum ((u_short *) dhcpcMsgOut.ip, (dhcpcMsgOut.ip->ip_v_hl & 0xf) << 2);#else dhcpcMsgOut.ip->ip_sum = checksum ((u_short *) dhcpcMsgOut.ip, dhcpcMsgOut.ip->ip_hl << 2);#endif return (msgsize);}/********************************************************************************* make_release - construct a DHCP release message** This routine constructs an outgoing UDP/IP message containing the values* required to relinquish the active lease.** RETURNS: Size of DHCP message, in bytes** ERRNO: N/A** NOMANUAL*/int make_release (struct dhcp_reqspec *pReqSpec, struct if_info *pIfData, /* interface used by lease */ BOOL oldFlag /* Use older (padded) DHCP message format? */ ){ int offopt = 0; /* offset in options field */ int msgsize; /* construct dhcp part */ bzero (sbuf.buf, sbuf.size); dhcpcMsgOut.dhcp->op = BOOTREQUEST; dhcpcMsgOut.dhcp->htype = pIfData->haddr.htype; dhcpcMsgOut.dhcp->hlen = pIfData->haddr.hlen; dhcpcMsgOut.dhcp->xid = htonl (generate_xid (pIfData)); dhcpcMsgOut.dhcp->ciaddr = pReqSpec->ipaddr; bcopy (pIfData->haddr.haddr, dhcpcMsgOut.dhcp->chaddr, dhcpcMsgOut.dhcp->hlen); /* insert magic cookie */ bcopy ((char *) dhcpCookie, dhcpcMsgOut.dhcp->options, MAGIC_LEN); offopt = MAGIC_LEN; /* insert message type */ dhcpcMsgOut.dhcp->options[offopt++] = _DHCP_MSGTYPE_TAG; dhcpcMsgOut.dhcp->options[offopt++] = 1; dhcpcMsgOut.dhcp->options[offopt++] = DHCPRELEASE; /* insert client identifier */ if (pReqSpec->clid != NULL) { dhcpcMsgOut.dhcp->options[offopt++] = _DHCP_CLIENT_ID_TAG; dhcpcMsgOut.dhcp->options[offopt++] = pReqSpec->clid->len; bcopy (pReqSpec->clid->id, &dhcpcMsgOut.dhcp->options[offopt], pReqSpec->clid->len); offopt += pReqSpec->clid->len; } /* insert server identifier */ dhcpcMsgOut.dhcp->options[offopt++] = _DHCP_SERVER_ID_TAG; dhcpcMsgOut.dhcp->options[offopt++] = 4; bcopy ((char *) &pReqSpec->srvaddr, &dhcpcMsgOut.dhcp->options[offopt], 4); offopt += 4; /* Insert error message, if available. */ if (pReqSpec->dhcp_errmsg != NULL) { dhcpcMsgOut.dhcp->options[offopt++] = _DHCP_ERRMSG_TAG; dhcpcMsgOut.dhcp->options[offopt++] = strlen (pReqSpec->dhcp_errmsg); bcopy (pReqSpec->dhcp_errmsg, &dhcpcMsgOut.dhcp->options[offopt], strlen (pReqSpec->dhcp_errmsg)); offopt += strlen (pReqSpec->dhcp_errmsg); } dhcpcMsgOut.dhcp->options[offopt] = _DHCP_END_TAG; msgsize = (DFLTDHCPLEN - DFLTOPTLEN) + offopt + 1; if (oldFlag) { /* * This flag indicates that the client did not receive a response * to the initial set of discover messages but did receive one * using the older message format. The (older) responding server * ignores messages less than the minimum length obtained with a * fixed options field, so pad the message to reach that length. */ if (msgsize < DFLTDHCPLEN) msgsize = DFLTDHCPLEN; } return (msgsize);}/********************************************************************************* dhcp_decline - send a DHCP decline message** This routine constructs a message declining an offered IP address and sends* it directly to the responding server. It is called when an ARP request * detects that the offered address is already in use.** RETURNS: 0 if message sent, or -1 on error.** ERRNO: N/A** NOMANUAL*/int dhcp_decline (struct dhcp_reqspec *pDhcpcReqSpec, struct if_info *pIfData /* interface used by lease */ ){ struct sockaddr_in dest; /* Server's destination address */ struct ifnet *pIf; /* Transmit device */ int length; /* Amount of data in message */#ifdef DHCPC_DEBUG char output[INET_ADDR_LEN];#endif if (pDhcpcReqSpec->srvaddr.s_addr == 0) return (-1); length = make_decline (pDhcpcReqSpec, pIfData); if (length == 0) return (-1); bzero ((char *) &dest, sizeof (struct sockaddr_in)); dest.sin_len = sizeof (struct sockaddr_in); dest.sin_family = AF_INET; dest.sin_addr.s_addr = INADDR_BROADCAST; pIf = pIfData->iface; if (dhcpSend (pIf, &dest, sbuf.buf, length, TRUE) == ERROR) {#ifdef DHCPC_DEBUG logMsg ("Can't send DHCPDECLINE.\n", 0, 0, 0, 0, 0, 0);#endif return (-1); }#ifdef DHCPC_DEBUG inet_ntoa_b (pDhcpcReqSpec->ipaddr, output); logMsg ("send DHCPDECLINE(%s)\n", (int) output, 0, 0, 0, 0, 0);#endif return (0);}/********************************************************************************* dhcp_release - send a DHCP release message** This routine constructs a message declining an offered IP address and sends* it directly to the responding server. It is called when an error prevents* the use of an acquired lease, or when the lease is relinquished manually* by a dhcpcRelease() or dhcpcShutdown() call. The message is sent directly to * the responding DHCP server.** RETURNS: 0 if message sent, or -1 on error.** ERRNO: N/A** NOMANUAL*/int dhcp_release (struct dhcp_reqspec *pDhcpcReqSpec, struct if_info *pIfData, /* interface used by lease */ BOOL oldFlag /* Use older (padded) DHCP message format? */ ){#ifdef DHCPC_DEBUG char output[INET_ADDR_LEN];#endif int length; if (pDhcpcReqSpec->srvaddr.s_addr == 0) return (-1); /* send DHCP message */ length = make_release (pDhcpcReqSpec, pIfData, oldFlag); if (send_unicast (&pDhcpcReqSpec->srvaddr, dhcpcMsgOut.dhcp, length) < 0) return (-1);#ifdef DHCPC_DEBUG inet_ntoa_b (pDhcpcReqSpec->ipaddr, output); logMsg ("send DHCPRELEASE(%s)\n", (int) output, 0, 0, 0, 0, 0);#endif return (0);}/********************************************************************************* dhcpcPrivateCleanup - remove data structures from client library** The dhcpcCleanup routine uses this routine to release the locally* allocated data structures which the initialize() call creates. It is* part of the shutdown process for the DHCP client library. The routine* executes after all leases are inactive and their data is released.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/voiddhcpcPrivateCleanup (void){ /* Close open file and remove BPF device for ARP probe. */ close (bpfArpDev); bpfDevDelete ("/bpf/dhcpc-arp"); /* Release transmission buffer. */ free (sbuf.buf); return;}/********************************************************************************* set_declinfo - initialize request specification for decline message** This routine assigns the fields in the request specifier used to construct* messages to the appropriate values for a DHCP decline message according to* the parameters of the currently active lease.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/void set_declinfo (struct dhcp_reqspec *pDhcpcReqSpec, LEASE_DATA * pLeaseData, char *errmsg, int arpans){ char output[INET_ADDR_LEN]; struct dhcp_param *paramp; paramp = pLeaseData->dhcpcParam; pDhcpcReqSpec->ipaddr = paramp->yiaddr; pDhcpcReqSpec->srvaddr = paramp->server_id; if (pLeaseData->leaseReqSpec.clid != NULL) pDhcpcReqSpec->clid = pLeaseData->leaseReqSpec.clid; else pDhcpcReqSpec->clid = NULL; if (errmsg[0] == 0) { inet_ntoa_b (paramp->yiaddr, output); if (arpans != OK) sprintf (errmsg, "IP address (%s) is already in use.", output); else sprintf (errmsg, "IP address (%s) doesn't match requested value.", output); } pDhcpcReqSpec->dhcp_errmsg = errmsg; return;}/********************************************************************************* set_relinfo - initialize request specification for release message** This routine assigns the fields in the request specifier used to construct* messages to the appropriate values for a DHCP release message according to* the parameters of the currently active lease.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/void set_relinfo (struct dhcp_reqspec *pDhcpcReqSpec, LEASE_DATA * pLeaseData, char *errmsg){ char output[INET_ADDR_LEN]; struct dhcp_param *paramp; paramp = pLeaseData->dhcpcParam; pDhcpcReqSpec->ipaddr.s_addr = paramp->yiaddr.s_addr; pDhcpcReqSpec->srvaddr.s_addr = paramp->server_id.s_addr; if (pLeaseData->leaseReqSpec.clid != NULL) pDhcpcReqSpec->clid = pLeaseData->leaseReqSpec.clid; else pDhcpcReqSpec->clid = NULL; if (pLeaseData->leaseReqSpec.dhcp_errmsg != NULL) pDhcpcReqSpec->dhcp_errmsg = pLeaseData->leaseReqSpec.dhcp_errmsg; else { inet_ntoa_b (paramp->yiaddr, output); sprintf (errmsg, "Releasing the current IP address (%s).", output); pDhcpcReqSpec->dhcp_errmsg = errmsg; } return;}/********************************************************************************* make_discover - construct a DHCP discover message** This routine constructs an outgoing UDP/IP message containing the values* required to broadcast a lease request. The <xidFlag> indicates whether* a transaction ID should be generated. Because multiple leases are supported,* the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -