Date: Fri, 13 Oct 2000 09:48:18 +0200 From: Danny Braniss <danny@cs.huji.ac.il> To: Paul Saab <paul@mu.org> Cc: freebsd-hackers@freebsd.org Subject: Re: bootp/diskless/kenv Message-ID: <E13jzZi-0001be-00@sexta.cs.huji.ac.il> In-Reply-To: Your message of Fri, 13 Oct 2000 00:40:00 -0700 .
next in thread | raw e-mail | index | archive | help
In message <20001013003959.A52126@elvis.mu.org>you write: }Danny Braniss (danny@cs.huji.ac.il) wrote: }> Im including a modified lib/libstand/bootp.c for evaluation. It has: }> o- fixes for evaluation of netmask - only if not supplied. }> o- puts in the environment the dhcp stuff }> it does not - yet -: }> do any good check for string overflow. }> check for environment buffer overflow - haven't found out }> how to do it yet }> }> since kenv can now be used early on the diskless boot process, i think }> it should be placed in /bin and staticaly linked. } }a diff would be a whole lot easier to read. } }paul your wish is my command: --- bootp.c Tue Sep 26 10:46:15 2000 +++ /vol/fbsd/current/lib/libstand/bootp.c Fri Sep 22 10:04:36 2000 @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * @(#) Header: bootp.c,v 1.4 93/09/11 03:13:51 leres Exp (LBL) - * $FreeBSD: src/lib/libstand/bootp.c,v 1.1.1.1.6.1 2000/09/10 02:52:19 ps Exp $ + * $FreeBSD: src/lib/libstand/bootp.c,v 1.3 2000/09/20 18:16:20 ps Exp $ */ #include <sys/types.h> @@ -46,14 +46,9 @@ #include <string.h> -/* #define BOOTP_DEBUGxx */ +#define BOOTP_DEBUGxx #define SUPPORT_DHCP -/*#define BOOTP_DEBUG /* danny */ -#if defined(BOOTP_DEBUG) || defined(BOOTP_DEBUGxx) -int debug=1; -#endif - #include "stand.h" #include "net.h" #include "netif.h" @@ -62,7 +57,7 @@ struct in_addr servip; -static n_long smask; +static n_long nmask, smask; static time_t bot; @@ -84,8 +79,6 @@ struct in_addr dhcp_serverip; #endif -static void setenv_dhcp(u_char *cp, u_int len); - /* Fetch required bootp infomation */ void bootp(sock, flag) @@ -102,9 +95,8 @@ u_char header[HEADER_SIZE]; struct bootp rbootp; } rbuf; - int j; -#ifdef BOOTP_DEBUGxx +#ifdef BOOTP_DEBUG if (debug) printf("bootp: socket=%d\n", sock); #endif @@ -115,7 +107,7 @@ printf("bootp: bad socket. %d\n", sock); return; } -#ifdef BOOTP_DEBUGxx +#ifdef BOOTP_DEBUG if (debug) printf("bootp: d=%lx\n", (long)d); #endif @@ -130,52 +122,37 @@ MACPY(d->myea, bp->bp_chaddr); strncpy(bp->bp_file, bootfile, sizeof(bp->bp_file)); bcopy(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)); - j = sizeof(vm_rfc1048); #ifdef SUPPORT_DHCP - bp->bp_vend[j++] = TAG_DHCP_MSGTYPE; - bp->bp_vend[j++] = 1; - bp->bp_vend[j++] = DHCPDISCOVER; -#if 0 - /* - * We send an RFC 1533 "Maximum DHCP Message Size" option, saying we - * can do 1200 bytes. If we don't ISC DHCPD will limit the answer to - * 64 bytes and root/swap and similar will be dropped. - */ - bp->bp_vend[j++] = TAG_MAXSIZE; - bp->bp_vend[j++] = 2; - bp->bp_vend[j++] = 1200 / 256; - bp->bp_vend[j++] = 1200 % 256; -#endif + bp->bp_vend[4] = TAG_DHCP_MSGTYPE; + bp->bp_vend[5] = 1; + bp->bp_vend[6] = DHCPDISCOVER; + /* * If we are booting from PXE, we want to send the string * 'PXEClient' to the DHCP server so you have the option of * only responding to PXE aware dhcp requests. */ if (flag & BOOTP_PXE) { - char *classid; - int len; - bp->bp_vend[j++] = TAG_CLASSID; -#if 0 - bp->bp_vend[j++] = 9; - bcopy("PXEClient", &bp->bp_vend[j], 9); - j += 9; + bp->bp_vend[7] = TAG_CLASSID; + bp->bp_vend[8] = 9; + bcopy("PXEClient", &bp->bp_vend[9], 9); + bp->bp_vend[18] = TAG_END; + } else + bp->bp_vend[7] = TAG_END; #else - classid = "FreeBSDc"; - bp->bp_vend[j++] = len = strlen(classid); - bcopy(classid, &bp->bp_vend[j], len); - j += len; + bp->bp_vend[4] = TAG_END; #endif - } - expected_dhcpmsgtype = DHCPOFFER; - dhcp_ok = 0; -#endif - bp->bp_vend[j++] = TAG_END; d->myip.s_addr = INADDR_ANY; d->myport = htons(IPPORT_BOOTPC); d->destip.s_addr = INADDR_BROADCAST; d->destport = htons(IPPORT_BOOTPS); +#ifdef SUPPORT_DHCP + expected_dhcpmsgtype = DHCPOFFER; + dhcp_ok = 0; +#endif + if(sendrecv(d, bootpsend, bp, sizeof(*bp), bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp)) @@ -187,39 +164,24 @@ #ifdef SUPPORT_DHCP if(dhcp_ok) { u_int32_t leasetime; - int j; - j = 6; - bp->bp_vend[j++] = DHCPREQUEST; - bp->bp_vend[j++] = TAG_REQ_ADDR; - bp->bp_vend[j++] = 4; - bcopy(&rbuf.rbootp.bp_yiaddr, &bp->bp_vend[j], 4); - j += 4; - bp->bp_vend[j++] = TAG_SERVERID; - bp->bp_vend[j++] = 4; - bcopy(&dhcp_serverip.s_addr, &bp->bp_vend[j], 4); - j += 4; - bp->bp_vend[j++] = TAG_LEASETIME; - bp->bp_vend[j++] = 4; + bp->bp_vend[6] = DHCPREQUEST; + bp->bp_vend[7] = TAG_REQ_ADDR; + bp->bp_vend[8] = 4; + bcopy(&rbuf.rbootp.bp_yiaddr, &bp->bp_vend[9], 4); + bp->bp_vend[13] = TAG_SERVERID; + bp->bp_vend[14] = 4; + bcopy(&dhcp_serverip.s_addr, &bp->bp_vend[15], 4); + bp->bp_vend[19] = TAG_LEASETIME; + bp->bp_vend[20] = 4; leasetime = htonl(300); - bcopy(&leasetime, &bp->bp_vend[j], 4); - j += 4; + bcopy(&leasetime, &bp->bp_vend[21], 4); if (flag & BOOTP_PXE) { -#if 0 - bp->bp_vend[j++] = TAG_CLASSID; - bp->bp_vend[j++] = 9; - bcopy("PXEClient", &bp->bp_vend[j], 9); - j += 9; -#else - char *classid; - int len; - - classid = "FreeBSDc"; - bp->bp_vend[j++] = len = strlen(classid); - bcopy(classid, &bp->bp_vend[j], len); - j += len; -#endif - } - bp->bp_vend[j++] = TAG_END; + bp->bp_vend[25] = TAG_CLASSID; + bp->bp_vend[26] = 9; + bcopy("PXEClient", &bp->bp_vend[27], 9); + bp->bp_vend[36] = TAG_END; + } else + bp->bp_vend[25] = TAG_END; expected_dhcpmsgtype = DHCPACK; @@ -231,7 +193,7 @@ return; } } -#endif /* SUPPORT_DHCP */ +#endif myip = d->myip = rbuf.rbootp.bp_yiaddr; servip = rbuf.rbootp.bp_siaddr; @@ -239,28 +201,50 @@ bcopy(rbuf.rbootp.bp_file, bootfile, sizeof(bootfile)); bootfile[sizeof(bootfile) - 1] = '\0'; - if(smask == 0) { - if(IN_CLASSA(ntohl(myip.s_addr))) - smask = htonl(IN_CLASSA_NET); - else - if(IN_CLASSB(ntohl(myip.s_addr))) - smask = htonl(IN_CLASSB_NET); - else - smask = htonl(IN_CLASSC_NET); + if (IN_CLASSA(ntohl(myip.s_addr))) + nmask = htonl(IN_CLASSA_NET); + else if (IN_CLASSB(ntohl(myip.s_addr))) + nmask = htonl(IN_CLASSB_NET); + else + nmask = htonl(IN_CLASSC_NET); +#ifdef BOOTP_DEBUG + if (debug) + printf("'native netmask' is %s\n", intoa(nmask)); +#endif + + /* Check subnet mask against net mask; toss if bogus */ + if ((nmask & smask) != nmask) { +#ifdef BOOTP_DEBUG + if (debug) + printf("subnet mask (%s) bad\n", intoa(smask)); +#endif + smask = 0; } + /* Get subnet (or natural net) mask */ - netmask = smask; + netmask = nmask; + if (smask) + netmask = smask; +#ifdef BOOTP_DEBUG + if (debug) + printf("mask: %s\n", intoa(netmask)); +#endif + /* We need a gateway if root is on a different net */ if (!SAMENET(myip, rootip, netmask)) { #ifdef BOOTP_DEBUG - if (debug) - printf("need gateway for root ip\n"); + if (debug) + printf("need gateway for root ip\n"); #endif } + /* Toss gateway if on a different net */ if (!SAMENET(myip, gateip, netmask)) { - printf("gateway ip (%s) is bad!\n", inet_ntoa(gateip)); - gateip.s_addr = 0; +#ifdef BOOTP_DEBUG + if (debug) + printf("gateway ip (%s) bad\n", inet_ntoa(gateip)); +#endif + gateip.s_addr = 0; } /* Bump xid so next request will be unique. */ @@ -276,7 +260,7 @@ { register struct bootp *bp; -#ifdef BOOTP_DEBUGxx +#ifdef BOOTP_DEBUG if (debug) printf("bootpsend: d=%lx called.\n", (long)d); #endif @@ -284,7 +268,7 @@ bp = pkt; bp->bp_secs = htons((u_short)(getsecs() - bot)); -#ifdef BOOTP_DEBUGxx +#ifdef BOOTP_DEBUG if (debug) printf("bootpsend: calling sendudp\n"); #endif @@ -302,7 +286,7 @@ register ssize_t n; register struct bootp *bp; -#ifdef BOOTP_DEBUGxx +#ifdef BOOTP_DEBUGx if (debug) printf("bootp_recvoffer: called\n"); #endif @@ -313,7 +297,7 @@ bp = (struct bootp *)pkt; -#ifdef BOOTP_DEBUGxx +#ifdef BOOTP_DEBUG if (debug) printf("bootprecv: checked. bp = 0x%lx, n = %d\n", (long)bp, (int)n); @@ -328,7 +312,7 @@ goto bad; } -#ifdef BOOTP_DEBUGxx +#ifdef BOOTP_DEBUG if (debug) printf("bootprecv: got one!\n"); #endif @@ -360,8 +344,6 @@ register int size; register u_char tag; - setenv_dhcp(cp, len); - #ifdef BOOTP_DEBUG if (debug) printf("vend_rfc1048 bootp info. len=%d\n", len); @@ -374,45 +356,38 @@ while (cp < ep) { tag = *cp++; size = *cp++; - switch(tag) { - case 0: - continue; - case TAG_END: - break; - case TAG_SUBNET_MASK: - bcopy(cp, &smask, sizeof(smask)); - break; - case TAG_GATEWAY: - bcopy(cp, &gateip.s_addr, sizeof(gateip.s_addr)); - break; - case TAG_SWAPSERVER: - /* let it override bp_siaddr */ - bcopy(cp, &rootip.s_addr, sizeof(swapip.s_addr)); - break; - case TAG_ROOTPATH: - strncpy(rootpath, (char *)cp, sizeof(rootpath)); - rootpath[size] = '\0'; - break; - case TAG_HOSTNAME: - strncpy(hostname, (char *)cp, sizeof(hostname)); - hostname[size] = '\0'; - break; + if (tag == TAG_END) + break; + + if (tag == TAG_SUBNET_MASK) { + bcopy(cp, &smask, sizeof(smask)); + } + if (tag == TAG_GATEWAY) { + bcopy(cp, &gateip.s_addr, sizeof(gateip.s_addr)); + } + if (tag == TAG_SWAPSERVER) { + /* let it override bp_siaddr */ + bcopy(cp, &rootip.s_addr, sizeof(swapip.s_addr)); + } + if (tag == TAG_ROOTPATH) { + strncpy(rootpath, (char *)cp, sizeof(rootpath)); + rootpath[size] = '\0'; + } + if (tag == TAG_HOSTNAME) { + strncpy(hostname, (char *)cp, sizeof(hostname)); + hostname[size] = '\0'; + } #ifdef SUPPORT_DHCP - case TAG_DHCP_MSGTYPE: - if(*cp != expected_dhcpmsgtype) - return(-1); - dhcp_ok = 1; - break; - case TAG_SERVERID: - bcopy(cp, &dhcp_serverip.s_addr, sizeof(dhcp_serverip.s_addr)); - break; -#endif -#ifdef BOOTP_DEBUG - default: - if (debug) - printf("unknown tag:%d size=%d\n", tag, size); -#endif + if (tag == TAG_DHCP_MSGTYPE) { + if(*cp != expected_dhcpmsgtype) + return(-1); + dhcp_ok = 1; + } + if (tag == TAG_SERVERID) { + bcopy(cp, &dhcp_serverip.s_addr, + sizeof(dhcp_serverip.s_addr)); } +#endif cp += size; } return(0); @@ -425,7 +400,7 @@ { register struct cmu_vend *vp; -#ifdef BOOTP_DEBUGxx +#ifdef BOOTP_DEBUG if (debug) printf("vend_cmu bootp info.\n"); #endif @@ -439,209 +414,3 @@ } } #endif - -/* - | DHCP Option names, formats and codes, from RFC1533. - */ -#define __IP 1 -#define __TXT 2 -#define __8 3 -#define __16 4 -#define __32 5 -#define __VE 6 - -struct dhcp_opt { - int tag; - int fmt; - char *desc; -} dhcp_opt[] = { -#define _DHCP(num, fmt, dsc) {num, fmt, dsc} - _DHCP(1, __IP, "subnet-mask"), - _DHCP(2, __32, "time-offset"), - _DHCP(3, __IP, "routers"), - _DHCP(4, __IP, "time-servers"), - _DHCP(5, __IP, "ien116-name-servers"), - _DHCP(6, __IP, "domain-name-servers"), - _DHCP(7, __IP, "log-servers"), - _DHCP(8, __IP, "cookie-servers"), - _DHCP(9, __IP, "lpr-servers"), - _DHCP(10, __IP, "impress-servers"), - _DHCP(11, __IP, "resource-location-servers"), - _DHCP(12, __TXT, "host-name"), - _DHCP(13, __16, "boot-size"), - _DHCP(14, __TXT, "merit-dump"), - _DHCP(15, __TXT, "domain-name"), - _DHCP(16, __IP, "swap-server"), - _DHCP(17, __TXT, "root-path"), - _DHCP(18, __TXT, "extensions-path"), - _DHCP(19, __8, "ip-forwarding"), - _DHCP(20, __8, "non-local-source-routing"), - _DHCP(21, __IP, "policy-filter"), - _DHCP(22, __16, "max-dgram-reassembly"), - _DHCP(23, __8, "default-ip-ttl"), - _DHCP(24, __32, "path-mtu-aging-timeout"), - _DHCP(25, __16, "path-mtu-plateau-table"), - _DHCP(26, __16, "interface-mtu"), - _DHCP(27, __8, "all-subnets-local"), - _DHCP(28, __IP, "broadcast-address"), - _DHCP(29, __8, "perform-mask-discovery"), - _DHCP(30, __8, "mask-supplier"), - _DHCP(31, __8, "router-discovery"), - _DHCP(32, __IP, "router-solicitation-address"), - _DHCP(33, __IP, "static-routes"), - _DHCP(34, __8, "trailer-encapsulation"), - _DHCP(35, __32, "arp-cache-timeout"), - _DHCP(36, __8, "ieee802-3-encapsulation"), - _DHCP(37, __8, "default-tcp-ttl"), - _DHCP(38, __32, "tcp-keepalive-interval"), - _DHCP(39, __8, "tcp-keepalive-garbage"), - _DHCP(40, __TXT, "nis-domain"), - _DHCP(41, __IP, "nis-servers"), - _DHCP(42, __IP, "ntp-servers"), - _DHCP(43, __VE, "vendor-encapsulated-options"), - _DHCP(44, __IP, "netbios-name-servers"), - _DHCP(45, __IP, "netbios-dd-server"), - _DHCP(46, __8, "netbios-node-type"), - _DHCP(47, __TXT, "netbios-scope"), - _DHCP(48, __IP, "font-servers"), - _DHCP(49, __IP, "x-display-manager"), - _DHCP(50, __IP, "dhcp-requested-address"), - _DHCP(51, __32, "dhcp-lease-time"), - _DHCP(52, __8, "dhcp-option-overload"), - _DHCP(53, __8, "dhcp-message-type"), - _DHCP(54, __IP, "dhcp-server-identifier"), - _DHCP(55, __8, "dhcp-parameter-request-list"), - _DHCP(56, __TXT, "dhcp-message"), - _DHCP(57, __16, "dhcp-max-message-size"), - _DHCP(58, __32, "dhcp-renewal-time"), - _DHCP(59, __32, "dhcp-rebinding-time"), - _DHCP(60, __TXT, "vendor-class-identifier"), - _DHCP(61, __TXT, "dhcp-client-identifier"), - _DHCP(64, __TXT, "nisplus-domain"), - _DHCP(65, __IP, "nisplus-servers"), - _DHCP(66, __TXT, "tftp-server-name"), - _DHCP(67, __TXT, "bootfile-name"), - _DHCP(68, __IP, "mobile-ip-home-agent"), - _DHCP(69, __IP, "smtp-server"), - _DHCP(70, __IP, "pop-server"), - _DHCP(71, __IP, "nntp-server"), - _DHCP(72, __IP, "www-server"), - _DHCP(73, __IP, "finger-server"), - _DHCP(74, __IP, "irc-server"), - _DHCP(75, __IP, "streettalk-server"), - _DHCP(76, __IP, "streettalk-directory-assistance-server"), - _DHCP(77, __TXT, "user-class"), - _DHCP(85, __IP, "nds-servers"), - _DHCP(86, __TXT, "nds-tree-name"), - _DHCP(87, __TXT, "nds-context"), - _DHCP(210, __TXT, "authenticate"), - {0} -}; - -struct dhcp_opt optdef = _DHCP(0, __TXT, "option-%d"); - -#undef _DHCP - -static void -setenv_dhcp(u_char *cp, u_int len) -{ - u_char *ep; - int size; - u_char tag; - char env[128], val[512], *vp, tags[512], *tp; - struct in_addr in_ip; - - ep = cp + len; - cp += sizeof(vm_rfc1048); /* hopefully this was checked? */ - tp = tags; - - while(cp < ep) { - struct dhcp_opt *op; - - tag = *cp++; - size = *cp++; - if(tag == TAG_END) - break; - if(tag == 0) - continue; - for(op = dhcp_opt; op->tag; op++) - if(op->tag >= tag) - break; - if(op->tag != tag) - op = &optdef; - vp = val; - switch(op->fmt) { - case __VE: /* vendor specific */ - while(size-- > 0) { - sprintf(vp, "%02x", *cp++); - vp += 2; - } - break; - - case __IP: /* ip address */ - while(size > 0) { - - if(vp != val) - *vp++ = ','; - bcopy(cp, &in_ip.s_addr, sizeof(in_ip.s_addr)); - sprintf(vp, "%s", inet_ntoa(in_ip)); - vp += strlen(vp); - size -= 4; - cp += 4; - } - break; - - case __TXT: - bcopy(cp, val, size); - val[size] = 0; - cp += size; - break; - case __8: - case __16: - case __32: - while(size > 0) { - int n = 0; - - if(vp != val) - *vp++ = ','; - switch(op->fmt) { - case __8: - sprintf(vp, "%02x", cp[0]); - n = 1; - break; - case __16: - sprintf(vp, "%02x%02x", cp[0], cp[1]); - n = 2; - break; - case __32: - sprintf(vp, "%02x%02x%02x%02x", cp[0], cp[1], cp[2], cp[3]); - n = 4; - break; - } - cp += n; - size -= n; - vp += strlen(vp); - } - break; - } - sprintf(tp, "%03d:", tag); - tp += strlen(tp); - - if(op == &optdef) - sprintf(env, "dhcp.option-%d", tag); - else - sprintf(env, "dhcp.%s", op->desc); -#ifdef BOOTP_DEBUG - if(debug) - printf("%s %s\n", env, val); -#endif - setenv(env, val, 1); - } - if(tp != tags) { -#ifdef BOOTP_DEBUG - if(debug) - printf("%s %s\n", "dhcp.tags", tags); -#endif - setenv("dhcp.tags", tags, 1); - } -} To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?E13jzZi-0001be-00>