--- oldbootp.c 2004-05-03 14:11:44.000000000 +0200 +++ bootp.c 2004-05-13 16:57:08.000000000 +0200 @@ -29,10 +29,12 @@ #define START_ADDR 15 -#define LEASE_TIME (24 * 3600) +#define LEASE_TIME (120) typedef struct { uint8_t allocated; + uint8_t macaddr[6]; + int time; } BOOTPClient; BOOTPClient bootp_clients[NB_ADDR]; @@ -50,26 +52,69 @@ { BOOTPClient *bc; int i; + int now=time(NULL); for(i = 0; i < NB_ADDR; i++) { if (!bootp_clients[i].allocated) goto found; } + for(i = 0; i < NB_ADDR; i++) { + if (now-bootp_clients[i].time > 3*LEASE_TIME) + goto found; + } return NULL; found: bc = &bootp_clients[i]; - bc->allocated = 1; paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR)); return bc; } +static BOOTPClient *find_addr(struct in_addr *paddr, const uint8_t *macaddr) +{ + BOOTPClient *bc; + int i; + + for(i = 0; i < NB_ADDR; i++) { + if (!memcmp(macaddr, bootp_clients[i].macaddr, 6)) + goto found; + } + return NULL; + found: + bc = &bootp_clients[i]; + paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR)); + return bc; +} + +static BOOTPClient *find_reqaddr(struct in_addr *paddr, struct in_addr *reqaddr, const uint8_t *macaddr) +{ + BOOTPClient *bc=NULL; + int i; + /*check the net prefix*/ + if ((ntohl(reqaddr->s_addr) & 0xffffff00) == + (ntohl(special_addr.s_addr) & 0xffffff00)) { + i=(ntohl(reqaddr->s_addr) & 0xff) - START_ADDR; + if (i>=0 && i< NB_ADDR) { + bc = &bootp_clients[i]; + if (bc->allocated && + (memcmp(macaddr, bootp_clients[i].macaddr, 6)==0)) { + paddr->s_addr = reqaddr->s_addr; + return bc; + } + else + bc=NULL; + } + } + return bc; +} + static void dhcp_decode(const uint8_t *buf, int size, - int *pmsg_type) + int *pmsg_type, struct sockaddr_in *preqaddr) { const uint8_t *p, *p_end; int len, tag; *pmsg_type = 0; + preqaddr->sin_addr.s_addr=htonl(0L); p = buf; p_end = buf + size; @@ -96,6 +141,10 @@ if (len >= 1) *pmsg_type = p[0]; break; + case RFC2132_REQ_ADDR: + if (len == 4) { + memcpy(&(preqaddr->sin_addr),p,4); + } default: break; } @@ -109,14 +158,14 @@ BOOTPClient *bc; struct mbuf *m; struct bootp_t *rbp; - struct sockaddr_in saddr, daddr; + struct sockaddr_in saddr, daddr, reqaddr; struct in_addr dns_addr; int dhcp_msg_type, val; - uint8_t *q; + uint8_t *q,replytype; /* extract exact DHCP msg type */ - dhcp_decode(bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type); - dprintf("bootp packet op=%d msgtype=%d\n", bp->bp_op, dhcp_msg_type); + dhcp_decode(bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type,&reqaddr); + dprintf("bootp packet op=%d msgtype=%d reqaddr=%x\n", bp->bp_op, dhcp_msg_type,ntohl(reqaddr.sin_addr.s_addr)); if (dhcp_msg_type != DHCPDISCOVER && dhcp_msg_type != DHCPREQUEST) @@ -131,11 +180,20 @@ m->m_data += sizeof(struct udpiphdr); memset(rbp, 0, sizeof(struct bootp_t)); + bc=NULL; + daddr.sin_addr.s_addr=htonl(0L); + if (dhcp_msg_type == DHCPREQUEST) { + if (reqaddr.sin_addr.s_addr != htonl(0L)) + bc = find_reqaddr(&daddr.sin_addr, &reqaddr.sin_addr, bp->bp_hwaddr); + else + bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr); + } + else if (dhcp_msg_type == DHCPDISCOVER) { + bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr); + if (!bc) bc = get_new_addr(&daddr.sin_addr); - if (!bc) { - dprintf("no address left\n"); - return; } + dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr)); saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS); @@ -155,18 +213,21 @@ memcpy(q, rfc1533_cookie, 4); q += 4; - if (dhcp_msg_type == DHCPDISCOVER) { - *q++ = RFC2132_MSG_TYPE; - *q++ = 1; - *q++ = DHCPOFFER; - } else if (dhcp_msg_type == DHCPREQUEST) { + if (bc != NULL) { + memcpy(bc->macaddr, client_ethaddr, 6); + bc->allocated = 1; + bc->time = time(NULL); + replytype=(dhcp_msg_type == DHCPDISCOVER)?DHCPOFFER:DHCPACK; + } + else + replytype=DHCPNACK; + *q++ = RFC2132_MSG_TYPE; *q++ = 1; - *q++ = DHCPACK; - } + *q++ = replytype; - if (dhcp_msg_type == DHCPDISCOVER || - dhcp_msg_type == DHCPREQUEST) { + if ((dhcp_msg_type == DHCPDISCOVER || + dhcp_msg_type == DHCPREQUEST) && replytype!=DHCPNACK) { *q++ = RFC2132_SRV_ID; *q++ = 4; memcpy(q, &saddr.sin_addr, 4);