Plan 9 from Bell Labs’s /usr/web/sources/contrib/steve/root/sys/src/cmd/ndb/glean/nbas.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


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

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.