📄 listen.c
字号:
error(E_SYS_ERROR, EXIT | NO_MSG); case POLLOUT: logmessage("poll() returned POLLOUT"); error(E_SYS_ERROR, EXIT | NO_MSG); default: logmessage("poll() returned unrecognized event"); error(E_SYS_ERROR, EXIT | NO_MSG); } } }}/* * doevent: handle an asynchronous event */doevent(fhead, phead, fd)struct call_list *fhead;struct call_list *phead;int fd;{ register struct callsave *current; register struct t_call *call; char scratch[BUFSIZ]; DEBUG((9, "in doevent")); switch (t_look(fd)) { case 0: sys_error(E_POLL, EXIT); /* no return */ case T_LISTEN: current = dequeue(fhead); call = current->c_cp; if (t_listen(fd, call) < 0) { tli_error(E_T_LISTEN, CONTINUE); return; } queue(phead, current); sprintf(scratch, "Connect pending on fd %d, seq # %d", fd, call->sequence); logmessage(scratch); DEBUG((9, "incoming call seq # %d", call->sequence)); break; case T_DISCONNECT: if (t_rcvdis(fd, disc) < 0) { tli_error(E_T_RCVDIS, EXIT); /* no return */ } sprintf(scratch, "Disconnect on fd %d, seq # %d", fd, disc->sequence); logmessage(scratch); DEBUG((9, "incoming disconnect seq # %d", disc->sequence)); pitchcall(fhead, phead, disc); break; default: tli_error(E_T_LOOK, CONTINUE); break; }}/* * trycon: try to accept a connection */trycon(fhead, phead, fd)struct call_list *fhead;struct call_list *phead;int fd;{ register struct callsave *current; register struct t_call *call; int pid; char scratch[BUFSIZ]; DEBUG((9, "in trycon")); while (!EMPTY(phead)) { current = dequeue(phead); call = current->c_cp; DEBUG((9, "try to accept #%d", call->sequence)); close(0); SPLhi(); if ((Nfd3 = open_bind(NULL, 0, 0, (unsigned int *) 0)) != 0) { error(E_OPENBIND, CONTINUE); clr_call(call); queue(fhead, current); continue; /* let transport provider generate disconnect */ } SPLlo(); if (t_accept(fd, Nfd3, call) < 0) { if (t_errno == TLOOK) { t_close(Nfd3); SPLhi(); if (dup(1) != 0) logmessage("Trouble duping fd 0"); SPLlo(); logmessage("t_accept collision"); DEBUG((9, "save call #%d", call->sequence)); pqueue(phead, current); return; } else { t_close(Nfd3); SPLhi(); if (dup(1) != 0) logmessage("Trouble duping fd 0"); SPLlo(); tli_error(E_T_ACCEPT, CONTINUE); clr_call(call); queue(fhead, current); return; } } sprintf(scratch, "Accepted request on fd %d, seq # %d", Nfd3, call->sequence); logmessage(scratch); DEBUG((9, "Accepted call %d", call->sequence)); check_dbf(); if ((pid = fork()) < 0) log(E_FORK_SERVICE); else if (!pid) { startit(Nfd3, call, (fd == Nfd1 ? LOGIN : GEN)); /* no return */ } clr_call(call); t_close(Nfd3); queue(fhead, current); SPLhi(); if (dup(1) != 0) logmessage("Trouble duping fd 0"); SPLlo(); }}/* * startit: start up a server */startit(fd, call, servtype)int fd;struct t_call *call;int servtype;{ DEBUG((9, "in startit")); setpgrp(); Child = 1; if (servtype == LOGIN) login(fd, call); else process(fd, call);/* * if login() or process() returns, an error * was encountered. Errors should be logged * by the subroutines -- exit done here. * (Subroutines shouldn't care if they are * a parent/child/whatever.) * * NOTE: timeout() is an exception; * it does an exit. * There can be no TLI calls after this point. * (non-tli modules may have been pushed) * */ DEBUG((9, "return in startit"));#ifdef COREDUMP abort();#endif exit(1); /* server failed, don't log */}/* * process: process an accepted connection request * for ms-net or NLP service. */process(fd, call)register fd;struct t_call *call;{ register size; char buf[RCVBUFSZ]; char **argv; register char *bp = buf; register dbf_t *dbp; extern dbf_t *getdbfentry(); extern char **mkdbfargv(); DEBUG((9,"in process (NLPS/SMB message)")); if ((size = getrequest(fd, bp)) <= 0) { logmessage("process(): No/bad service request received"); return(-1); } if (size < MINMSGSZ) { DEBUG((7,"process(): msg size (%d) too small",size)); logmessage("process(): Message size too small"); return(-1); } /* * if message is NLPS protocol... */ if ((!strncmp(bp,NLPSIDSTR,NLPSIDSZ)) && /* NLPS request */ (*(bp + NLPSIDSZ) == NLPSSEPCHAR)) { nls_service(fd, bp, size, call); (void)sleep(10); /* if returned to here, then * must sleep for a short period of time to * insure that the client received any possible * exit response message from the listener. */ /* * else if message is for the MS-NET file server... */ } else if ( (*bp == (char)0xff) && (!strncmp(bp+1,SMBIDSTR,SMBIDSZ)) ) { if (dbp = getdbfentry(DBF_SMB_CODE)) if (dbp->dbf_flags & DBF_OFF) logmessage("SMB message, server disabled in data base"); else { argv = mkdbfargv(dbp); smbservice(fd, bp, size, call, argv); } else logmessage("SMB message, no data base entry"); /* * else, message type is unknown... */ } else { logmessage("Process(): Unknown service request (ignored)"); DEBUG((7,"msg size: %d; 1st four chars (hex) %x %x %x %x", *bp, *(bp+1), *(bp+2), *(bp+3))); } /* * the routines that start servers return only if there was an error * and will have logged their own errors. */ return(-1);}/* * getrequest: read in a full message. Timeout, in case the client died. * returns: -1 = timeout or other error. * positive number = message size. */intgetrequest(fd, bp)register fd;register char *bp;{ register size; register char *tmp = bp; int flags; extern void timeout(); extern unsigned alarm(); unsigned short cnt; DEBUG((9,"in getrequest")); signal(SIGALRM, timeout); (void)alarm(ALARMTIME); /* read in MINMSGSZ to determine type of msg */ if ((size = l_rcv(fd, bp, MINMSGSZ, &flags)) != MINMSGSZ) { DEBUG((9, "getrequest: l_rcv returned %d", size)); tli_error(E_RCV_MSG, CONTINUE); return(-1); } tmp += size; /* * if message is NLPS protocol... */ if ((!strncmp(bp,NLPSIDSTR,NLPSIDSZ)) && /* NLPS request */ (*(bp + NLPSIDSZ) == NLPSSEPCHAR)) { do { if (++size > RCVBUFSZ) { logmessage("Getrequest(): recieve buffer not large enough"); return(-1); } if (t_rcv(fd, tmp, sizeof(char), &flags) != sizeof(char)) { tli_error(E_RCV_MSG, CONTINUE); return(-1); } } while (*tmp++ != '\0'); /* * else if message is for the MS-NET file server... */ } else if ( (*bp == (char)0xff) && (!strncmp(bp+1,SMBIDSTR,SMBIDSZ)) ) { /* read in 28 more bytes to get count of paramter words */ if (l_rcv(fd, tmp, 28, &flags) != 28) { tli_error(E_RCV_MSG, CONTINUE); return(-1); } tmp += 28; size += 28; /* * read amount of paramater words plus word for * the number of data bytes to follow (2 bytes/word) */ cnt = (int)*(tmp - 1) * 2 + 2; if ((size += cnt) > RCVBUFSZ) { logmessage("Getrequest(): recieve buffer not large enough"); return(-1); } if (l_rcv(fd, tmp, cnt, &flags) != cnt) { tli_error(E_RCV_MSG, CONTINUE); return(-1); } tmp += cnt; getword(tmp - 2, &cnt); if ((size += cnt) > RCVBUFSZ) { logmessage("Getrequest(): recieve buffer not large enough"); return(-1); } if (l_rcv(fd, tmp, cnt, &flags) != cnt) { tli_error(E_RCV_MSG, CONTINUE); return(-1); } nullfix(fd); /* * else, message type is unknown... */ } else { logmessage("Getrequest(): Unknown service request (ignored)"); DEBUG((7,"msg size: %d; 1st four chars (hex) %x %x %x %x", *bp, *(bp+1), *(bp+2), *(bp+3))); return(-1); } (void)alarm(0); signal(SIGALRM, SIG_IGN); DEBUG((7,"t_rcv returned %d, flags: %x",size,flags)); return(size);}/* * The following code is for patching a 6300 side bug. The original * message that comes over may contain 2 null bytes which aren't * part of the message, and if left on the stream, will poison the * server. Peek into the stream and snarf up those bytes if they * are there. If anything goes wrong with the I_PEEK, just continue, * if the nulls weren't there, it'll work, and if they were, all that * will happen is that the server will fail. Just note what happened * in the log file. */nullfix(fd)int fd;{ struct strpeek peek; register struct strpeek *peekp; char scratch[BUFSIZ]; char junk[2]; int flags; int ret; peekp = &peek; peekp->flags = 0; /* need to ask for ctl info to avoid bug in I_PEEK code */ peekp->ctlbuf.maxlen = 1; peekp->ctlbuf.buf = junk; peekp->databuf.maxlen = 2; peekp->databuf.buf = junk; ret = ioctl(fd, I_PEEK, &peek); if (ret == -1) { sprintf(scratch, "nullfix(): unable to PEEK, errno is %d", errno); DEBUG((9, "nullfix(): I_PEEK failed, errno is %d", errno)); logmessage(scratch); } else if (ret == 0) { DEBUG((9, "nullfix(): no messages on stream to PEEK")); } else { if (peekp->databuf.len == 2) { /* Note: junk contains "peeked" data */ DEBUG((9, "peeked <%x> <%x>", junk[0], junk[1])); if ((junk[0] == 0) && (junk[1] == 0)) { /* pitch the nulls */ DEBUG((9, "pitching 2 nulls from first peek")); l_rcv(fd, junk, 2, &flags); } } /* * this represents a somewhat pathological case where * the "2 nulls" are broken across message boundaries. * Pitch the first and hope the next one is there */ else if (peekp->databuf.len == 1) { DEBUG((9, "peeked <%x>", junk[0])); if (junk[0] == 0) { /* pitch the first */ DEBUG((9, "split nulls, pitching first")); l_rcv(fd, junk, 1, &flags); peekp->databuf.maxlen = 1; ret = ioctl(fd, I_PEEK, &peek); if (ret == -1) { sprintf(scratch, "nullfix(): unable to PEEK second time, errno is %d", errno); DEBUG((9, "second peek failed, errno %d", errno)); logmessage(scratch); } else if (ret == 0) { DEBUG((9, "no messages for 2nd peek")); } else { if (peekp->databuf.len == 1) { DEBUG((9, "2nd peek <%x>", junk[0])); if (junk[0] == 0) { /* pitch the second */ DEBUG((9, "pitching 2nd single null")); l_rcv(fd, junk, 1, &flags); } else { /* uh oh, server will most likely fail */ DEBUG((9, "2nd null not found")); logmessage("nullfix(): threw away a valid null byte"); } } } } } }}/* * timeout: SIGALRM signal handler. Invoked if t_rcv timed out. * See comments about 'exit' in process(). */voidtimeout(){ DEBUG((9, "TIMEOUT")); error(E_RCV_TMO, EXIT | NOCORE);}/* * nls_service: Validate and start a server requested via the NLPS protocol * * version 0:1 -- expect "NLPS:000:001:service_code". * * returns only if there was an error (either msg format, or couldn't exec) */static char *badversion = "Unknown version of an NLPS service request: %d:%d";static char *disabledmsg = "Request for service code <%s> denied, service is disabled";static char *nlsunknown = "Request for service code <%s> denied, unknown service code";/* * Nlsversion can be used as a NLPS flag (< 0 == not nls service) * and when >= 0, indicates the version of the NLPS protocol used */static int Nlsversion = -1; /* protocol version */intnls_service(fd, bp, size, call)int fd, size;char *bp;struct t_call *call;{ int low, high; char svc_buf[64]; register char *svc_code_p = svc_buf; char scratch[256]; register dbf_t *dbp; extern dbf_t *getdbfentry(); extern char **mkdbfargv(); if (nls_chkmsg(bp, size, &low, &high, svc_code_p)) { if ((low == 0) || (low == 2)) Nlsversion = low; else { sprintf(scratch, badversion, low, high); logmessage(scratch); error(E_BAD_VERSION, CONTINUE); return(-1); } DEBUG((9,"nls_service: protocol version %d", Nlsversion)); /* * common code for protocol version 0 or 2 * version 0 allows no answerback message * version 2 allows exactly 1 answerback message */ if (dbp = getdbfentry(svc_code_p)) if (dbp->dbf_flags & DBF_OFF) { sprintf(scratch, disabledmsg, svc_code_p); logmessage(scratch); nls_reply(NLSDISABLED, scratch); } else start_server(fd, dbp, (char **)0, call); /* return is an error */ else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -