/* handle the details of establishing the RFCNB session with remote end */ static int RFCNB_Session_Req(struct RFCNB_Con *con, char *Called_Name, char *Calling_Name, BOOL * redirect, struct in_addr *Dest_IP, int *port) { char *sess_pkt; /* Response packet should be no more than 9 bytes, make 16 jic */ char resp[16]; int len; struct RFCNB_Pkt *pkt, res_pkt; /* We build and send the session request, then read the response */ pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Sess_Len); if (pkt == NULL) { return RFCNBE_Bad; /* Leave the error that RFCNB_Alloc_Pkt gives) */ } sess_pkt = pkt->data; /* Get pointer to packet proper */ sess_pkt[RFCNB_Pkt_Type_Offset] = RFCNB_SESSION_REQUEST; RFCNB_Put_Pkt_Len(sess_pkt, RFCNB_Pkt_Sess_Len - RFCNB_Pkt_Hdr_Len); sess_pkt[RFCNB_Pkt_N1Len_Offset] = 32; sess_pkt[RFCNB_Pkt_N2Len_Offset] = 32; RFCNB_CvtPad_Name(Called_Name, (sess_pkt + RFCNB_Pkt_Called_Offset)); RFCNB_CvtPad_Name(Calling_Name, (sess_pkt + RFCNB_Pkt_Calling_Offset)); /* Now send the packet */ #ifdef RFCNB_DEBUG fprintf(stderr, "Sending packet: "); #endif if ((len = RFCNB_Put_Pkt(con, pkt, RFCNB_Pkt_Sess_Len)) < 0) return RFCNBE_Bad; /* Should be able to write that lot ... */ #ifdef RFCNB_DEBUG fprintf(stderr, "Getting packet.\n"); #endif res_pkt.data = resp; res_pkt.len = sizeof(resp); res_pkt.next = NULL; if ((len = RFCNB_Get_Pkt(con, &res_pkt, sizeof(resp))) < 0) return RFCNBE_Bad; /* Now analyze the packet ... */ switch (RFCNB_Pkt_Type(resp)) { case RFCNB_SESSION_REJ: /* Didnt like us ... too bad */ /* Why did we get rejected ? */ switch (CVAL(resp, RFCNB_Pkt_Error_Offset)) { case 0x80: RFCNB_errno = RFCNBE_CallRejNLOCN; break; case 0x81: RFCNB_errno = RFCNBE_CallRejNLFCN; break; case 0x82: RFCNB_errno = RFCNBE_CallRejCNNP; break; case 0x83: RFCNB_errno = RFCNBE_CallRejInfRes; break; case 0x8F: RFCNB_errno = RFCNBE_CallRejUnSpec; break; default: RFCNB_errno = RFCNBE_ProtErr; break; } return (RFCNBE_Bad); break; case RFCNB_SESSION_ACK: /* Got what we wanted ... */ return (0); break; case RFCNB_SESSION_RETARGET: /* Go elsewhere */ *redirect = TRUE; /* Copy port and ip addr */ memcpy(Dest_IP, (resp + RFCNB_Pkt_IP_Offset), sizeof(struct in_addr)); *port = SVAL(resp, RFCNB_Pkt_Port_Offset); return 0; break; default: /* A protocol error */ RFCNB_errno = RFCNBE_ProtErr; return (RFCNBE_Bad); break; } }
int RFCNB_Get_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len) { int read_len, pkt_len; char hdr[RFCNB_Pkt_Hdr_Len]; /* Local space for the header */ struct RFCNB_Pkt *pkt_frag; int more, this_time, offset, frag_len, this_len; BOOL seen_keep_alive = TRUE; /* Read that header straight into the buffer */ if (len < RFCNB_Pkt_Hdr_Len) { /* What a bozo */ #ifdef RFCNB_DEBUG fprintf(stderr, "Trying to read less than a packet:"); perror(""); #endif RFCNB_errno = RFCNBE_BadParam; return (RFCNBE_Bad); } /* We discard keep alives here ... */ if (RFCNB_Timeout > 0) alarm(RFCNB_Timeout); while (seen_keep_alive) { if ((read_len = read(con->fd, hdr, sizeof(hdr))) < 0) { /* Problems */ #ifdef RFCNB_DEBUG fprintf(stderr, "Reading the packet, we got:"); perror(""); #endif if (errno == EINTR) RFCNB_errno = RFCNBE_Timeout; else RFCNB_errno = RFCNBE_BadRead; RFCNB_saved_errno = errno; return (RFCNBE_Bad); } /* Now we check out what we got */ if (read_len == 0) { /* Connection closed, send back eof? */ #ifdef RFCNB_DEBUG fprintf(stderr, "Connection closed reading\n"); #endif if (errno == EINTR) RFCNB_errno = RFCNBE_Timeout; else RFCNB_errno = RFCNBE_ConGone; RFCNB_saved_errno = errno; return (RFCNBE_Bad); } if (RFCNB_Pkt_Type(hdr) == RFCNB_SESSION_KEEP_ALIVE) { #ifdef RFCNB_DEBUG fprintf(stderr, "RFCNB KEEP ALIVE received\n"); #endif } else { seen_keep_alive = FALSE; } } /* What if we got less than or equal to a hdr size in bytes? */ if (read_len < sizeof(hdr)) { /* We got a small packet */ /* Now we need to copy the hdr portion we got into the supplied packet */ memcpy(pkt->data, hdr, read_len); /*Copy data */ #ifdef RFCNB_DEBUG RFCNB_Print_Pkt(stderr, "rcvd", pkt, read_len); #endif return (read_len); } /* Now, if we got at least a hdr size, alloc space for rest, if we need it */ pkt_len = RFCNB_Pkt_Len(hdr); #ifdef RFCNB_DEBUG fprintf(stderr, "Reading Pkt: Length = %i\n", pkt_len); #endif /* Now copy in the hdr */ memcpy(pkt->data, hdr, sizeof(hdr)); /* Get the rest of the packet ... first figure out how big our buf is? */ /* And make sure that we handle the fragments properly ... Sure should */ /* use an iovec ... */ if (len < pkt_len) /* Only get as much as we have space for */ more = len - RFCNB_Pkt_Hdr_Len; else more = pkt_len; this_time = 0; /* We read for each fragment ... */ if (pkt->len == read_len) { /* If this frag was exact size */ pkt_frag = pkt->next; /* Stick next lot in next frag */ offset = 0; /* then we start at 0 in next */ } else { pkt_frag = pkt; /* Otherwise use rest of this frag */ offset = RFCNB_Pkt_Hdr_Len; /* Otherwise skip the header */ } frag_len = pkt_frag->len; if (more <= frag_len) /* If len left to get less than frag space */ this_len = more; /* Get the rest ... */ else this_len = frag_len - offset; while (more > 0) { if ((this_time = read(con->fd, (pkt_frag->data) + offset, this_len)) <= 0) { /* Problems */ if (errno == EINTR) { RFCNB_errno = RFCNB_Timeout; } else { if (this_time < 0) RFCNB_errno = RFCNBE_BadRead; else RFCNB_errno = RFCNBE_ConGone; } RFCNB_saved_errno = errno; return (RFCNBE_Bad); } #ifdef RFCNB_DEBUG fprintf(stderr, "Frag_Len = %i, this_time = %i, this_len = %i, more = %i\n", frag_len, this_time, this_len, more); #endif read_len = read_len + this_time; /* How much have we read ... */ /* Now set up the next part */ if (pkt_frag->next == NULL) break; /* That's it here */ pkt_frag = pkt_frag->next; this_len = pkt_frag->len; offset = 0; more = more - this_time; } #ifdef RFCNB_DEBUG fprintf(stderr, "Pkt Len = %i, read_len = %i\n", pkt_len, read_len); RFCNB_Print_Pkt(stderr, "rcvd", pkt, read_len + sizeof(hdr)); #endif if (read_len < (pkt_len + sizeof(hdr))) { /* Discard the rest */ return (RFCNB_Discard_Rest(con, (pkt_len + sizeof(hdr)) - read_len)); } if (RFCNB_Timeout > 0) alarm(0); /* Reset that sucker */ return (read_len + sizeof(RFCNB_Hdr)); }