--- a/sys/vfs/nfs/bootp_subr.c +++ b/sys/vfs/nfs/bootp_subr.c @@ -588,6 +588,7 @@ int retry; const char *s; char hexstr[64]; + struct sockaddr *fromp = NULL; /* * Create socket and set its recieve timeout. @@ -717,7 +718,7 @@ } hexncpy((u_char *)LLADDR(ifctx->sdl), ifctx->sdl->sdl_alen, hexstr, - HEX_NCPYLEN(ifctx->sdl->sdl_alen), ":"); + sizeof(hexstr), ":"); kprintf("Sending %s packet from " "interface %s (%s)\n", s, ifctx->ireq.ifr_name, @@ -804,7 +805,11 @@ auio.uio_td = td; rcvflg = 0; - error = soreceive(so, NULL, &auio, + if (fromp != NULL) { + kfree(fromp, M_SONAME); + fromp = NULL; + } + error = soreceive(so, &fromp, &auio, NULL, NULL, &rcvflg); gctx->secs = time_uptime - gctx->starttime; for (ifctx = gctx->interfaces; @@ -820,6 +825,13 @@ continue; if (error != 0) goto out; + if (fromp == NULL || + ((struct sockaddr_in *)fromp)->sin_port != + htons(IPPORT_BOOTPS)) { + kprintf("bootpc: reply not from server port %d, ignored\n", + IPPORT_BOOTPS); + continue; + } len = sizeof(gctx->reply) - auio.uio_resid; /* Do we have the required number of bytes ? */ @@ -1045,11 +1057,20 @@ sdl = NULL; TAILQ_FOREACH(ifac, &ifctx->ifp->if_addrheads[mycpuid], ifa_link) { struct ifaddr *ifa = ifac->ifa; + struct sockaddr_dl *sdl2; - if (ifa->ifa_addr->sa_family == AF_LINK && - (sdl = ((struct sockaddr_dl *) ifa->ifa_addr)) != NULL && - sdl->sdl_type == IFT_ETHER) + if (ifa->ifa_addr->sa_family != AF_LINK) + continue; + sdl2 = (struct sockaddr_dl *)ifa->ifa_addr; + /* Only accept an address that fits chaddr[16] (and is + * nonzero): every byte of it is copied into the BOOTP + * query and compared on replies. */ + if (sdl2->sdl_type == IFT_ETHER && + sdl2->sdl_alen > 0 && + sdl2->sdl_alen <= sizeof(ifctx->call.chaddr)) { + sdl = sdl2; break; + } } if (sdl == NULL) @@ -1285,6 +1306,10 @@ return; } len = *j++; + if (code == TAG_OVERLOAD && len != 1) { + tctx->badopt = 1; + return; + } if (code == tag) { if (tctx->taglen + len > TAG_MAXLEN) { tctx->badtag = 1; @@ -1535,7 +1560,7 @@ gctx = kmalloc(sizeof(*gctx), M_TEMP, M_WAITOK | M_ZERO); - gctx->xid = ~0xFFFF; + gctx->xid = karc4random(); gctx->starttime = time_uptime; ifctx = allocifctx(gctx);