Index: Build
===================================================================
RCS file: Build
diff -N Build
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Build	22 Mar 2004 01:16:31 -0000	1.2
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+source ../../Config.sh
+
+pp_do "$@"
Index: Makefile
===================================================================
RCS file: /srv/CVS/pp_shared/bootpc/Makefile,v
retrieving revision 1.1.123.1
retrieving revision 1.2
diff -u -r1.1.123.1 -r1.2
--- Makefile	29 Sep 2003 13:34:38 -0000	1.1.123.1
+++ Makefile	29 Sep 2003 13:40:10 -0000	1.2
@@ -1,13 +1,16 @@
 # Last updated : Tue Dec 15 03:38:58 1998
 # Version 0.64
 #
-# $Revision: 1.9 $
+# $Revision: 1.1.28.1.2.2 $
 #
+
+include ../../Config.mk
+
 PROG=bootpc
-CFLAGS=-O2 -Wall
+CFLAGS=$(FW_CFLAGS_3RDPARTY) -Wall
 
 # list the Cfiles here
-CFILES=bootpc.c main.c
+CFILES=bootpc.c main.c udpipgen.c
 
 # List the header files here
 CHEADS=bootpc.h bootp.h bptypes.h log.h
@@ -17,8 +20,8 @@
 	 ChangeLog rc.bootp VERSION
 
 # the delete command
-RM=/bin/rm
-SED=/usr/bin/sed
+RM=rm
+SED=sed
 
 # we generate this from the list of C files above
 OBJS=$(CFILES:.c=.o)
@@ -33,11 +36,13 @@
 
 ${PROG}: ${OBJS}
 	${CC} -o ${PROG} ${CFLAGS} ${OBJS}
-	strip ${PROG}
 
 ${PROG}-static: ${OBJS}
 	${CC} -static -o ${PROG} ${CFLAGS} ${OBJS}
-	strip ${PROG}
+
+install: all
+	install -d $(DESTDIR)/bin
+	install -m 755 $(PROG) $(DESTDIR)/bin/
 
 # Make up a distribution file from the bits we want people to see
 distrib:  $(CFILES) $(CHEADS) $(MISC)
Index: bootp.h
===================================================================
RCS file: /srv/CVS/pp_shared/bootpc/bootp.h,v
retrieving revision 1.1.123.1
retrieving revision 1.2
diff -u -r1.1.123.1 -r1.2
--- bootp.h	29 Sep 2003 13:34:38 -0000	1.1.123.1
+++ bootp.h	29 Sep 2003 13:40:10 -0000	1.2
@@ -23,7 +23,7 @@
 /*
  * Bootstrap Protocol (BOOTP).  RFC951 and RFC1395.
  *
- * $Id: bootp.h,v 1.1 1996/04/16 14:09:03 jp107 Exp $
+ * $Id: bootp.h,v 1.1.28.1.2.2 2003/01/30 15:21:58 rwa Exp $
  *
  *
  * This file specifies the "implementation-independent" BOOTP protocol
@@ -31,8 +31,19 @@
  *
  */
 
+#include "linux/if_ether.h"	/* for int32, u_int32 */
 #include "bptypes.h"	/* for int32, u_int32 */
 
+#ifdef BUFSIZ
+# undef BUFSIZ
+#endif
+#define BUFSIZ	       1500
+
+#define IPPACKET_SIZE  1500
+#define MAC_BCAST_ADDR "\xff\xff\xff\xff\xff\xff"
+#define BOOTP_INITIAL_RTO (4*1000000)
+#define BOOTP_MAX_RTO     (64*1000000)
+
 #define BP_CHADDR_LEN	 16
 #define BP_SNAME_LEN	 64
 #define BP_FILE_LEN	128
@@ -58,6 +69,18 @@
     /* note that bp_vend can be longer, extending to end of packet. */
 };
 
