#include #include #include #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; }