]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/ip/cifsd/main.c
socksd: setnetmtpt
[plan9front.git] / sys / src / cmd / ip / cifsd / main.c
1 #include <u.h>
2 #include <libc.h>
3 #include "dat.h"
4 #include "fns.h"
5
6 enum {
7         LENHDR = 4,
8
9         MAGIC = 0xFF | ('S'<<8) | ('M'<<16) | ('B'<<24),
10
11         SMB_FLAGS_CASE_INSENSITIVE = 0x08,
12         SMB_FLAGS_CANONICALIZED_PATHS = 0x10,
13         SMB_FLAGS_REPLY = 0x80,
14
15         NOCASEMASK = SMB_FLAGS_CASE_INSENSITIVE | SMB_FLAGS_CANONICALIZED_PATHS,
16
17         SMB_FLAGS2_LONG_NAMES = 0x0001,
18         SMB_FLAGS2_EAS = 0x0002,
19         SMB_FLAGS2_IS_LONG_NAME = 0x0040,
20         SMB_FLAGS2_NT_STATUS = 0x4000,
21         SMB_FLAGS2_UNICODE = 0x8000,
22 };
23
24 static int casesensitive = 0;
25
26 static void
27 respond(Req *r, int err)
28 {
29         int n, flags, flags2;
30
31         if(err && !(r->flags2 & SMB_FLAGS2_NT_STATUS))
32                 err = doserror(err);
33         flags = (r->flags & (r->namecmp != strcmp ? NOCASEMASK : 0)) |
34                 SMB_FLAGS_REPLY;
35         flags2 = (r->flags2 & (SMB_FLAGS2_NT_STATUS | 
36                 SMB_FLAGS2_LONG_NAMES | SMB_FLAGS2_UNICODE)) | 
37                 SMB_FLAGS2_IS_LONG_NAME;
38         if(r->cmd != 0x73) /* SMB_COM_SESSION_SETUP_ANDX */
39                 memset(r->sig, 0, sizeof(r->sig));
40         n = pack(r->rh, r->rh, r->rh+32, "lblbww[]__wwww",
41                 MAGIC, r->cmd, err, flags,  flags2, r->pid>>16, r->sig, r->sig+sizeof(r->sig),
42                 r->tid, r->pid & 0xFFFF, r->uid, r->mid);
43         if(err){
44                 r->rp = r->rh+n;
45                 r->rp += pack(r->rh, r->rp, r->re, "#0b{*2}#1w{}");
46         }
47         if(debug > 1)
48                 dumphex("respond", r->rh, r->rp);
49         if(debug)
50                 fprint(2, "respond: err=%x\n\n", err);
51         n = r->rp - r->rh;
52         r->lh[0] = 0;
53         r->lh[1] = 0;
54         r->lh[2] = n>>8 & 0xFF;
55         r->lh[3] = n & 0xFF;
56         write(1, r->lh, LENHDR+n);
57 }
58
59 static void
60 receive(uchar *h, uchar *e)
61 {
62         static uchar buffer[LENHDR + BUFFERSIZE];
63         static Rop rop8 = {
64                 .strpack = smbstrpack8,
65                 .strunpack = smbstrunpack8,
66                 .namepack = smbnamepack8,
67                 .nameunpack = smbnameunpack8,
68                 .untermstrpack = smbuntermstrpack8,
69                 .untermnamepack = smbuntermnamepack8,
70         }, rop16 = {
71                 .strpack = smbstrpack16,
72                 .strunpack = smbstrunpack16,
73                 .namepack = smbnamepack16,
74                 .nameunpack = smbnameunpack16,
75                 .untermstrpack = smbuntermstrpack16,
76                 .untermnamepack = smbuntermnamepack16,
77         };
78
79         uchar *sig;
80         int n, hpid, magic;
81         Req r;
82
83         if(debug > 1)
84                 dumphex("receive", h, e);
85         if((n = unpack(h, h, e, "lb____bww{.________}__wwww", &magic,
86                 &r.cmd, &r.flags, &r.flags2, &hpid, &sig, &r.tid, &r.pid, &r.uid, &r.mid)) == 0){
87                 logit("bad smb header");
88                 return;
89         }
90         if(magic != MAGIC){
91                 logit("bad smb magic");
92                 return;
93         }
94         r.pid |= hpid<<16;
95         r.lh = buffer;
96         r.rh = r.lh + LENHDR;
97         r.rp = r.rh + n;
98         r.re = r.rh + remotebuffersize;
99         r.o = (r.flags2 & SMB_FLAGS2_UNICODE) ? &rop16 : &rop8;
100         memmove(r.sig, sig, sizeof(r.sig));
101         r.name = nil;
102         r.respond = respond;
103         r.namecmp = ((r.flags & NOCASEMASK) && !casesensitive) ? cistrcmp : strcmp;
104         smbcmd(&r, r.cmd, h, h+n, e);
105 }
106
107 static void
108 serve(void)
109 {
110         static uchar buffer[LENHDR + BUFFERSIZE];
111         uchar *m, *me;
112         uchar *p, *pe;
113         uchar *hl;
114         int n;
115
116         p = hl = buffer;
117         pe = p + LENHDR+BUFFERSIZE;
118
119         for(;;){
120                 n = read(0, p, pe - p);
121                 if(n <= 0)
122                         break;
123                 p += n;
124 Next:
125                 if(p - hl < LENHDR)
126                         continue;
127                 n = hl[2]<<8 | hl[3];
128                 m = hl + LENHDR;
129                 me = m + n;
130                 if(me > pe){
131                         logit("message too big");
132                         break;
133                 }
134                 if(me > p)
135                         continue;
136                 receive(m, me);
137                 n = p - me;
138                 p = hl + n;
139                 if(n > 0){
140                         memmove(hl, me, n);
141                         goto Next;
142                 }
143         }
144 }
145
146 void
147 main(int argc, char *argv[])
148 {
149         static struct {
150                 char *s;
151                 int *v;
152         } opts[] = {
153                 { "trspaces", &trspaces },
154                 { "casesensitive", &casesensitive },
155                 { nil, nil }
156         }, *o;
157
158         char *log, *opt;
159         Tm *tm;
160         int pid;
161
162         debug = 0;
163         trspaces = 0;
164         needauth = 1;
165         domain = "WORKGROUP";
166         progname = "cifsd";
167         osname = "Plan 9";
168         log = nil;
169
170         ARGBEGIN {
171         case 't':
172                 needauth = 0;
173                 break;
174         case 'd':
175                 debug++;
176                 break;
177         case 'f':
178                 log = EARGF(exits("bad arg"));
179                 break;
180         case 'w':
181                 domain = EARGF(exits("bad arg"));
182                 break;
183         case 'o':
184                 opt = EARGF(exits("bad arg"));
185                 for(o=opts; o->s; o++)
186                         if(strcmp(opt, o->s) == 0){
187                                 *o->v = 1;
188                                 break;
189                         }
190                 if(o->s == nil)
191                         exits("bad arg");
192                 break;
193         } ARGEND
194
195         close(2);
196         if(!log || open(log, OWRITE) < 0){
197                 open("/dev/null", OWRITE);
198                 debug = 0;
199         }
200
201         remotesys = argc ? getremote(argv[argc-1]) : nil;
202         remoteuser = nil;
203         remotebuffersize = BUFFERSIZE;
204         starttime = time(nil);
205         pid = getpid();
206         srand(starttime ^ pid);
207         tm = localtime(starttime);
208         tzoff = tm->tzoff;
209
210         logit("started [%d]", pid);
211         serve();
212         logoff();
213         logit("exited [%d]", pid);
214 }