+struct packed_ether_header {
+  u_int8_t  ether_dhost[ETH_ALEN];      /* destination eth addr */
+  u_int8_t  ether_shost[ETH_ALEN];      /* source ether addr    */
+  u_int16_t ether_type;                 /* packet type ID field */
+} __attribute__((packed));
+
+typedef struct udpipMessage
+{
+  struct packed_ether_header	ethhdr;
+  char	 udpipmsg[IPPACKET_SIZE];
+} __attribute__((packed)) udpipMessage;
+
 /*
  * UDP port numbers, server and client.
  */
Index: bootpc.c
===================================================================
RCS file: /srv/CVS/pp_shared/bootpc/bootpc.c,v
retrieving revision 1.1.123.1
retrieving revision 1.2
diff -u -r1.1.123.1 -r1.2
--- bootpc.c	29 Sep 2003 13:34:38 -0000	1.1.123.1
+++ bootpc.c	29 Sep 2003 13:40:10 -0000	1.2
@@ -7,16 +7,18 @@
   Copyright (c) University of Cambridge, 1993-1996
   See the file NOTICE for conditions of use and distribution.
 
-  $Revision: 1.11 $
-  $Date: 1998/12/15 03:42:28 $
+  $Revision: 1.1.28.1.2.1 $
+  $Date: 2003/01/30 15:21:58 $
 */
 
 /* Standard headers */
 #include <stdio.h>
+#include <linux/if_ether.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <sys/time.h>
+#include <net/if_packet.h>
 #include <netinet/in.h>
 #include <netinet/ip.h>
 #include <netinet/ip_icmp.h>
@@ -31,9 +33,11 @@
 #include <errno.h>
 #include <ctype.h>
 #include <resolv.h>
+#include <time.h>
 
 /* local headers */
 #include "bootpc.h"
+#include "udpipgen.h"
 
 /* My global variables */
 int bootp_verbose = 0 ;   /* verbose mode or not 10/02/94 JSP */
@@ -42,6 +46,47 @@
 static int returniffail ;  /* Return to the user if we fail */
 static int printflag;      /* Print control */
 static int sockfd;
+unsigned char	ClientHwAddr[ETH_ALEN];
+
+static int timeval_subtract(struct timeval *result,
+			    struct timeval *x,
+			    struct timeval *y)
+{
+  /* Perform the carry for the later subtraction by updating Y. */
+  if (x->tv_usec < y->tv_usec) {
+    int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
+    y->tv_usec -= 1000000 * nsec;
+    y->tv_sec += nsec;
+  }
+  if (x->tv_usec - y->tv_usec > 1000000) {
+    int nsec = (x->tv_usec - y->tv_usec) / 1000000;
+    y->tv_usec += 1000000 * nsec;
+    y->tv_sec -= nsec;
+  }
+
+  /* Compute the time remaining to wait.
+     `tv_usec' is certainly positive. */
+  result->tv_sec = x->tv_sec - y->tv_sec;
+  result->tv_usec = x->tv_usec - y->tv_usec;
+
+  /* Return 1 if result is negative. */
+  return x->tv_sec < y->tv_sec;
+}
+
+int peekfd(int s, time_t tv_usec)
+{
+  fd_set fs;
+  struct timeval tv;
+
+  FD_ZERO(&fs);
+  FD_SET(s,&fs);
+  tv.tv_sec=tv_usec/1000000;
+  tv.tv_usec=tv_usec%1000000;
+
+  if ( select(s+1,&fs,NULL,NULL,&tv) == -1 ) return -1;
+  if ( FD_ISSET(s,&fs) ) return 0;
+  return 1;
+}
 
 int performBootp(char *device,
 		 char *server,
@@ -55,75 +100,88 @@
 		 int broadcast)
 {
   struct ifreq ifr;
-  struct sockaddr_in cli_addr, serv_addr;
+  struct sockaddr addr;
+  struct sockaddr_pkt sap;
+  struct ip ipRecv_local;
+  udpipMessage	udpIpMsgSend,udpIpMsgRecv;
+  const struct udphdr *udpRecv=(struct udphdr *)((char *)(((struct udpiphdr *)udpIpMsgRecv.udpipmsg)->ip)+sizeof(struct ip));
+  struct bootp *bootpMsgSend = (struct bootp *)&udpIpMsgSend.udpipmsg[sizeof(udpiphdr)];
+  struct bootp *bootpMsgRecv = (struct bootp *)&udpIpMsgRecv.udpipmsg[sizeof(udpiphdr)];
   struct bootp *bootp_xmit, *bootp_recv;
-  fd_set rfds, wfds, xfds;
-  struct timeval timeout ;
+  int timeout ;
   int32 rancopy ;
   int cookielength ;
-  long plen ;
-  int retry_wait, waited=0 ;
+  long plen, len;
+  struct timeval begin, current, diff;
   int one=1, i ;
+  int j=BOOTP_INITIAL_RTO/2;
   struct timeval tp;
   int received_packet = 0 ;
 /* See RFC1497, RFC1542  09/02/94   JSP  */
   unsigned char mincookie[] = {99,130,83,99,255} ;
+  unsigned char vendor_options[] = {99,130,83,99,57,2,4,0,255} ;
 
   returniffail=bp_rif ;
   printflag=bp_pr ;
 
-/* zero structure before use */
-  memset((char *) &serv_addr, 0, sizeof(serv_addr));
+  memset(&ifr,0,sizeof(struct ifreq));
+  memcpy(ifr.ifr_name,device,strlen(device)+1);
 
-  serv_addr.sin_family = AF_INET;
-  serv_addr.sin_addr.s_addr = inet_addr(server) ;
-  serv_addr.sin_port = htons(IPPORT_BOOTPS);
-
-  if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-    perror("bootpc: socket failed");
-    return BootpFatal();
-  }
-  
-  if (setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&one,sizeof(one))==-1) {
-    perror("bootpc: setsockopt failed");
-    return BootpFatal();
-  }
-  
-  memset((char *) &cli_addr, 0, sizeof(cli_addr));
-  cli_addr.sin_family = AF_INET;
-  cli_addr.sin_addr.s_addr = htonl(INADDR_ANY);
-  cli_addr.sin_port = htons(IPPORT_BOOTPC);
-
-  if(bind(sockfd, (struct sockaddr *) &cli_addr, sizeof(cli_addr)) < 0) {
-    perror("bootpc: bind failed");
-    return BootpFatal();
+  if ((sockfd = socket(AF_PACKET,SOCK_PACKET,htons(ETH_P_ALL))) < 0) {
+      perror("bootpc: socket failed");
+      return BootpFatal();
   }
 
-/* allocate bootp packet before we use it */
-  bootp_xmit = (struct bootp *) malloc(BUFSIZ) ;
-  memset((char *) bootp_xmit, 0, BUFSIZ) ;
-
-  bootp_recv = (struct bootp *) malloc(BUFSIZ) ;
-  memset((char *) bootp_recv, 0, BUFSIZ) ;
+  if (ioctl(sockfd,SIOCGIFHWADDR, &ifr) < 0) {
+      perror("bootpc: ioctl(SIOCGIFHWADDR) failed");
+      return BootpFatal();
+  }
 
-  /* Server needs to broadcast for me to see it */
-  if (broadcast || givenhwaddr)
-    bootp_xmit->bp_flags |= htons(BPFLAG_BROADCAST);
+  if (setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&one,sizeof(one)) < 0) {
+      perror("bootpc: setsockopt failed");
+      return BootpFatal();
+  }
+  ifr.ifr_flags = IFF_UP | IFF_BROADCAST | IFF_NOTRAILERS | IFF_RUNNING | IFF_MULTICAST;
+  if (ioctl(sockfd,SIOCSIFFLAGS,&ifr) < 0) {
+      perror("bootpc: ioctl(SIOCSIFFLAGS) failed");
+      return BootpFatal();
+  }
+  memset(&sap,0,sizeof(sap));
+  sap.spkt_family = AF_PACKET;
+  sap.spkt_protocol = htons(ETH_P_ALL);
+  memcpy(sap.spkt_device,device,strlen(device)+1);
+  if (bind(sockfd,(void*)&sap,sizeof(struct sockaddr)) < 0) {
+      perror("bootpc: bind failed");
+      return BootpFatal();
+  }
 
