#include <u.h>
#include <libc.h>
#include <ip.h>
#include "nbcache.h"
static int
req(int fd)
{
Pkt *p;
int trn;
p = allocpkt(1024);
trn = rand() & 0xffff;
wb16(p, trn); /* ID */
wb16(p, 0); /* flags (unicast, name query) */
wb16(p, 1); /* # questions */
wb16(p, 0); /* # answers */
wb16(p, 0); /* # authritative answers */
wb16(p, 0); /* # additional answers */
pnbname(p, "*", '\0', '\0'); /* question name */
wb16(p, 0x21); /* question type (adapter status) */
wb16(p, 1); /* question class (inet) */
write(fd, p->buf, p->pos - p->buf);
free(p);
return trn;
}
static int
ans(int fd, int trn, uchar mac[Etheraddrlen], char sysname[NBnamelen],
char domain[NBnamelen], char role[32])
{
Pkt *p;
char junk[64], name[NBnamelen];
int svs, flg, try, i, j, num, ans;
p = allocpkt(1024);
for(try = 0; try < 5; try++){
alarm(100);
num = read(fd, p->buf, p->size);
alarm(0);
if(num < 0)
continue;
p->end = p->buf +num;
if(rb16(p) == trn) /* transaction ID */
break;
}
if(try >= 5){
free(p);
return -1;
}
if(rb16(p) != 0x8400){ /* flags (must be NBAS, no errors) */
free(p);
return -1;
}
rb16(p); /* questions */
ans = rb16(p); /* answers */
rb16(p); /* authoritave answers */
rb16(p); /* additional answers */
for(i = 0; i < ans; i++){
rnbname(p, junk, sizeof(junk)); /* question name */
rb16(p); /* question type */
rb16(p); /* class */
rb32(p); /* time to live (always zero) */
rb16(p); /* data length */
num = r8(p); /* number of names */
for(j = 0; j < num; j++){
rmem(p, name, 16);
svs = name[15];
name[15] = 0;
flg = rb16(p);
strlwr(name);
trim(name, ' ');
if((flg & 0x8000) != 0 && svs == 0) /* unique && workstation service */
strcpy(sysname, name);
if((flg & 0x8000) == 0)
switch(svs){
case 0:
strcpy(domain, name);
break;
case 0x1d:
strcpy(role, "LMB");
break;
case 0x1b:
strcpy(role, "DMB");
break;
case 0x1c:
strcpy(role, "DC");
break;
}
}
}
rmem(p, mac, Etheraddrlen);
free(p);
return 0;
}
int
adapter_status(Attr *a, int ttl, uchar ip[IPv4addrlen])
{
Attr *a1;
Node *n;
int rc, fd, trn;
char *vendor, ipstr[32];
uchar mac[Etheraddrlen];
char domain[NBnamelen], sysname[NBnamelen], role[32];
static uchar zeros[Etheraddrlen];
if(Passive)
return -1;
snprint(ipstr, sizeof(ipstr), "%V", ip);
if((fd = dial(netmkaddr(ipstr, "udp", "137"), "137", 0, 0)) < 0){
if(Debug)
fprint(2, "%s: nbas: can't dial - %s : %r", argv0, ipstr);
return -1;
}
trn = req(fd);
memset(mac, 0, sizeof mac);
memset(role, 0, sizeof role);
memset(domain, 0, sizeof domain);
memset(sysname, 0, sizeof sysname);
rc = ans(fd, trn, mac, domain, sysname, role);
close(fd);
if(rc == -1)
return -1;
if(memcmp(mac, zeros, Etheraddrlen) != 0){
addval(a, "ether", "%E", mac);
if((vendor = nicvendor(mac)) != nil){
addval(a, "vendor", vendor);
free(vendor);
}
}
if(*domain){
n = getnode(Tdomain, ttl, domain, role);
if(*sysname){
a1 = setval(n, "member", sysname);
if(*role)
addval(a1, "nb-role", role);
}
}
return rc;
}
|