📄 client.c
字号:
ifr.ifr_flags = saved_if_flags | IFF_UP | IFF_BROADCAST | IFF_NOTRAILERS | IFF_RUNNING; if (ioctl(dhcpSocket,SIOCSIFFLAGS,&ifr)) { syslog(LOG_ERR,"Start: ioctl SIOCSIFFLAGS: %m\n"); exit(1); } memset(&sap,0,sizeof(sap)); do { i++; if (i > 1) syslog(LOG_WARNING,"Start: retrying MAC address request " "(returned %02x:%02x:%02x:%02x:%02x:%02x)", ClientHwAddr[0],ClientHwAddr[1],ClientHwAddr[2], ClientHwAddr[3],ClientHwAddr[4],ClientHwAddr[5]); if (ioctl(dhcpSocket,SIOCGIFHWADDR,&ifr)) { syslog(LOG_ERR,"dhcpStart: ioctl SIOCGIFHWADDR: %m\n"); exit(1); } if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { syslog(LOG_ERR,"Start: interface %s is not Ethernet or 802.2 Token Ring\n",ifr.ifr_name); exit(1); } if (setsockopt(dhcpSocket,SOL_SOCKET,SO_BROADCAST,&o,sizeof(o)) == -1) { syslog(LOG_ERR,"Start: setsockopt: %m\n"); exit(1); } ifr.ifr_flags = saved_if_flags | IFF_UP | IFF_BROADCAST | IFF_NOTRAILERS | IFF_RUNNING; if (ioctl(dhcpSocket,SIOCSIFFLAGS,&ifr)) { syslog(LOG_ERR,"Start: ioctl SIOCSIFFLAGS: %m\n"); exit(1); } memset(&sap,0,sizeof(sap)); sap.spkt_protocol = htons(ETH_P_ALL); memcpy(sap.spkt_device,IfNameExt,IfNameExt_len); sap.spkt_family = PF_PACKET; if (bind(dhcpSocket,(void*)&sap,sizeof(struct sockaddr)) == -1) syslog(LOG_ERR,"Start: bind: %m\n"); memcpy(ClientHwAddr,ifr.ifr_hwaddr.sa_data,ETH_ALEN); if (DebugFlag) fprintf(stdout,"mydhcpcd: MAC address = %02x:%02x:%02x:%02x:%02x:%02x\n", ClientHwAddr[0], ClientHwAddr[1], ClientHwAddr[2], ClientHwAddr[3], ClientHwAddr[4], ClientHwAddr[5]); } while ( !ClientHwAddr[0] && !ClientHwAddr[1] && !ClientHwAddr[2] && !ClientHwAddr[3] && !ClientHwAddr[4] && !ClientHwAddr[5] && i<HWADDR_TRIES ); i=time(NULL)+ClientHwAddr[5]+4*ClientHwAddr[4]+8*ClientHwAddr[3]+16*ClientHwAddr[2]+32*ClientHwAddr[1]+64*ClientHwAddr[0]; srandom(i); ip_id=i&0xffff; udpFooSocket = socket(AF_INET,SOCK_DGRAM,0); if (udpFooSocket == -1) { syslog(LOG_ERR,"Start: socket: %m\n"); exit(1); } if (setsockopt(udpFooSocket,SOL_SOCKET,SO_BROADCAST,&o,sizeof(o))) syslog(LOG_ERR,"Start: setsockopt: %m\n"); memset(&clientAddr.sin_addr,0,sizeof(&clientAddr.sin_addr)); clientAddr.sin_family = AF_INET; clientAddr.sin_port = htons(DHCP_CLIENT_PORT); if (bind(udpFooSocket,(struct sockaddr *)&clientAddr,sizeof(clientAddr))) { if (errno != EADDRINUSE) syslog(LOG_ERR,"Start: bind: %m\n"); close(udpFooSocket); udpFooSocket = -1; } else if (fcntl(udpFooSocket,F_SETFL,O_NONBLOCK) == -1) { syslog(LOG_ERR,"Start: fcntl: %m\n"); exit(1); } return &Init;}void classclientsetup(){ if (ClassID) { memcpy(DhcpIface.class_id,ClassID,ClassID_len); DhcpIface.class_len=ClassID_len; } else classIDsetup(); clientIDsetup();}void *Reboot(){ if (sigsetjmp(env,0xffff)) { if (DebugFlag) printf("timed out waiting for DHCP_ACK response\n"); if (TimeOut != 0) alarm(TimeOut); return &Init; } Start(); memset(&DhcpOptions,0,sizeof(DhcpOptions)); memset(&DhcpIface,0,sizeof(dhcpInterface)); classclientsetup(); return Request(random(),&setDhcpReboot);}void *Init(){ if (sigsetjmp(env,0xffff)) { if (DebugFlag) printf("time out at Init\n"); if (autoip_flag) { sleep(autoip_sleep); printf("I have slept for %d secs\n",autoip_sleep); } else { autoip(); autoip_flag = 1; } if(TimeOut != 0) alarm(TimeOut); return &Init; } releaseDhcpOptions(); if (DebugFlag) printf("broadcasting DHCP_DISCOVER\n"); if (dhcpSendAndRecv(random(),DHCP_OFFER,&setDhcpDiscover)) { Stop(); return 0; } if (SendSecondDiscover) { if (DebugFlag) syslog(LOG_DEBUG,"broadcasting second DHCP_DISCOVER\n"); dhcpSendAndRecv(DhcpMsgRecv->xid,DHCP_OFFER,&setDhcpDiscover); } prev_ip_addr = DhcpIface.ciaddr; DhcpIface.ciaddr = DhcpMsgRecv->yiaddr; memcpy(&DhcpIface.siaddr,DhcpOptions.val[dhcpServerIdentifier],4); memcpy(DhcpIface.shaddr,UdpIpMsgRecv.ethhdr.ether_shost,ETH_ALEN); DhcpIface.xid = DhcpMsgRecv->xid;/* DHCP_OFFER received */ if (DebugFlag) printf("DHCP_OFFER received from %s (%u.%u.%u.%u)\n", DhcpMsgRecv->sname, ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[0], ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[1], ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[2], ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[3]); return Request(DhcpIface.xid,&setDhcpRequest);}void *Request(xid,buildDhcpMsg)unsigned xid;void (*buildDhcpMsg)(unsigned);{/* send the message and read and parse replies into DhcpOptions */ if (DebugFlag) syslog(LOG_DEBUG,"broadcasting DHCP_REQUEST for %u.%u.%u.%u\n", ((unsigned char *)&DhcpIface.ciaddr)[0], ((unsigned char *)&DhcpIface.ciaddr)[1], ((unsigned char *)&DhcpIface.ciaddr)[2], ((unsigned char *)&DhcpIface.ciaddr)[3]); if (dhcpSendAndRecv(xid,DHCP_ACK,buildDhcpMsg)) return &Init; ReqSentTime=time(NULL); if (DebugFlag) syslog(LOG_DEBUG, "DHCP_ACK received from %s (%u.%u.%u.%u)\n",DhcpMsgRecv->sname, ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[0], ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[1], ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[2], ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[3]);/* check if the offered IP address already in use */ /* if (checkIP(DhcpIface.ciaddr)) { if (DebugFlag) printf( "requested %u.%u.%u.%u address is in use\n", ((unsigned char *)&DhcpIface.ciaddr)[0], ((unsigned char *)&DhcpIface.ciaddr)[1], ((unsigned char *)&DhcpIface.ciaddr)[2], ((unsigned char *)&DhcpIface.ciaddr)[3]); DhcpIface.ciaddr = 0; return &Decline; }*/ if (DebugFlag) printf("verified %u.%u.%u.%u address is not in use\n", ((unsigned char *)&DhcpIface.ciaddr)[0], ((unsigned char *)&DhcpIface.ciaddr)[1], ((unsigned char *)&DhcpIface.ciaddr)[2], ((unsigned char *)&DhcpIface.ciaddr)[3]); if (dhcpConfig()) { Stop(); return (0); } /* Successfull ACK: Use the fields obtained for future requests */ memcpy(&DhcpIface.siaddr,DhcpOptions.val[dhcpServerIdentifier],4); memcpy(DhcpIface.shaddr,UdpIpMsgRecv.ethhdr.ether_shost,ETH_ALEN); return &Bound;}void *Bound(){ int i, maxfd; fd_set rset; char foobuf[512]; if (sigsetjmp(env,0xffff)) return &Renew; i=ReqSentTime+ntohl(*(unsigned int *)DhcpOptions.val[dhcpT1value])-time(NULL); if ( i > 0 ) alarm(i); else return &Renew; while(1) { FD_ZERO(&rset); maxfd = dhcpSocket; FD_SET(dhcpSocket, &rset); if (udpFooSocket != -1) { if (udpFooSocket > maxfd) maxfd = udpFooSocket; FD_SET(udpFooSocket, &rset); } if (select(maxfd+1, &rset, NULL, NULL, NULL) == -1) { if (errno != EINTR) return &Renew; } else { if (udpFooSocket != -1 && FD_ISSET(udpFooSocket, &rset)) while (recvfrom(udpFooSocket,(void *)foobuf,sizeof(foobuf),0,NULL,NULL) != -1 ); if (FD_ISSET(dhcpSocket, &rset)) while (recvfrom(dhcpSocket,(void *)foobuf,sizeof(foobuf),0,NULL,NULL) != -1 ); } }}void *Renew(){ int i; if (sigsetjmp(env,0xffff)) return &Rebind; i = ReqSentTime+ntohl(*(unsigned int *)DhcpOptions.val[dhcpT2value])-time(NULL); if (i > 0) alarm(i); else return &Rebind; if (DebugFlag) printf("sending DHCP_REQUEST for %u.%u.%u.%u to %u.%u.%u.%u\n", ((unsigned char *)&DhcpIface.ciaddr)[0], ((unsigned char *)&DhcpIface.ciaddr)[1], ((unsigned char *)&DhcpIface.ciaddr)[2], ((unsigned char *)&DhcpIface.ciaddr)[3], ((unsigned char *)&DhcpIface.siaddr)[0], ((unsigned char *)&DhcpIface.siaddr)[1], ((unsigned char *)&DhcpIface.siaddr)[2], ((unsigned char *)&DhcpIface.siaddr)[3]); if (dhcpSendAndRecv(random(),DHCP_ACK,&setDhcpRenew)) return &Rebind; ReqSentTime=time(NULL); if (DebugFlag) printf("DHCP_ACK received from %s (%u.%u.%u.%u)\n",DhcpMsgRecv->sname, ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[0], ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[1], ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[2], ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[3]); return &Bound;}void *Rebind(){ int i; if (sigsetjmp(env,0xffff)) { if (TimeOut != 0) { alarm(2*TimeOut); } return &Stop; } i = ReqSentTime+ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime])-time(NULL); if (i > 0) alarm(i); else return &Stop; if (DebugFlag) printf("broadcasting DHCP_REQUEST for %u.%u.%u.%u\n", ((unsigned char *)&DhcpIface.ciaddr)[0], ((unsigned char *)&DhcpIface.ciaddr)[1], ((unsigned char *)&DhcpIface.ciaddr)[2], ((unsigned char *)&DhcpIface.ciaddr)[3]); if (dhcpSendAndRecv(random(),DHCP_ACK,&setDhcpRebind)) return &Stop; ReqSentTime=time(NULL); if (DebugFlag) printf("DHCP_ACK received from %s (%u.%u.%u.%u)\n",DhcpMsgRecv->sname, ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[0], ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[1], ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[2], ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[3]); /* Successfull ACK: Use the fields obtained for future requests */ memcpy(&DhcpIface.siaddr,DhcpOptions.val[dhcpServerIdentifier],4); memcpy(DhcpIface.shaddr,UdpIpMsgRecv.ethhdr.ether_shost,ETH_ALEN); return &Bound;}void *Release(){ struct sockaddr addr; if (DhcpIface.ciaddr == 0) return &Init; setDhcpRelease(random()); memset(&addr,0,sizeof(struct sockaddr)); memcpy(addr.sa_data,IfNameExt,IfNameExt_len); if (DebugFlag) printf("sending DHCP_RELEASE for %u.%u.%u.%u to %u.%u.%u.%u\n", ((unsigned char *)&DhcpIface.ciaddr)[0], ((unsigned char *)&DhcpIface.ciaddr)[1], ((unsigned char *)&DhcpIface.ciaddr)[2], ((unsigned char *)&DhcpIface.ciaddr)[3], ((unsigned char *)&DhcpIface.siaddr)[0], ((unsigned char *)&DhcpIface.siaddr)[1], ((unsigned char *)&DhcpIface.siaddr)[2], ((unsigned char *)&DhcpIface.siaddr)[3]); if (sendto(dhcpSocket,&UdpIpMsgSend,sizeof(struct packed_ether_header) + sizeof(udpiphdr)+sizeof(dhcpMessage),0, &addr,sizeof(struct sockaddr)) == -1 ) syslog(LOG_ERR,"Release: sendto: %m\n"); sendRelArp(); /* clear ARP cache entries for client IP addr */ if (SetHostName) { sethostname(InitialHostName,InitialHostName_len); if (DebugFlag) fprintf(stdout,"dhcpcd: your hostname = %s\n",InitialHostName); } DhcpIface.ciaddr=0; return &Init;}void *Stop(){ struct ifreq ifr; struct sockaddr_in *p = (struct sockaddr_in *)&(ifr.ifr_addr); releaseDhcpOptions(); memset(&ifr,0,sizeof(struct ifreq)); memcpy(ifr.ifr_name,IfNameExt,IfNameExt_len); p->sin_family = AF_INET; p->sin_addr.s_addr = 0; if (DownIfaceOnStop) { ifr.ifr_flags = saved_if_flags & ~IFF_UP; if (ioctl(dhcpSocket,SIOCSIFFLAGS,&ifr)) syslog(LOG_ERR,"Stop: ioctl SIOCSIFFLAGS: %m\n"); }tsc: close(dhcpSocket); return &Start;}void *Decline(){ struct sockaddr addr; memset(&UdpIpMsgSend,0,sizeof(udpipMessage)); memcpy(UdpIpMsgSend.ethhdr.ether_dhost,MAC_BCAST_ADDR,ETH_ALEN); memcpy(UdpIpMsgSend.ethhdr.ether_shost,ClientHwAddr,ETH_ALEN); UdpIpMsgSend.ethhdr.ether_type = htons(ETHERTYPE_IP); setDhcpDecline(random()); udpipgen((udpiphdr *)&UdpIpMsgSend.udpipmsg,0,INADDR_BROADCAST, htons(DHCP_CLIENT_PORT),htons(DHCP_SERVER_PORT),sizeof(dhcpMessage)); memset(&addr,0,sizeof(struct sockaddr)); memcpy(addr.sa_data,IfNameExt,IfNameExt_len); if ( DebugFlag ) syslog(LOG_DEBUG,"broadcasting DHCP_DECLINE\n"); if ( sendto(dhcpSocket,&UdpIpMsgSend,sizeof(struct packed_ether_header) + sizeof(udpiphdr)+sizeof(dhcpMessage),0, &addr,sizeof(struct sockaddr)) == -1 ) syslog(LOG_ERR,"Decline: sendto: %m\n"); return &Init;}void *Inform(){ Start(); memset(&DhcpOptions,0,sizeof(DhcpOptions)); memset(&DhcpIface,0,sizeof(dhcpInterface)); if (! inform_ipaddr.s_addr) { struct ifreq ifr; struct sockaddr_in *p = (struct sockaddr_in *)&(ifr.ifr_addr); memset(&ifr,0,sizeof(struct ifreq)); memcpy(ifr.ifr_name,IfNameExt,IfNameExt_len); p->sin_family = AF_INET; if (ioctl(dhcpSocket,SIOCGIFADDR,&ifr) == 0) inform_ipaddr.s_addr=p->sin_addr.s_addr; if (! inform_ipaddr.s_addr) { inform_ipaddr.s_addr=DhcpIface.ciaddr; } } DhcpIface.ciaddr=inform_ipaddr.s_addr; if (! DhcpIface.class_len) { if (ClassID) { memcpy(DhcpIface.class_id,ClassID,ClassID_len); DhcpIface.class_len=ClassID_len; } else classIDsetup(); } if (! DhcpIface.client_len) clientIDsetup(); if (sigsetjmp(env,0xffff)) { if (DebugFlag) printf("timed out waiting for DHCP_ACK response\n"); return 0; } if (DebugFlag) printf("broadcasting DHCP_INFORM for %u.%u.%u.%u\n", ((unsigned char *)&DhcpIface.ciaddr)[0], ((unsigned char *)&DhcpIface.ciaddr)[1], ((unsigned char *)&DhcpIface.ciaddr)[2], ((unsigned char *)&DhcpIface.ciaddr)[3]); if (dhcpSendAndRecv(random(),DHCP_ACK,setDhcpInform)) return 0; if (DebugFlag) printf("DHCP_ACK received from %s (%u.%u.%u.%u)\n",DhcpMsgRecv->sname, ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[0], ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[1], ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[2], ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[3]);/* check if the offered IP address already in use */ if (checkIP(DhcpIface.ciaddr)) { if (DebugFlag) printf("requested %u.%u.%u.%u address is in use\n", ((unsigned char *)&DhcpIface.ciaddr)[0], ((unsigned char *)&DhcpIface.ciaddr)[1], ((unsigned char *)&DhcpIface.ciaddr)[2], ((unsigned char *)&DhcpIface.ciaddr)[3]); return &Decline; } if (DebugFlag) printf("verified %u.%u.%u.%u address is not in use\n", ((unsigned char *)&DhcpIface.ciaddr)[0], ((unsigned char *)&DhcpIface.ciaddr)[1], ((unsigned char *)&DhcpIface.ciaddr)[2], ((unsigned char *)&DhcpIface.ciaddr)[3]); if (dhcpConfig()) return 0; exit(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -