sdhcp

simple dhcp client
git clone git://git.2f30.org/sdhcp.git
Log | Files | Refs | LICENSE

commit d64b498944cd8ca265e167f130992dff5b744e68
parent 2a32d2ca9330dbf0c660827daf2da3d3e657697d
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date:   Mon Apr 27 22:59:41 +0200

code-style, remove debug.c, config.mk: default c99

Diffstat:
TODO | 5+----
config.mk | 5++---
debug.c | 148-------------------------------------------------------------------------------
sdhcp.c | 90++++++++++++++++++++++++++++++++++---------------------------------------------
util/eprintf.c | 14++++++--------
5 files changed, 48 insertions(+), 214 deletions(-)
diff --git a/TODO b/TODO @@ -2,9 +2,6 @@ TODO: [ ] manual check memcpy bounds. [ ] add flag (-s?) to probe a specific DHCP server, not broadcast? probably skip in run() Init: etc stages. -[ ] sane default value for client-id and test it. -[ ] add new options to man page (-d, -i). -[ ] update LICENSE. [ ] replace unsigned char ip[4] and so on from function declarations. [?] ipv6 support ? @@ -20,7 +17,6 @@ Changed (for now): - typos: - sdhcp.c: interface typo. - sdhcp.1: shdcp typo. - - make exit([01]), EXIT_SUCCESS or EXIT_FAILURE. - replace write() for stdout messages with fprintf() - replace die() with eprintf(). - makefile: @@ -33,6 +29,7 @@ Changed (for now): "vaio". - add -d flag, don't update /etc/resolv.conf. - add -i flag, don't set ip. + - add -f flag, run in foreground. - add -e flag, run program, this has the following variables set: $SERVER, DHCP ip. $DNS, DNS ip. diff --git a/config.mk b/config.mk @@ -6,8 +6,7 @@ DESTDIR = MANPREFIX = $(PREFIX)/share/man CC = cc -#CC = musl-gcc LD = $(CC) CPPFLAGS = -D_BSD_SOURCE -CFLAGS = -g -Wall -Wextra -O0 -ansi $(CPPFLAGS) -LDFLAGS = -g +CFLAGS = -Wall -Wextra -pedantic -std=c99 $(CPPFLAGS) +LDFLAGS = diff --git a/debug.c b/debug.c @@ -1,148 +0,0 @@ -#include <stdarg.h> - -void bpdump(unsigned char *p, int n); - -unsigned short -nhgets(unsigned char c[2]) -{ - return ((c[0] << 8) + c[1]) & 0xffff; -} - -unsigned long -nhgetl(unsigned char c[4]) -{ - return (nhgets(c) << 16) + nhgets(c + 2); -} - -char * -ipstr(unsigned char *ip) -{ - char * ch = malloc(3 * 4 + 3 + 10); - sprintf(ch, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); - return ch; -} - -#if 0 -void -dbgprintf(char *str, ...) -{ - va_list ap; - va_start(ap, str); - vfprintf(stderr, str, ap); - va_end(ap); -} -#endif - -void -bpdump(unsigned char *p, int n) -{ - int len, i, code; - Bootp *bp; - unsigned char type; - char *types[] = { - "discover", "offer", "request", - "decline", "ack", "nak", "release", "inform" - }; - /* Udphdr *up; */ - - bp = (Bootp*)p; - /* up = (Udphdr*)bp->udphdr; */ - - if(n < bp->magic - p) { - fprintf(stderr, "dhcpclient: short bootp packet"); - return; - } - - optget(bp, &type, ODtype, sizeof type); - fprintf(stderr, "DHCP%s\n", types[type - 1]); - /* fprintf(stderr, "laddr=%I lport=%d raddr=%I rport=%d\n", up->laddr, - nhgets(up->lport), up->raddr, nhgets(up->rport)); */ - fprintf(stderr, "op = %d htype = %d hlen = %d hops = %d\n", *bp->op, *bp->htype, - *bp->hlen, *bp->hops); - fprintf(stderr, "xid = %x secs = %d flags = %x\n", nhgetl(bp->xid), - nhgets(bp->secs), nhgets(bp->flags)); - fprintf(stderr, "ciaddr = %s, yiaddr = %s, siaddr = %s, giaddr = %s\n", - ipstr(bp->ciaddr), ipstr(bp->yiaddr), ipstr(bp->siaddr), ipstr(bp->giaddr)); - fprintf(stderr, "chaddr ="); - for(i=0; i<15; i++) - fprintf(stderr, "%.2x:", bp->chaddr[i]); - fprintf(stderr, "%.2x\n", bp->chaddr[15]); - fprintf(stderr, "sname = %s\n", bp->sname); - fprintf(stderr, "file = %s\n", bp->file); - - n -= bp->magic - p; - p = bp->magic; - - if(n < 4) - return; - if(memcmp(magic, p, 4) != 0) - fprintf(stderr, "dhcpclient: bad opt magic %#x %#x %#x %#x\n", - p[0], p[1], p[2], p[3]); - p += 4; - n -= 4; - - while(n > 0) { - code = *p++; - n--; - if(code == OBpad) - continue; - if(code == OBend) - break; - if(n == 0) { - fprintf(stderr, " bad option: %d", code); - return; - } - len = *p++; - n--; - if(len > n) { - fprintf(stderr, " bad option: %d", code); - return; - } - switch(code) { - case ODtype: - fprintf(stderr, "DHCP type %d\n", p[0]); - break; - case ODclientid: - fprintf(stderr, "client id="); - for(i = 0; i<len; i++) - fprintf(stderr, "%x ", p[i]); - fprintf(stderr, "\n"); - break; - case ODlease: - fprintf(stderr, "lease=%d sec\n", nhgetl(p)); - break; - case ODserverid: - fprintf(stderr, "server id=%s\n", ipstr(p)); - break; - case OBmask: - fprintf(stderr, "mask=%s\n", ipstr(p)); - break; - case OBrouter: - fprintf(stderr, "router=%s\n", ipstr(p)); - break; - case ODipaddr: - fprintf(stderr, "ip addr=%s\n", ipstr(p)); - break; - case OBdnsserver: - fprintf(stderr, "dns=%s\n", ipstr(p)); - break; - case OBbaddr: - fprintf(stderr, "broadcast=%s\n", ipstr(p)); - break; - case ODrenewaltime: - fprintf(stderr, "renew time=%d sec\n", nhgetl(p)); - break; - case ODrebindingtime: - fprintf(stderr, "rebind time=%d sec\n", nhgetl(p)); - break; - default: - fprintf(stderr, "unknown option %d\n", code); - for(i = 0; i<len; i++) - fprintf(stderr, "%x ", p[i]); - fprintf(stderr, "\n"); - break; - } - p += len; - n -= len; - } -} diff --git a/sdhcp.c b/sdhcp.c @@ -108,7 +108,7 @@ hnput(unsigned char *dst, unsigned long long src, size_t n) { unsigned int i; - for(i = 0; n--; i++) + for (i = 0; n--; i++) dst[i] = (src >> (n * 8)) & 0xff; } @@ -120,6 +120,7 @@ iptoaddr(struct sockaddr *ifaddr, unsigned char ip[4], int port) in->sin_family = AF_INET; in->sin_port = htons(port); memcpy(&(in->sin_addr), ip, sizeof in->sin_addr); + return ifaddr; } @@ -132,8 +133,9 @@ udpsend(unsigned char ip[4], int fd, void *data, size_t n) ssize_t sent; iptoaddr(&addr, ip, 67); /* bootp server */ - if((sent = sendto(fd, data, n, 0, &addr, addrlen)) == -1) + if ((sent = sendto(fd, data, n, 0, &addr, addrlen)) == -1) eprintf("sendto:"); + return sent; } @@ -146,8 +148,9 @@ udprecv(unsigned char ip[4], int fd, void *data, size_t n) ssize_t r; iptoaddr(&addr, ip, 68); /* bootp client */ - if((r = recvfrom(fd, data, n, 0, &addr, &addrlen)) == -1) + if ((r = recvfrom(fd, data, n, 0, &addr, &addrlen)) == -1) eprintf("recvfrom:"); + return r; } @@ -163,7 +166,7 @@ setip(unsigned char ip[4], unsigned char mask[4], unsigned char gateway[4]) strlcpy(ifreq.ifr_name, ifname, IF_NAMESIZE); iptoaddr(&(ifreq.ifr_addr), ip, 0); - if((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) == -1) + if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) == -1) eprintf("can't set ip, socket:"); ioctl(fd, SIOCSIFADDR, &ifreq); iptoaddr(&(ifreq.ifr_netmask), mask, 0); @@ -186,9 +189,9 @@ cat(int dfd, char *src) char buf[BUFSIZ]; int n, fd; - if((fd = open(src, O_RDONLY)) == -1) + if ((fd = open(src, O_RDONLY)) == -1) return; /* can't read, but don't error out */ - while((n = read(fd, buf, sizeof buf)) > 0) + while ((n = read(fd, buf, sizeof buf)) > 0) write(dfd, buf, n); close(fd); } @@ -199,12 +202,12 @@ setdns(unsigned char dns[4]) char buf[128]; int fd; - if((fd = creat("/etc/resolv.conf", 0644)) == -1) { + if ((fd = creat("/etc/resolv.conf", 0644)) == -1) { weprintf("can't change /etc/resolv.conf:"); return; } cat(fd, "/etc/resolv.conf.head"); - if(snprintf(buf, sizeof(buf) - 1, "\nnameserver %d.%d.%d.%d\n", + if (snprintf(buf, sizeof(buf) - 1, "\nnameserver %d.%d.%d.%d\n", dns[0], dns[1], dns[2], dns[3]) > 0) write(fd, buf, strlen(buf)); cat(fd, "/etc/resolv.conf.tail"); @@ -218,18 +221,18 @@ optget(Bootp *bp, void *data, int opt, int n) unsigned char *top = ((unsigned char *)bp) + sizeof *bp; int code, len; - while(p < top) { + while (p < top) { code = *p++; - if(code == OBpad) + if (code == OBpad) continue; - if(code == OBend || p == top) + if (code == OBend || p == top) break; len = *p++; - if(len > top - p) + if (len > top - p) break; - if(code == opt) { + if (code == opt) { memcpy(data, p, MIN(len, n)); - return; + break; } p += len; } @@ -241,6 +244,7 @@ optput(unsigned char *p, int opt, unsigned char *data, size_t len) *p++ = opt; *p++ = (unsigned char)len; memcpy(p, data, len); + return p + len; } @@ -250,6 +254,7 @@ hnoptput(unsigned char *p, int opt, long long data, size_t len) *p++ = opt; *p++ = (unsigned char)len; hnput(p, data, len); + return p + len; } @@ -303,14 +308,15 @@ dhcprecv(void) pfd.events = POLLIN; memset(&bp, 0, sizeof bp); - if(poll(&pfd, 1, -1) == -1) { - if(errno != EINTR) + if (poll(&pfd, 1, -1) == -1) { + if (errno != EINTR) eprintf("poll:"); else return Timeout; } udprecv(IP(255, 255, 255, 255), sock, &bp, sizeof bp); optget(&bp, &type, ODtype, sizeof type); + return type; } @@ -319,11 +325,11 @@ acceptlease(void) { char buf[128]; - if(iflag == 1) + if (iflag) setip(client, mask, router); - if(dflag == 1) + if (dflag) setdns(dns); - if(*program) { + if (*program) { snprintf(buf, sizeof(buf), "%d.%d.%d.%d", server[0], server[1], server[2], server[3]); setenv("SERVER", buf, 1); snprintf(buf, sizeof(buf), "%d.%d.%d.%d", client[0], client[1], client[2], client[3]); @@ -344,20 +350,6 @@ run(void) { int forked = 0; -#if 0 -InitReboot: - /* send DHCPrequest to old server */ - dhcpsend(DHCPrequest, Broadcast); - goto Rebooting; -Rebooting: - switch (dhcprecv()) { - case DHCPnak: - goto Init; - case DHCPack: - acceptoffer(); - goto Bound; - } -#endif Init: dhcpsend(DHCPdiscover, Broadcast); alarm(1); @@ -384,20 +376,15 @@ Requesting: switch(dhcprecv()) { case DHCPoffer: goto Requesting; /* ignore other offers. */ -#if 0 - case DHCPack: /* (and you don't want it) ? */ - dhcpsend(DHCPdecline, Unicast); - goto Init; -#endif case DHCPack: acceptlease(); goto Bound; } Bound: fputs("Congrats! You should be on the 'net.\n", stdout); - if(!fflag && !forked) { - if(fork()) - exit(EXIT_SUCCESS); + if (!fflag && !forked) { + if (fork()) + exit(0); forked = 1; } switch (dhcprecv()) { @@ -441,13 +428,13 @@ void cleanexit(int unused) { (void) unused; dhcpsend(DHCPrelease, Unicast); - exit(EXIT_SUCCESS); + exit(0); } static void usage(void) { - eprintf("usage: sdhcp [-d] [-e program] [-f] [-i] [ifname] [clientid]\n"); + eprintf("usage: %s [-d] [-e program] [-f] [-i] [ifname] [clientid]\n", argv0); } int @@ -476,36 +463,37 @@ main(int argc, char *argv[]) break; } ARGEND; - if(argc >= 1) + if (argc) ifname = argv[0]; /* interface name */ - if(argc >= 2) + if (argc >= 2) cid = argv[1]; /* client-id */ memset(&ifreq, 0, sizeof(ifreq)); signal(SIGALRM, nop); signal(SIGTERM, cleanexit); - if((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) eprintf("socket:"); - if(setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof bcast) == -1) + if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof bcast) == -1) eprintf("setsockopt:"); strlcpy(ifreq.ifr_name, ifname, IF_NAMESIZE); ioctl(sock, SIOCGIFINDEX, &ifreq); - if(setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifreq, sizeof ifreq) == -1) + if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifreq, sizeof ifreq) == -1) eprintf("setsockopt:"); iptoaddr(&addr, IP(255, 255, 255, 255), 68); - if(bind(sock, (void*)&addr, sizeof addr) != 0) + if (bind(sock, (void*)&addr, sizeof addr) != 0) eprintf("bind:"); ioctl(sock, SIOCGIFHWADDR, &ifreq); memcpy(hwaddr, ifreq.ifr_hwaddr.sa_data, sizeof ifreq.ifr_hwaddr.sa_data); - if((rnd = open("/dev/urandom", O_RDONLY)) == -1) + if ((rnd = open("/dev/urandom", O_RDONLY)) == -1) eprintf("can't open /dev/urandom to generate unique transaction identifier:"); read(rnd, xid, sizeof xid); close(rnd); starttime = time(NULL); run(); - return EXIT_SUCCESS; + + return 0; } diff --git a/util/eprintf.c b/util/eprintf.c @@ -16,7 +16,7 @@ eprintf(const char *fmt, ...) va_list ap; va_start(ap, fmt); - venprintf(EXIT_FAILURE, fmt, ap); + venprintf(1, fmt, ap); va_end(ap); } @@ -33,13 +33,12 @@ enprintf(int status, const char *fmt, ...) void venprintf(int status, const char *fmt, va_list ap) { -#ifdef DEBUG - fprintf(stderr, "%s: ", argv0); -#endif + if (strncmp(fmt, "usage", strlen("usage"))) + fprintf(stderr, "%s: ", argv0); vfprintf(stderr, fmt, ap); - if(fmt[0] && fmt[strlen(fmt)-1] == ':') { + if (fmt[0] && fmt[strlen(fmt)-1] == ':') { fputc(' ', stderr); perror(NULL); } @@ -52,9 +51,8 @@ weprintf(const char *fmt, ...) { va_list ap; -#ifdef DEBUG - fprintf(stderr, "%s: ", argv0); -#endif + if (strncmp(fmt, "usage", strlen("usage"))) + fprintf(stderr, "%s: ", argv0); va_start(ap, fmt); vfprintf(stderr, fmt, ap);