123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- /*
- * netbios dial, read, write
- */
- #include <u.h>
- #include <libc.h>
- #include <ctype.h>
- #include <fcall.h>
- #include <thread.h>
- #include <9p.h>
- #include "cifs.h"
- enum {
- MAXNBPKT = 8096, /* max netbios packet size */
- NBquery = 0, /* packet type - query */
- NBAdapterStatus = 0x21, /* get host interface info */
- NBInternet = 1, /* scope for info */
- NBmessage = 0x00, /* Netbios packet types */
- NBrequest = 0x81,
- NBpositive,
- NBnegative,
- NBretarget,
- NBkeepalive,
- ISgroup = 0x8000,
- };
- static char *NBerr[] = {
- [0] "not listening on called name",
- [1] "not listening for calling name",
- [2] "called name not present",
- [3] "insufficient resources",
- [15] "unspecified error"
- };
- static uint32_t
- GL32(uint8_t **p)
- {
- uint32_t n;
- n = *(*p)++;
- n |= *(*p)++ << 8;
- n |= *(*p)++ << 16;
- n |= *(*p)++ << 24;
- return n;
- }
- static uint16_t
- GL16(uint8_t **p)
- {
- uint16_t n;
- n = *(*p)++;
- n |= *(*p)++ << 8;
- return n;
- }
- void
- Gmem(uint8_t **p, void *v, int n)
- {
- uint8_t *str = v;
- while(n--)
- *str++ = *(*p)++;
- }
- static uint16_t
- GB16(uint8_t **p)
- {
- uint16_t n;
- n = *(*p)++ << 8;
- n |= *(*p)++;
- return n;
- }
- static uint8_t
- G8(uint8_t **p)
- {
- return *(*p)++;
- }
- static void
- PB16(uint8_t **p, uint n)
- {
- *(*p)++ = n >> 8;
- *(*p)++ = n;
- }
- static void
- P8(uint8_t **p, uint n)
- {
- *(*p)++ = n;
- }
- static void
- nbname(uint8_t **p, char *name, char pad)
- {
- char c;
- int i;
- int done = 0;
- *(*p)++ = 0x20;
- for(i = 0; i < 16; i++) {
- c = pad;
- if(!done && name[i] == '\0')
- done = 1;
- if(!done)
- c = toupper(name[i]);
- *(*p)++ = ((uint8_t)c >> 4) + 'A';
- *(*p)++ = (c & 0xf) + 'A';
- }
- *(*p)++ = 0;
- }
- int
- calledname(char *host, char *name)
- {
- char *addr;
- uint8_t buf[1024], *p;
- static char tmp[20];
- int num, flg, svs, j, i, fd, trn;
- trn = (getpid() ^ time(0)) & 0xffff;
- if((addr = netmkaddr(host, "udp", "137")) == nil)
- return -1;
- if((fd = dial(addr, "137", 0, 0)) < 0)
- return -1;
- p = buf;
- PB16(&p, trn); /* TRNid */
- P8(&p, 0); /* flags */
- P8(&p, 0x10); /* type */
- PB16(&p, 1); /* # questions */
- PB16(&p, 0); /* # answers */
- PB16(&p, 0); /* # authority RRs */
- PB16(&p, 0); /* # Aditional RRs */
- nbname(&p, "*", 0);
- PB16(&p, NBAdapterStatus);
- PB16(&p, NBInternet);
- if(Debug && strstr(Debug, "dump"))
- xd(nil, buf, p-buf);
- if(write(fd, buf, p-buf) != p-buf)
- return -1;
- p = buf;
- for(i = 0; i < 3; i++){
- memset(buf, 0, sizeof(buf));
- alarm(NBNSTOUT);
- read(fd, buf, sizeof(buf));
- alarm(0);
- if(GB16(&p) == trn)
- break;
- }
- close(fd);
- if(i >= 3)
- return -1;
- p = buf +56;
- num = G8(&p); /* number of names */
- for(i = 0; i < num; i++){
- memset(tmp, 0, sizeof(tmp));
- Gmem(&p, tmp, 15);
- svs = G8(&p);
- flg = GB16(&p);
- for(j = 14; j >= 0 && tmp[j] == ' '; j--)
- tmp[j] = 0;
- if(svs == 0 && !(flg & ISgroup))
- strcpy(name, tmp);
- }
- return 0;
- }
- int
- nbtdial(char *addr, char *called, char *sysname)
- {
- char redir[20];
- uint8_t *p, *lenp, buf[1024];
- int type, len, err, fd, nkeepalive, nretarg;
- nretarg = 0;
- nkeepalive = 0;
- Redial:
- if((addr = netmkaddr(addr, "tcp", "139")) == nil ||
- (fd = dial(addr, 0, 0, 0)) < 0)
- return -1;
- memset(buf, 0, sizeof(buf));
- p = buf;
- P8(&p, NBrequest); /* type */
- P8(&p, 0); /* flags */
- lenp = p; PB16(&p, 0); /* length placeholder */
- nbname(&p, called, ' '); /* remote NetBios name */
- nbname(&p, sysname, ' '); /* our machine name */
- PB16(&lenp, p-lenp -2); /* length re-write */
- if(Debug && strstr(Debug, "dump"))
- xd(nil, buf, p-buf);
- if(write(fd, buf, p-buf) != p-buf)
- goto Error;
- Reread:
- p = buf;
- memset(buf, 0, sizeof(buf));
- if(readn(fd, buf, 4) < 4)
- goto Error;
- type = G8(&p);
- G8(&p); /* flags */
- len = GB16(&p);
- if(readn(fd, buf +4, len -4) < len -4)
- goto Error;
- if(Debug && strstr(Debug, "dump"))
- xd(nil, buf, len+4);
- switch(type) {
- case NBpositive:
- return fd;
- case NBnegative:
- if(len < 1) {
- werrstr("nbdial: bad error pkt");
- goto Error;
- }
- err = G8(&p);
- if(err < 0 || err > nelem(NBerr) || NBerr[err] == nil)
- werrstr("NBT: %d - unknown error", err);
- else
- werrstr("NBT: %s", NBerr[err]);
- goto Error;
- case NBkeepalive:
- if(++nkeepalive >= 16){
- werrstr("nbdial: too many keepalives");
- goto Error;
- }
- goto Reread;
- case NBretarget:
- if(++nretarg >= 16) {
- werrstr("nbdial: too many redirects");
- goto Error;
- }
- if(len < 4) {
- werrstr("nbdial: bad redirect pkt");
- goto Error;
- }
- sprint(redir, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
- addr = redir;
- goto Redial;
- default:
- werrstr("nbdial: 0x%x - unknown packet in netbios handshake", type);
- goto Error;
- }
- Error:
- close(fd);
- return -1;
- }
- void
- nbthdr(Pkt *p)
- {
- p->pos = p->buf;
- memset(p->buf, 0xa5, MTU);
- p8(p, NBmessage); /* type */
- p8(p, 0); /* flags */
- pb16(p, 0); /* length (filled in later) */
- }
- int
- nbtrpc(Pkt *p)
- {
- int len, got, type, nkeep;
- len = p->pos - p->buf;
- p->pos = p->buf +2;
- pb16(p, len - NBHDRLEN); /* length */
- if(Debug && strstr(Debug, "dump"))
- xd("tx", p->buf, len);
- alarm(NBRPCTOUT);
- if(write(p->s->fd, p->buf, len) != len){
- werrstr("nbtrpc: write failed - %r");
- alarm(0);
- return -1;
- }
- nkeep = 0;
- retry:
- p->pos = p->buf;
- memset(p->buf, 0xa5, MTU);
- got = readn(p->s->fd, p->buf, NBHDRLEN);
- if(got < NBHDRLEN){
- werrstr("nbtrpc: short read - %r");
- alarm(0);
- return -1;
- }
- p->eop = p->buf + got;
- type = g8(p); /* NBT type (session) */
- if(type == NBkeepalive){
- if(++nkeep > 16) {
- werrstr("nbtrpc: too many keepalives (%d attempts)", nkeep);
- alarm(0);
- return -1;
- }
- goto retry;
- }
- g8(p); /* NBT flags (none) */
- len = gb16(p); /* NBT payload length */
- if((len +NBHDRLEN) > MTU){
- werrstr("nbtrpc: packet bigger than MTU, (%d > %d)", len, MTU);
- alarm(0);
- return -1;
- }
- got = readn(p->s->fd, p->buf +NBHDRLEN, len);
- alarm(0);
- if(Debug && strstr(Debug, "dump"))
- xd("rx", p->buf, got +NBHDRLEN);
- if(got < 0)
- return -1;
- p->eop = p->buf + got +NBHDRLEN;
- return got+NBHDRLEN;
- }
- void
- xd(char *str, void *buf, int n)
- {
- int fd, flg, flags2, cmd;
- uint sum;
- int32_t err;
- uint8_t *p, *end;
- if(n == 0)
- return;
- p = buf;
- end = (uint8_t *)buf +n;
- if(Debug && strstr(Debug, "log") != nil){
- if((fd = open("pkt.log", ORDWR)) == -1)
- return;
- seek(fd, 0, 2);
- fprint(fd, "%d ", 0);
- while(p < end)
- fprint(fd, "%02x ", *p++);
- fprint(fd, "\n");
- close(fd);
- return;
- }
- if(!str)
- goto Raw;
- p = (uint8_t *)buf + 4;
- if(GL32(&p) == 0x424d53ff){
- buf = (uint8_t *)buf + 4;
- n -= 4;
- }
- end = (uint8_t *)buf + n;
- sum = 0;
- p = buf;
- while(p < end)
- sum += *p++;
- p = buf;
- fprint(2, "%s : len=%ud sum=%d\n", str, n, sum);
- fprint(2, "mag=0x%ulx ", GL32(&p));
- fprint(2, "cmd=0x%ux ", cmd = G8(&p));
- fprint(2, "err=0x%ulx ", err=GL32(&p));
- fprint(2, "flg=0x%02ux ", flg = G8(&p));
- fprint(2, "flg2=0x%04ux\n", flags2= GL16(&p));
- fprint(2, "dfs=%s\n", (flags2 & FL2_DFS)? "y": "n");
- fprint(2, "pidl=%ud ", GL16(&p));
- fprint(2, "res=%uld ", GL32(&p));
- fprint(2, "sid=%ud ", GL16(&p));
- fprint(2, "seq=0x%ux ", GL16(&p));
- fprint(2, "pad=%ud ", GL16(&p));
- fprint(2, "tid=%ud ", GL16(&p));
- fprint(2, "pid=%ud ", GL16(&p));
- fprint(2, "uid=%ud ", GL16(&p));
- fprint(2, "mid=%ud\n", GL16(&p));
- if(cmd == 0x32 && (flg & 0x80) == 0){ /* TRANS 2, TX */
- fprint(2, "words=%ud ", G8(&p));
- fprint(2, "totparams=%ud ", GL16(&p));
- fprint(2, "totdata=%ud ", GL16(&p));
- fprint(2, "maxparam=%ud ", GL16(&p));
- fprint(2, "maxdata=%ud\n", GL16(&p));
- fprint(2, "maxsetup=%ud ", G8(&p));
- fprint(2, "reserved=%ud ", G8(&p));
- fprint(2, "flags=%ud ", GL16(&p));
- fprint(2, "timeout=%uld\n", GL32(&p));
- fprint(2, "reserved=%ud ", GL16(&p));
- fprint(2, "paramcnt=%ud ", GL16(&p));
- fprint(2, "paramoff=%ud ", GL16(&p));
- fprint(2, "datacnt=%ud ", GL16(&p));
- fprint(2, "dataoff=%ud ", GL16(&p));
- fprint(2, "setupcnt=%ud ", G8(&p));
- fprint(2, "reserved=%ud\n", G8(&p));
- fprint(2, "trans2=0x%02x ", GL16(&p));
- fprint(2, "data-words=%d ", G8(&p));
- fprint(2, "padding=%d\n", G8(&p));
- }
- if(cmd == 0x32 && (flg & 0x80) == 0x80){ /* TRANS 2, RX */
- fprint(2, "words=%ud ", G8(&p));
- fprint(2, "totparams=%ud ", GL16(&p));
- fprint(2, "totdata=%ud ", GL16(&p));
- fprint(2, "reserved=%ud ", GL16(&p));
- fprint(2, "paramcnt=%ud\n", GL16(&p));
- fprint(2, "paramoff=%ud ", GL16(&p));
- fprint(2, "paramdisp=%ud ", GL16(&p));
- fprint(2, "datacnt=%ud\n", GL16(&p));
- fprint(2, "dataoff=%ud ", GL16(&p));
- fprint(2, "datadisp=%ud ", GL16(&p));
- fprint(2, "setupcnt=%ud ", G8(&p));
- fprint(2, "reserved=%ud\n", G8(&p));
- }
- if(err)
- if(flags2 & FL2_NT_ERRCODES)
- fprint(2, "err=%s\n", nterrstr(err));
- else
- fprint(2, "err=%s\n", doserrstr(err));
- Raw:
- fprint(2, "\n");
- for(; p < end; p++){
- if((p - (uint8_t *)buf) % 16 == 0)
- fprint(2, "\n%06lx\t", p - (uint8_t *)buf);
- if(isprint((char)*p))
- fprint(2, "%c ", (char )*p);
- else
- fprint(2, "%02ux ", *p);
- }
- fprint(2, "\n");
- }
|