xref: /plan9/sys/src/cmd/ip/dhcpd/testlook.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1 #include <u.h>
2 #include <libc.h>
3 #include <ip.h>
4 #include <bio.h>
5 #include <ndb.h>
6 
7 static uchar noether[6];
8 
9 /*
10  *  Look for a pair with the given attribute.  look first on the same line,
11  *  then in the whole entry.
12  */
13 static Ndbtuple*
lookval(Ndbtuple * entry,Ndbtuple * line,char * attr,char * to)14 lookval(Ndbtuple *entry, Ndbtuple *line, char *attr, char *to)
15 {
16 	Ndbtuple *nt;
17 
18 	/* first look on same line (closer binding) */
19 	for(nt = line;;){
20 		if(strcmp(attr, nt->attr) == 0){
21 			strncpy(to, nt->val, Ndbvlen);
22 			return nt;
23 		}
24 		nt = nt->line;
25 		if(nt == line)
26 			break;
27 	}
28 	/* search whole tuple */
29 	for(nt = entry; nt; nt = nt->entry)
30 		if(strcmp(attr, nt->attr) == 0){
31 			strncpy(to, nt->val, Ndbvlen);
32 			return nt;
33 		}
34 	return 0;
35 }
36 
37 /*
38  *  lookup an ip address
39  */
40 static uchar*
lookupip(Ndb * db,char * name,uchar * to,Ipinfo * iip)41 lookupip(Ndb *db, char *name, uchar *to, Ipinfo *iip)
42 {
43 	Ndbtuple *t, *nt;
44 	char buf[Ndbvlen];
45 	uchar subnet[IPaddrlen];
46 	Ndbs s;
47 	char *attr;
48 
49 	attr = ipattr(name);
50 	if(strcmp(attr, "ip") == 0){
51 		parseip(to, name);
52 		return to;
53 	}
54 
55 	t = ndbgetval(db, &s, attr, name, "ip", buf);
56 	if(t){
57 		/* first look for match on same subnet */
58 		for(nt = t; nt; nt = nt->entry){
59 			if(strcmp(nt->attr, "ip") != 0)
60 				continue;
61 			parseip(to, nt->val);
62 			maskip(to, iip->ipmask, subnet);
63 			if(memcmp(subnet, iip->ipnet, sizeof(subnet)) == 0)
64 				return to;
65 		}
66 
67 		/* otherwise, just take what we have */
68 		ndbfree(t);
69 		parseip(to, buf);
70 		return to;
71 	}
72 	return 0;
73 }
74 
75 /*
76  *  lookup a subnet and fill in anything we can
77  */
78 static void
recursesubnet(Ndb * db,uchar * mask,Ipinfo * iip,char * fs,char * gw,char * au)79 recursesubnet(Ndb *db, uchar *mask, Ipinfo *iip, char *fs, char *gw, char *au)
80 {
81 	Ndbs s;
82 	Ndbtuple *t;
83 	uchar submask[IPaddrlen];
84 	char ip[Ndbvlen];
85 
86 	memmove(iip->ipmask, mask, 4);
87 	maskip(iip->ipaddr, iip->ipmask, iip->ipnet);
88 	sprint(ip, "%I", iip->ipnet);
89 	t = ndbsearch(db, &s, "ip", ip);
90 print("%s->", ip);
91 	if(t){
92 		/* look for a further subnet */
93 		if(lookval(t, s.t, "ipmask", ip)){
94 			parseip(submask, ip);
95 
96 			/* recurse only if it has changed */
97 			if(!equivip(submask, mask))
98 				recursesubnet(db, submask, iip, fs, gw, au);
99 
100 		}
101 
102 		/* fill in what we don't have */
103 		if(gw[0] == 0)
104 			lookval(t, s.t, "ipgw", gw);
105 		if(fs[0] == 0)
106 			lookval(t, s.t, "fs", fs);
107 		if(au[0] == 0)
108 			lookval(t, s.t, "auth", au);
109 
110 		ndbfree(t);
111 	}
112 }
113 #ifdef foo
114 /*
115  *  find out everything we can about a system from what has been
116  *  specified.
117  */
118 int
ipinfo(Ndb * db,char * etherin,char * ipin,char * name,Ipinfo * iip)119 ipinfo(Ndb *db, char *etherin, char *ipin, char *name, Ipinfo *iip)
120 {
121 	Ndbtuple *t;
122 	Ndbs s;
123 	char ether[Ndbvlen];
124 	char ip[Ndbvlen];
125 	char fsname[Ndbvlen];
126 	char gwname[Ndbvlen];
127 	char auname[Ndbvlen];
128 
129 	memset(iip, 0, sizeof(Ipinfo));
130 	fsname[0] = 0;
131 	gwname[0] = 0;
132 	auname[0] = 0;
133 
134 	/*
135 	 *  look for a matching entry
136 	 */
137 	t = 0;
138 	if(etherin)
139 		t = ndbgetval(db, &s, "ether", etherin, "ip", ip);
140 	if(t == 0 && ipin)
141 		t = ndbsearch(db, &s, "ip", ipin);
142 	if(t == 0 && name)
143 		t = ndbgetval(db, &s, ipattr(name), name, "ip", ip);
144 	if(t){
145 		/*
146 		 *  copy in addresses and name
147 		 */
148 		if(lookval(t, s.t, "ip", ip))
149 			parseip(iip->ipaddr, ip);
150 		if(lookval(t, s.t, "ether", ether))
151 			parseether(iip->etheraddr, ether);
152 		lookval(t, s.t, "dom", iip->domain);
153 
154 		/*
155 		 *  Look for bootfile, fs, and gateway.
156 		 *  If necessary, search through all entries for
157 		 *  this ip address.
158 		 */
159 		while(t){
160 			if(iip->bootf[0] == 0)
161 				lookval(t, s.t, "bootf", iip->bootf);
162 			if(fsname[0] == 0)
163 				lookval(t, s.t, "fs", fsname);
164 			if(gwname[0] == 0)
165 				lookval(t, s.t, "ipgw", gwname);
166 			if(auname[0] == 0)
167 				lookval(t, s.t, "auth", auname);
168 			ndbfree(t);
169 			if(iip->bootf[0] && fsname[0] && gwname[0] && auname[0])
170 				break;
171 			t = ndbsnext(&s, "ether", ether);
172 		}
173 	} else if(ipin) {
174 		/*
175 		 *  copy in addresses (all we know)
176 		 */
177 		parseip(iip->ipaddr, ipin);
178 		if(etherin)
179 			parseether(iip->etheraddr, etherin);
180 	} else
181 		return -1;
182 
183 	/*
184 	 *  Look up the client's network and find a subnet mask for it.
185 	 *  Fill in from the subnet (or net) entry anything we can't figure
186 	 *  out from the client record.
187 	 */
188 	recursesubnet(db, classmask[CLASS(iip->ipaddr)], iip, fsname, gwname, auname);
189 
190 	/* lookup fs's and gw's ip addresses */
191 
192 	if(fsname[0])
193 		lookupip(db, fsname, iip->fsip, iip);
194 	if(gwname[0])
195 		lookupip(db, gwname, iip->gwip, iip);
196 	if(auname[0])
197 		lookupip(db, auname, iip->auip, iip);
198 	return 0;
199 }
200 #endif
201 void
main(int argc,char ** argv)202 main(int argc, char **argv)
203 {
204 	Ipinfo ii;
205 	Ndb *db;
206 
207 	db = ndbopen(0);
208 
209 	fmtinstall('E', eipconv);
210 	fmtinstall('I', eipconv);
211 	if(argc < 2)
212 		exits(0);
213 	if(strchr(argv[1], '.')){
214 		if(ipinfo(db, 0, argv[1], 0, &ii) < 0)
215 			exits(0);
216 	} else {
217 		if(ipinfo(db, argv[1], 0, 0, &ii) < 0)
218 			exits(0);
219 	}
220 	fprint(2, "a %I m %I n %I f %s e %E\n", ii.ipaddr,
221 		ii.ipmask, ii.ipnet, ii.bootf, ii.etheraddr);
222 }
223