-/* Don't do this if we were given the MAC address to use.  27/09/94  JSP */
   if (givenhwaddr) {
     /* Assuming ETHER if given HW */
     ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER ;
     ifr.ifr_hwaddr = their_ifr->ifr_hwaddr ;
   } else {
-/* Get the hardware address, and family information */
+    /* Get the hardware address, and family information */
+    memset(&ifr,0,sizeof(struct ifreq));
     memcpy(ifr.ifr_name, device, strlen(device)+1);
     if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) {
-      perror("bootpc: ioctl failed");
+      perror("bootpc: ioctl(SIOCGIFHWADDR) failed");
       return BootpFatal();
     }
   }
 
+  memcpy(ClientHwAddr,ifr.ifr_hwaddr.sa_data,ETH_ALEN);
+
+/* allocate bootp packet before we use it */
+  bootp_xmit = (struct bootp *) malloc(BUFSIZ) ;
+  memset((char *) bootp_xmit, 0, BUFSIZ) ;
+
+  bootp_recv = (struct bootp *) malloc(BUFSIZ) ;
+  memset((char *) bootp_recv, 0, BUFSIZ) ;
+
+  /* Server needs to broadcast for me to see it */
+  if (broadcast || givenhwaddr)
+    bootp_xmit->bp_flags |= htons(BPFLAG_BROADCAST);
+
 /* Check the network family if in NET3 or later, before NET3 you couldn't
    examine this info (as far as I know.) */
 
@@ -150,7 +208,9 @@
       ((unsigned char *)(ifr.use_hwaddr))[i] ;
   }
 /* and set the seed */
