📄 dhcpc_subr.c
字号:
* NOMANUAL*/int initialize ( int serverPort, /* port monitored by DHCP servers */ int clientPort /* port monitored by DHCP client */ ) { char * sbufp; /* Always use default ports for client and server. */ dhcps_port = htons (serverPort); dhcpc_port = htons (clientPort); dhcpif.rbufsize = DFLTDHCPLEN + UDPHL + IPHL + ETHERHL; /* Include offset to allow 4-byte alignment of IP header for Sun BSP's. */ dhcpif.rbuf = (char *)memalign (4, dhcpif.rbufsize + DHCPC_OFF); if (dhcpif.rbuf == NULL) {#ifdef DHCPC_DEBUG logMsg ("allocation error for rbuf in initialize\n", 0, 0, 0, 0, 0, 0);#endif return (-1); } bzero (dhcpif.rbuf, dhcpif.rbufsize + DHCPC_OFF); pDhcpcRecvBuf = (char *)memalign (4, dhcpif.rbufsize + DHCPC_OFF); if (pDhcpcRecvBuf == NULL) { return (-1); } bzero (pDhcpcRecvBuf, dhcpif.rbufsize + DHCPC_OFF); sbuf.size = ETHERHL + IPHL + UDPHL + DFLTDHCPLEN; /* Include offset to allow 4-byte alignment of IP header for Sun BSP's. */ if ( (sbuf.buf = (char *)memalign (4, sbuf.size + DHCPC_OFF)) == NULL) {#ifdef DHCPC_DEBUG logMsg ("allocation error for sbuf in initialize\n", 0, 0, 0, 0, 0, 0);#endif return(-1); } bzero (sbuf.buf, sbuf.size + DHCPC_OFF); sbufp = &sbuf.buf [DHCPC_OFF]; dhcpcMsgOut.ether = (struct ether_header *)sbufp; dhcpcMsgOut.ip = (struct ip *)&sbufp [ETHERHL]; dhcpcMsgOut.udp = (struct udphdr *)&sbufp [ETHERHL + IPHL]; dhcpcMsgOut.dhcp = (struct dhcp *)&sbufp [ETHERHL + IPHL + UDPHL]; return (0); }/********************************************************************************* reset_if - halt the network and reset the network interface** This routine sets the IP address of the network interface to a random* value of 10.x.x.x, which is an old ARPA debugging address, resets the* broadcast address and subnet mask, and flushes the routing tables.* It is called before initiating a lease negotiation if no event notification * hook is present. It is also always called for a lease established at boot * time, whether or not an event hook is registered for that lease.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/void reset_if ( struct if_info * pIfData /* interface used by lease */ ) { struct in_addr addr; struct in_addr mask; struct in_addr brdaddr; addr.s_addr = htonl ( (generate_xid (pIfData) & 0xfff) | 0x0a000000); mask.s_addr = htonl (0xff000000); brdaddr.s_addr = inet_addr ("255.255.255.255"); config_if (pIfData, &addr, &mask, &brdaddr); flushroutes (); }/********************************************************************************* down_if - change network interface flags** This routine clears the IFF_UP flag of the network interface. It is called* when a lease is manually terminated with a dhcpcRelease() or dhcpcShutdown()* call if no event hook is present for the lease. It is always called when* removing a lease established at boot time.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/void down_if ( struct if_info *ifp ) { int sockfd; struct ifreq ridreq; reset_if (ifp); if ( (sockfd = socket (AF_INET, SOCK_RAW, 0)) < 0) return; bzero ( (char *)&ridreq, sizeof (struct ifreq)); sprintf (ridreq.ifr_name, "%s%d", ifp->name, ifp->unit); ridreq.ifr_addr.sa_len = sizeof (struct sockaddr_in); /* down interface */ ioctl (sockfd, SIOCGIFFLAGS, (int) (caddr_t) &ridreq); ridreq.ifr_flags &= (~IFF_UP); ioctl (sockfd, SIOCSIFFLAGS, (int) (caddr_t) &ridreq); close (sockfd); return; }/********************************************************************************* config_if - configure network interface** This routine sets one or more of the current address, broadcast address, and * subnet mask, depending on whether or not the corresponding parameters are * NULL. It is called when a lease is obtained or the network is reset. When a * new lease is obtained, a successful return value is used to cause assignment * of new routing tables.** RETURNS: -1 on error, 0 if new settings assigned, 1 otherwise.** ERRNO: N/A** NOMANUAL*/int config_if ( struct if_info *ifp, struct in_addr *addr, struct in_addr *mask, struct in_addr *brdcst ) { int sockfd = 0; int status; struct ifreq ifr; struct in_addr current_addr; struct in_addr current_mask; struct in_addr current_brdcst; if ( (sockfd = socket (AF_INET, SOCK_RAW, 0)) < 0) return (-1); bzero ( (char *)¤t_addr, sizeof (current_addr)); bzero ( (char *)¤t_mask, sizeof (current_mask)); bzero ( (char *)¤t_brdcst, sizeof (current_brdcst)); bzero ( (char *)&ifr, sizeof (struct ifreq)); sprintf (ifr.ifr_name, "%s%d", ifp->name, ifp->unit); ifr.ifr_addr.sa_len = sizeof (struct sockaddr_in); status = ioctl (sockfd, SIOCGIFADDR, (int)&ifr); current_addr.s_addr = ( (struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; status = ioctl (sockfd, SIOCGIFNETMASK, (int)&ifr); current_mask.s_addr = ( (struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; status = ioctl (sockfd, SIOCGIFBRDADDR, (int)&ifr); current_brdcst.s_addr = ( (struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr.s_addr; if (current_addr.s_addr == addr->s_addr && (mask == NULL || current_mask.s_addr == mask->s_addr) && (brdcst == NULL || current_brdcst.s_addr == brdcst->s_addr)) { close (sockfd); return (1); } flushroutes (); /* down interface */ ioctl (sockfd, SIOCGIFFLAGS, (int)&ifr); ifr.ifr_flags &= (~IFF_UP); ioctl (sockfd, SIOCSIFFLAGS, (int)&ifr); /* * Deleting the interface address is required to correctly scrub the * routing table based on the current netmask. */ bzero ( (char *)&ifr, sizeof (struct ifreq)); sprintf (ifr.ifr_name, "%s%d", ifp->name, ifp->unit); ifr.ifr_addr.sa_len = sizeof (struct sockaddr_in); ( (struct sockaddr_in *) &ifr.ifr_addr)->sin_family = AF_INET; ( (struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = current_addr.s_addr; status = ioctl (sockfd, SIOCDIFADDR, (int)&ifr); if (status < 0) { /* Sometimes no address has been set, so ignore that error. */ if (errno != EADDRNOTAVAIL) { close (sockfd); return (-1); } } if (mask != NULL) { bzero ( (char *)&ifr, sizeof (struct ifreq)); sprintf (ifr.ifr_name, "%s%d", ifp->name, ifp->unit); ifr.ifr_addr.sa_len = sizeof (struct sockaddr_in); ( (struct sockaddr_in *) &ifr.ifr_addr)->sin_family = AF_INET; ( (struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = mask->s_addr; status = ioctl (sockfd, SIOCSIFNETMASK, (int)&ifr); if (status < 0) { close (sockfd); return (-1); } } if (brdcst != NULL) { bzero ( (char *)&ifr, sizeof (struct ifreq)); sprintf (ifr.ifr_name, "%s%d", ifp->name, ifp->unit); ifr.ifr_addr.sa_len = sizeof (struct sockaddr_in); ( (struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_family = AF_INET; ( (struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr.s_addr = brdcst->s_addr; status = ioctl (sockfd, SIOCSIFBRDADDR, (int)&ifr); if (status < 0) { close (sockfd); return (-1); } } if (addr != NULL) { bzero ( (char *)&ifr, sizeof (struct ifreq)); sprintf (ifr.ifr_name, "%s%d", ifp->name, ifp->unit); ifr.ifr_addr.sa_len = sizeof (struct sockaddr_in); ( (struct sockaddr_in *) &ifr.ifr_addr)->sin_family = AF_INET; ( (struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = addr->s_addr; status = ioctl (sockfd, SIOCSIFADDR, (int)&ifr); if (status < 0) { close (sockfd); return (-1); } } /* bring interface back up */ ioctl (sockfd, SIOCGIFFLAGS, (int)&ifr); ifr.ifr_flags |= IFF_UP; ioctl (sockfd, SIOCSIFFLAGS, (int)&ifr); close (sockfd); return (0); }/********************************************************************************* set_route - set network routing table** This routine is called when config_if() assigns new address information.* It sets the default route for a new lease if the DHCP server provided the* router IP address.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/void set_route ( struct dhcp_param *param ) { int sockfd = 0;#if BSD<44 struct rtentry rt;#else struct ortentry rt;#endif struct sockaddr dst, gateway; if (param == NULL) return; sockfd = socket(AF_INET, SOCK_RAW, 0); if (sockfd < 0) {#ifdef DHCPC_DEBUG logMsg("socket() error in set_route()\n", 0, 0, 0, 0, 0, 0);#endif return; } /* set default route, if router IP address is available. */ if (ISSET(param->got_option, _DHCP_ROUTER_TAG) && param->router != NULL && param->router->addr != NULL) {#if BSD<44 bzero ( (char *)&rt, sizeof (struct rtentry));#else bzero ( (char *)&rt, sizeof (struct ortentry));#endif bzero ( (char *)&dst, sizeof (struct sockaddr)); bzero ( (char *)&gateway, sizeof (struct sockaddr)); rt.rt_flags = RTF_UP | RTF_GATEWAY; ( (struct sockaddr_in *)&dst)->sin_family = AF_INET; ( (struct sockaddr_in *)&dst)->sin_len = sizeof (struct sockaddr_in); ( (struct sockaddr_in *)&dst)->sin_addr.s_addr = INADDR_ANY; ( (struct sockaddr_in *)&gateway)->sin_family = AF_INET; ( (struct sockaddr_in *)&gateway)->sin_len = sizeof (struct sockaddr_in); ( (struct sockaddr_in *)&gateway)->sin_addr.s_addr = param->router->addr->s_addr; rt.rt_dst = dst; rt.rt_gateway = gateway; if (ioctl (sockfd, SIOCADDRT, (int)&rt) < 0) {#ifdef DHCPC_DEBUG logMsg ("SIOCADDRT (default route)\n", 0, 0, 0, 0, 0, 0);#endif close (sockfd); } } close (sockfd); return; }/********************************************************************************* make_decline - construct a DHCP decline message** This routine constructs an outgoing UDP/IP message containing the values* required to decline an offered IP address.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/void make_decline ( char *lsbuf, struct dhcp_reqspec *pDhcpcReqSpec, struct if_info * pIfData /* interface used by lease */ ) { int offopt = 0; /* offset in options field */ int i = 0; u_long tmpul = 0; struct dhcp *lsdhcp = NULL; struct udphdr *lsudp = NULL; struct ip *lsip = NULL; struct ether_header *lsether = NULL; struct ps_udph pudph; bzero ( (char *)&pudph, sizeof (pudph)); lsether = (struct ether_header *)lsbuf; lsip = (struct ip *)&lsbuf [ETHERHL]; lsudp = (struct udphdr *)&lsbuf [ETHERHL + IPHL]; lsdhcp = (struct dhcp *)&lsbuf [ETHERHL + IPHL + UDPHL]; /* construct dhcp part */ lsdhcp->op = BOOTREQUEST; lsdhcp->htype = pIfData->haddr.htype; lsdhcp->hlen = pIfData->haddr.hlen; lsdhcp->xid = generate_xid (pIfData); lsdhcp->giaddr = dhcpcMsgIn.dhcp->giaddr; bcopy (pIfData->haddr.haddr, lsdhcp->chaddr, lsdhcp->hlen); /* insert magic cookie */ bcopy ( (char *)dhcpCookie, lsdhcp->options, MAGIC_LEN); offopt = MAGIC_LEN; /* insert message type */ lsdhcp->options [offopt++] = _DHCP_MSGTYPE_TAG; lsdhcp->options [offopt++] = 1; lsdhcp->options [offopt++] = DHCPDECLINE; /* insert requested IP */ if (pDhcpcReqSpec->ipaddr.s_addr == 0) return; else if (CHKOFF (4))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -