xref: /plan9-contrib/sys/src/cmd/aquarela/findname.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1 #include <u.h>
2 #include <libc.h>
3 #include <ip.h>
4 #include <thread.h>
5 #include "netbios.h"
6 
7 int
nbnsfindname(uchar * serveripaddr,NbName name,uchar * ipaddr,ulong * ttlp)8 nbnsfindname(uchar *serveripaddr, NbName name, uchar *ipaddr, ulong *ttlp)
9 {
10 	NbnsMessage *nq;
11 	Alt aa[3];
12 	int tries = NbnsRetryBroadcast;
13 	NbnsAlarm *a;
14 	int rv;
15 	NbnsMessage *response;
16 
17 	nq = nbnsmessagenamequeryrequestnew(0, serveripaddr == nil, name);
18 	if (nq == nil)
19 		return -1;
20 	a = nbnsalarmnew();
21 	if (a == nil) {
22 		free(nq);
23 		return -1;
24 	}
25 	aa[0].c = a->c;
26 	aa[0].v = nil;
27 	aa[0].op = CHANRCV;
28 	aa[1].op = CHANRCV;
29 	aa[2].op = CHANEND;
30 	while (tries > 0) {
31 		NbnsTransaction *t;
32 		nq->id = nbnsnextid();
33 		t = nbnstransactionnew(nq, serveripaddr);
34 		aa[1].c = t->c;
35 		aa[1].v = &response;
36 		nbnsalarmset(a, NbnsTimeoutBroadcast);
37 		for (;;) {
38 			int i;
39 			i = alt(aa);
40 			if (i == 0) {
41 				tries--;
42 				break;
43 			}
44 			else if (i == 1) {
45 				if (response->opcode == NbnsOpQuery) {
46 					nbnstransactionfree(&t);
47 					goto done;
48 				}
49 				nbnsmessagefree(&response);
50 			}
51 		}
52 		nbnstransactionfree(&t);
53 	}
54 done:
55 	if (tries == 0)
56 		rv = -1;
57 	else {
58 		if (response->rcode != 0)
59 			rv = response->rcode;
60 		else if (response->an == nil)
61 			rv = -1;
62 		else {
63 			rv = 0;
64 			v4tov6(ipaddr, response->an->rdata + 2);
65 			if (ttlp)
66 				*ttlp = response->an->ttl;
67 		}
68 		nbnsmessagefree(&response);
69 	}
70 	nbnsalarmfree(&a);
71 	nbnsmessagefree(&nq);
72 	return rv;
73 }
74