-  srand(rancopy) ;
+  srandom(rancopy) ;
+
+  ip_id=time(NULL)&0xffff;
 
   if(bootp_debug) {
     logMessage("hardware addr is :") ;
@@ -190,77 +250,102 @@
   bootp_xmit->bp_secs = 0;
 
 /* Put in the minimal RFC1497 Magic cookie 09/02/94 JSP */
-  memcpy(bootp_xmit->bp_vend, mincookie, sizeof(mincookie));
+  memcpy(bootp_xmit->bp_vend, vendor_options, sizeof(vendor_options));
 
 /* Put the user precified bootfile name in place 12/02/94 */
   memcpy(bootp_xmit->bp_file, bootfile, strlen(bootfile)+1);
 
-/* put a random value in here, but keep a copy to check later 09/02/94  JSP */
-  bootp_xmit->bp_xid = rancopy = rand() ;
-
-  retry_wait = 2 ;
-  if (bootp_verbose)
-    logMessage("BOOTPclient broadcast...");
-
-  while (((waited <= timeout_wait) && !received_packet) ||
-	 ((waited <= waitformore) && received_packet)) {
-    
-    if (!received_packet) {  /* Move this to a sendpacket function */
-      /* set time of this timeout  09/02/94  JSP */
-      bootp_xmit->bp_secs = waited ;
-      if (bootp_verbose) {
-	logMessage("."); fflush(stderr);
-      }
-      if (bootp_debug) {
-	logMessage("Size = %ld", (long)sizeof(struct bootp)) ;
-      }
+  alarm(timeout_wait);
+  do {
+    /* put a random value in here, but keep a copy to check later 09/02/94  JSP */
+    bootp_xmit->bp_xid = rancopy = random() ;
 
-      if(sendto(sockfd, bootp_xmit, sizeof(struct bootp), 0, 
-		(struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
-	perror("bootpc: sendto");
-	return BootpFatal();
-      }
-    }
+    if (bootp_verbose)
+      logMessage("BOOTPclient broadcast...");
 
-    /* Move rest of this loop to a receivepacket function */
-    FD_ZERO(&rfds);
-/* The above was missing, thanks to
-   Gilles Detillieux <grdetil@cliff.scrc.UManitoba.CA> for pointing it out */
-    FD_SET(sockfd,&rfds);
-    FD_ZERO(&wfds);
-    FD_ZERO(&xfds);
-
-/* Randomise the delays a little as suggested in RFC1542  09/02/94  JSP */
-    timeout.tv_sec = retry_wait + (1+(rand() & (retry_wait-1))) ;
-    timeout.tv_usec = 0;
-    waited += timeout.tv_sec ;  /* Add this to the total time we have waited */
+    do {
+      j+=j;
+      if (j > BOOTP_MAX_RTO) j = BOOTP_MAX_RTO;
 
-    if(select(sockfd+1, &rfds, &wfds, &xfds, &timeout)<0) {
-      perror("bootpc: select");
-      return BootpFatal();
-    }
+      if (!received_packet) {  /* Move this to a sendpacket function */
+	bootp_xmit->bp_secs = htons(3);
+	if (bootp_verbose) {
+	  logMessage("."); fflush(stderr);
+	}
+	if (bootp_debug) {
+	  logMessage("Size = %ld", (long)sizeof(struct bootp)) ;
+	}
 
-    if(!FD_ISSET(sockfd, &rfds)) {
-      retry_wait = retry_wait*2;
-    } else {
-      if ((plen = recvfrom(sockfd, bootp_recv, BUFSIZ, 0,
+	memset(&addr,0,sizeof(struct sockaddr));
+	memcpy(addr.sa_data,device,strlen(device)+1);
+	/* build bootp request packet */
+	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(ETH_P_IP);
+	memcpy(bootpMsgSend, bootp_xmit, sizeof(struct bootp));
+	udpipgen((udpiphdr *)udpIpMsgSend.udpipmsg,0,INADDR_BROADCAST,
+		 htons(IPPORT_BOOTPC),htons(IPPORT_BOOTPS),sizeof(struct bootp));
+	if(sendto(sockfd, &udpIpMsgSend, sizeof(struct packed_ether_header)+
+		  sizeof(udpiphdr)+sizeof(struct bootp), 0, 
+		  (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+	  perror("bootpc: sendto");
+	  return BootpFatal();
+	}
+      }
+      gettimeofday(&begin, NULL);
+      i=random();
+    } while (peekfd(sockfd,j+i%200000));
+
+    do {
+      memset(&udpIpMsgRecv,0,sizeof(udpipMessage));
+      if ((plen = recvfrom(sockfd, &udpIpMsgRecv, sizeof(udpipMessage), 0,
 			   (struct sockaddr *)NULL, (int *)NULL)) < 0){
 	perror("bootpc: recvfrom");
 	return BootpFatal();
       }
+      gettimeofday(&current, NULL);
+      timeval_subtract(&diff, &current, &begin);
+      timeout = j - diff.tv_sec*1000000 - diff.tv_usec + random()%200000;
+      
+      if (udpIpMsgRecv.ethhdr.ether_type != htons(ETH_P_IP)) continue;
+      /* Use local copy because ipRecv is not aligned.  */
+      memcpy(&ipRecv_local, ((struct udpiphdr *)udpIpMsgRecv.udpipmsg)->ip,
+	     sizeof(struct ip));
+      if (ipRecv_local.ip_p != IPPROTO_UDP ) continue;
+      len = plen - sizeof(struct packed_ether_header);
+      i=(int )ntohs(ipRecv_local.ip_len);
+      if (len < i) {
+	if (bootp_verbose) {
+	  logMessage("corrupted IP packet of size=%d and ip_len=%d discarded\n",
+		     len,i);
+	}
+	continue;
+      }
+      len=i-(ipRecv_local.ip_hl<<2);
+      i=(int )ntohs(udpRecv->uh_ulen);
+      if (len < i) {
+	if (bootp_verbose) {
+	  logMessage("corrupted UDP msg of size=%d and uh_ulen=%d discarded\n",
+		     len,i);
+	}
+	continue;
+      }
+      plen -= sizeof(struct packed_ether_header) + sizeof(udpiphdr);
 
       if (bootp_debug) {
 	logMessage("plen = %ld  plen - sizeof(struct bootp) = %ld",
 		   (long)plen, (long)(plen - sizeof(struct bootp))) ;
       }
-      cookielength = 64 + plen - sizeof(struct bootp) ;
+      cookielength = 64 + plen - sizeof(struct bootp);
+
+      bootpMsgRecv = (struct bootp *)&udpIpMsgRecv.udpipmsg[(ipRecv_local.ip_hl<<2)+sizeof(struct udphdr)];
+      memcpy(bootp_recv, bootpMsgRecv, plen);
       
       if (bootp_recv->bp_xid == rancopy) {  /* is xid right */
+	if (bootp_recv->bp_op != BOOTREPLY) continue; /* check if it's a reply */
 	if (!received_packet) {
-	  /* If we haven't already recieved a packet then set the time to wait
-	     further to be now + time user specified */
-	  waitformore += waited ;
-	  received_packet = 1 ;
+	    received_packet = 1 ;
 	} else {
 	  /* To make it look a bit prettier */
 	  if (printflag & BP_PRINT_OUT)
@@ -270,9 +355,8 @@
 	   the cookie parser.  It needs our address to get the network and
 	   broadcast bits right if the SUBNET is defined in the cookie.
 	   10/02/94  JSP */
-	ParsePacket(bootp_recv,
-		    cookielength,
-		    mincookie) ;
+	ParsePacket(bootp_recv, cookielength, mincookie);
+	break;
       } else {
 	/* xid mismatch so normally silently ignore */
 	if (bootp_verbose) {
@@ -280,15 +364,14 @@
 		     (long)bootp_recv->bp_xid, (long)rancopy) ;
 	}
       }
-    }
-  }
-  if (!received_packet) {
-    logMessage("No response from BOOTP server");
-    return BootpFatal();
-  }
+    } while (timeout > 0 && peekfd(sockfd, timeout) == 0);
 
-  if (sockfd)
-    close (sockfd) ;
+    if (received_packet) {
+	close(sockfd);
+	break;
+    }
+  } while (1);
+  alarm(0);
   return 0 ;  /* Normal exit */
 }
     
@@ -542,8 +625,36 @@
 	  else
 	    logMessage("Unknown TAG %d at %d (len %d)", tag, i, len) ;
 	}
-	sprintf(name, "T%3.3d", tag) ;
-	OutString(name, cookie+i+2, len) ;
+	if (tag == 43) {
+	    unsigned char *subcookie = &cookie[i+2];
+	    int subcookielength = len;
+	    int j = 0;
+	    while (j < subcookielength && subcookie[j] != TAG_END) {
+		int subtag = subcookie[j];
+		int sublen;
+		/* If we arn't at the end of the cookie and we will need it extract len */
+		if ((j < subcookielength - 1) && (subtag != TAG_PAD)) {
+		    sublen = subcookie[j+1];
+		} else {
+		    sublen = 0;
+		}
+
+		/* Warn if the "length" takes us out of the cookie and truncate */
+		if (sublen + j > subcookielength) {
+		    if (bootp_verbose)
+			logMessage("Vendor TAG %d at %d.  len %d, overrun %d",
+				   subcookie[j], i+2+j, sublen, j + sublen - subcookielength);
+		    /* And truncate in any case even with no warning */
+		    sublen = subcookielength - j;
+		}
+		sprintf(name, "T%3.3d_%3.3d", tag, subtag) ;
+		OutString(name, subcookie+j+2, sublen);
+		j += 2 + sublen;
+	    }
+	} else {
+	    sprintf(name, "T%3.3d", tag) ;
+	    OutString(name, cookie+i+2, len) ;
+	}
 	i += 2 + len ;
       }
       break ;
Index: main.c
===================================================================
RCS file: /srv/CVS/pp_shared/bootpc/main.c,v
retrieving revision 1.1.123.1
retrieving revision 1.2
diff -u -r1.1.123.1 -r1.2
--- main.c	29 Sep 2003 13:34:38 -0000	1.1.123.1
+++ main.c	29 Sep 2003 13:40:10 -0000	1.2
@@ -7,8 +7,8 @@
   Copyright (c) University of Cambridge, 1993-1996
   See the file NOTICE for conditions of use and distribution.
 
-  $Revision: 1.3 $
-  $Date: 1998/12/15 03:43:00 $
+  $Revision: 1.1.28.1.2.2 $
+  $Date: 2003/01/30 15:21:58 $
 */
 
 /* Standard headers */
@@ -16,12 +16,16 @@
 #include <netinet/in.h>
 #include <net/if.h>
 #include <getopt.h>
+#include <signal.h>
 #include <stdlib.h>
+#include <string.h>
 #include <errno.h>
 
 #include "bootpc.h"
 
-FILE * logfile = stderr ;
+FILE * logfile;
+
+static void timeout_handler(int sig);
 
 int main(int argc,
 	 char *argv[])
@@ -32,6 +36,9 @@
   int givenhwaddr, i, serverbcast=0;
   char *device, *bootfile, *server ;
   int returniffail=0, printflag = BP_PRINT_OUT ;
+  struct sigaction action;
+
+  logfile = stderr ;
 
 /* defaults unless overridden by command line options 10/02/94  JSP */
   device = "eth0" ;             /* first ethernet card */
@@ -148,6 +155,10 @@
   }
 
 
+  action.sa_handler= timeout_handler;
+  action.sa_flags = 0;
+  sigaction(SIGALRM,&action,NULL);
+
   return performBootp(device, server, bootfile, timeout_wait,
 		      givenhwaddr, &ifr,
 		      waitformore, returniffail,
@@ -164,3 +175,11 @@
     fprintf(logfile, "\n");
     va_end(args);
 }
+
+static void timeout_handler(int sig)
+{
+  if (sig == SIGALRM) {
+    logMessage("bootpc: timed out waiting for a valid BOOTP server response\n");
+    exit(1);
+  }
+}
Index: udpipgen.c
===================================================================
RCS file: udpipgen.c
diff -N udpipgen.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ udpipgen.c	29 Sep 2003 13:40:10 -0000	1.1
@@ -0,0 +1,124 @@
+/*
+ * dhcpcd - DHCP client daemon -
+ * Copyright (C) January, 1998 Sergei Viznyuk <sv@phystech.com>
+ * 
+ * dhcpcd is an RFC2131 and RFC1541 compliant DHCP client daemon.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <string.h>
+#include "udpipgen.h"
+
+unsigned short ip_id;
+/*****************************************************************************/
+unsigned short in_cksum(addr,len)
+unsigned short *addr;
+int len;
+{
+  register int sum = 0;
+  register u_short *w = addr;
+  register int nleft = len;
+  while ( nleft > 1 )
+    {
+      sum += *w++;
+      nleft -= 2;
+    }
+  if ( nleft == 1 )
+    {
+      u_char a = 0;
+      memcpy(&a,w,1);
+      sum += a;
+    }
+  sum = (sum >> 16) + (sum & 0xffff);
+  sum += (sum >> 16);
+  return ~sum;
+}
+/*****************************************************************************/
+void udpipgen(udpip,saddr,daddr,sport,dport,msglen)
+udpiphdr *udpip;
+unsigned int saddr,daddr;
+unsigned short sport,dport,msglen;
+{
+  /* Use local copy because udpip->ip is not aligned.  */
+  struct ip ip_local;
+  struct ip *ip=&ip_local;
+  struct ipovly *io=(struct ipovly *)udpip->ip;
+  struct udphdr *udp=(struct udphdr *)udpip->udp;
+
+  io->ih_next = io->ih_prev = 0;
+  io->ih_x1 = 0;
+  io->ih_pr = IPPROTO_UDP;
+  io->ih_len = htons(msglen + sizeof(struct udphdr));
+  io->ih_src.s_addr = saddr;
+  io->ih_dst.s_addr = daddr;
+  udp->uh_sport = sport;
+  udp->uh_dport = dport;
+  udp->uh_ulen = io->ih_len;
+  udp->uh_sum = 0;
+  udp->uh_sum=in_cksum((unsigned short *)udpip,msglen+sizeof(udpiphdr));
+  if ( udp->uh_sum == 0 ) udp->uh_sum = 0xffff;
+  ip->ip_hl = 5;
+  ip->ip_v = IPVERSION;
+  ip->ip_tos = 0;	/* normal service */
+  ip->ip_len = htons(msglen + sizeof(udpiphdr));
+  ip->ip_id = htons(ip_id);
+  ip->ip_off = 0;
+  ip->ip_ttl = IPDEFTTL; /* time to live, 64 by default */
+  ip->ip_p = IPPROTO_UDP;
+  ip->ip_src.s_addr = saddr;
+  ip->ip_dst.s_addr = daddr;
+#ifdef __GLIBC__
+  ip->ip_sum = 0;
+  ip->ip_sum = in_cksum((unsigned short *)&ip_local,sizeof(struct ip));
+#else
+  ip->ip_csum = 0;
+  ip->ip_csum = in_cksum((unsigned short *)&ip_local,sizeof(struct ip));
+#endif
+  memcpy(udpip->ip, ip, sizeof(struct ip));
+  ip_id++;
+}
+/*****************************************************************************/
+int udpipchk(udpip)
+udpiphdr *udpip;
+{
+  int hl;
+  struct ip save_ip;
+  struct ip *ip=(struct ip *)udpip->ip;
+  struct ipovly *io=(struct ipovly *)udpip->ip;
+  struct udphdr *udp=(struct udphdr *)udpip->udp;
+  udpiphdr *nudpip = udpip;
+
+  hl = ip->ip_hl<<2;
+  if ( in_cksum((unsigned short *)udpip,hl) ) return -1;
+  memcpy(&save_ip, udpip->ip, sizeof(struct ip));
+  hl -= sizeof(struct ip);
+  if ( hl )
+    { /* thrash IP options */
+      nudpip = (udpiphdr *)((char *)udpip+hl);
+      memmove((char *)nudpip,udpip,sizeof(struct ip));
+      io=(struct ipovly *)nudpip->ip;
+      ip=(struct ip *)nudpip->ip;
+      udp=(struct udphdr *)nudpip->udp;
+    }
+  if ( udp->uh_sum == 0 ) return 0; /* no checksum has been done by sender */
+  io->ih_next = io->ih_prev = 0;
+  io->ih_x1 = 0;
+  io->ih_len = udp->uh_ulen;
+  hl = ntohs(udp->uh_ulen)+sizeof(struct ip);
+  if ( in_cksum((unsigned short *)nudpip,hl) ) return -2;
+  memcpy(udpip->ip, &save_ip, sizeof(struct ip));
+  return 0;
+}
Index: udpipgen.h
===================================================================
RCS file: udpipgen.h
diff -N udpipgen.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ udpipgen.h	29 Sep 2003 13:40:10 -0000	1.1
@@ -0,0 +1,61 @@
+/*
+ * dhcpcd - DHCP client daemon -
+ * Copyright (C) January, 1998 Sergei Viznyuk <sv@phystech.com>
+ * 
+ * dhcpcd is an RFC2131 and RFC1541 compliant DHCP client daemon.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef UDPIPGEN_H
+#define UDPIPGEN_H
+
+#include <netinet/ip.h>
+
+#ifndef IPDEFTTL
+#define IPDEFTTL 64
+#endif
+
+struct ipovly
+{
+  int ih_next,ih_prev;
+  u_char ih_x1;
+  u_char ih_pr;
+  u_short ih_len;
+  struct in_addr ih_src;
+  struct in_addr ih_dst;
+} __attribute__((packed));
+
+struct udphdr
+{
+  u_int16_t uh_sport;
+  u_int16_t uh_dport;
+  u_int16_t uh_ulen;
+  u_int16_t uh_sum;
+} __attribute__((packed));
+
+typedef struct udpiphdr
+{
+  char ip[sizeof(struct ip)];
+  char udp[sizeof(struct udphdr)];
+} __attribute__((packed)) udpiphdr;
+
+extern unsigned short ip_id;
+
+void udpipgen(udpiphdr *udpip,unsigned int saddr,unsigned int daddr,
+unsigned short sport,unsigned short dport,unsigned short msglen);
+int udpipchk(udpiphdr *udpip);
+
+#endif
