forward.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:23k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. /* Some of the code in this file was originally based on the following file:
  2.  * gateway.c : Paul Healy, EI9GL, 900818
  3.  *
  4.  * Rewrote forwarding mechanism to use "X-Forwarded-To" paradigm instead of
  5.  * "X-BBS-To", added timer support, etc.  Anders Klemets, SM0RGV, 901009.
  6.  */
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <ctype.h>
  10. #include <time.h>
  11. #include "global.h"
  12. #include "config.h"
  13. #include "bm.h"
  14. #include "mailbox.h"
  15. #include "smtp.h"
  16. #include "cmdparse.h"
  17. #include "proc.h"
  18. #include "socket.h"
  19. #include "timer.h"
  20. #include "usock.h"
  21. #include "netuser.h"
  22. #include "ax25.h"
  23. #include "netrom.h"
  24. #include "nr4.h"
  25. #include "files.h"
  26. #define ISPROMPT(s) (strlen(s) > 1 && s[strlen(s)-2] == '>')
  27. static struct timer fwdtimer;
  28. static char *findident(char *str, int n, char *result);
  29. static void sendmsg(struct mbx *m,int msgn);
  30. static char *mbxtime(char *line);
  31. static int fwdinit(struct mbx *m);
  32. static char *fwdanybbs(struct mbx *m);
  33. static int timeok(char *line);
  34. static void fwdtick(void *v);
  35. static int isconnbbs(struct mbx *m);
  36. static void startfwd(int a,void *v1,void *v2);
  37. static int openconn(int argc,char *argv[],void *p);
  38. static int sendmsgtobbs(struct mbx *m,int msgn,char *dest,int bulletin);
  39. static int makecl(struct mbx *m,int msgn,char *dest,char *line,char *subj,int bulletin);
  40. static char *grabtext(char *from,char *to,int marker);
  41. /***************************************************************************
  42.    findident copies the 'n'th alphanumeric sequence from 'str' to result.
  43.    It returns a ptr to result. It returns "" for missing identifier etc.
  44.    Uses isalnum macro to decide on alphanumeric/non-alnum status.
  45. */
  46. static char *
  47. findident(str, n, result)
  48. char *str, *result;
  49. int n;
  50. {
  51.    int count; /* current identifier */
  52.    count = 0;
  53.    *result = '';
  54.    while ( (count<n) && (*str!='') ) { /* Process alnum or non alnum seq */
  55.       while ( (*str!='') && (!isalnum(*str)) ) /* Get rid of ';:.@%"# etc */
  56.          str++;
  57.       if ( (str!='') && isalnum(*str) ) { /* this is an alnum seq */
  58.          count++;
  59.          while ( (*str!='') && (isalnum(*str) || (*str=='_')) )
  60.             if (count==n)
  61.                *result++ = *str++;
  62.             else str++;
  63.          if (count==n)
  64.             *result = '';
  65.          }
  66.       }
  67.    return result;
  68. }
  69. /**************************************************************************/
  70. static void
  71. sendmsg(m,msgn)
  72. struct mbx *m;
  73. int msgn;
  74. {
  75. char buf[LINELEN], tb[LINELEN], *cp;
  76. int len, rec = 0;
  77. long cnt;
  78. fseek(m->mfile,m->mbox[msgn].start,0);
  79. cnt = m->mbox[msgn].size;
  80. /* If the data part of the message starts with "R:" the RFC-822
  81.  * headers will not be forwarded. Instead we will add an R:
  82.  * line of our own.
  83.  */
  84. for(;;) {
  85. if(fgets(buf,sizeof(buf),m->mfile) == NULL)
  86. break;
  87. cnt -= strlen(buf);
  88. if(rec == 1) { /* look at the line following Received: */
  89.      ++rec;
  90.      if((cp = strchr(buf,';')) != NULL){
  91.   strcpy(tb,cp+1);  /* get the date of receipt */
  92.   ++rec;
  93.      }
  94. }
  95. /* The first Received: line is the one that we have added */
  96. if(!rec && htype(buf) == RECEIVED)
  97.      ++rec;
  98. if(*buf == 'n') {
  99.      if(rec == 3 && cnt > 1) {
  100.   fread(buf,1,2,m->mfile);
  101.   cnt -= 2;
  102.   if(strncmp(buf,"R:",2) == 0) {
  103.        pax25(buf,Mycall);
  104.        if((cp = strchr(buf,'-')) != NULL)
  105.     *cp = ''; /* remove SSID */
  106.        fprintf(m->user,"R:%s @%s %s (%s)nR:",
  107. mbxtime(tb),buf,Hostname,Version);
  108.        break;
  109.   }
  110.      }
  111.      /* Start over, forwarding the RFC-822 headers */
  112.      fseek(m->mfile,m->mbox[msgn].start,0);
  113.      cnt = m->mbox[msgn].size;
  114.      rec = 0;
  115.      break;
  116. }
  117.    }
  118. while(rec != 3) { /* Forward the RFC-822 headers */
  119. if(fgets(buf,sizeof(buf),m->mfile) == NULL)
  120. break;
  121. cnt -= strlen(buf);
  122. switch(htype(buf)) {
  123. case XFORWARD: /* Do not forward the "X-Forwarded-To:" lines */
  124. case STATUS:   /* Don't forward the "Status:" line either */
  125.      break;
  126. default:
  127.      fputs(buf,m->user);
  128. }
  129. if(*buf == 'n') /* last header line */
  130. break;
  131. }
  132. do { /* the rest of the message is treated below */
  133. len = min(cnt,sizeof(buf)-1);
  134. if(fread(buf,1,len,m->mfile) != len)
  135. break;
  136. cnt -= len;
  137. buf[len] = '';
  138. fputs(buf,m->user);
  139. } while(cnt);
  140. }
  141. /* Parse a line for date and time in Arpanet format
  142.  * (Day, day Month year hh:mm:ss Zone) and return it in mailbox format
  143.  * (yymmdd/hhmmz)
  144.  */
  145. static char *
  146. mbxtime(line)
  147. char *line;
  148. {
  149.      extern char *Months[];
  150.      static char buf[13];
  151.      char *cp;
  152.      int i, day;
  153.      cp = line;
  154.      while(isspace(*cp)) /* skip initial blanks */
  155.   ++cp;
  156.      if(*cp == '')
  157.   return NULL;
  158.      if(strlen(cp) < 22)
  159.   return NULL;
  160.      cp += 5;
  161.      day = atoi(cp);
  162.      if(*(++cp) != ' ')
  163.   ++cp;
  164.      ++cp;
  165.      for(i=0; i < 12; ++i)
  166.   if(strnicmp(Months[i],cp,3) == 0)
  167.        break;
  168.      if(i == 12)
  169.   return NULL;
  170.      sprintf(buf,"%02d%02d%02d/%02d%02d%c",atoi(cp + 4),i+1,day,atoi(cp + 7),
  171.      atoi(cp + 10), (strnicmp(cp + 16,"GMT",3) &&
  172.      strnicmp(cp + 16,"UTC",3)) ? ' ' : 'z');
  173.      return buf;
  174. }
  175.      
  176. static char *
  177. grabtext(from, to, marker)
  178. char *from, *to;
  179. int marker;
  180. {
  181.    while (*from!=marker)
  182.       *to++ = *from++;
  183.    *to = '';
  184.    return from+1;
  185. }
  186. /* Makes a command line and returns -1 if the message cannot be sent. */
  187. static int
  188. makecl(m, msgn, dest, line, subj, bulletin)
  189. struct mbx *m;
  190. int msgn; /* Message number */
  191. char *dest; /* Destination address to use instead of To: line */
  192. char *line, *subj; /* Buffers to keep command line and subject */
  193. int bulletin; /* True if message is in public message area */
  194. {
  195.    char bid[LINELEN], to[LINELEN], atbbs[LINELEN], from[LINELEN],
  196. buf[LINELEN], *cp;
  197.    if(m->mfile == NULL)
  198. return -1;
  199.    if(!bulletin && (m->mbox[msgn].status & BM_READ))
  200. return -1; /* the message was already read */
  201.    fseek(m->mfile,m->mbox[msgn].start,0);
  202.    *bid = *to = *atbbs = *from = '';
  203.    if(subj != NULL)
  204. *subj = '';
  205.    m->stype = bulletin ? 'B' : 'P'; /* default to SB or SP */
  206.    while (fgets(buf,sizeof(buf),m->mfile) != NULL) {
  207.       if (buf[0] == 'n')
  208.          break; /* envelope finished */
  209.       switch (htype(buf)) {
  210.       case TO:
  211.     /* The following code tries to parse "To: " lines where the
  212.      * address looks like any of the following: "to@atbbs",
  213.      * "<to@atbbs>", "<to%atbbs@host>" and with possible spaces
  214.      * surrounding the '<>' characters.
  215.      */
  216.     if((cp = getaddress(buf,0)) == NULL)
  217. break;
  218.     strcpy(to,cp);
  219.     if((cp = strchr(to,'%')) != NULL) { /* look for a '%' */
  220.  strcpy(atbbs,cp + 1);
  221.  *cp = ''; /* "to" ends at the '%' character */
  222.     }
  223.     else { /* no '%' but maybe a '@'? */
  224.  if((cp = strchr(to,'@')) != NULL) {
  225.       strcpy(atbbs,cp + 1);
  226.       *cp = ''; /* "to" ends at the '@' character */
  227.  }
  228.     }
  229.     if(*atbbs != '') /* either '%' or '@' found */
  230.  /* cut "atbbs" at the first '@' character */
  231.  for(cp = atbbs; *cp != ''; ++cp)
  232.       if(*cp == '@') {
  233.    *cp = '';
  234.    break;
  235.       }
  236.     /* "to" or "atbbs" should not be more than 6 characters (ALEN).
  237.      * If "to" is too long, it might simply be because the area name
  238.      * is longer than 6 characters, but it might also be because
  239.      * the address on the To: line is in an obscure format that we
  240.      * failed to parse (eg '!' character notation.)
  241.      */
  242.     if(strlen(to) > ALEN) {
  243. /* Play safe and set "to" and "atbbs" to the area name */
  244. strcpy(to,m->area);
  245. strcpy(atbbs,m->area);
  246.            }
  247.     if(*atbbs == '')
  248. strcpy(atbbs,to);
  249.            to[ALEN] = '';
  250.     /* Only if the BBS supports "hierarchical routing designators"
  251.      * is the atbbs field allowd to be longer than 6 characters and
  252.      * have dots in it.
  253.      */
  254.     if((m->sid & MBX_HIER_SID) == 0) {
  255.  atbbs[ALEN] = ''; /* 6 character limit */
  256.  if((cp = strchr(atbbs,'.')) != NULL)
  257.       *cp = ''; /* cut "atbbs" at first dot */
  258.     }
  259.             break;
  260.       case MSGID:
  261.     /* The following code distinguishes between two different types
  262.      * of Message-IDs: <abcde@callsign.bbs> and <abcde@host.domain>.
  263.      * The first type is converted to $abcde and the second to
  264.      * $abcde_host.domain. This preserves compability with BBSes.
  265.      */
  266.     if((cp = getname(buf)) == NULL)
  267.  break;
  268.     bid[0] = '$';
  269.     strcpy(&bid[1],cp);
  270.            cp = strchr(bid,'@');
  271.     /* A trailing ".bbs" indicates that the Message-ID was generated
  272.      * from a BBS style message, and not a RFC-822 message.
  273.      */
  274.     if(cp != NULL && stricmp(&bid[strlen(bid) - 4], ".bbs") == 0)
  275. *cp = '';
  276.     else
  277. *cp = '_';
  278.     bid[13] = ''; /* BIDs should be no longer than 13 bytes */
  279.            break;
  280.       case SUBJECT:
  281.     if(subj != NULL)
  282.        (void) grabtext(buf+9, subj, 'n');
  283.             break;
  284.       case FROM:
  285.     if((cp = getaddress(buf,0)) != NULL) {
  286. findident(cp, 1, from); /* cp points to from@domain */
  287. from[ALEN] = ''; /* 6 character limit */
  288.     }
  289.             break;
  290.       case XFORWARD:
  291.     if((cp = getaddress(buf,0)) == NULL)
  292.  break;
  293.     if(stricmp(m->name,cp) == 0)
  294. /* This message has already been forwarded, abort */
  295. return -1;
  296.     break;
  297.       case BBSTYPE:
  298.     m->stype = buf[16];
  299.     break;
  300.       default:
  301.     break;
  302.       }
  303.    }
  304.    /* Check for an invalid RFC-822 header */
  305.    if((to[0] == '' && ((dest != NULL && *dest == '') ||
  306.       dest == NULL)) || from[0] == '')
  307. return -1;
  308.    if(line != NULL) {
  309. if(dest != NULL && *dest != ''){
  310.      /* strip off hierarchical routing designators from the predefined
  311.       * destination address if they are not supported
  312.       */
  313.      if((m->sid & MBX_HIER_SID) == 0 && (cp = strchr(dest,'.')) !=
  314.        NULL)
  315. *cp = '';
  316.      sprintf(line, "S%c %s < %s ", m->stype, dest, from);
  317. }
  318. else
  319.      sprintf(line, "S%c %s @ %s < %s ", m->stype, to, atbbs, from);
  320. if(bulletin & (m->sid & MBX_SID))
  321.      strcat(line,bid);
  322. strcat(line,"n");
  323.    }
  324.    return 0;
  325. }
  326. static int /* 0 = ok, -1 = problem so disc */
  327. sendmsgtobbs(m, msgn, dest, bulletin)
  328. struct mbx *m;
  329. int msgn;
  330. char *dest; /* Optional destination address to override To: line */
  331. int bulletin;
  332. {
  333.    int result = -1;
  334.    char line[64], subj[256];
  335.    if(makecl(m, msgn, dest, line, subj, bulletin) == -1)
  336. return 0; /* do not forward this particular message */
  337.    fputs(line,stdout);  /* Send mail offer to bbs */
  338.    rip(line);
  339.    fflush(m->user);
  340.    if (fgets(m->line, MBXLINE,m->user) != NULL ) {
  341.       if (m->line[0] == 'O' || m->line[0] == 'o' || (m->sid & MBX_SID) == 0) {
  342.  /* Got 'OK' or any line if the bbs is unsofisticated */
  343.          printf("%sn", subj);
  344.  sendmsg(m,msgn); /* send the message */
  345.          puts("/EX"); /* was 0x1a */
  346.          fflush(m->user);
  347.         /* get F> for a good deliver */
  348.         while (fgets(m->line, MBXLINE,m->user) != NULL )
  349. if (ISPROMPT(m->line)) {
  350. logmsg(fileno(m->user),"MBOX bbs mail sent: %s ", line);
  351. if(bulletin)
  352. m->mbox[msgn].status |= BM_FORWARDED;
  353. else
  354. m->mbox[msgn].status |= BM_DELETE;
  355. m->change = 1;
  356. result = 0;
  357. break;
  358. }
  359.       }
  360.       else { /* OK response not received from bbs */
  361.    if (m->line[0] == 'N' || m->line[0] == 'n') { /* 'NO' respone */
  362.            logmsg(fileno(m->user),"MBOX bbs mail refused: %sn     %s",line,m->line);
  363. /* Mark refused message as forwarded if it is a bulletin.
  364.  * The message was probably a duplicate. Non-bulletin
  365.  * messages are sent without BID, so they cannot be dected
  366.  * as duplicates. The reason why it was refused is probably
  367.  * because the address was invalid. Retry later.
  368.  */
  369. if(bulletin){
  370. m->mbox[msgn].status |= BM_FORWARDED;
  371. m->change = 1;
  372. }
  373.           }
  374.          /* should get a F> here */
  375.           while (fgets(m->line, MBXLINE,m->user) != NULL )
  376.        if (ISPROMPT(m->line)) {
  377.        result = 0;
  378. break;
  379.        }
  380.       }
  381.    } /* OK or NO here */
  382.    return result;
  383. }
  384. /* This is the main entry point for reverse forwarding. It is also used
  385.  * for normal, "forward", forwarding.
  386.  */
  387. int
  388. dorevfwd(argc,argv,p)
  389. int argc;
  390. char *argv[];
  391. void *p;
  392. {
  393. char oldarea[64], *cp;
  394. struct mbx *m;
  395. int i, bulletin, err = 0;
  396. m = (struct mbx *)p;
  397. logmsg(fileno(m->user),"MBOX forwarding mail to: %s ", m->name);
  398. /* indicate we are doing reverse forwarding, if we are not already
  399.  * doing normal forwarding.
  400.  */
  401. if(m->state != MBX_FORWARD)
  402. m->state = MBX_REVFWD;
  403. if(fwdinit(m) != -1) {
  404. strcpy(oldarea,m->area);
  405. while(!err && fgets(m->line,MBXLINE,m->tfile) != NULL) {
  406. if(*m->line == '-') /* end of record reached */
  407. break;
  408. rip(m->line); /* adds extra null at end */
  409. cp = strchr(m->line,' '); /* remove trailing blanks */
  410. if(cp != NULL)
  411. *cp = '';
  412. if((cp = strchr(m->line,'t')) != NULL)
  413. *cp = '';
  414. if(*m->line == '' || *m->line == '.')
  415. continue;
  416. changearea(m,m->line);
  417. bulletin = isarea(m->line); /* public area */
  418. /* get the optional destination field, cp will point
  419.  * at null byte if it is missing.
  420.  */
  421. cp = &m->line[strlen(m->line)] + 1;
  422. while(*cp != '' && isspace(*cp)) /* strip blanks */
  423.      ++cp;
  424. for(i=1; i<=m->nmsgs; i++)
  425. if(sendmsgtobbs(m, i, cp, bulletin) == -1) {
  426. err = 1; /* abort */
  427. break;
  428. }
  429. }
  430. fclose(m->tfile);
  431. m->tfile = NULL;
  432. if(*oldarea != '')
  433. changearea(m,oldarea);
  434. }
  435. if(m->state == MBX_FORWARD)
  436. return 0;
  437. printf("*** Donen");
  438. if((m->sid & MBX_RLI_SID)) /* disconnect if it is a W0RLI bbs */
  439. return domboxbye(0,NULL,m);
  440. return 0;
  441. }
  442. /* Read the forward file for a record for the connected BBS. If found,
  443.  * return 1 if this is the right time to forward, m->tfile is left pointing
  444.  * at the first message area to be forwarded.
  445.  */
  446. static int
  447. fwdinit(m)
  448. struct mbx *m;
  449. {
  450. char host[80];
  451. int start = 1;
  452. if((m->tfile = fopen(Forwardfile,READ_TEXT)) == NULL)
  453. return -1;
  454. while(fgets(m->line,MBXLINE,m->tfile) != NULL) {
  455. if(*m->line == 'n')
  456. continue;
  457. /* lines starting with '-' separate the forwarding records */
  458. if(*m->line == '-') {
  459. start = 1;
  460. continue;
  461. }
  462. if(start) {
  463. start = 0;
  464. /* get the name of this forwarding record */
  465. findident(m->line,1,host);
  466. if(stricmp(m->name,host) == 0) {
  467. if(!timeok(m->line))
  468. break;
  469. /* eat the connect command line */
  470. fgets(m->line,MBXLINE,m->tfile);
  471. return 0;
  472. }
  473. }
  474. }
  475. fclose(m->tfile);
  476. m->tfile = NULL;
  477. return -1;
  478. }
  479. /* Read the forward file for a record for the connected BBS. If found,
  480.  * determine if this is the right time to forward, and return the command
  481.  * line to establish a forwarding connection. m->tfile is left pointing
  482.  * at the first message area to be forwarded.
  483.  */
  484. static char *
  485. fwdanybbs(m)
  486. struct mbx *m;
  487. {
  488. char host[80];
  489. int start = 1;
  490. if(m->tfile == NULL && (m->tfile = fopen(Forwardfile,READ_TEXT))
  491. == NULL)
  492. return NULL;
  493. while(fgets(m->line,MBXLINE,m->tfile) != NULL) {
  494. if(*m->line == 'n')
  495. continue;
  496. /* lines starting with '-' separate the forwarding records */
  497. if(*m->line == '-') {
  498. start = 1;
  499. continue;
  500. }
  501. if(start) {
  502. start = 0;
  503. /* get the name of this forwarding record */
  504. findident(m->line,1,host);
  505. strcpy(m->name,host);
  506. if(!timeok(m->line))
  507. continue; /* too late or too early */
  508. /* get the connect command line */
  509. fgets(m->line,MBXLINE,m->tfile);
  510. return strdup(m->line);
  511. }
  512. }
  513. fclose(m->tfile);
  514. m->tfile = NULL;
  515. return NULL;
  516. }
  517. /* get any groups of four digits that specify the begin and ending hours of
  518.  * forwarding. Returns 1 if forwarding may take place.
  519.  */
  520. static int
  521. timeok(line)
  522. char *line;
  523. {
  524. char hours[80], *now;
  525. long t;
  526. int t1, t2, pos = 2;
  527. findident(line,pos++,hours);
  528. if(*hours == '')
  529. return 1; /* no digits default to 0023, ie. anytime */
  530. time(&t);
  531. now = ctime(&t) + 11;
  532. *(now + 2) = '';
  533. while(*hours != '') {
  534. t1 = (*hours - '0') * 10 + (*(hours+1) - '0');
  535. t2 = (*(hours+2) - '0') * 10 + (*(hours+3) - '0');
  536. if(atoi(now) >= t1 && atoi(now) <= t2)
  537. return 1; /* right in time */
  538. findident(line,pos++,hours); /* get next group if any */
  539. }
  540. return 0; /* too early or too late */
  541. }
  542. int
  543. dombtimer(argc,argv,p)
  544. int argc;
  545. char *argv[];
  546. void *p;
  547. {
  548. if(argc < 2){
  549. printf("Forwarding timer: %lu/%lun",
  550. read_timer(&fwdtimer)/1000L,
  551. dur_timer(&fwdtimer)/1000L);
  552. return 0;
  553. }
  554. fwdtimer.func = (void (*)())fwdtick;/* what to call on timeout */
  555. fwdtimer.arg = NULL; /* dummy value */
  556. set_timer(&fwdtimer,atol(argv[1])*1000L); /* set timer duration */
  557. start_timer(&fwdtimer); /* and fire it up */
  558. return 0;
  559. }
  560. int
  561. dombkick(argc,argv,p)
  562. int argc;
  563. char *argv[];
  564. void *p;
  565. {
  566. fwdtick(NULL);
  567. return 0;
  568. }
  569. /* called when the forward timer expires or explicitly by dombkick() */
  570. static void
  571. fwdtick(v)
  572. void *v;
  573. {
  574. char *cc, *cp;
  575. struct mbx *m;
  576. int i, bulletin, skip = 0;
  577. /* restart the timer */
  578. start_timer(&fwdtimer);
  579. if((m = newmbx()) == NULL)
  580. return;
  581. m->user = stdout;
  582. m->state = MBX_TRYING;
  583. while((cc = fwdanybbs(m)) != NULL) {
  584. if(isconnbbs(m)) /* already connected to this BBS, skip it */
  585. skip = 1;
  586. while(fgets(m->line,MBXLINE,m->tfile) != NULL) {
  587. if(*m->line == '-') { /* end of record reached */
  588. skip = 0;
  589. break;
  590. }
  591. if((cp = strchr(m->line,' ')) != NULL)
  592. *cp = '';
  593. if((cp = strchr(m->line,'t')) != NULL)
  594. *cp = '';
  595. if(skip || *m->line == '' || *m->line == '.')
  596. continue;
  597. rip(m->line);
  598. changearea(m,m->line);
  599. bulletin = isarea(m->line); /* public area */
  600. /* check if there are any messages in this area
  601.  * that need to be forwarded.
  602.  */
  603. for(i=1; i<=m->nmsgs; i++)
  604. if(makecl(m, i, NULL, NULL, NULL,
  605.    bulletin) == 0) {
  606. newproc("Mbox forwarding", 2048,
  607. startfwd, 0, (void *)cc,
  608. (void *)strdup(m->name),0);
  609. skip = 1;
  610. cc = NULL;
  611. break;
  612. }
  613. }
  614. free(cc);
  615. }
  616. exitbbs(m);
  617. }
  618. /* returns 1 if m->name matches the name of another connected mailbox. */
  619. static int
  620. isconnbbs(m)
  621. struct mbx *m;
  622. {
  623. int i;
  624. for(i = 0; i < NUMMBX; ++i)
  625. if(Mbox[i] != NULL && Mbox[i] != m &&
  626. stricmp(m->name,Mbox[i]->name) == 0)
  627. return 1;
  628. return 0;
  629. }
  630. /* possible commands on the command line in the forwarding file */
  631. static struct cmds cfwdcmds[] = {
  632. "tcp", openconn, 0, 0, NULL,
  633. "telnet", openconn, 0, 0, NULL,
  634. #ifdef AX25
  635. "ax25", openconn, 0, 0, NULL,
  636. "connect", openconn, 0, 0, NULL,
  637. #endif
  638. #ifdef NETROM
  639. "netrom", openconn, 0, 0, NULL,
  640. #endif
  641. NULL
  642. };
  643. /* this function is called whenever the forwarding timer expires */
  644. static void
  645. startfwd(a,v1,v2)
  646. int a;
  647. void *v1, *v2;
  648. {
  649. struct mbx *m;
  650. char *cc;
  651. cc = (char *) v1;
  652. if((m = newmbx()) == NULL) {
  653. free(cc);
  654. free(v2);
  655. return;
  656. }
  657. strcpy(m->name,(char *)v2);
  658. free(v2);
  659. m->state = MBX_TRYING;
  660. /* open the connection, m->user will be the new stream */
  661. if(cmdparse(cfwdcmds,cc,(void *)m) == -1) {
  662. free(cc);
  663. exitbbs(m);
  664. return;
  665. }
  666. free(cc);
  667. m->state = MBX_FORWARD;
  668. sockowner(fileno(m->user),Curproc);
  669. /* m->user will be closed automatically when this process exits */
  670. stdin = stdout = m->user;
  671. if(fwdinit(m) == -1) {
  672. /* it is probably not the right time to forward anymore */
  673. exitbbs(m);
  674. return;
  675. }
  676. /* read the connect script. Lines starting with a dot will be sent
  677.  * to the remote BBS.
  678.  */
  679. while(fgets(m->line,MBXLINE,m->tfile) != NULL)
  680. if(*m->line == '.')
  681. fputs(m->line + 1,stdout);
  682. else
  683. break;
  684. fflush(m->user);
  685. fclose(m->tfile);
  686. m->tfile = NULL;
  687. /* read the initial output from the bbs, looking for the SID */
  688. for(;;) {
  689. if(fgets(m->line,MBXLINE,m->user) == NULL) {
  690. exitbbs(m);
  691. return;
  692. }
  693. if(ISPROMPT(m->line))
  694. break;
  695. if(*m->line == '[') { /* parse the SID */
  696. rip(m->line);
  697. mbx_parse(m);
  698. continue;
  699. }
  700. }
  701. /* Now sync the two ends as telnet password messes them up */
  702. if(socklen(fileno(m->user),0)) /* discard any remaining input */
  703. recv_mbuf(fileno(m->user),NULL,0,NULL,0);
  704. /* send our SID if the peer announced its SID */
  705. if(m->sid & MBX_SID) {
  706. puts("[NET-HMR$]");
  707. fflush(m->user);
  708. for(;;) {
  709. if(fgets(m->line,MBXLINE,m->user) == NULL) {
  710. exitbbs(m);
  711. return;
  712. }
  713. if(ISPROMPT(m->line))
  714. break;
  715. }
  716. }
  717. /* start the actual forwarding */
  718. dorevfwd(0,NULL,(void *)m);
  719. /* ask for reverse forwarding or just disconnect */
  720. if(((m->sid & MBX_SID) && puts("F>") == -1) ||
  721.    (m->sid & MBX_SID) == 0) {
  722. exitbbs(m);
  723. fclose(stdout);
  724. return;
  725. }
  726. fflush(m->user);
  727. /* parse the commands that are are received during reverse
  728.  * forwarding.
  729.  */
  730. while(fgets(m->line,MBXLINE,m->user) != NULL) {
  731. rip(m->line);
  732. if(mbx_parse(m) == 2) /* got the "*** Done" command */
  733. break;
  734. puts("F>");
  735. fflush(m->user);
  736. }
  737. exitbbs(m);
  738. fclose(stdout);
  739. }
  740. /* open a network connection based upon information in the cc line.
  741.  * m->user is set to the socket number.
  742.  */
  743. static int
  744. openconn(argc,argv,p)
  745. int argc;
  746. char *argv[];
  747. void *p;
  748. {
  749. struct mbx *m;
  750. struct sockaddr sock;
  751. uint8 *np;
  752. char alias[AXBUF];
  753. union sp sp;
  754. int len;
  755. int s;
  756. m = (struct mbx *)p;
  757. sp.sa = &sock;
  758. if(argc < 2)
  759. return -1;
  760. switch(*argv[0]) {
  761. case 't':
  762. sp.in->sin_family = AF_INET;
  763. if((sp.in->sin_addr.s_addr = resolve(argv[1])) == 0)
  764. return -1;
  765. /* get the optional port number */
  766. if(argc > 2)
  767. sp.in->sin_port = atoi(argv[2]);
  768. else
  769. sp.in->sin_port = IPPORT_TELNET;
  770. if((s = socket(AF_INET,SOCK_STREAM,0)) == -1)
  771. return -1;
  772. m->user = fdopen(s,"r+t");
  773. len = sizeof(*sp.in);
  774. break;
  775. #ifdef AX25
  776. case 'a':
  777. case 'c': /* allow 'c' for 'connect' as well */
  778. if(argc < 3)
  779. return -1;
  780. sp.ax->sax_family = AF_AX25;
  781. strncpy(sp.ax->iface,argv[1],ILEN); /* the interface name */
  782. setcall(sp.ax->ax25_addr,argv[2]); /* the remote callsign */
  783. /* no digipeaters for now, use the "ax25 route add" command */
  784. if((s = socket(AF_AX25,SOCK_STREAM,0)) == -1)
  785. return -1;
  786. m->user = fdopen(s,"r+t");
  787. len = sizeof(*sp.ax);
  788. break;
  789. #endif /* AX25 */
  790. #ifdef NETROM
  791. case 'n':
  792. sp.nr->nr_family = AF_NETROM;
  793. len = sizeof(*sp.nr);
  794. if((s = socket(AF_NETROM,SOCK_SEQPACKET,0)) == -1)
  795. return -1;
  796. m->user = fdopen(s,"r+t");
  797. memcpy(sp.nr->nr_addr.user,Nr4user,AXALEN);
  798. memcpy(sp.nr->nr_addr.node,Mycall,AXALEN);
  799. bind(s,sp.sa,len);
  800. /* See if the requested destination could be an alias, and
  801.  * use it if it is.  Otherwise assume it is an AX.25
  802.  * address.
  803.  */
  804. if (putalias(alias,argv[1],0) != -1 &&
  805. (np = find_nralias(alias)) != NULL) {
  806. memcpy(sp.nr->nr_addr.user,np,AXALEN) ;
  807. memcpy(sp.nr->nr_addr.node,np,AXALEN) ;
  808. }
  809. else { /* parse ax25 callsign */
  810. /* Only the user callsign of the remote station is never
  811.  * used by NET/ROM, but it is needed for the psocket() call.
  812.  */
  813. setcall(sp.nr->nr_addr.user,argv[1]);
  814. setcall(sp.nr->nr_addr.node,argv[1]);
  815. }
  816. break;
  817. #endif /* NETROM */
  818. default:
  819. return -1;
  820. }
  821. if(connect(fileno(m->user),sp.sa,len) == -1) {
  822. logmsg(fileno(m->user),"MBOX forward failed: %s errno %d",
  823. sockerr(fileno(m->user)),errno);
  824. fclose(m->user);
  825. return -1;
  826. }
  827. return 0;
  828. }