13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
3219b2ee8SDavid du Colombier #include <auth.h>
43e12c5d1SDavid du Colombier #include <fcall.h>
53e12c5d1SDavid du Colombier #include <bio.h>
63e12c5d1SDavid du Colombier #include <ctype.h>
73e12c5d1SDavid du Colombier #include <ndb.h>
83e12c5d1SDavid du Colombier #include <ip.h>
995a264b3SDavid du Colombier #include <String.h>
103e12c5d1SDavid du Colombier
113e12c5d1SDavid du Colombier enum
123e12c5d1SDavid du Colombier {
1380ee5cbfSDavid du Colombier Nreply= 20,
143e12c5d1SDavid du Colombier Maxreply= 256,
157dd7cddfSDavid du Colombier Maxrequest= 128,
167dd7cddfSDavid du Colombier Maxpath= 128,
179a747e4fSDavid du Colombier Maxfdata= 8192,
1895a264b3SDavid du Colombier Maxhost= 64, /* maximum host name size */
1995a264b3SDavid du Colombier Maxservice= 64, /* maximum service name size */
203e12c5d1SDavid du Colombier
219a747e4fSDavid du Colombier Qdir= 0,
223e12c5d1SDavid du Colombier Qcs= 1,
233e12c5d1SDavid du Colombier };
243e12c5d1SDavid du Colombier
253e12c5d1SDavid du Colombier typedef struct Mfile Mfile;
26219b2ee8SDavid du Colombier typedef struct Mlist Mlist;
273e12c5d1SDavid du Colombier typedef struct Network Network;
287dd7cddfSDavid du Colombier typedef struct Flushreq Flushreq;
297dd7cddfSDavid du Colombier typedef struct Job Job;
303e12c5d1SDavid du Colombier
313e12c5d1SDavid du Colombier int vers; /* incremented each clone/attach */
323e12c5d1SDavid du Colombier
333e12c5d1SDavid du Colombier struct Mfile
343e12c5d1SDavid du Colombier {
353e12c5d1SDavid du Colombier int busy;
36219b2ee8SDavid du Colombier
379a747e4fSDavid du Colombier char *user;
383e12c5d1SDavid du Colombier Qid qid;
393e12c5d1SDavid du Colombier int fid;
403e12c5d1SDavid du Colombier
4180ee5cbfSDavid du Colombier /*
4280ee5cbfSDavid du Colombier * current request
4380ee5cbfSDavid du Colombier */
4480ee5cbfSDavid du Colombier char *net;
4580ee5cbfSDavid du Colombier char *host;
4680ee5cbfSDavid du Colombier char *serv;
4780ee5cbfSDavid du Colombier char *rem;
4880ee5cbfSDavid du Colombier
4980ee5cbfSDavid du Colombier /*
5080ee5cbfSDavid du Colombier * result of the last lookup
5180ee5cbfSDavid du Colombier */
5280ee5cbfSDavid du Colombier Network *nextnet;
53219b2ee8SDavid du Colombier int nreply;
54219b2ee8SDavid du Colombier char *reply[Nreply];
55219b2ee8SDavid du Colombier int replylen[Nreply];
56219b2ee8SDavid du Colombier };
57219b2ee8SDavid du Colombier
58219b2ee8SDavid du Colombier struct Mlist
59219b2ee8SDavid du Colombier {
60219b2ee8SDavid du Colombier Mlist *next;
61219b2ee8SDavid du Colombier Mfile mf;
623e12c5d1SDavid du Colombier };
633e12c5d1SDavid du Colombier
649a747e4fSDavid du Colombier
65244672c5SDavid du Colombier /*
66244672c5SDavid du Colombier * active requests
67244672c5SDavid du Colombier */
687dd7cddfSDavid du Colombier struct Job
697dd7cddfSDavid du Colombier {
707dd7cddfSDavid du Colombier Job *next;
717dd7cddfSDavid du Colombier int flushed;
727dd7cddfSDavid du Colombier Fcall request;
737dd7cddfSDavid du Colombier Fcall reply;
747dd7cddfSDavid du Colombier };
757dd7cddfSDavid du Colombier Lock joblock;
767dd7cddfSDavid du Colombier Job *joblist;
777dd7cddfSDavid du Colombier
78219b2ee8SDavid du Colombier Mlist *mlist;
793e12c5d1SDavid du Colombier int mfd[2];
803e12c5d1SDavid du Colombier int debug;
817dd7cddfSDavid du Colombier int paranoia;
82b8b25780SDavid du Colombier int ipv6lookups = 1;
833e12c5d1SDavid du Colombier jmp_buf masterjmp; /* return through here after a slave process has been created */
843e12c5d1SDavid du Colombier int *isslave; /* *isslave non-zero means this is a slave process */
85bd389b36SDavid du Colombier char *dbfile;
867dd7cddfSDavid du Colombier Ndb *db, *netdb;
873e12c5d1SDavid du Colombier
889a747e4fSDavid du Colombier void rversion(Job*);
897dd7cddfSDavid du Colombier void rflush(Job*);
907dd7cddfSDavid du Colombier void rattach(Job*, Mfile*);
917dd7cddfSDavid du Colombier char* rwalk(Job*, Mfile*);
927dd7cddfSDavid du Colombier void ropen(Job*, Mfile*);
937dd7cddfSDavid du Colombier void rcreate(Job*, Mfile*);
947dd7cddfSDavid du Colombier void rread(Job*, Mfile*);
957dd7cddfSDavid du Colombier void rwrite(Job*, Mfile*);
967dd7cddfSDavid du Colombier void rclunk(Job*, Mfile*);
977dd7cddfSDavid du Colombier void rremove(Job*, Mfile*);
987dd7cddfSDavid du Colombier void rstat(Job*, Mfile*);
997dd7cddfSDavid du Colombier void rwstat(Job*, Mfile*);
1009a747e4fSDavid du Colombier void rauth(Job*);
1017dd7cddfSDavid du Colombier void sendmsg(Job*, char*);
1023e12c5d1SDavid du Colombier void error(char*);
1037dd7cddfSDavid du Colombier void mountinit(char*, char*);
1043e12c5d1SDavid du Colombier void io(void);
1057dd7cddfSDavid du Colombier void ndbinit(void);
1067dd7cddfSDavid du Colombier void netinit(int);
1073e12c5d1SDavid du Colombier void netadd(char*);
108219b2ee8SDavid du Colombier char *genquery(Mfile*, char*);
1097dd7cddfSDavid du Colombier char* ipinfoquery(Mfile*, char**, int);
110bd389b36SDavid du Colombier int needproto(Network*, Ndbtuple*);
1119a747e4fSDavid du Colombier int lookup(Mfile*);
1123e12c5d1SDavid du Colombier Ndbtuple* reorder(Ndbtuple*, Ndbtuple*);
1137dd7cddfSDavid du Colombier void ipid(void);
1147dd7cddfSDavid du Colombier void readipinterfaces(void);
1157dd7cddfSDavid du Colombier void* emalloc(int);
1169a747e4fSDavid du Colombier char* estrdup(char*);
1177dd7cddfSDavid du Colombier Job* newjob(void);
1187dd7cddfSDavid du Colombier void freejob(Job*);
1197dd7cddfSDavid du Colombier void setext(char*, int, char*);
12080ee5cbfSDavid du Colombier void cleanmf(Mfile*);
1213e12c5d1SDavid du Colombier
122bd389b36SDavid du Colombier extern void paralloc(void);
123bd389b36SDavid du Colombier
124bd389b36SDavid du Colombier Lock dblock; /* mutex on database operations */
1257dd7cddfSDavid du Colombier Lock netlock; /* mutex for netinit() */
126bd389b36SDavid du Colombier
127219b2ee8SDavid du Colombier char *logfile = "cs";
1287dd7cddfSDavid du Colombier char *paranoiafile = "cs.paranoia";
129219b2ee8SDavid du Colombier
1307dd7cddfSDavid du Colombier char mntpt[Maxpath];
1317dd7cddfSDavid du Colombier char netndb[Maxpath];
1327dd7cddfSDavid du Colombier
13380ee5cbfSDavid du Colombier /*
13480ee5cbfSDavid du Colombier * Network specific translators
13580ee5cbfSDavid du Colombier */
13680ee5cbfSDavid du Colombier Ndbtuple* iplookup(Network*, char*, char*, int);
13780ee5cbfSDavid du Colombier char* iptrans(Ndbtuple*, Network*, char*, char*, int);
13880ee5cbfSDavid du Colombier Ndbtuple* telcolookup(Network*, char*, char*, int);
13980ee5cbfSDavid du Colombier char* telcotrans(Ndbtuple*, Network*, char*, char*, int);
14080ee5cbfSDavid du Colombier Ndbtuple* dnsiplookup(char*, Ndbs*);
14180ee5cbfSDavid du Colombier
14280ee5cbfSDavid du Colombier struct Network
14380ee5cbfSDavid du Colombier {
14480ee5cbfSDavid du Colombier char *net;
14580ee5cbfSDavid du Colombier Ndbtuple *(*lookup)(Network*, char*, char*, int);
14680ee5cbfSDavid du Colombier char *(*trans)(Ndbtuple*, Network*, char*, char*, int);
147617c0e1eSDavid du Colombier int considered; /* flag: ignored for "net!"? */
148617c0e1eSDavid du Colombier int fasttimeouthack; /* flag. was for IL */
14980ee5cbfSDavid du Colombier Network *next;
15080ee5cbfSDavid du Colombier };
15180ee5cbfSDavid du Colombier
15280ee5cbfSDavid du Colombier enum
15380ee5cbfSDavid du Colombier {
15475766116SDavid du Colombier Ntcp = 0,
15580ee5cbfSDavid du Colombier };
15680ee5cbfSDavid du Colombier
15780ee5cbfSDavid du Colombier /*
158244672c5SDavid du Colombier * net doesn't apply to (r)udp, icmp(v6), or telco (for speed).
15980ee5cbfSDavid du Colombier */
16080ee5cbfSDavid du Colombier Network network[] = {
161617c0e1eSDavid du Colombier [Ntcp] { "tcp", iplookup, iptrans, 0 },
162617c0e1eSDavid du Colombier { "udp", iplookup, iptrans, 1 },
163617c0e1eSDavid du Colombier { "icmp", iplookup, iptrans, 1 },
164617c0e1eSDavid du Colombier { "icmpv6", iplookup, iptrans, 1 },
165617c0e1eSDavid du Colombier { "rudp", iplookup, iptrans, 1 },
166*9d244d11SDavid du Colombier { "ssh", iplookup, iptrans, 1 },
167617c0e1eSDavid du Colombier { "telco", telcolookup, telcotrans, 1 },
16880ee5cbfSDavid du Colombier { 0 },
16980ee5cbfSDavid du Colombier };
17080ee5cbfSDavid du Colombier
17180ee5cbfSDavid du Colombier Lock ipifclock;
17280ee5cbfSDavid du Colombier Ipifc *ipifcs;
17380ee5cbfSDavid du Colombier
17495a264b3SDavid du Colombier char eaddr[16]; /* ascii ethernet address */
17595a264b3SDavid du Colombier char ipaddr[64]; /* ascii internet address */
17680ee5cbfSDavid du Colombier uchar ipa[IPaddrlen]; /* binary internet address */
17795a264b3SDavid du Colombier char *mysysname;
17880ee5cbfSDavid du Colombier
17980ee5cbfSDavid du Colombier Network *netlist; /* networks ordered by preference */
18080ee5cbfSDavid du Colombier Network *last;
18180ee5cbfSDavid du Colombier
18295a264b3SDavid du Colombier static void
nstrcpy(char * to,char * from,int len)18395a264b3SDavid du Colombier nstrcpy(char *to, char *from, int len)
18495a264b3SDavid du Colombier {
18595a264b3SDavid du Colombier strncpy(to, from, len);
18695a264b3SDavid du Colombier to[len-1] = 0;
18795a264b3SDavid du Colombier }
18895a264b3SDavid du Colombier
1897dd7cddfSDavid du Colombier void
usage(void)1907dd7cddfSDavid du Colombier usage(void)
1917dd7cddfSDavid du Colombier {
19275766116SDavid du Colombier fprint(2, "usage: %s [-dn] [-f ndb-file] [-x netmtpt]\n", argv0);
1937dd7cddfSDavid du Colombier exits("usage");
1947dd7cddfSDavid du Colombier }
195219b2ee8SDavid du Colombier
196254fe3d3SDavid du Colombier /*
197254fe3d3SDavid du Colombier * based on libthread's threadsetname, but drags in less library code.
198254fe3d3SDavid du Colombier * actually just sets the arguments displayed.
199254fe3d3SDavid du Colombier */
200254fe3d3SDavid du Colombier void
procsetname(char * fmt,...)201254fe3d3SDavid du Colombier procsetname(char *fmt, ...)
202254fe3d3SDavid du Colombier {
203254fe3d3SDavid du Colombier int fd;
204254fe3d3SDavid du Colombier char *cmdname;
205254fe3d3SDavid du Colombier char buf[128];
206254fe3d3SDavid du Colombier va_list arg;
207254fe3d3SDavid du Colombier
208254fe3d3SDavid du Colombier va_start(arg, fmt);
209254fe3d3SDavid du Colombier cmdname = vsmprint(fmt, arg);
210254fe3d3SDavid du Colombier va_end(arg);
211254fe3d3SDavid du Colombier if (cmdname == nil)
212254fe3d3SDavid du Colombier return;
213254fe3d3SDavid du Colombier snprint(buf, sizeof buf, "#p/%d/args", getpid());
214254fe3d3SDavid du Colombier if((fd = open(buf, OWRITE)) >= 0){
215254fe3d3SDavid du Colombier write(fd, cmdname, strlen(cmdname)+1);
216254fe3d3SDavid du Colombier close(fd);
217254fe3d3SDavid du Colombier }
218254fe3d3SDavid du Colombier free(cmdname);
219254fe3d3SDavid du Colombier }
220254fe3d3SDavid du Colombier
2213e12c5d1SDavid du Colombier void
main(int argc,char * argv[])2223e12c5d1SDavid du Colombier main(int argc, char *argv[])
2233e12c5d1SDavid du Colombier {
224219b2ee8SDavid du Colombier int justsetname;
22575766116SDavid du Colombier char ext[Maxpath], servefile[Maxpath];
2263e12c5d1SDavid du Colombier
227219b2ee8SDavid du Colombier justsetname = 0;
2287dd7cddfSDavid du Colombier setnetmtpt(mntpt, sizeof(mntpt), nil);
2297dd7cddfSDavid du Colombier ext[0] = 0;
2303e12c5d1SDavid du Colombier ARGBEGIN{
231b8b25780SDavid du Colombier case '4':
232b8b25780SDavid du Colombier ipv6lookups = 0;
233b8b25780SDavid du Colombier break;
2343e12c5d1SDavid du Colombier case 'd':
2353e12c5d1SDavid du Colombier debug = 1;
2363e12c5d1SDavid du Colombier break;
237bd389b36SDavid du Colombier case 'f':
23875766116SDavid du Colombier dbfile = EARGF(usage());
239bd389b36SDavid du Colombier break;
240219b2ee8SDavid du Colombier case 'n':
241219b2ee8SDavid du Colombier justsetname = 1;
242219b2ee8SDavid du Colombier break;
24375766116SDavid du Colombier case 'x':
24475766116SDavid du Colombier setnetmtpt(mntpt, sizeof(mntpt), EARGF(usage()));
24575766116SDavid du Colombier setext(ext, sizeof(ext), mntpt);
24675766116SDavid du Colombier break;
2473e12c5d1SDavid du Colombier }ARGEND
2483e12c5d1SDavid du Colombier USED(argc);
2493e12c5d1SDavid du Colombier USED(argv);
2503e12c5d1SDavid du Colombier
2517dd7cddfSDavid du Colombier rfork(RFREND|RFNOTEG);
2527dd7cddfSDavid du Colombier
2537dd7cddfSDavid du Colombier snprint(servefile, sizeof(servefile), "#s/cs%s", ext);
2547dd7cddfSDavid du Colombier snprint(netndb, sizeof(netndb), "%s/ndb", mntpt);
2557dd7cddfSDavid du Colombier unmount(servefile, mntpt);
2567dd7cddfSDavid du Colombier remove(servefile);
2577dd7cddfSDavid du Colombier
2589a747e4fSDavid du Colombier fmtinstall('E', eipfmt);
2599a747e4fSDavid du Colombier fmtinstall('I', eipfmt);
2609a747e4fSDavid du Colombier fmtinstall('M', eipfmt);
2619a747e4fSDavid du Colombier fmtinstall('F', fcallfmt);
2627dd7cddfSDavid du Colombier
2637dd7cddfSDavid du Colombier ndbinit();
2647dd7cddfSDavid du Colombier netinit(0);
2657dd7cddfSDavid du Colombier
2667dd7cddfSDavid du Colombier if(!justsetname){
2677dd7cddfSDavid du Colombier mountinit(servefile, mntpt);
2687dd7cddfSDavid du Colombier io();
2697dd7cddfSDavid du Colombier }
270219b2ee8SDavid du Colombier exits(0);
271219b2ee8SDavid du Colombier }
272219b2ee8SDavid du Colombier
2737dd7cddfSDavid du Colombier /*
2747dd7cddfSDavid du Colombier * if a mount point is specified, set the cs extention to be the mount point
2757dd7cddfSDavid du Colombier * with '_'s replacing '/'s
2767dd7cddfSDavid du Colombier */
2777dd7cddfSDavid du Colombier void
setext(char * ext,int n,char * p)2787dd7cddfSDavid du Colombier setext(char *ext, int n, char *p)
2797dd7cddfSDavid du Colombier {
2807dd7cddfSDavid du Colombier int i, c;
2813e12c5d1SDavid du Colombier
2827dd7cddfSDavid du Colombier n--;
2837dd7cddfSDavid du Colombier for(i = 0; i < n; i++){
2847dd7cddfSDavid du Colombier c = p[i];
2857dd7cddfSDavid du Colombier if(c == 0)
2867dd7cddfSDavid du Colombier break;
2877dd7cddfSDavid du Colombier if(c == '/')
2887dd7cddfSDavid du Colombier c = '_';
2897dd7cddfSDavid du Colombier ext[i] = c;
2907dd7cddfSDavid du Colombier }
2917dd7cddfSDavid du Colombier ext[i] = 0;
2923e12c5d1SDavid du Colombier }
2933e12c5d1SDavid du Colombier
2943e12c5d1SDavid du Colombier void
mountinit(char * service,char * mntpt)2957dd7cddfSDavid du Colombier mountinit(char *service, char *mntpt)
2963e12c5d1SDavid du Colombier {
2973e12c5d1SDavid du Colombier int f;
2983e12c5d1SDavid du Colombier int p[2];
2993e12c5d1SDavid du Colombier char buf[32];
3003e12c5d1SDavid du Colombier
3013e12c5d1SDavid du Colombier if(pipe(p) < 0)
3023e12c5d1SDavid du Colombier error("pipe failed");
303a9f680aeSDavid du Colombier
304a9f680aeSDavid du Colombier /*
305a9f680aeSDavid du Colombier * make a /srv/cs
306a9f680aeSDavid du Colombier */
307a9f680aeSDavid du Colombier f = create(service, OWRITE|ORCLOSE, 0666);
308a9f680aeSDavid du Colombier if(f < 0)
309a9f680aeSDavid du Colombier error(service);
310a9f680aeSDavid du Colombier snprint(buf, sizeof(buf), "%d", p[1]);
311a9f680aeSDavid du Colombier if(write(f, buf, strlen(buf)) != strlen(buf))
312a9f680aeSDavid du Colombier error("write /srv/cs");
313a9f680aeSDavid du Colombier
314219b2ee8SDavid du Colombier switch(rfork(RFFDG|RFPROC|RFNAMEG)){
3153e12c5d1SDavid du Colombier case 0:
316219b2ee8SDavid du Colombier close(p[1]);
317254fe3d3SDavid du Colombier procsetname("%s", mntpt);
3183e12c5d1SDavid du Colombier break;
3193e12c5d1SDavid du Colombier case -1:
3203e12c5d1SDavid du Colombier error("fork failed\n");
3213e12c5d1SDavid du Colombier default:
3223e12c5d1SDavid du Colombier /*
3233e12c5d1SDavid du Colombier * put ourselves into the file system
3243e12c5d1SDavid du Colombier */
325219b2ee8SDavid du Colombier close(p[0]);
3269a747e4fSDavid du Colombier if(mount(p[1], -1, mntpt, MAFTER, "") < 0)
3273e12c5d1SDavid du Colombier error("mount failed\n");
328219b2ee8SDavid du Colombier _exits(0);
3293e12c5d1SDavid du Colombier }
3303e12c5d1SDavid du Colombier mfd[0] = mfd[1] = p[0];
3313e12c5d1SDavid du Colombier }
3323e12c5d1SDavid du Colombier
3337dd7cddfSDavid du Colombier void
ndbinit(void)3347dd7cddfSDavid du Colombier ndbinit(void)
3357dd7cddfSDavid du Colombier {
3367dd7cddfSDavid du Colombier db = ndbopen(dbfile);
3377dd7cddfSDavid du Colombier if(db == nil)
3387dd7cddfSDavid du Colombier error("can't open network database");
3397dd7cddfSDavid du Colombier
3407dd7cddfSDavid du Colombier netdb = ndbopen(netndb);
3417dd7cddfSDavid du Colombier if(netdb != nil){
3427dd7cddfSDavid du Colombier netdb->nohash = 1;
3437dd7cddfSDavid du Colombier db = ndbcat(netdb, db);
3447dd7cddfSDavid du Colombier }
3457dd7cddfSDavid du Colombier }
3467dd7cddfSDavid du Colombier
3473e12c5d1SDavid du Colombier Mfile*
newfid(int fid)3483e12c5d1SDavid du Colombier newfid(int fid)
3493e12c5d1SDavid du Colombier {
350219b2ee8SDavid du Colombier Mlist *f, *ff;
3513e12c5d1SDavid du Colombier Mfile *mf;
3523e12c5d1SDavid du Colombier
353219b2ee8SDavid du Colombier ff = 0;
354219b2ee8SDavid du Colombier for(f = mlist; f; f = f->next)
355219b2ee8SDavid du Colombier if(f->mf.busy && f->mf.fid == fid)
356219b2ee8SDavid du Colombier return &f->mf;
357219b2ee8SDavid du Colombier else if(!ff && !f->mf.busy)
358219b2ee8SDavid du Colombier ff = f;
359219b2ee8SDavid du Colombier if(ff == 0){
3607dd7cddfSDavid du Colombier ff = emalloc(sizeof *f);
361219b2ee8SDavid du Colombier ff->next = mlist;
362219b2ee8SDavid du Colombier mlist = ff;
3633e12c5d1SDavid du Colombier }
364219b2ee8SDavid du Colombier mf = &ff->mf;
365219b2ee8SDavid du Colombier memset(mf, 0, sizeof *mf);
3663e12c5d1SDavid du Colombier mf->fid = fid;
3673e12c5d1SDavid du Colombier return mf;
3683e12c5d1SDavid du Colombier }
3693e12c5d1SDavid du Colombier
3707dd7cddfSDavid du Colombier Job*
newjob(void)3717dd7cddfSDavid du Colombier newjob(void)
3727dd7cddfSDavid du Colombier {
3737dd7cddfSDavid du Colombier Job *job;
3747dd7cddfSDavid du Colombier
3757dd7cddfSDavid du Colombier job = mallocz(sizeof(Job), 1);
3767dd7cddfSDavid du Colombier lock(&joblock);
3777dd7cddfSDavid du Colombier job->next = joblist;
3787dd7cddfSDavid du Colombier joblist = job;
3797dd7cddfSDavid du Colombier job->request.tag = -1;
3807dd7cddfSDavid du Colombier unlock(&joblock);
3817dd7cddfSDavid du Colombier return job;
3827dd7cddfSDavid du Colombier }
3837dd7cddfSDavid du Colombier
3847dd7cddfSDavid du Colombier void
freejob(Job * job)3857dd7cddfSDavid du Colombier freejob(Job *job)
3867dd7cddfSDavid du Colombier {
3877dd7cddfSDavid du Colombier Job **l;
3887dd7cddfSDavid du Colombier
3897dd7cddfSDavid du Colombier lock(&joblock);
3907dd7cddfSDavid du Colombier for(l = &joblist; *l; l = &(*l)->next){
3917dd7cddfSDavid du Colombier if((*l) == job){
3927dd7cddfSDavid du Colombier *l = job->next;
3937dd7cddfSDavid du Colombier free(job);
3947dd7cddfSDavid du Colombier break;
3957dd7cddfSDavid du Colombier }
3967dd7cddfSDavid du Colombier }
3977dd7cddfSDavid du Colombier unlock(&joblock);
3987dd7cddfSDavid du Colombier }
3997dd7cddfSDavid du Colombier
4007dd7cddfSDavid du Colombier void
flushjob(int tag)4017dd7cddfSDavid du Colombier flushjob(int tag)
4027dd7cddfSDavid du Colombier {
4037dd7cddfSDavid du Colombier Job *job;
4047dd7cddfSDavid du Colombier
4057dd7cddfSDavid du Colombier lock(&joblock);
4067dd7cddfSDavid du Colombier for(job = joblist; job; job = job->next){
4077dd7cddfSDavid du Colombier if(job->request.tag == tag && job->request.type != Tflush){
4087dd7cddfSDavid du Colombier job->flushed = 1;
4097dd7cddfSDavid du Colombier break;
4107dd7cddfSDavid du Colombier }
4117dd7cddfSDavid du Colombier }
4127dd7cddfSDavid du Colombier unlock(&joblock);
4137dd7cddfSDavid du Colombier }
4147dd7cddfSDavid du Colombier
4153e12c5d1SDavid du Colombier void
io(void)4163e12c5d1SDavid du Colombier io(void)
4173e12c5d1SDavid du Colombier {
4183e12c5d1SDavid du Colombier long n;
4193e12c5d1SDavid du Colombier Mfile *mf;
4203e12c5d1SDavid du Colombier int slaveflag;
4219a747e4fSDavid du Colombier uchar mdata[IOHDRSZ + Maxfdata];
4227dd7cddfSDavid du Colombier Job *job;
4233e12c5d1SDavid du Colombier
4243e12c5d1SDavid du Colombier /*
4253e12c5d1SDavid du Colombier * if we ask dns to fulfill requests,
4263e12c5d1SDavid du Colombier * a slave process is created to wait for replies. The
4279a747e4fSDavid du Colombier * master process returns immediately via a longjmp
4283e12c5d1SDavid du Colombier * through 'masterjmp'.
4293e12c5d1SDavid du Colombier *
4303e12c5d1SDavid du Colombier * *isslave is a pointer into the call stack to a variable
4313e12c5d1SDavid du Colombier * that tells whether or not the current process is a slave.
4323e12c5d1SDavid du Colombier */
4333e12c5d1SDavid du Colombier slaveflag = 0; /* init slave variable */
4343e12c5d1SDavid du Colombier isslave = &slaveflag;
4353e12c5d1SDavid du Colombier setjmp(masterjmp);
4363e12c5d1SDavid du Colombier
4373e12c5d1SDavid du Colombier for(;;){
4389a747e4fSDavid du Colombier n = read9pmsg(mfd[0], mdata, sizeof mdata);
4393e12c5d1SDavid du Colombier if(n<=0)
4403e12c5d1SDavid du Colombier error("mount read");
4417dd7cddfSDavid du Colombier job = newjob();
4429a747e4fSDavid du Colombier if(convM2S(mdata, n, &job->request) != n){
443271b8d73SDavid du Colombier syslog(1, logfile, "format error %ux %ux %ux %ux %ux",
444271b8d73SDavid du Colombier mdata[0], mdata[1], mdata[2], mdata[3], mdata[4]);
4457dd7cddfSDavid du Colombier freejob(job);
4463e12c5d1SDavid du Colombier continue;
4473e12c5d1SDavid du Colombier }
448bd389b36SDavid du Colombier lock(&dblock);
4497dd7cddfSDavid du Colombier mf = newfid(job->request.fid);
450219b2ee8SDavid du Colombier if(debug)
4517dd7cddfSDavid du Colombier syslog(0, logfile, "%F", &job->request);
4523e12c5d1SDavid du Colombier
4533e12c5d1SDavid du Colombier
4547dd7cddfSDavid du Colombier switch(job->request.type){
4553e12c5d1SDavid du Colombier default:
4567dd7cddfSDavid du Colombier syslog(1, logfile, "unknown request type %d", job->request.type);
4573e12c5d1SDavid du Colombier break;
4589a747e4fSDavid du Colombier case Tversion:
4599a747e4fSDavid du Colombier rversion(job);
4603e12c5d1SDavid du Colombier break;
4619a747e4fSDavid du Colombier case Tauth:
4629a747e4fSDavid du Colombier rauth(job);
4633e12c5d1SDavid du Colombier break;
4643e12c5d1SDavid du Colombier case Tflush:
4657dd7cddfSDavid du Colombier rflush(job);
4663e12c5d1SDavid du Colombier break;
4673e12c5d1SDavid du Colombier case Tattach:
4687dd7cddfSDavid du Colombier rattach(job, mf);
4693e12c5d1SDavid du Colombier break;
4703e12c5d1SDavid du Colombier case Twalk:
4717dd7cddfSDavid du Colombier rwalk(job, mf);
4723e12c5d1SDavid du Colombier break;
4733e12c5d1SDavid du Colombier case Topen:
4747dd7cddfSDavid du Colombier ropen(job, mf);
4753e12c5d1SDavid du Colombier break;
4763e12c5d1SDavid du Colombier case Tcreate:
4777dd7cddfSDavid du Colombier rcreate(job, mf);
4783e12c5d1SDavid du Colombier break;
4793e12c5d1SDavid du Colombier case Tread:
4807dd7cddfSDavid du Colombier rread(job, mf);
4813e12c5d1SDavid du Colombier break;
4823e12c5d1SDavid du Colombier case Twrite:
4837dd7cddfSDavid du Colombier rwrite(job, mf);
4843e12c5d1SDavid du Colombier break;
4853e12c5d1SDavid du Colombier case Tclunk:
4867dd7cddfSDavid du Colombier rclunk(job, mf);
4873e12c5d1SDavid du Colombier break;
4883e12c5d1SDavid du Colombier case Tremove:
4897dd7cddfSDavid du Colombier rremove(job, mf);
4903e12c5d1SDavid du Colombier break;
4913e12c5d1SDavid du Colombier case Tstat:
4927dd7cddfSDavid du Colombier rstat(job, mf);
4933e12c5d1SDavid du Colombier break;
4943e12c5d1SDavid du Colombier case Twstat:
4957dd7cddfSDavid du Colombier rwstat(job, mf);
4963e12c5d1SDavid du Colombier break;
4973e12c5d1SDavid du Colombier }
498bd389b36SDavid du Colombier unlock(&dblock);
4997dd7cddfSDavid du Colombier
5007dd7cddfSDavid du Colombier freejob(job);
5017dd7cddfSDavid du Colombier
5023e12c5d1SDavid du Colombier /*
5033e12c5d1SDavid du Colombier * slave processes die after replying
5043e12c5d1SDavid du Colombier */
505219b2ee8SDavid du Colombier if(*isslave){
506219b2ee8SDavid du Colombier if(debug)
507219b2ee8SDavid du Colombier syslog(0, logfile, "slave death %d", getpid());
5083e12c5d1SDavid du Colombier _exits(0);
5093e12c5d1SDavid du Colombier }
5103e12c5d1SDavid du Colombier }
511219b2ee8SDavid du Colombier }
512219b2ee8SDavid du Colombier
513219b2ee8SDavid du Colombier void
rversion(Job * job)5149a747e4fSDavid du Colombier rversion(Job *job)
515219b2ee8SDavid du Colombier {
5169a747e4fSDavid du Colombier if(job->request.msize > IOHDRSZ + Maxfdata)
5179a747e4fSDavid du Colombier job->reply.msize = IOHDRSZ + Maxfdata;
5189a747e4fSDavid du Colombier else
5199a747e4fSDavid du Colombier job->reply.msize = job->request.msize;
5209a747e4fSDavid du Colombier if(strncmp(job->request.version, "9P2000", 6) != 0)
5219a747e4fSDavid du Colombier sendmsg(job, "unknown 9P version");
5229a747e4fSDavid du Colombier else{
5239a747e4fSDavid du Colombier job->reply.version = "9P2000";
5247dd7cddfSDavid du Colombier sendmsg(job, 0);
525219b2ee8SDavid du Colombier }
5269a747e4fSDavid du Colombier }
5273e12c5d1SDavid du Colombier
5283e12c5d1SDavid du Colombier void
rauth(Job * job)5299a747e4fSDavid du Colombier rauth(Job *job)
5303e12c5d1SDavid du Colombier {
5313ff48bf5SDavid du Colombier sendmsg(job, "cs: authentication not required");
5327dd7cddfSDavid du Colombier }
5337dd7cddfSDavid du Colombier
5347dd7cddfSDavid du Colombier /*
5357dd7cddfSDavid du Colombier * don't flush till all the slaves are done
5367dd7cddfSDavid du Colombier */
5377dd7cddfSDavid du Colombier void
rflush(Job * job)5387dd7cddfSDavid du Colombier rflush(Job *job)
5397dd7cddfSDavid du Colombier {
5407dd7cddfSDavid du Colombier flushjob(job->request.oldtag);
5417dd7cddfSDavid du Colombier sendmsg(job, 0);
5423e12c5d1SDavid du Colombier }
5433e12c5d1SDavid du Colombier
5443e12c5d1SDavid du Colombier void
rattach(Job * job,Mfile * mf)5457dd7cddfSDavid du Colombier rattach(Job *job, Mfile *mf)
5463e12c5d1SDavid du Colombier {
5473e12c5d1SDavid du Colombier if(mf->busy == 0){
5483e12c5d1SDavid du Colombier mf->busy = 1;
5499a747e4fSDavid du Colombier mf->user = estrdup(job->request.uname);
5503e12c5d1SDavid du Colombier }
5513e12c5d1SDavid du Colombier mf->qid.vers = vers++;
5529a747e4fSDavid du Colombier mf->qid.type = QTDIR;
5539a747e4fSDavid du Colombier mf->qid.path = 0LL;
5547dd7cddfSDavid du Colombier job->reply.qid = mf->qid;
5557dd7cddfSDavid du Colombier sendmsg(job, 0);
5563e12c5d1SDavid du Colombier }
5573e12c5d1SDavid du Colombier
5583e12c5d1SDavid du Colombier
5593e12c5d1SDavid du Colombier char*
rwalk(Job * job,Mfile * mf)5607dd7cddfSDavid du Colombier rwalk(Job *job, Mfile *mf)
5613e12c5d1SDavid du Colombier {
5623e12c5d1SDavid du Colombier char *err;
5639a747e4fSDavid du Colombier char **elems;
5649a747e4fSDavid du Colombier int nelems;
5659a747e4fSDavid du Colombier int i;
5669a747e4fSDavid du Colombier Mfile *nmf;
5679a747e4fSDavid du Colombier Qid qid;
5683e12c5d1SDavid du Colombier
5693e12c5d1SDavid du Colombier err = 0;
5709a747e4fSDavid du Colombier nmf = nil;
5719a747e4fSDavid du Colombier elems = job->request.wname;
5729a747e4fSDavid du Colombier nelems = job->request.nwname;
5739a747e4fSDavid du Colombier job->reply.nwqid = 0;
5749a747e4fSDavid du Colombier
5759a747e4fSDavid du Colombier if(job->request.newfid != job->request.fid){
5769a747e4fSDavid du Colombier /* clone fid */
5779a747e4fSDavid du Colombier nmf = newfid(job->request.newfid);
5789a747e4fSDavid du Colombier if(nmf->busy){
5799a747e4fSDavid du Colombier nmf = nil;
5809a747e4fSDavid du Colombier err = "clone to used channel";
5819a747e4fSDavid du Colombier goto send;
5829a747e4fSDavid du Colombier }
5839a747e4fSDavid du Colombier *nmf = *mf;
5849a747e4fSDavid du Colombier nmf->user = estrdup(mf->user);
5859a747e4fSDavid du Colombier nmf->fid = job->request.newfid;
5869a747e4fSDavid du Colombier nmf->qid.vers = vers++;
5879a747e4fSDavid du Colombier mf = nmf;
5889a747e4fSDavid du Colombier }
5899a747e4fSDavid du Colombier /* else nmf will be nil */
5909a747e4fSDavid du Colombier
5919a747e4fSDavid du Colombier qid = mf->qid;
5929a747e4fSDavid du Colombier if(nelems > 0){
5939a747e4fSDavid du Colombier /* walk fid */
5949a747e4fSDavid du Colombier for(i=0; i<nelems && i<MAXWELEM; i++){
5959a747e4fSDavid du Colombier if((qid.type & QTDIR) == 0){
5963e12c5d1SDavid du Colombier err = "not a directory";
5979a747e4fSDavid du Colombier break;
5983e12c5d1SDavid du Colombier }
5999a747e4fSDavid du Colombier if(strcmp(elems[i], "..") == 0 || strcmp(elems[i], ".") == 0){
6009a747e4fSDavid du Colombier qid.type = QTDIR;
6019a747e4fSDavid du Colombier qid.path = Qdir;
6029a747e4fSDavid du Colombier Found:
6039a747e4fSDavid du Colombier job->reply.wqid[i] = qid;
6049a747e4fSDavid du Colombier job->reply.nwqid++;
6059a747e4fSDavid du Colombier continue;
6063e12c5d1SDavid du Colombier }
6079a747e4fSDavid du Colombier if(strcmp(elems[i], "cs") == 0){
6089a747e4fSDavid du Colombier qid.type = QTFILE;
6099a747e4fSDavid du Colombier qid.path = Qcs;
6109a747e4fSDavid du Colombier goto Found;
6113e12c5d1SDavid du Colombier }
6129a747e4fSDavid du Colombier err = "file does not exist";
6139a747e4fSDavid du Colombier break;
6149a747e4fSDavid du Colombier }
6159a747e4fSDavid du Colombier }
6169a747e4fSDavid du Colombier
6173e12c5d1SDavid du Colombier send:
6189a747e4fSDavid du Colombier if(nmf != nil && (err!=nil || job->reply.nwqid<nelems)){
619a9f680aeSDavid du Colombier cleanmf(nmf);
620a9f680aeSDavid du Colombier free(nmf->user);
621a9f680aeSDavid du Colombier nmf->user = 0;
6229a747e4fSDavid du Colombier nmf->busy = 0;
6239a747e4fSDavid du Colombier nmf->fid = 0;
6249a747e4fSDavid du Colombier }
6259a747e4fSDavid du Colombier if(err == nil)
6269a747e4fSDavid du Colombier mf->qid = qid;
6277dd7cddfSDavid du Colombier sendmsg(job, err);
6283e12c5d1SDavid du Colombier return err;
6293e12c5d1SDavid du Colombier }
6303e12c5d1SDavid du Colombier
6313e12c5d1SDavid du Colombier void
ropen(Job * job,Mfile * mf)6327dd7cddfSDavid du Colombier ropen(Job *job, Mfile *mf)
6333e12c5d1SDavid du Colombier {
6343e12c5d1SDavid du Colombier int mode;
6353e12c5d1SDavid du Colombier char *err;
6363e12c5d1SDavid du Colombier
6373e12c5d1SDavid du Colombier err = 0;
6387dd7cddfSDavid du Colombier mode = job->request.mode;
6399a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){
6403e12c5d1SDavid du Colombier if(mode)
6413e12c5d1SDavid du Colombier err = "permission denied";
6429a747e4fSDavid du Colombier }
6437dd7cddfSDavid du Colombier job->reply.qid = mf->qid;
6449a747e4fSDavid du Colombier job->reply.iounit = 0;
6457dd7cddfSDavid du Colombier sendmsg(job, err);
6463e12c5d1SDavid du Colombier }
6473e12c5d1SDavid du Colombier
6483e12c5d1SDavid du Colombier void
rcreate(Job * job,Mfile * mf)6497dd7cddfSDavid du Colombier rcreate(Job *job, Mfile *mf)
6503e12c5d1SDavid du Colombier {
6513e12c5d1SDavid du Colombier USED(mf);
6527dd7cddfSDavid du Colombier sendmsg(job, "creation permission denied");
6533e12c5d1SDavid du Colombier }
6543e12c5d1SDavid du Colombier
6553e12c5d1SDavid du Colombier void
rread(Job * job,Mfile * mf)6567dd7cddfSDavid du Colombier rread(Job *job, Mfile *mf)
6573e12c5d1SDavid du Colombier {
658219b2ee8SDavid du Colombier int i, n, cnt;
659219b2ee8SDavid du Colombier long off, toff, clock;
6603e12c5d1SDavid du Colombier Dir dir;
661254fe3d3SDavid du Colombier uchar buf[Maxfdata];
6623e12c5d1SDavid du Colombier char *err;
6633e12c5d1SDavid du Colombier
6643e12c5d1SDavid du Colombier n = 0;
6653e12c5d1SDavid du Colombier err = 0;
6667dd7cddfSDavid du Colombier off = job->request.offset;
6677dd7cddfSDavid du Colombier cnt = job->request.count;
6689a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){
6693e12c5d1SDavid du Colombier clock = time(0);
6703e12c5d1SDavid du Colombier if(off == 0){
6716aaebd7dSDavid du Colombier memset(&dir, 0, sizeof dir);
6729a747e4fSDavid du Colombier dir.name = "cs";
6739a747e4fSDavid du Colombier dir.qid.type = QTFILE;
6743e12c5d1SDavid du Colombier dir.qid.vers = vers;
6753e12c5d1SDavid du Colombier dir.qid.path = Qcs;
6763e12c5d1SDavid du Colombier dir.mode = 0666;
6773e12c5d1SDavid du Colombier dir.length = 0;
6789a747e4fSDavid du Colombier dir.uid = mf->user;
6799a747e4fSDavid du Colombier dir.gid = mf->user;
6809a747e4fSDavid du Colombier dir.muid = mf->user;
6813e12c5d1SDavid du Colombier dir.atime = clock; /* wrong */
6823e12c5d1SDavid du Colombier dir.mtime = clock; /* wrong */
6839a747e4fSDavid du Colombier n = convD2M(&dir, buf, sizeof buf);
6843e12c5d1SDavid du Colombier }
6859a747e4fSDavid du Colombier job->reply.data = (char*)buf;
6863e12c5d1SDavid du Colombier } else {
68780ee5cbfSDavid du Colombier for(;;){
68880ee5cbfSDavid du Colombier /* look for an answer at the right offset */
689219b2ee8SDavid du Colombier toff = 0;
690219b2ee8SDavid du Colombier for(i = 0; mf->reply[i] && i < mf->nreply; i++){
691219b2ee8SDavid du Colombier n = mf->replylen[i];
692219b2ee8SDavid du Colombier if(off < toff + n)
693219b2ee8SDavid du Colombier break;
694219b2ee8SDavid du Colombier toff += n;
6953e12c5d1SDavid du Colombier }
69680ee5cbfSDavid du Colombier if(i < mf->nreply)
69780ee5cbfSDavid du Colombier break; /* got something to return */
69880ee5cbfSDavid du Colombier
69980ee5cbfSDavid du Colombier /* try looking up more answers */
70080ee5cbfSDavid du Colombier if(lookup(mf) == 0){
70180ee5cbfSDavid du Colombier /* no more */
702219b2ee8SDavid du Colombier n = 0;
703219b2ee8SDavid du Colombier goto send;
704219b2ee8SDavid du Colombier }
70580ee5cbfSDavid du Colombier }
70680ee5cbfSDavid du Colombier
70780ee5cbfSDavid du Colombier /* give back a single reply (or part of one) */
7087dd7cddfSDavid du Colombier job->reply.data = mf->reply[i] + (off - toff);
709219b2ee8SDavid du Colombier if(cnt > toff - off + n)
710219b2ee8SDavid du Colombier n = toff - off + n;
711219b2ee8SDavid du Colombier else
712219b2ee8SDavid du Colombier n = cnt;
7133e12c5d1SDavid du Colombier }
7143e12c5d1SDavid du Colombier send:
7157dd7cddfSDavid du Colombier job->reply.count = n;
7167dd7cddfSDavid du Colombier sendmsg(job, err);
7177dd7cddfSDavid du Colombier }
71880ee5cbfSDavid du Colombier void
cleanmf(Mfile * mf)71980ee5cbfSDavid du Colombier cleanmf(Mfile *mf)
7207dd7cddfSDavid du Colombier {
7217dd7cddfSDavid du Colombier int i;
7227dd7cddfSDavid du Colombier
7239a747e4fSDavid du Colombier if(mf->net != nil){
72480ee5cbfSDavid du Colombier free(mf->net);
72580ee5cbfSDavid du Colombier mf->net = nil;
7269a747e4fSDavid du Colombier }
7279a747e4fSDavid du Colombier if(mf->host != nil){
72880ee5cbfSDavid du Colombier free(mf->host);
72980ee5cbfSDavid du Colombier mf->host = nil;
7309a747e4fSDavid du Colombier }
7319a747e4fSDavid du Colombier if(mf->serv != nil){
73280ee5cbfSDavid du Colombier free(mf->serv);
73380ee5cbfSDavid du Colombier mf->serv = nil;
7349a747e4fSDavid du Colombier }
7359a747e4fSDavid du Colombier if(mf->rem != nil){
73680ee5cbfSDavid du Colombier free(mf->rem);
73780ee5cbfSDavid du Colombier mf->rem = nil;
7389a747e4fSDavid du Colombier }
73980ee5cbfSDavid du Colombier for(i = 0; i < mf->nreply; i++){
74080ee5cbfSDavid du Colombier free(mf->reply[i]);
74180ee5cbfSDavid du Colombier mf->reply[i] = nil;
74280ee5cbfSDavid du Colombier mf->replylen[i] = 0;
7437dd7cddfSDavid du Colombier }
74480ee5cbfSDavid du Colombier mf->nreply = 0;
74580ee5cbfSDavid du Colombier mf->nextnet = netlist;
7463e12c5d1SDavid du Colombier }
7473e12c5d1SDavid du Colombier
7483e12c5d1SDavid du Colombier void
rwrite(Job * job,Mfile * mf)7497dd7cddfSDavid du Colombier rwrite(Job *job, Mfile *mf)
7503e12c5d1SDavid du Colombier {
7513e12c5d1SDavid du Colombier int cnt, n;
75280ee5cbfSDavid du Colombier char *err;
7537dd7cddfSDavid du Colombier char *field[4];
754271b8d73SDavid du Colombier char curerr[64];
7553e12c5d1SDavid du Colombier
7563e12c5d1SDavid du Colombier err = 0;
7577dd7cddfSDavid du Colombier cnt = job->request.count;
7589a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){
7593e12c5d1SDavid du Colombier err = "can't write directory";
7603e12c5d1SDavid du Colombier goto send;
7613e12c5d1SDavid du Colombier }
7623e12c5d1SDavid du Colombier if(cnt >= Maxrequest){
7633e12c5d1SDavid du Colombier err = "request too long";
7643e12c5d1SDavid du Colombier goto send;
7653e12c5d1SDavid du Colombier }
7667dd7cddfSDavid du Colombier job->request.data[cnt] = 0;
7673e12c5d1SDavid du Colombier
7683e12c5d1SDavid du Colombier /*
769219b2ee8SDavid du Colombier * toggle debugging
770219b2ee8SDavid du Colombier */
7717dd7cddfSDavid du Colombier if(strncmp(job->request.data, "debug", 5)==0){
772219b2ee8SDavid du Colombier debug ^= 1;
773219b2ee8SDavid du Colombier syslog(1, logfile, "debug %d", debug);
774219b2ee8SDavid du Colombier goto send;
775219b2ee8SDavid du Colombier }
776219b2ee8SDavid du Colombier
777219b2ee8SDavid du Colombier /*
778b8b25780SDavid du Colombier * toggle ipv6 lookups
779b8b25780SDavid du Colombier */
780b8b25780SDavid du Colombier if(strncmp(job->request.data, "ipv6", 4)==0){
781b8b25780SDavid du Colombier ipv6lookups ^= 1;
782b8b25780SDavid du Colombier syslog(1, logfile, "ipv6lookups %d", ipv6lookups);
783b8b25780SDavid du Colombier goto send;
784b8b25780SDavid du Colombier }
785b8b25780SDavid du Colombier
786b8b25780SDavid du Colombier /*
7877dd7cddfSDavid du Colombier * toggle debugging
7887dd7cddfSDavid du Colombier */
7897dd7cddfSDavid du Colombier if(strncmp(job->request.data, "paranoia", 8)==0){
7907dd7cddfSDavid du Colombier paranoia ^= 1;
7917dd7cddfSDavid du Colombier syslog(1, logfile, "paranoia %d", paranoia);
7927dd7cddfSDavid du Colombier goto send;
7937dd7cddfSDavid du Colombier }
7947dd7cddfSDavid du Colombier
7957dd7cddfSDavid du Colombier /*
7963e12c5d1SDavid du Colombier * add networks to the default list
7973e12c5d1SDavid du Colombier */
7987dd7cddfSDavid du Colombier if(strncmp(job->request.data, "add ", 4)==0){
7997dd7cddfSDavid du Colombier if(job->request.data[cnt-1] == '\n')
8007dd7cddfSDavid du Colombier job->request.data[cnt-1] = 0;
8017dd7cddfSDavid du Colombier netadd(job->request.data+4);
8027dd7cddfSDavid du Colombier readipinterfaces();
8037dd7cddfSDavid du Colombier goto send;
8047dd7cddfSDavid du Colombier }
8057dd7cddfSDavid du Colombier
8067dd7cddfSDavid du Colombier /*
8077dd7cddfSDavid du Colombier * refresh all state
8087dd7cddfSDavid du Colombier */
8097dd7cddfSDavid du Colombier if(strncmp(job->request.data, "refresh", 7)==0){
8107dd7cddfSDavid du Colombier netinit(1);
8113e12c5d1SDavid du Colombier goto send;
8123e12c5d1SDavid du Colombier }
8133e12c5d1SDavid du Colombier
81480ee5cbfSDavid du Colombier /* start transaction with a clean slate */
81580ee5cbfSDavid du Colombier cleanmf(mf);
81680ee5cbfSDavid du Colombier
8173e12c5d1SDavid du Colombier /*
818219b2ee8SDavid du Colombier * look for a general query
819219b2ee8SDavid du Colombier */
8207dd7cddfSDavid du Colombier if(*job->request.data == '!'){
8217dd7cddfSDavid du Colombier err = genquery(mf, job->request.data+1);
822219b2ee8SDavid du Colombier goto send;
823219b2ee8SDavid du Colombier }
824219b2ee8SDavid du Colombier
8257dd7cddfSDavid du Colombier if(debug)
8267dd7cddfSDavid du Colombier syslog(0, logfile, "write %s", job->request.data);
8277dd7cddfSDavid du Colombier if(paranoia)
8287dd7cddfSDavid du Colombier syslog(0, paranoiafile, "write %s by %s", job->request.data, mf->user);
8297dd7cddfSDavid du Colombier
830219b2ee8SDavid du Colombier /*
8313e12c5d1SDavid du Colombier * break up name
8323e12c5d1SDavid du Colombier */
8337dd7cddfSDavid du Colombier n = getfields(job->request.data, field, 4, 1, "!");
8343e12c5d1SDavid du Colombier switch(n){
8353e12c5d1SDavid du Colombier case 1:
83680ee5cbfSDavid du Colombier mf->net = strdup("net");
83780ee5cbfSDavid du Colombier mf->host = strdup(field[0]);
8387dd7cddfSDavid du Colombier break;
8397dd7cddfSDavid du Colombier case 4:
84080ee5cbfSDavid du Colombier mf->rem = strdup(field[3]);
84180ee5cbfSDavid du Colombier /* fall through */
84280ee5cbfSDavid du Colombier case 3:
84380ee5cbfSDavid du Colombier mf->serv = strdup(field[2]);
84480ee5cbfSDavid du Colombier /* fall through */
84580ee5cbfSDavid du Colombier case 2:
84680ee5cbfSDavid du Colombier mf->host = strdup(field[1]);
84780ee5cbfSDavid du Colombier mf->net = strdup(field[0]);
8483e12c5d1SDavid du Colombier break;
8493e12c5d1SDavid du Colombier }
8503e12c5d1SDavid du Colombier
85180ee5cbfSDavid du Colombier /*
85280ee5cbfSDavid du Colombier * do the first net worth of lookup
85380ee5cbfSDavid du Colombier */
854271b8d73SDavid du Colombier if(lookup(mf) == 0){
855271b8d73SDavid du Colombier rerrstr(curerr, sizeof curerr);
856271b8d73SDavid du Colombier err = curerr;
857271b8d73SDavid du Colombier }
8583e12c5d1SDavid du Colombier send:
8597dd7cddfSDavid du Colombier job->reply.count = cnt;
8607dd7cddfSDavid du Colombier sendmsg(job, err);
8613e12c5d1SDavid du Colombier }
8623e12c5d1SDavid du Colombier
8633e12c5d1SDavid du Colombier void
rclunk(Job * job,Mfile * mf)8647dd7cddfSDavid du Colombier rclunk(Job *job, Mfile *mf)
8653e12c5d1SDavid du Colombier {
86680ee5cbfSDavid du Colombier cleanmf(mf);
867a9f680aeSDavid du Colombier free(mf->user);
868a9f680aeSDavid du Colombier mf->user = 0;
8693e12c5d1SDavid du Colombier mf->busy = 0;
8703e12c5d1SDavid du Colombier mf->fid = 0;
8717dd7cddfSDavid du Colombier sendmsg(job, 0);
8723e12c5d1SDavid du Colombier }
8733e12c5d1SDavid du Colombier
8743e12c5d1SDavid du Colombier void
rremove(Job * job,Mfile * mf)8757dd7cddfSDavid du Colombier rremove(Job *job, Mfile *mf)
8763e12c5d1SDavid du Colombier {
8773e12c5d1SDavid du Colombier USED(mf);
8787dd7cddfSDavid du Colombier sendmsg(job, "remove permission denied");
8793e12c5d1SDavid du Colombier }
8803e12c5d1SDavid du Colombier
8813e12c5d1SDavid du Colombier void
rstat(Job * job,Mfile * mf)8827dd7cddfSDavid du Colombier rstat(Job *job, Mfile *mf)
8833e12c5d1SDavid du Colombier {
8843e12c5d1SDavid du Colombier Dir dir;
8859a747e4fSDavid du Colombier uchar buf[IOHDRSZ+Maxfdata];
8863e12c5d1SDavid du Colombier
8876aaebd7dSDavid du Colombier memset(&dir, 0, sizeof dir);
8889a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){
8899a747e4fSDavid du Colombier dir.name = ".";
8909a747e4fSDavid du Colombier dir.mode = DMDIR|0555;
891219b2ee8SDavid du Colombier } else {
8929a747e4fSDavid du Colombier dir.name = "cs";
8933e12c5d1SDavid du Colombier dir.mode = 0666;
894219b2ee8SDavid du Colombier }
895219b2ee8SDavid du Colombier dir.qid = mf->qid;
8963e12c5d1SDavid du Colombier dir.length = 0;
8979a747e4fSDavid du Colombier dir.uid = mf->user;
8989a747e4fSDavid du Colombier dir.gid = mf->user;
8999a747e4fSDavid du Colombier dir.muid = mf->user;
9003e12c5d1SDavid du Colombier dir.atime = dir.mtime = time(0);
9019a747e4fSDavid du Colombier job->reply.nstat = convD2M(&dir, buf, sizeof buf);
9029a747e4fSDavid du Colombier job->reply.stat = buf;
9037dd7cddfSDavid du Colombier sendmsg(job, 0);
9043e12c5d1SDavid du Colombier }
9053e12c5d1SDavid du Colombier
9063e12c5d1SDavid du Colombier void
rwstat(Job * job,Mfile * mf)9077dd7cddfSDavid du Colombier rwstat(Job *job, Mfile *mf)
9083e12c5d1SDavid du Colombier {
9093e12c5d1SDavid du Colombier USED(mf);
9107dd7cddfSDavid du Colombier sendmsg(job, "wstat permission denied");
9113e12c5d1SDavid du Colombier }
9123e12c5d1SDavid du Colombier
9133e12c5d1SDavid du Colombier void
sendmsg(Job * job,char * err)9147dd7cddfSDavid du Colombier sendmsg(Job *job, char *err)
9153e12c5d1SDavid du Colombier {
9163e12c5d1SDavid du Colombier int n;
9179a747e4fSDavid du Colombier uchar mdata[IOHDRSZ + Maxfdata];
9189a747e4fSDavid du Colombier char ename[ERRMAX];
9193e12c5d1SDavid du Colombier
9203e12c5d1SDavid du Colombier if(err){
9217dd7cddfSDavid du Colombier job->reply.type = Rerror;
9229a747e4fSDavid du Colombier snprint(ename, sizeof(ename), "cs: %s", err);
9239a747e4fSDavid du Colombier job->reply.ename = ename;
9243e12c5d1SDavid du Colombier }else{
9257dd7cddfSDavid du Colombier job->reply.type = job->request.type+1;
9263e12c5d1SDavid du Colombier }
9277dd7cddfSDavid du Colombier job->reply.tag = job->request.tag;
9289a747e4fSDavid du Colombier n = convS2M(&job->reply, mdata, sizeof mdata);
929219b2ee8SDavid du Colombier if(n == 0){
9307dd7cddfSDavid du Colombier syslog(1, logfile, "sendmsg convS2M of %F returns 0", &job->reply);
931219b2ee8SDavid du Colombier abort();
932219b2ee8SDavid du Colombier }
9337dd7cddfSDavid du Colombier lock(&joblock);
9347dd7cddfSDavid du Colombier if(job->flushed == 0)
9359a747e4fSDavid du Colombier if(write(mfd[1], mdata, n)!=n)
9363e12c5d1SDavid du Colombier error("mount write");
9377dd7cddfSDavid du Colombier unlock(&joblock);
938219b2ee8SDavid du Colombier if(debug)
9397dd7cddfSDavid du Colombier syslog(0, logfile, "%F %d", &job->reply, n);
9403e12c5d1SDavid du Colombier }
9413e12c5d1SDavid du Colombier
9423e12c5d1SDavid du Colombier void
error(char * s)9433e12c5d1SDavid du Colombier error(char *s)
9443e12c5d1SDavid du Colombier {
945bd389b36SDavid du Colombier syslog(1, "cs", "%s: %r", s);
946bd389b36SDavid du Colombier _exits(0);
9473e12c5d1SDavid du Colombier }
9483e12c5d1SDavid du Colombier
9497dd7cddfSDavid du Colombier static int
isvalidip(uchar * ip)9507dd7cddfSDavid du Colombier isvalidip(uchar *ip)
9517dd7cddfSDavid du Colombier {
9527dd7cddfSDavid du Colombier return ipcmp(ip, IPnoaddr) != 0 && ipcmp(ip, v4prefix) != 0;
9537dd7cddfSDavid du Colombier }
9543e12c5d1SDavid du Colombier
9550103620dSDavid du Colombier static uchar loopbacknet[IPaddrlen] = {
9560103620dSDavid du Colombier 0, 0, 0, 0,
9570103620dSDavid du Colombier 0, 0, 0, 0,
9580103620dSDavid du Colombier 0, 0, 0xff, 0xff,
9590103620dSDavid du Colombier 127, 0, 0, 0
9600103620dSDavid du Colombier };
9610103620dSDavid du Colombier static uchar loopbackmask[IPaddrlen] = {
9620103620dSDavid du Colombier 0xff, 0xff, 0xff, 0xff,
9630103620dSDavid du Colombier 0xff, 0xff, 0xff, 0xff,
9640103620dSDavid du Colombier 0xff, 0xff, 0xff, 0xff,
9650103620dSDavid du Colombier 0xff, 0, 0, 0
9660103620dSDavid du Colombier };
9670103620dSDavid du Colombier
9687dd7cddfSDavid du Colombier void
readipinterfaces(void)9697dd7cddfSDavid du Colombier readipinterfaces(void)
9707dd7cddfSDavid du Colombier {
9710103620dSDavid du Colombier if(myipaddr(ipa, mntpt) != 0)
9720103620dSDavid du Colombier ipmove(ipa, IPnoaddr);
9737dd7cddfSDavid du Colombier sprint(ipaddr, "%I", ipa);
9747dd7cddfSDavid du Colombier if (debug)
9757dd7cddfSDavid du Colombier syslog(0, "dns", "ipaddr is %s\n", ipaddr);
9767dd7cddfSDavid du Colombier }
9773e12c5d1SDavid du Colombier
9783e12c5d1SDavid du Colombier /*
9797dd7cddfSDavid du Colombier * get the system name
9803e12c5d1SDavid du Colombier */
9813e12c5d1SDavid du Colombier void
ipid(void)9823e12c5d1SDavid du Colombier ipid(void)
9833e12c5d1SDavid du Colombier {
9843e12c5d1SDavid du Colombier uchar addr[6];
985a9f680aeSDavid du Colombier Ndbtuple *t, *tt;
986219b2ee8SDavid du Colombier char *p, *attr;
9873e12c5d1SDavid du Colombier Ndbs s;
9883e12c5d1SDavid du Colombier int f;
9897dd7cddfSDavid du Colombier char buf[Maxpath];
9903e12c5d1SDavid du Colombier
991219b2ee8SDavid du Colombier /* use environment, ether addr, or ipaddr to get system name */
99295a264b3SDavid du Colombier if(mysysname == 0){
9937dd7cddfSDavid du Colombier /*
9947dd7cddfSDavid du Colombier * environment has priority.
9957dd7cddfSDavid du Colombier *
9967dd7cddfSDavid du Colombier * on the sgi power the default system name
9977dd7cddfSDavid du Colombier * is the ip address. ignore that.
9987dd7cddfSDavid du Colombier *
9997dd7cddfSDavid du Colombier */
1000219b2ee8SDavid du Colombier p = getenv("sysname");
1001447d6a7dSDavid du Colombier if(p && *p){
1002219b2ee8SDavid du Colombier attr = ipattr(p);
1003219b2ee8SDavid du Colombier if(strcmp(attr, "ip") != 0)
100495a264b3SDavid du Colombier mysysname = strdup(p);
10053e12c5d1SDavid du Colombier }
10063e12c5d1SDavid du Colombier
10073e12c5d1SDavid du Colombier /*
10087dd7cddfSDavid du Colombier * the /net/ndb contains what the network
10097dd7cddfSDavid du Colombier * figured out from DHCP. use that name if
10107dd7cddfSDavid du Colombier * there is one.
10113e12c5d1SDavid du Colombier */
101295a264b3SDavid du Colombier if(mysysname == 0 && netdb != nil){
10137dd7cddfSDavid du Colombier ndbreopen(netdb);
1014a9f680aeSDavid du Colombier for(tt = t = ndbparse(netdb); t != nil; t = t->entry){
10157dd7cddfSDavid du Colombier if(strcmp(t->attr, "sys") == 0){
101695a264b3SDavid du Colombier mysysname = strdup(t->val);
10173e12c5d1SDavid du Colombier break;
10183e12c5d1SDavid du Colombier }
10197dd7cddfSDavid du Colombier }
1020a9f680aeSDavid du Colombier ndbfree(tt);
10217dd7cddfSDavid du Colombier }
10227dd7cddfSDavid du Colombier
10237dd7cddfSDavid du Colombier /* next network database, ip address, and ether address to find a name */
102495a264b3SDavid du Colombier if(mysysname == 0){
10257dd7cddfSDavid du Colombier t = nil;
10267dd7cddfSDavid du Colombier if(isvalidip(ipa))
102757837e0bSDavid du Colombier free(ndbgetvalue(db, &s, "ip", ipaddr, "sys", &t));
102895a264b3SDavid du Colombier if(t == nil){
10297dd7cddfSDavid du Colombier for(f = 0; f < 3; f++){
10307dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%s/ether%d", mntpt, f);
10317dd7cddfSDavid du Colombier if(myetheraddr(addr, buf) >= 0){
10327dd7cddfSDavid du Colombier snprint(eaddr, sizeof(eaddr), "%E", addr);
103357837e0bSDavid du Colombier free(ndbgetvalue(db, &s, "ether", eaddr, "sys", &t));
10347dd7cddfSDavid du Colombier if(t != nil)
10357dd7cddfSDavid du Colombier break;
10367dd7cddfSDavid du Colombier }
10377dd7cddfSDavid du Colombier }
10387dd7cddfSDavid du Colombier }
1039b7327ca2SDavid du Colombier for(tt = t; tt != nil; tt = tt->entry){
1040b7327ca2SDavid du Colombier if(strcmp(tt->attr, "sys") == 0){
1041b7327ca2SDavid du Colombier mysysname = strdup(tt->val);
104295a264b3SDavid du Colombier break;
104395a264b3SDavid du Colombier }
1044b7327ca2SDavid du Colombier }
10457dd7cddfSDavid du Colombier ndbfree(t);
10467dd7cddfSDavid du Colombier }
10477dd7cddfSDavid du Colombier
104880ee5cbfSDavid du Colombier /* nothing else worked, use the ip address */
104995a264b3SDavid du Colombier if(mysysname == 0 && isvalidip(ipa))
105095a264b3SDavid du Colombier mysysname = strdup(ipaddr);
105180ee5cbfSDavid du Colombier
105280ee5cbfSDavid du Colombier
1053dc5a79c1SDavid du Colombier /* set /dev/sysname if we now know it */
105495a264b3SDavid du Colombier if(mysysname){
10557dd7cddfSDavid du Colombier f = open("/dev/sysname", OWRITE);
10567dd7cddfSDavid du Colombier if(f >= 0){
10577dd7cddfSDavid du Colombier write(f, mysysname, strlen(mysysname));
10583e12c5d1SDavid du Colombier close(f);
10593e12c5d1SDavid du Colombier }
10603e12c5d1SDavid du Colombier }
10613e12c5d1SDavid du Colombier }
10623e12c5d1SDavid du Colombier }
10633e12c5d1SDavid du Colombier
10643e12c5d1SDavid du Colombier /*
10653e12c5d1SDavid du Colombier * Set up a list of default networks by looking for
1066254fe3d3SDavid du Colombier * /net/^*^/clone.
10673e12c5d1SDavid du Colombier */
10683e12c5d1SDavid du Colombier void
netinit(int background)10697dd7cddfSDavid du Colombier netinit(int background)
10703e12c5d1SDavid du Colombier {
10717dd7cddfSDavid du Colombier char clone[Maxpath];
10723e12c5d1SDavid du Colombier Network *np;
10737dd7cddfSDavid du Colombier static int working;
10747dd7cddfSDavid du Colombier
10757dd7cddfSDavid du Colombier if(background){
10767dd7cddfSDavid du Colombier switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){
10777dd7cddfSDavid du Colombier case 0:
10787dd7cddfSDavid du Colombier break;
10797dd7cddfSDavid du Colombier default:
10807dd7cddfSDavid du Colombier return;
10817dd7cddfSDavid du Colombier }
10827dd7cddfSDavid du Colombier lock(&netlock);
10837dd7cddfSDavid du Colombier }
10843e12c5d1SDavid du Colombier
10853e12c5d1SDavid du Colombier /* add the mounted networks to the default list */
10863e12c5d1SDavid du Colombier for(np = network; np->net; np++){
10877dd7cddfSDavid du Colombier if(np->considered)
10887dd7cddfSDavid du Colombier continue;
10897dd7cddfSDavid du Colombier snprint(clone, sizeof(clone), "%s/%s/clone", mntpt, np->net);
10909a747e4fSDavid du Colombier if(access(clone, AEXIST) < 0)
10913e12c5d1SDavid du Colombier continue;
10923e12c5d1SDavid du Colombier if(netlist)
10933e12c5d1SDavid du Colombier last->next = np;
10943e12c5d1SDavid du Colombier else
10953e12c5d1SDavid du Colombier netlist = np;
10963e12c5d1SDavid du Colombier last = np;
10973e12c5d1SDavid du Colombier np->next = 0;
10987dd7cddfSDavid du Colombier np->considered = 1;
10993e12c5d1SDavid du Colombier }
11003e12c5d1SDavid du Colombier
11017dd7cddfSDavid du Colombier /* find out what our ip address is */
11027dd7cddfSDavid du Colombier readipinterfaces();
11033e12c5d1SDavid du Colombier
110432411399SDavid du Colombier /* set the system name if we need to, these days ip is all we have */
11053e12c5d1SDavid du Colombier ipid();
11063e12c5d1SDavid du Colombier
1107219b2ee8SDavid du Colombier if(debug)
11087dd7cddfSDavid du Colombier syslog(0, logfile, "mysysname %s eaddr %s ipaddr %s ipa %I\n",
110995a264b3SDavid du Colombier mysysname?mysysname:"???", eaddr, ipaddr, ipa);
11107dd7cddfSDavid du Colombier
11117dd7cddfSDavid du Colombier if(background){
11127dd7cddfSDavid du Colombier unlock(&netlock);
11137dd7cddfSDavid du Colombier _exits(0);
11147dd7cddfSDavid du Colombier }
11153e12c5d1SDavid du Colombier }
11163e12c5d1SDavid du Colombier
11173e12c5d1SDavid du Colombier /*
11183e12c5d1SDavid du Colombier * add networks to the standard list
11193e12c5d1SDavid du Colombier */
11203e12c5d1SDavid du Colombier void
netadd(char * p)11213e12c5d1SDavid du Colombier netadd(char *p)
11223e12c5d1SDavid du Colombier {
11233e12c5d1SDavid du Colombier Network *np;
11243e12c5d1SDavid du Colombier char *field[12];
11253e12c5d1SDavid du Colombier int i, n;
11263e12c5d1SDavid du Colombier
11277dd7cddfSDavid du Colombier n = getfields(p, field, 12, 1, " ");
11283e12c5d1SDavid du Colombier for(i = 0; i < n; i++){
11293e12c5d1SDavid du Colombier for(np = network; np->net; np++){
11303e12c5d1SDavid du Colombier if(strcmp(field[i], np->net) != 0)
11313e12c5d1SDavid du Colombier continue;
11327dd7cddfSDavid du Colombier if(np->considered)
11333e12c5d1SDavid du Colombier break;
11343e12c5d1SDavid du Colombier if(netlist)
11353e12c5d1SDavid du Colombier last->next = np;
11363e12c5d1SDavid du Colombier else
11373e12c5d1SDavid du Colombier netlist = np;
11383e12c5d1SDavid du Colombier last = np;
11393e12c5d1SDavid du Colombier np->next = 0;
11407dd7cddfSDavid du Colombier np->considered = 1;
11413e12c5d1SDavid du Colombier }
11423e12c5d1SDavid du Colombier }
11433e12c5d1SDavid du Colombier }
11443e12c5d1SDavid du Colombier
114580ee5cbfSDavid du Colombier int
lookforproto(Ndbtuple * t,char * proto)114680ee5cbfSDavid du Colombier lookforproto(Ndbtuple *t, char *proto)
114780ee5cbfSDavid du Colombier {
114880ee5cbfSDavid du Colombier for(; t != nil; t = t->entry)
114980ee5cbfSDavid du Colombier if(strcmp(t->attr, "proto") == 0 && strcmp(t->val, proto) == 0)
115080ee5cbfSDavid du Colombier return 1;
115180ee5cbfSDavid du Colombier return 0;
115280ee5cbfSDavid du Colombier }
115380ee5cbfSDavid du Colombier
1154219b2ee8SDavid du Colombier /*
11553e12c5d1SDavid du Colombier * lookup a request. the network "net" means we should pick the
11563e12c5d1SDavid du Colombier * best network to get there.
11573e12c5d1SDavid du Colombier */
11583e12c5d1SDavid du Colombier int
lookup(Mfile * mf)115980ee5cbfSDavid du Colombier lookup(Mfile *mf)
11603e12c5d1SDavid du Colombier {
116180ee5cbfSDavid du Colombier Network *np;
1162219b2ee8SDavid du Colombier char *cp;
1163219b2ee8SDavid du Colombier Ndbtuple *nt, *t;
1164219b2ee8SDavid du Colombier char reply[Maxreply];
116580ee5cbfSDavid du Colombier int i, rv;
116680ee5cbfSDavid du Colombier int hack;
11673e12c5d1SDavid du Colombier
11683e12c5d1SDavid du Colombier /* open up the standard db files */
11693e12c5d1SDavid du Colombier if(db == 0)
11707dd7cddfSDavid du Colombier ndbinit();
11713e12c5d1SDavid du Colombier if(db == 0)
117280ee5cbfSDavid du Colombier error("can't open mf->network database\n");
11733e12c5d1SDavid du Colombier
117480ee5cbfSDavid du Colombier rv = 0;
117580ee5cbfSDavid du Colombier
117680ee5cbfSDavid du Colombier if(mf->net == nil)
117780ee5cbfSDavid du Colombier return 0; /* must have been a genquery */
117880ee5cbfSDavid du Colombier
117980ee5cbfSDavid du Colombier if(strcmp(mf->net, "net") == 0){
11803e12c5d1SDavid du Colombier /*
11813e12c5d1SDavid du Colombier * go through set of default nets
11823e12c5d1SDavid du Colombier */
118380ee5cbfSDavid du Colombier for(np = mf->nextnet; np; np = np->next){
118480ee5cbfSDavid du Colombier nt = (*np->lookup)(np, mf->host, mf->serv, 1);
118580ee5cbfSDavid du Colombier if(nt == nil)
1186219b2ee8SDavid du Colombier continue;
118780ee5cbfSDavid du Colombier hack = np->fasttimeouthack && !lookforproto(nt, np->net);
118880ee5cbfSDavid du Colombier for(t = nt; mf->nreply < Nreply && t; t = t->entry){
118980ee5cbfSDavid du Colombier cp = (*np->trans)(t, np, mf->serv, mf->rem, hack);
1190219b2ee8SDavid du Colombier if(cp){
119180ee5cbfSDavid du Colombier /* avoid duplicates */
119280ee5cbfSDavid du Colombier for(i = 0; i < mf->nreply; i++)
119380ee5cbfSDavid du Colombier if(strcmp(mf->reply[i], cp) == 0)
119480ee5cbfSDavid du Colombier break;
119580ee5cbfSDavid du Colombier if(i == mf->nreply){
119680ee5cbfSDavid du Colombier /* save the reply */
1197219b2ee8SDavid du Colombier mf->replylen[mf->nreply] = strlen(cp);
1198219b2ee8SDavid du Colombier mf->reply[mf->nreply++] = cp;
119980ee5cbfSDavid du Colombier rv++;
1200219b2ee8SDavid du Colombier }
1201219b2ee8SDavid du Colombier }
1202219b2ee8SDavid du Colombier }
1203219b2ee8SDavid du Colombier ndbfree(nt);
120480ee5cbfSDavid du Colombier np = np->next;
120580ee5cbfSDavid du Colombier break;
120680ee5cbfSDavid du Colombier }
120780ee5cbfSDavid du Colombier mf->nextnet = np;
120880ee5cbfSDavid du Colombier return rv;
120980ee5cbfSDavid du Colombier }
121080ee5cbfSDavid du Colombier
121180ee5cbfSDavid du Colombier /*
121280ee5cbfSDavid du Colombier * if not /net, we only get one lookup
121380ee5cbfSDavid du Colombier */
121480ee5cbfSDavid du Colombier if(mf->nreply != 0)
1215219b2ee8SDavid du Colombier return 0;
121680ee5cbfSDavid du Colombier /*
121780ee5cbfSDavid du Colombier * look for a specific network
121880ee5cbfSDavid du Colombier */
121995a264b3SDavid du Colombier for(np = netlist; np && np->net != nil; np++){
122080ee5cbfSDavid du Colombier if(np->fasttimeouthack)
122180ee5cbfSDavid du Colombier continue;
122280ee5cbfSDavid du Colombier if(strcmp(np->net, mf->net) == 0)
122380ee5cbfSDavid du Colombier break;
122480ee5cbfSDavid du Colombier }
122580ee5cbfSDavid du Colombier
122695a264b3SDavid du Colombier if(np && np->net != nil){
122780ee5cbfSDavid du Colombier /*
122880ee5cbfSDavid du Colombier * known network
122980ee5cbfSDavid du Colombier */
123080ee5cbfSDavid du Colombier nt = (*np->lookup)(np, mf->host, mf->serv, 1);
123180ee5cbfSDavid du Colombier for(t = nt; mf->nreply < Nreply && t; t = t->entry){
123280ee5cbfSDavid du Colombier cp = (*np->trans)(t, np, mf->serv, mf->rem, 0);
123380ee5cbfSDavid du Colombier if(cp){
123480ee5cbfSDavid du Colombier mf->replylen[mf->nreply] = strlen(cp);
123580ee5cbfSDavid du Colombier mf->reply[mf->nreply++] = cp;
123680ee5cbfSDavid du Colombier rv++;
123780ee5cbfSDavid du Colombier }
123880ee5cbfSDavid du Colombier }
123980ee5cbfSDavid du Colombier ndbfree(nt);
124080ee5cbfSDavid du Colombier return rv;
12413e12c5d1SDavid du Colombier } else {
12423e12c5d1SDavid du Colombier /*
1243219b2ee8SDavid du Colombier * not a known network, don't translate host or service
12443e12c5d1SDavid du Colombier */
124580ee5cbfSDavid du Colombier if(mf->serv)
12467dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s",
124780ee5cbfSDavid du Colombier mntpt, mf->net, mf->host, mf->serv);
1248bd389b36SDavid du Colombier else
12497dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s",
125080ee5cbfSDavid du Colombier mntpt, mf->net, mf->host);
1251219b2ee8SDavid du Colombier mf->reply[0] = strdup(reply);
1252219b2ee8SDavid du Colombier mf->replylen[0] = strlen(reply);
1253219b2ee8SDavid du Colombier mf->nreply = 1;
125480ee5cbfSDavid du Colombier return 1;
12553e12c5d1SDavid du Colombier }
12563e12c5d1SDavid du Colombier }
12573e12c5d1SDavid du Colombier
12583e12c5d1SDavid du Colombier /*
12593e12c5d1SDavid du Colombier * translate an ip service name into a port number. If it's a numeric port
12603e12c5d1SDavid du Colombier * number, look for restricted access.
12613e12c5d1SDavid du Colombier *
12623e12c5d1SDavid du Colombier * the service '*' needs no translation.
12633e12c5d1SDavid du Colombier */
12643e12c5d1SDavid du Colombier char*
ipserv(Network * np,char * name,char * buf,int blen)126595a264b3SDavid du Colombier ipserv(Network *np, char *name, char *buf, int blen)
12663e12c5d1SDavid du Colombier {
12673e12c5d1SDavid du Colombier char *p;
12683e12c5d1SDavid du Colombier int alpha = 0;
12693e12c5d1SDavid du Colombier int restr = 0;
127095a264b3SDavid du Colombier char port[10];
12713e12c5d1SDavid du Colombier Ndbtuple *t, *nt;
12723e12c5d1SDavid du Colombier Ndbs s;
12733e12c5d1SDavid du Colombier
12743e12c5d1SDavid du Colombier /* '*' means any service */
12753e12c5d1SDavid du Colombier if(strcmp(name, "*")==0){
12763e12c5d1SDavid du Colombier strcpy(buf, name);
12773e12c5d1SDavid du Colombier return buf;
12783e12c5d1SDavid du Colombier }
12793e12c5d1SDavid du Colombier
12803e12c5d1SDavid du Colombier /* see if it's numeric or symbolic */
12813e12c5d1SDavid du Colombier port[0] = 0;
12823e12c5d1SDavid du Colombier for(p = name; *p; p++){
12833e12c5d1SDavid du Colombier if(isdigit(*p))
12849a747e4fSDavid du Colombier {}
12853e12c5d1SDavid du Colombier else if(isalpha(*p) || *p == '-' || *p == '$')
12863e12c5d1SDavid du Colombier alpha = 1;
12873e12c5d1SDavid du Colombier else
12883e12c5d1SDavid du Colombier return 0;
12893e12c5d1SDavid du Colombier }
129057837e0bSDavid du Colombier t = nil;
129157837e0bSDavid du Colombier p = nil;
12923e12c5d1SDavid du Colombier if(alpha){
129357837e0bSDavid du Colombier p = ndbgetvalue(db, &s, np->net, name, "port", &t);
1294b7327ca2SDavid du Colombier if(p == nil)
1295b7327ca2SDavid du Colombier return 0;
12963e12c5d1SDavid du Colombier } else {
12973cc1eb97SDavid du Colombier /* look up only for tcp ports < 1024 to get the restricted
12983cc1eb97SDavid du Colombier * attribute
12993cc1eb97SDavid du Colombier */
13003cc1eb97SDavid du Colombier if(atoi(name) < 1024 && strcmp(np->net, "tcp") == 0)
130157837e0bSDavid du Colombier p = ndbgetvalue(db, &s, "port", name, "port", &t);
130257837e0bSDavid du Colombier if(p == nil)
130357837e0bSDavid du Colombier p = strdup(name);
13043e12c5d1SDavid du Colombier }
13053e12c5d1SDavid du Colombier
13063e12c5d1SDavid du Colombier if(t){
13073e12c5d1SDavid du Colombier for(nt = t; nt; nt = nt->entry)
13083e12c5d1SDavid du Colombier if(strcmp(nt->attr, "restricted") == 0)
13093e12c5d1SDavid du Colombier restr = 1;
13103e12c5d1SDavid du Colombier ndbfree(t);
13113e12c5d1SDavid du Colombier }
131257837e0bSDavid du Colombier snprint(buf, blen, "%s%s", p, restr ? "!r" : "");
131357837e0bSDavid du Colombier free(p);
131457837e0bSDavid du Colombier
13153e12c5d1SDavid du Colombier return buf;
13163e12c5d1SDavid du Colombier }
13173e12c5d1SDavid du Colombier
13183e12c5d1SDavid du Colombier /*
13197dd7cddfSDavid du Colombier * lookup an ip attribute
13203e12c5d1SDavid du Colombier */
13217dd7cddfSDavid du Colombier int
ipattrlookup(Ndb * db,char * ipa,char * attr,char * val,int vlen)132295a264b3SDavid du Colombier ipattrlookup(Ndb *db, char *ipa, char *attr, char *val, int vlen)
13233e12c5d1SDavid du Colombier {
13243e12c5d1SDavid du Colombier
13257dd7cddfSDavid du Colombier Ndbtuple *t, *nt;
13267dd7cddfSDavid du Colombier char *alist[2];
13273e12c5d1SDavid du Colombier
13287dd7cddfSDavid du Colombier alist[0] = attr;
13297dd7cddfSDavid du Colombier t = ndbipinfo(db, "ip", ipa, alist, 1);
13307dd7cddfSDavid du Colombier if(t == nil)
13317dd7cddfSDavid du Colombier return 0;
13329a747e4fSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry){
13337dd7cddfSDavid du Colombier if(strcmp(nt->attr, attr) == 0){
133495a264b3SDavid du Colombier nstrcpy(val, nt->val, vlen);
13353e12c5d1SDavid du Colombier ndbfree(t);
13367dd7cddfSDavid du Colombier return 1;
1337219b2ee8SDavid du Colombier }
13389a747e4fSDavid du Colombier }
13393e12c5d1SDavid du Colombier
13407dd7cddfSDavid du Colombier /* we shouldn't get here */
13413e12c5d1SDavid du Colombier ndbfree(t);
13427dd7cddfSDavid du Colombier return 0;
13433e12c5d1SDavid du Colombier }
13443e12c5d1SDavid du Colombier
13453e12c5d1SDavid du Colombier /*
13463e12c5d1SDavid du Colombier * lookup (and translate) an ip destination
13473e12c5d1SDavid du Colombier */
1348219b2ee8SDavid du Colombier Ndbtuple*
iplookup(Network * np,char * host,char * serv,int nolookup)1349219b2ee8SDavid du Colombier iplookup(Network *np, char *host, char *serv, int nolookup)
13503e12c5d1SDavid du Colombier {
13519dfc0cb2SDavid du Colombier char *attr, *dnsname;
13527dd7cddfSDavid du Colombier Ndbtuple *t, *nt;
13533e12c5d1SDavid du Colombier Ndbs s;
135495a264b3SDavid du Colombier char ts[Maxservice];
135595a264b3SDavid du Colombier char dollar[Maxhost];
13567dd7cddfSDavid du Colombier uchar ip[IPaddrlen];
13577dd7cddfSDavid du Colombier uchar net[IPaddrlen];
13587dd7cddfSDavid du Colombier uchar tnet[IPaddrlen];
13597dd7cddfSDavid du Colombier Ipifc *ifc;
13609a747e4fSDavid du Colombier Iplifc *lifc;
13613e12c5d1SDavid du Colombier
1362219b2ee8SDavid du Colombier USED(nolookup);
1363219b2ee8SDavid du Colombier
13643e12c5d1SDavid du Colombier /*
13653e12c5d1SDavid du Colombier * start with the service since it's the most likely to fail
13663e12c5d1SDavid du Colombier * and costs the least
13673e12c5d1SDavid du Colombier */
13687dd7cddfSDavid du Colombier werrstr("can't translate address");
136995a264b3SDavid du Colombier if(serv==0 || ipserv(np, serv, ts, sizeof ts) == 0){
1370271b8d73SDavid du Colombier werrstr("can't translate service");
1371219b2ee8SDavid du Colombier return 0;
13727dd7cddfSDavid du Colombier }
13733e12c5d1SDavid du Colombier
13743e12c5d1SDavid du Colombier /* for dial strings with no host */
1375219b2ee8SDavid du Colombier if(strcmp(host, "*") == 0)
137695a264b3SDavid du Colombier return ndbnew("ip", "*");
13773e12c5d1SDavid du Colombier
13783e12c5d1SDavid du Colombier /*
13797dd7cddfSDavid du Colombier * hack till we go v6 :: = 0.0.0.0
13807dd7cddfSDavid du Colombier */
13817dd7cddfSDavid du Colombier if(strcmp("::", host) == 0)
138295a264b3SDavid du Colombier return ndbnew("ip", "*");
13837dd7cddfSDavid du Colombier
13847dd7cddfSDavid du Colombier /*
13853e12c5d1SDavid du Colombier * '$' means the rest of the name is an attribute that we
13863e12c5d1SDavid du Colombier * need to search for
13873e12c5d1SDavid du Colombier */
13883e12c5d1SDavid du Colombier if(*host == '$'){
138995a264b3SDavid du Colombier if(ipattrlookup(db, ipaddr, host+1, dollar, sizeof dollar))
13903e12c5d1SDavid du Colombier host = dollar;
13913e12c5d1SDavid du Colombier }
13923e12c5d1SDavid du Colombier
13933e12c5d1SDavid du Colombier /*
13947dd7cddfSDavid du Colombier * turn '[ip address]' into just 'ip address'
13957dd7cddfSDavid du Colombier */
13967dd7cddfSDavid du Colombier if(*host == '[' && host[strlen(host)-1] == ']'){
13977dd7cddfSDavid du Colombier host++;
13987dd7cddfSDavid du Colombier host[strlen(host)-1] = 0;
13997dd7cddfSDavid du Colombier }
14007dd7cddfSDavid du Colombier
14017dd7cddfSDavid du Colombier /*
14023e12c5d1SDavid du Colombier * just accept addresses
14033e12c5d1SDavid du Colombier */
1404219b2ee8SDavid du Colombier attr = ipattr(host);
1405219b2ee8SDavid du Colombier if(strcmp(attr, "ip") == 0)
140695a264b3SDavid du Colombier return ndbnew("ip", host);
14073e12c5d1SDavid du Colombier
14083e12c5d1SDavid du Colombier /*
14093e12c5d1SDavid du Colombier * give the domain name server the first opportunity to
1410bd389b36SDavid du Colombier * resolve domain names. if that fails try the database.
14113e12c5d1SDavid du Colombier */
14123e12c5d1SDavid du Colombier t = 0;
1413271b8d73SDavid du Colombier werrstr("can't translate address");
14143e12c5d1SDavid du Colombier if(strcmp(attr, "dom") == 0)
14157dd7cddfSDavid du Colombier t = dnsiplookup(host, &s);
14163e12c5d1SDavid du Colombier if(t == 0)
141757837e0bSDavid du Colombier free(ndbgetvalue(db, &s, attr, host, "ip", &t));
14189dfc0cb2SDavid du Colombier if(t == 0){
14199dfc0cb2SDavid du Colombier dnsname = ndbgetvalue(db, &s, attr, host, "dom", nil);
14209dfc0cb2SDavid du Colombier if(dnsname){
14219dfc0cb2SDavid du Colombier t = dnsiplookup(dnsname, &s);
14229dfc0cb2SDavid du Colombier free(dnsname);
14239dfc0cb2SDavid du Colombier }
14249dfc0cb2SDavid du Colombier }
14253e12c5d1SDavid du Colombier if(t == 0)
14267dd7cddfSDavid du Colombier t = dnsiplookup(host, &s);
14277dd7cddfSDavid du Colombier if(t == 0)
1428219b2ee8SDavid du Colombier return 0;
1429bd389b36SDavid du Colombier
1430bd389b36SDavid du Colombier /*
1431bd389b36SDavid du Colombier * reorder the tuple to have the matched line first and
1432bd389b36SDavid du Colombier * save that in the request structure.
1433bd389b36SDavid du Colombier */
14347dd7cddfSDavid du Colombier t = reorder(t, s.t);
14357dd7cddfSDavid du Colombier
14367dd7cddfSDavid du Colombier /*
14377dd7cddfSDavid du Colombier * reorder according to our interfaces
14387dd7cddfSDavid du Colombier */
14397dd7cddfSDavid du Colombier lock(&ipifclock);
14409a747e4fSDavid du Colombier for(ifc = ipifcs; ifc != nil; ifc = ifc->next){
14419a747e4fSDavid du Colombier for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){
14429a747e4fSDavid du Colombier maskip(lifc->ip, lifc->mask, net);
14437dd7cddfSDavid du Colombier for(nt = t; nt; nt = nt->entry){
14447dd7cddfSDavid du Colombier if(strcmp(nt->attr, "ip") != 0)
14457dd7cddfSDavid du Colombier continue;
14467dd7cddfSDavid du Colombier parseip(ip, nt->val);
14479a747e4fSDavid du Colombier maskip(ip, lifc->mask, tnet);
14487dd7cddfSDavid du Colombier if(memcmp(net, tnet, IPaddrlen) == 0){
14497dd7cddfSDavid du Colombier t = reorder(t, nt);
14507dd7cddfSDavid du Colombier unlock(&ipifclock);
14517dd7cddfSDavid du Colombier return t;
14527dd7cddfSDavid du Colombier }
14537dd7cddfSDavid du Colombier }
14547dd7cddfSDavid du Colombier }
14559a747e4fSDavid du Colombier }
14567dd7cddfSDavid du Colombier unlock(&ipifclock);
14577dd7cddfSDavid du Colombier
14587dd7cddfSDavid du Colombier return t;
14593e12c5d1SDavid du Colombier }
14603e12c5d1SDavid du Colombier
14613e12c5d1SDavid du Colombier /*
14623e12c5d1SDavid du Colombier * translate an ip address
14633e12c5d1SDavid du Colombier */
1464219b2ee8SDavid du Colombier char*
iptrans(Ndbtuple * t,Network * np,char * serv,char * rem,int hack)146580ee5cbfSDavid du Colombier iptrans(Ndbtuple *t, Network *np, char *serv, char *rem, int hack)
14663e12c5d1SDavid du Colombier {
146795a264b3SDavid du Colombier char ts[Maxservice];
1468219b2ee8SDavid du Colombier char reply[Maxreply];
146995a264b3SDavid du Colombier char x[Maxservice];
14703e12c5d1SDavid du Colombier
1471219b2ee8SDavid du Colombier if(strcmp(t->attr, "ip") != 0)
14723e12c5d1SDavid du Colombier return 0;
1473219b2ee8SDavid du Colombier
147495a264b3SDavid du Colombier if(serv == 0 || ipserv(np, serv, ts, sizeof ts) == 0){
1475271b8d73SDavid du Colombier werrstr("can't translate service");
1476219b2ee8SDavid du Colombier return 0;
1477271b8d73SDavid du Colombier }
14787dd7cddfSDavid du Colombier if(rem != nil)
14797dd7cddfSDavid du Colombier snprint(x, sizeof(x), "!%s", rem);
14807dd7cddfSDavid du Colombier else
14817dd7cddfSDavid du Colombier *x = 0;
148280ee5cbfSDavid du Colombier
1483219b2ee8SDavid du Colombier if(*t->val == '*')
14847dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s%s",
14857dd7cddfSDavid du Colombier mntpt, np->net, ts, x);
1486219b2ee8SDavid du Colombier else
148780ee5cbfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s%s",
148880ee5cbfSDavid du Colombier mntpt, np->net, t->val, ts, x, hack? "!fasttimeout": "");
1489219b2ee8SDavid du Colombier
1490219b2ee8SDavid du Colombier return strdup(reply);
14913e12c5d1SDavid du Colombier }
14923e12c5d1SDavid du Colombier
1493219b2ee8SDavid du Colombier /*
1494219b2ee8SDavid du Colombier * lookup a telephone number
1495219b2ee8SDavid du Colombier */
1496219b2ee8SDavid du Colombier Ndbtuple*
telcolookup(Network * np,char * host,char * serv,int nolookup)1497219b2ee8SDavid du Colombier telcolookup(Network *np, char *host, char *serv, int nolookup)
1498219b2ee8SDavid du Colombier {
1499219b2ee8SDavid du Colombier Ndbtuple *t;
1500219b2ee8SDavid du Colombier Ndbs s;
1501219b2ee8SDavid du Colombier
1502219b2ee8SDavid du Colombier USED(np, nolookup, serv);
1503219b2ee8SDavid du Colombier
1504271b8d73SDavid du Colombier werrstr("can't translate address");
150557837e0bSDavid du Colombier free(ndbgetvalue(db, &s, "sys", host, "telco", &t));
1506219b2ee8SDavid du Colombier if(t == 0)
150795a264b3SDavid du Colombier return ndbnew("telco", host);
1508219b2ee8SDavid du Colombier
1509219b2ee8SDavid du Colombier return reorder(t, s.t);
1510219b2ee8SDavid du Colombier }
1511219b2ee8SDavid du Colombier
1512219b2ee8SDavid du Colombier /*
1513219b2ee8SDavid du Colombier * translate a telephone address
1514219b2ee8SDavid du Colombier */
1515219b2ee8SDavid du Colombier char*
telcotrans(Ndbtuple * t,Network * np,char * serv,char * rem,int)151680ee5cbfSDavid du Colombier telcotrans(Ndbtuple *t, Network *np, char *serv, char *rem, int)
1517219b2ee8SDavid du Colombier {
1518219b2ee8SDavid du Colombier char reply[Maxreply];
151995a264b3SDavid du Colombier char x[Maxservice];
1520219b2ee8SDavid du Colombier
1521219b2ee8SDavid du Colombier if(strcmp(t->attr, "telco") != 0)
1522219b2ee8SDavid du Colombier return 0;
1523219b2ee8SDavid du Colombier
15247dd7cddfSDavid du Colombier if(rem != nil)
15257dd7cddfSDavid du Colombier snprint(x, sizeof(x), "!%s", rem);
1526219b2ee8SDavid du Colombier else
15277dd7cddfSDavid du Colombier *x = 0;
15287dd7cddfSDavid du Colombier if(serv)
15297dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s", mntpt, np->net,
15307dd7cddfSDavid du Colombier t->val, serv, x);
15317dd7cddfSDavid du Colombier else
15327dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s%s", mntpt, np->net,
15337dd7cddfSDavid du Colombier t->val, x);
1534219b2ee8SDavid du Colombier return strdup(reply);
1535219b2ee8SDavid du Colombier }
15363e12c5d1SDavid du Colombier
15373e12c5d1SDavid du Colombier /*
15383e12c5d1SDavid du Colombier * reorder the tuple to put x's line first in the entry
15393e12c5d1SDavid du Colombier */
15403e12c5d1SDavid du Colombier Ndbtuple*
reorder(Ndbtuple * t,Ndbtuple * x)15413e12c5d1SDavid du Colombier reorder(Ndbtuple *t, Ndbtuple *x)
15423e12c5d1SDavid du Colombier {
15433e12c5d1SDavid du Colombier Ndbtuple *nt;
15443e12c5d1SDavid du Colombier Ndbtuple *line;
15453e12c5d1SDavid du Colombier
1546219b2ee8SDavid du Colombier /* find start of this entry's line */
1547219b2ee8SDavid du Colombier for(line = x; line->entry == line->line; line = line->line)
15483e12c5d1SDavid du Colombier ;
1549219b2ee8SDavid du Colombier line = line->line;
1550219b2ee8SDavid du Colombier if(line == t)
1551219b2ee8SDavid du Colombier return t; /* already the first line */
15523e12c5d1SDavid du Colombier
1553219b2ee8SDavid du Colombier /* remove this line and everything after it from the entry */
1554219b2ee8SDavid du Colombier for(nt = t; nt->entry != line; nt = nt->entry)
1555219b2ee8SDavid du Colombier ;
1556219b2ee8SDavid du Colombier nt->entry = 0;
15573e12c5d1SDavid du Colombier
1558219b2ee8SDavid du Colombier /* make that the start of the entry */
1559219b2ee8SDavid du Colombier for(nt = line; nt->entry; nt = nt->entry)
1560219b2ee8SDavid du Colombier ;
15613e12c5d1SDavid du Colombier nt->entry = t;
15623e12c5d1SDavid du Colombier return line;
15633e12c5d1SDavid du Colombier }
15643e12c5d1SDavid du Colombier
15653e12c5d1SDavid du Colombier /*
15663e12c5d1SDavid du Colombier * create a slave process to handle a request to avoid one request blocking
15677dd7cddfSDavid du Colombier * another. parent returns to job loop.
15683e12c5d1SDavid du Colombier */
15693e12c5d1SDavid du Colombier void
slave(char * host)1570254fe3d3SDavid du Colombier slave(char *host)
15713e12c5d1SDavid du Colombier {
15723e12c5d1SDavid du Colombier if(*isslave)
15733e12c5d1SDavid du Colombier return; /* we're already a slave process */
15743e12c5d1SDavid du Colombier
15753e12c5d1SDavid du Colombier switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){
15763e12c5d1SDavid du Colombier case -1:
15773e12c5d1SDavid du Colombier break;
15783e12c5d1SDavid du Colombier case 0:
1579219b2ee8SDavid du Colombier if(debug)
1580219b2ee8SDavid du Colombier syslog(0, logfile, "slave %d", getpid());
1581254fe3d3SDavid du Colombier procsetname("%s", host);
15823e12c5d1SDavid du Colombier *isslave = 1;
15833e12c5d1SDavid du Colombier break;
15843e12c5d1SDavid du Colombier default:
15853e12c5d1SDavid du Colombier longjmp(masterjmp, 1);
15863e12c5d1SDavid du Colombier }
15873e12c5d1SDavid du Colombier
1588219b2ee8SDavid du Colombier }
1589219b2ee8SDavid du Colombier
1590b8b25780SDavid du Colombier static Ndbtuple*
dnsip6lookup(char * mntpt,char * buf,Ndbtuple * t)1591b8b25780SDavid du Colombier dnsip6lookup(char *mntpt, char *buf, Ndbtuple *t)
1592b8b25780SDavid du Colombier {
1593b8b25780SDavid du Colombier Ndbtuple *t6, *tt;
1594b8b25780SDavid du Colombier
1595b8b25780SDavid du Colombier t6 = dnsquery(mntpt, buf, "ipv6"); /* lookup AAAA dns RRs */
1596b8b25780SDavid du Colombier if (t6 == nil)
1597b8b25780SDavid du Colombier return t;
1598b8b25780SDavid du Colombier
1599b8b25780SDavid du Colombier /* convert ipv6 attr to ip */
1600b8b25780SDavid du Colombier for (tt = t6; tt != nil; tt = tt->entry)
1601b8b25780SDavid du Colombier if (strcmp(tt->attr, "ipv6") == 0)
1602b8b25780SDavid du Colombier strncpy(tt->attr, "ip", sizeof tt->attr - 1);
1603b8b25780SDavid du Colombier
1604b8b25780SDavid du Colombier if (t == nil)
1605b8b25780SDavid du Colombier return t6;
1606b8b25780SDavid du Colombier
1607b8b25780SDavid du Colombier /* append t6 list to t list */
1608b8b25780SDavid du Colombier for (tt = t; tt->entry != nil; tt = tt->entry)
1609b8b25780SDavid du Colombier ;
1610b8b25780SDavid du Colombier tt->entry = t6;
1611b8b25780SDavid du Colombier return t;
1612b8b25780SDavid du Colombier }
1613b8b25780SDavid du Colombier
16143e12c5d1SDavid du Colombier /*
16153e12c5d1SDavid du Colombier * call the dns process and have it try to translate a name
16163e12c5d1SDavid du Colombier */
16173e12c5d1SDavid du Colombier Ndbtuple*
dnsiplookup(char * host,Ndbs * s)16187dd7cddfSDavid du Colombier dnsiplookup(char *host, Ndbs *s)
16193e12c5d1SDavid du Colombier {
162095a264b3SDavid du Colombier char buf[Maxreply];
16217dd7cddfSDavid du Colombier Ndbtuple *t;
16223e12c5d1SDavid du Colombier
1623bd389b36SDavid du Colombier unlock(&dblock);
1624bd389b36SDavid du Colombier
16253e12c5d1SDavid du Colombier /* save the name before starting a slave */
16267dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s", host);
16273e12c5d1SDavid du Colombier
1628254fe3d3SDavid du Colombier slave(host);
16293e12c5d1SDavid du Colombier
16307dd7cddfSDavid du Colombier if(strcmp(ipattr(buf), "ip") == 0)
16317dd7cddfSDavid du Colombier t = dnsquery(mntpt, buf, "ptr");
1632b8b25780SDavid du Colombier else {
16337dd7cddfSDavid du Colombier t = dnsquery(mntpt, buf, "ip");
1634b8b25780SDavid du Colombier /* special case: query ipv6 (AAAA dns RR) too */
1635b8b25780SDavid du Colombier if (ipv6lookups)
1636b8b25780SDavid du Colombier t = dnsip6lookup(mntpt, buf, t);
1637b8b25780SDavid du Colombier }
16383e12c5d1SDavid du Colombier s->t = t;
16397dd7cddfSDavid du Colombier
1640271b8d73SDavid du Colombier if(t == nil){
1641271b8d73SDavid du Colombier rerrstr(buf, sizeof buf);
1642271b8d73SDavid du Colombier if(strstr(buf, "exist"))
1643271b8d73SDavid du Colombier werrstr("can't translate address: %s", buf);
1644271b8d73SDavid du Colombier else if(strstr(buf, "dns failure"))
1645271b8d73SDavid du Colombier werrstr("temporary problem: %s", buf);
1646271b8d73SDavid du Colombier }
1647271b8d73SDavid du Colombier
1648bd389b36SDavid du Colombier lock(&dblock);
16493e12c5d1SDavid du Colombier return t;
16503e12c5d1SDavid du Colombier }
1651219b2ee8SDavid du Colombier
1652219b2ee8SDavid du Colombier int
qmatch(Ndbtuple * t,char ** attr,char ** val,int n)1653219b2ee8SDavid du Colombier qmatch(Ndbtuple *t, char **attr, char **val, int n)
1654219b2ee8SDavid du Colombier {
1655219b2ee8SDavid du Colombier int i, found;
1656219b2ee8SDavid du Colombier Ndbtuple *nt;
1657219b2ee8SDavid du Colombier
1658219b2ee8SDavid du Colombier for(i = 1; i < n; i++){
1659219b2ee8SDavid du Colombier found = 0;
1660219b2ee8SDavid du Colombier for(nt = t; nt; nt = nt->entry)
1661219b2ee8SDavid du Colombier if(strcmp(attr[i], nt->attr) == 0)
1662219b2ee8SDavid du Colombier if(strcmp(val[i], "*") == 0
1663219b2ee8SDavid du Colombier || strcmp(val[i], nt->val) == 0){
1664219b2ee8SDavid du Colombier found = 1;
1665219b2ee8SDavid du Colombier break;
1666219b2ee8SDavid du Colombier }
1667219b2ee8SDavid du Colombier if(found == 0)
1668219b2ee8SDavid du Colombier break;
1669219b2ee8SDavid du Colombier }
1670219b2ee8SDavid du Colombier return i == n;
1671219b2ee8SDavid du Colombier }
1672219b2ee8SDavid du Colombier
1673219b2ee8SDavid du Colombier void
qreply(Mfile * mf,Ndbtuple * t)1674219b2ee8SDavid du Colombier qreply(Mfile *mf, Ndbtuple *t)
1675219b2ee8SDavid du Colombier {
1676219b2ee8SDavid du Colombier Ndbtuple *nt;
167795a264b3SDavid du Colombier String *s;
1678219b2ee8SDavid du Colombier
167995a264b3SDavid du Colombier s = s_new();
1680219b2ee8SDavid du Colombier for(nt = t; mf->nreply < Nreply && nt; nt = nt->entry){
168195a264b3SDavid du Colombier s_append(s, nt->attr);
168295a264b3SDavid du Colombier s_append(s, "=");
168395a264b3SDavid du Colombier s_append(s, nt->val);
168495a264b3SDavid du Colombier
168595a264b3SDavid du Colombier if(nt->line != nt->entry){
168695a264b3SDavid du Colombier mf->replylen[mf->nreply] = s_len(s);
168795a264b3SDavid du Colombier mf->reply[mf->nreply++] = strdup(s_to_c(s));
168895a264b3SDavid du Colombier s_restart(s);
1689219b2ee8SDavid du Colombier } else
169095a264b3SDavid du Colombier s_append(s, " ");
1691219b2ee8SDavid du Colombier }
169295a264b3SDavid du Colombier s_free(s);
1693219b2ee8SDavid du Colombier }
1694219b2ee8SDavid du Colombier
16957dd7cddfSDavid du Colombier enum
16967dd7cddfSDavid du Colombier {
16977dd7cddfSDavid du Colombier Maxattr= 32,
16987dd7cddfSDavid du Colombier };
16997dd7cddfSDavid du Colombier
1700219b2ee8SDavid du Colombier /*
17017dd7cddfSDavid du Colombier * generic query lookup. The query is of one of the following
17027dd7cddfSDavid du Colombier * forms:
17037dd7cddfSDavid du Colombier *
17047dd7cddfSDavid du Colombier * attr1=val1 attr2=val2 attr3=val3 ...
17057dd7cddfSDavid du Colombier *
17067dd7cddfSDavid du Colombier * returns the matching tuple
17077dd7cddfSDavid du Colombier *
17087dd7cddfSDavid du Colombier * ipinfo attr=val attr1 attr2 attr3 ...
17097dd7cddfSDavid du Colombier *
17107dd7cddfSDavid du Colombier * is like ipinfo and returns the attr{1-n}
17117dd7cddfSDavid du Colombier * associated with the ip address.
1712219b2ee8SDavid du Colombier */
1713219b2ee8SDavid du Colombier char*
genquery(Mfile * mf,char * query)1714219b2ee8SDavid du Colombier genquery(Mfile *mf, char *query)
1715219b2ee8SDavid du Colombier {
1716219b2ee8SDavid du Colombier int i, n;
1717219b2ee8SDavid du Colombier char *p;
17187dd7cddfSDavid du Colombier char *attr[Maxattr];
17197dd7cddfSDavid du Colombier char *val[Maxattr];
1720219b2ee8SDavid du Colombier Ndbtuple *t;
1721219b2ee8SDavid du Colombier Ndbs s;
1722219b2ee8SDavid du Colombier
1723b8b25780SDavid du Colombier n = getfields(query, attr, nelem(attr), 1, " ");
1724219b2ee8SDavid du Colombier if(n == 0)
1725219b2ee8SDavid du Colombier return "bad query";
1726219b2ee8SDavid du Colombier
17277dd7cddfSDavid du Colombier if(strcmp(attr[0], "ipinfo") == 0)
17287dd7cddfSDavid du Colombier return ipinfoquery(mf, attr, n);
17297dd7cddfSDavid du Colombier
1730219b2ee8SDavid du Colombier /* parse pairs */
1731219b2ee8SDavid du Colombier for(i = 0; i < n; i++){
1732219b2ee8SDavid du Colombier p = strchr(attr[i], '=');
1733219b2ee8SDavid du Colombier if(p == 0)
1734219b2ee8SDavid du Colombier return "bad query";
1735219b2ee8SDavid du Colombier *p++ = 0;
1736219b2ee8SDavid du Colombier val[i] = p;
1737219b2ee8SDavid du Colombier }
1738219b2ee8SDavid du Colombier
1739219b2ee8SDavid du Colombier /* give dns a chance */
1740219b2ee8SDavid du Colombier if((strcmp(attr[0], "dom") == 0 || strcmp(attr[0], "ip") == 0) && val[0]){
17417dd7cddfSDavid du Colombier t = dnsiplookup(val[0], &s);
1742219b2ee8SDavid du Colombier if(t){
1743219b2ee8SDavid du Colombier if(qmatch(t, attr, val, n)){
1744219b2ee8SDavid du Colombier qreply(mf, t);
1745219b2ee8SDavid du Colombier ndbfree(t);
1746219b2ee8SDavid du Colombier return 0;
1747219b2ee8SDavid du Colombier }
1748219b2ee8SDavid du Colombier ndbfree(t);
1749219b2ee8SDavid du Colombier }
1750219b2ee8SDavid du Colombier }
1751219b2ee8SDavid du Colombier
1752219b2ee8SDavid du Colombier /* first pair is always the key. It can't be a '*' */
1753219b2ee8SDavid du Colombier t = ndbsearch(db, &s, attr[0], val[0]);
1754219b2ee8SDavid du Colombier
1755219b2ee8SDavid du Colombier /* search is the and of all the pairs */
1756219b2ee8SDavid du Colombier while(t){
1757219b2ee8SDavid du Colombier if(qmatch(t, attr, val, n)){
1758219b2ee8SDavid du Colombier qreply(mf, t);
1759219b2ee8SDavid du Colombier ndbfree(t);
1760219b2ee8SDavid du Colombier return 0;
1761219b2ee8SDavid du Colombier }
1762219b2ee8SDavid du Colombier
1763219b2ee8SDavid du Colombier ndbfree(t);
1764219b2ee8SDavid du Colombier t = ndbsnext(&s, attr[0], val[0]);
1765219b2ee8SDavid du Colombier }
1766219b2ee8SDavid du Colombier
1767219b2ee8SDavid du Colombier return "no match";
1768219b2ee8SDavid du Colombier }
17697dd7cddfSDavid du Colombier
17707dd7cddfSDavid du Colombier /*
17717dd7cddfSDavid du Colombier * resolve an ip address
17727dd7cddfSDavid du Colombier */
17737dd7cddfSDavid du Colombier static Ndbtuple*
ipresolve(char * attr,char * host)17747dd7cddfSDavid du Colombier ipresolve(char *attr, char *host)
17757dd7cddfSDavid du Colombier {
17767dd7cddfSDavid du Colombier Ndbtuple *t, *nt, **l;
17777dd7cddfSDavid du Colombier
17787dd7cddfSDavid du Colombier t = iplookup(&network[Ntcp], host, "*", 0);
17797dd7cddfSDavid du Colombier for(l = &t; *l != nil; ){
17807dd7cddfSDavid du Colombier nt = *l;
17817dd7cddfSDavid du Colombier if(strcmp(nt->attr, "ip") != 0){
17827dd7cddfSDavid du Colombier *l = nt->entry;
17837dd7cddfSDavid du Colombier nt->entry = nil;
17847dd7cddfSDavid du Colombier ndbfree(nt);
17857dd7cddfSDavid du Colombier continue;
17867dd7cddfSDavid du Colombier }
17877dd7cddfSDavid du Colombier strcpy(nt->attr, attr);
17887dd7cddfSDavid du Colombier l = &nt->entry;
17897dd7cddfSDavid du Colombier }
17907dd7cddfSDavid du Colombier return t;
17917dd7cddfSDavid du Colombier }
17927dd7cddfSDavid du Colombier
17937dd7cddfSDavid du Colombier char*
ipinfoquery(Mfile * mf,char ** list,int n)17947dd7cddfSDavid du Colombier ipinfoquery(Mfile *mf, char **list, int n)
17957dd7cddfSDavid du Colombier {
17967dd7cddfSDavid du Colombier int i, nresolve;
17977dd7cddfSDavid du Colombier int resolve[Maxattr];
17987dd7cddfSDavid du Colombier Ndbtuple *t, *nt, **l;
17997dd7cddfSDavid du Colombier char *attr, *val;
18007dd7cddfSDavid du Colombier
18017dd7cddfSDavid du Colombier /* skip 'ipinfo' */
18027dd7cddfSDavid du Colombier list++; n--;
18037dd7cddfSDavid du Colombier
18048a2c5ad0SDavid du Colombier if(n < 1)
18057dd7cddfSDavid du Colombier return "bad query";
18067dd7cddfSDavid du Colombier
18078a2c5ad0SDavid du Colombier /* get search attribute=value, or assume ip=myipaddr */
18088a2c5ad0SDavid du Colombier attr = *list;
18098a2c5ad0SDavid du Colombier if((val = strchr(attr, '=')) != nil){
18107dd7cddfSDavid du Colombier *val++ = 0;
18118a2c5ad0SDavid du Colombier list++;
18128a2c5ad0SDavid du Colombier n--;
18138a2c5ad0SDavid du Colombier }else{
18148a2c5ad0SDavid du Colombier attr = "ip";
18158a2c5ad0SDavid du Colombier val = ipaddr;
18168a2c5ad0SDavid du Colombier }
18178a2c5ad0SDavid du Colombier
18188a2c5ad0SDavid du Colombier if(n < 1)
18198a2c5ad0SDavid du Colombier return "bad query";
18207dd7cddfSDavid du Colombier
18217dd7cddfSDavid du Colombier /*
18227dd7cddfSDavid du Colombier * don't let ndbipinfo resolve the addresses, we're
18237dd7cddfSDavid du Colombier * better at it.
18247dd7cddfSDavid du Colombier */
18257dd7cddfSDavid du Colombier nresolve = 0;
18267dd7cddfSDavid du Colombier for(i = 0; i < n; i++)
1827107aedb4SDavid du Colombier if(*list[i] == '@'){ /* @attr=val ? */
18287dd7cddfSDavid du Colombier list[i]++;
1829107aedb4SDavid du Colombier resolve[i] = 1; /* we'll resolve it */
18307dd7cddfSDavid du Colombier nresolve++;
18317dd7cddfSDavid du Colombier } else
18327dd7cddfSDavid du Colombier resolve[i] = 0;
18337dd7cddfSDavid du Colombier
18347dd7cddfSDavid du Colombier t = ndbipinfo(db, attr, val, list, n);
18357dd7cddfSDavid du Colombier if(t == nil)
18367dd7cddfSDavid du Colombier return "no match";
18377dd7cddfSDavid du Colombier
18387dd7cddfSDavid du Colombier if(nresolve != 0){
18397dd7cddfSDavid du Colombier for(l = &t; *l != nil;){
18407dd7cddfSDavid du Colombier nt = *l;
18417dd7cddfSDavid du Colombier
18427dd7cddfSDavid du Colombier /* already an address? */
18437dd7cddfSDavid du Colombier if(strcmp(ipattr(nt->val), "ip") == 0){
18447dd7cddfSDavid du Colombier l = &(*l)->entry;
18457dd7cddfSDavid du Colombier continue;
18467dd7cddfSDavid du Colombier }
18477dd7cddfSDavid du Colombier
18487dd7cddfSDavid du Colombier /* user wants it resolved? */
18497dd7cddfSDavid du Colombier for(i = 0; i < n; i++)
18507dd7cddfSDavid du Colombier if(strcmp(list[i], nt->attr) == 0)
18517dd7cddfSDavid du Colombier break;
18527dd7cddfSDavid du Colombier if(i >= n || resolve[i] == 0){
18537dd7cddfSDavid du Colombier l = &(*l)->entry;
18547dd7cddfSDavid du Colombier continue;
18557dd7cddfSDavid du Colombier }
18567dd7cddfSDavid du Colombier
18577dd7cddfSDavid du Colombier /* resolve address and replace entry */
18587dd7cddfSDavid du Colombier *l = ipresolve(nt->attr, nt->val);
18597dd7cddfSDavid du Colombier while(*l != nil)
18607dd7cddfSDavid du Colombier l = &(*l)->entry;
18617dd7cddfSDavid du Colombier *l = nt->entry;
18627dd7cddfSDavid du Colombier
18637dd7cddfSDavid du Colombier nt->entry = nil;
18647dd7cddfSDavid du Colombier ndbfree(nt);
18657dd7cddfSDavid du Colombier }
18667dd7cddfSDavid du Colombier }
18677dd7cddfSDavid du Colombier
18687dd7cddfSDavid du Colombier /* make it all one line */
18697dd7cddfSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry){
18707dd7cddfSDavid du Colombier if(nt->entry == nil)
18717dd7cddfSDavid du Colombier nt->line = t;
18727dd7cddfSDavid du Colombier else
18737dd7cddfSDavid du Colombier nt->line = nt->entry;
18747dd7cddfSDavid du Colombier }
18757dd7cddfSDavid du Colombier
18767dd7cddfSDavid du Colombier qreply(mf, t);
18777dd7cddfSDavid du Colombier
18787dd7cddfSDavid du Colombier return nil;
18797dd7cddfSDavid du Colombier }
18807dd7cddfSDavid du Colombier
18817dd7cddfSDavid du Colombier void*
emalloc(int size)18827dd7cddfSDavid du Colombier emalloc(int size)
18837dd7cddfSDavid du Colombier {
18847dd7cddfSDavid du Colombier void *x;
18857dd7cddfSDavid du Colombier
18867dd7cddfSDavid du Colombier x = malloc(size);
18877dd7cddfSDavid du Colombier if(x == nil)
18887dd7cddfSDavid du Colombier abort();
18897dd7cddfSDavid du Colombier memset(x, 0, size);
18907dd7cddfSDavid du Colombier return x;
18917dd7cddfSDavid du Colombier }
18929a747e4fSDavid du Colombier
18939a747e4fSDavid du Colombier char*
estrdup(char * s)18949a747e4fSDavid du Colombier estrdup(char *s)
18959a747e4fSDavid du Colombier {
18969a747e4fSDavid du Colombier int size;
18979a747e4fSDavid du Colombier char *p;
18989a747e4fSDavid du Colombier
18999a747e4fSDavid du Colombier size = strlen(s)+1;
19009a747e4fSDavid du Colombier p = malloc(size);
19019a747e4fSDavid du Colombier if(p == nil)
19029a747e4fSDavid du Colombier abort();
19039a747e4fSDavid du Colombier memmove(p, s, size);
19049a747e4fSDavid du Colombier return p;
19059a747e4fSDavid du Colombier }
1906