📄 dhcprelay.c
字号:
struct server *srvp ) { int i, n; int sockfd = -1; int msgsize = DHCPLEN (dhcpMsgIn.udp); struct sockaddr_in my_addr, serv_addr; int result;#ifdef DHCPR_DEBUG char output [INET_ADDR_LEN];#endif if ( (sockfd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) {#ifdef DHCPR_DEBUG logMsg ("socket() error in forwarding()\n", 0, 0, 0, 0, 0, 0);#endif return (ERROR); } bzero ((char *)&my_addr, sizeof (my_addr)); my_addr.sin_family = AF_INET; my_addr.sin_addr.s_addr = htonl (INADDR_ANY); my_addr.sin_port = dhcpc_port; /* Servers expect client port. */ if (bind (sockfd, (struct sockaddr *) &my_addr, sizeof (my_addr)) < 0) {#ifdef DHCPR_DEBUG logMsg("bind() error in forwarding()\n", 0, 0, 0, 0, 0, 0);#endif close (sockfd); return (ERROR); } dhcprMsgOut.dhcp = dhcpMsgIn.dhcp; result = setsockopt (sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&msgsize, sizeof (msgsize)); if (result < 0) {#ifdef DHCPR_DEBUG logMsg ("Warning: can't set send buffer in forwarding().\n", 0, 0, 0, 0, 0, 0);#endif close (sockfd); return (ERROR); } n = sizeof(serv_addr); for (i = 0; i < dhcpNumTargets; i++) { bzero ((char *)&serv_addr, n); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = srvp->ip.s_addr; serv_addr.sin_port = dhcps_port;#ifdef DHCPR_DEBUG inet_ntoa_b (srvp->ip, output); printf ("Server relay: sending %d bytes to %s.\n", msgsize, output);#endif sendto (sockfd, (char *)dhcprMsgOut.dhcp, msgsize, 0, (struct sockaddr *)&serv_addr, n); srvp = srvp->next; } close (sockfd); return (OK); }/********************************************************************************* dhcpClientRelay - send DHCP/BOOTP replies to client** This routine relays a DHCP or BOOTP reply to the client which generated* the initial request. The routine accesses global pointers already set to * indicate the reply. All messages are discarded after the hops field exceeds * 16 to comply with the relay agent behavior specified in RFC 1542. The relay * agent normally discards such messages before this routine is called. They * will only be received by this routine if the user ignores the instructions * in the manual and sets the value of DHCP_MAX_HOPS higher than 16.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/void dhcpClientRelay ( struct if_info *list, int dhcplen, char * pSendBuf /* Transmit buffer for fragmented message. */ ) { int total; char devName [10]; struct if_info *ifp; struct sockaddr_in dest; BOOL bcastFlag; int msgtype = 0; char *option = NULL; struct ifnet *pIf; STATUS result;#ifdef DHCPR_DEBUG char srcAddr [INET_ADDR_LEN]; char dstAddr [INET_ADDR_LEN];#endif if (dhcpMsgIn.dhcp->hops >= 17) /* RFC limits to 16 hops - ignore. */ return; ifp = list; while (ifp != NULL) { if (ifp->ipaddr.s_addr == dhcpMsgIn.dhcp->giaddr.s_addr) break; ifp = ifp->next; } if (ifp == NULL) { #ifdef DHCPR_DEBUG inet_ntoa_b (dhcpMsgIn.ip->ip_src, srcAddr); logMsg ("Warning: DHCP message from server(%s) has no interface.\n", srcAddr, 0, 0, 0, 0, 0);#endif return; } sprintf (devName, "%s%d", ifp->name, ifp->unit); pIf = ifunit (devName); if (pIf == NULL) {#ifdef DHCPR_DEBUG logMsg ("Warning: couldn't access network interface %s.\n", (int)ifp->name, 0, 0, 0, 0, 0);#endif return; } if ( (option = pickup_opt (dhcpMsgIn.dhcp, dhcplen, _DHCP_MSGTYPE_TAG)) != NULL) msgtype = *OPTBODY(option); /* There is already space for the IP and UDP headers. */ dhcprMsgOut.dhcp = dhcpMsgIn.dhcp; dhcprMsgOut.udp = dhcpMsgIn.udp; dhcprMsgOut.ip = dhcpMsgIn.ip;#ifdef DHCPR_DEBUG logMsg ("Client relay: Headers found.\n", 0, 0, 0, 0, 0, 0);#endif#ifdef DHCPR_DEBUG logMsg ("Setting parameters.\n", 0, 0, 0, 0, 0, 0);#endif bzero ( (char *)&dest, sizeof (struct sockaddr_in)); dest.sin_len = sizeof (struct sockaddr_in); dest.sin_family = AF_INET; if (ISBRDCST (dhcpMsgIn.dhcp->flags)) {#ifdef DHCPR_DEBUG logMsg ("Broadcasting reply.\n", 0, 0, 0, 0, 0, 0);#endif dest.sin_addr.s_addr = dhcprMsgOut.ip->ip_dst.s_addr = 0xffffffff; dhcprMsgOut.ip->ip_src.s_addr = ifp->ipaddr.s_addr; bcastFlag = TRUE; } else { if (msgtype == DHCPNAK) { dest.sin_addr.s_addr = dhcprMsgOut.ip->ip_dst.s_addr = 0xffffffff; bcastFlag = TRUE; } else { dhcprMsgOut.ip->ip_dst.s_addr = dhcpMsgIn.dhcp->yiaddr.s_addr; dest.sin_addr.s_addr = dhcpMsgIn.dhcp->yiaddr.s_addr; bcastFlag = FALSE; } dhcprMsgOut.ip->ip_src.s_addr = ifp->ipaddr.s_addr;#ifdef DHCPR_DEBUG inet_ntoa_b (dhcprMsgOut.ip->ip_src, srcAddr); inet_ntoa_b (dhcprMsgOut.ip->ip_dst, dstAddr); logMsg ("Sending reply from %s to %s.\n", srcAddr, dstAddr, 0, 0, 0, 0);#endif } dhcprMsgOut.udp->uh_sport = dhcps_port; dhcprMsgOut.udp->uh_dport = dhcpc_port; dhcprMsgOut.udp->uh_ulen = htons (dhcplen + UDPHL); dhcprMsgOut.udp->uh_sum = get_udpsum (dhcprMsgOut.ip, dhcprMsgOut.udp); dhcprMsgOut.ip->ip_v = IPVERSION; dhcprMsgOut.ip->ip_hl = IPHL >> 2; dhcprMsgOut.ip->ip_tos = 0; dhcprMsgOut.ip->ip_len = htons (dhcplen + UDPHL + IPHL); dhcprMsgOut.ip->ip_id = dhcprMsgOut.udp->uh_sum; dhcprMsgOut.ip->ip_ttl = 0x20; /* XXX */ dhcprMsgOut.ip->ip_p = IPPROTO_UDP; total = dhcplen + IPHL + UDPHL; if (total <= pIf->if_mtu) { /* * The message fits within the MTU size of the outgoing interface. * Send it "in place", altering the UDP and IP headers of the * original (incoming) message's buffer. */ dhcprMsgOut.ip->ip_off = 0; dhcprMsgOut.ip->ip_sum = get_ipsum (dhcprMsgOut.ip);#ifdef DHCPR_DEBUG logMsg ("Writing %d bytes.\n", total, 0, 0, 0, 0, 0);#endif result = dhcpsSend (pIf, dhcprMsgOut.dhcp->chaddr, dhcprMsgOut.dhcp->hlen, &dest, (char *)dhcprMsgOut.ip, total, bcastFlag);#ifdef DHCPR_DEBUG if (result != OK) logMsg ("Error %d relaying message to client.\n", errno, 0, 0, 0, 0, 0);#endif } else { /* * The message exceeds the MTU size of the outgoing interface. * Split it into fragments and send them using the provided * transmit buffer. */ char *n, *end, *begin; begin = (char *) dhcprMsgOut.udp; end = &begin [total]; total = pIf->if_mtu - IPHL; for (n = begin; n < end; n += total) { if ((end - n) >= total) { dhcprMsgOut.ip->ip_len = htons (pIf->if_mtu); dhcprMsgOut.ip->ip_off = htons(IP_MF | ((((n - begin) / 8)) & 0x1fff)); dhcprMsgOut.ip->ip_sum = get_ipsum (dhcprMsgOut.ip); bcopy ( (char *)dhcprMsgOut.ip, pSendBuf, IPHL); bcopy ( (char *)n, &pSendBuf [IPHL], total); } else { /* Last fragment of message. */ dhcprMsgOut.ip->ip_len = htons (IPHL + end - n); dhcprMsgOut.ip->ip_off = htons(((n - begin) / 8) & 0x1fff); dhcprMsgOut.ip->ip_sum = get_ipsum(dhcprMsgOut.ip); bcopy ( (char *)dhcprMsgOut.ip, pSendBuf, IPHL); bcopy ( (char *)n, &pSendBuf [IPHL], end - n); } dhcpsSend (pIf, dhcprMsgOut.dhcp->chaddr, dhcprMsgOut.dhcp->hlen, &dest, pSendBuf, ntohs (dhcprMsgOut.ip->ip_len), bcastFlag); } /* Send complete: clean the transmit buffer before later use. */ bzero (pSendBuf, total + IPHL); } return; }/********************************************************************************* read_server_db - read IP addresses to receive relayed packets** This routine extracts the IP address entries hard-coded into usrNetwork.c as * dhcpTargetTbl[] and stores them in a circular linked list. Each of these * address entries must be on a different subnet from the calling server* or relay agent. Each entry in the list will receive a copy of every DHCP or* BOOTP message arriving at the client port.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/void read_server_db (int dbsize) { char targetIP [sizeof ("255.255.255.255")]; struct server *srvp = NULL; struct server *lastp = NULL; int loop; /* Read IP addresses of target servers or relay agents. */ for (loop = 0; (loop < dbsize) && (pDhcpRelayTargetTbl [loop].pAddress); loop++) { sprintf (targetIP, "%s", pDhcpRelayTargetTbl [loop].pAddress); srvp = (struct server *)calloc (1, sizeof (struct server)); if (srvp == NULL) {#ifdef DHCPR_DEBUG logMsg ("Memory allocation error reading relay target database.\n", 0, 0, 0, 0, 0, 0);#endif break; } srvp->ip.s_addr = inet_addr (targetIP); if (srvp->ip.s_addr == -1) {#ifdef DHCPR_DEBUG logMsg ("Conversion error reading relay target database.\n", 0, 0, 0, 0, 0, 0);#endif free (srvp); continue; } dhcpNumTargets++; srvp->next = pDhcpTargetList; if (pDhcpTargetList == NULL) lastp = srvp; pDhcpTargetList = srvp; } if (lastp == NULL) /* No target DHCP servers. */ return; /* Create circular list of DHCP server addresses. */ lastp->next = pDhcpTargetList;#ifdef DHCPR_DEBUG logMsg ("read %d entries from relay target database", dhcpNumTargets, 0, 0, 0, 0, 0);#endif return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -