1
/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
6
* Copyright (C) Richard Sharpe 1996
11
* This program is free software; you can redistribute it and/or modify
12
* it under the terms of the GNU General Public License as published by
13
* the Free Software Foundation; either version 2 of the License, or
14
* (at your option) any later version.
16
* This program is distributed in the hope that it will be useful,
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
* GNU General Public License for more details.
21
* You should have received a copy of the GNU General Public License
22
* along with this program; if not, write to the Free Software
23
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30
int RFCNB_saved_errno = 0;
33
#include "std-includes.h"
34
#include <netinet/tcp.h>
35
#include "rfcnb-priv.h"
36
#include "rfcnb-util.h"
39
/* global data structures */
41
char *RFCNB_Error_Strings[] =
44
"RFCNBE_OK: Routine completed successfully.",
45
"RFCNBE_NoSpace: No space available for a malloc call.",
46
"RFCNBE_BadName: NetBIOS name could not be translated to IP address.",
47
"RFCNBE_BadRead: Read system call returned an error. Check errno.",
48
"RFCNBE_BadWrite: Write system call returned an error. Check errno.",
49
"RFCNBE_ProtErr: A protocol error has occurred.",
50
"RFCNBE_ConGone: Connection dropped during a read or write system call.",
51
"RFCNBE_BadHandle: Bad connection handle passed.",
52
"RFCNBE_BadSocket: Problems creating socket.",
53
"RFCNBE_ConnectFailed: Connection failed. See errno.",
54
"RFCNBE_CallRejNLOCN: Call rejected. Not listening on called name.",
55
"RFCNBE_CallRejNLFCN: Call rejected. Not listening for called name.",
56
"RFCNBE_CallRejCNNP: Call rejected. Called name not present.",
57
"RFCNBE_CallRejInfRes: Call rejected. Name present, but insufficient resources.",
58
"RFCNBE_CallRejUnSpec: Call rejected. Unspecified error.",
59
"RFCNBE_BadParam: Bad parameters passed to a routine.",
60
"RFCNBE_Timeout: IO Operation timed out ..."
64
int RFCNB_Stats[RFCNB_MAX_STATS];
66
void (*Prot_Print_Routine) () = NULL; /* Pointer to print routine */
68
/* Set up a session with a remote name. We are passed Called_Name as a
69
* string which we convert to a NetBIOS name, ie space terminated, up to
70
* 16 characters only if we need to. If Called_Address is not empty, then
71
* we use it to connect to the remote end, but put in Called_Name ... Called
72
* Address can be a DNS based name, or a TCP/IP address ...
76
RFCNB_Call(char *Called_Name, char *Calling_Name, char *Called_Address,
79
struct RFCNB_Con *con;
80
struct IN_ADDR Dest_IP;
83
struct redirect_addr *redir_addr;
84
char *Service_Address;
86
/* Now, we really should look up the port in /etc/services ... */
89
port = RFCNB_Default_Port;
91
/* Create a connection structure first */
93
if ((con = (struct RFCNB_Con *) malloc(sizeof(struct RFCNB_Con))) == NULL) { /* Error in size */
95
RFCNB_errno = RFCNBE_NoSpace;
96
RFCNB_saved_errno = errno;
100
con->fd = -0; /* no descriptor yet */
101
con->rfc_errno = 0; /* no error yet */
102
con->timeout = 0; /* no timeout */
104
con->redirect_list = NULL; /* Fix bug still in version 0.50 */
106
/* Resolve that name into an IP address */
108
Service_Address = Called_Name;
109
if (strcmp(Called_Address, "") != 0) { /* If the Called Address = "" */
110
Service_Address = Called_Address;
112
if ((errno = RFCNB_Name_To_IP(Service_Address, &Dest_IP)) < 0) { /* Error */
114
/* No need to modify RFCNB_errno as it was done by RFCNB_Name_To_IP */
119
/* Now connect to the remote end */
121
redirect = TRUE; /* Fudge this one so we go once through */
123
while (redirect) { /* Connect and get session info etc */
125
redirect = FALSE; /* Assume all OK */
127
/* Build the redirect info. First one is first addr called */
128
/* And tack it onto the list of addresses we called */
130
if ((redir_addr = (struct redirect_addr *) malloc(sizeof(struct redirect_addr))) == NULL) { /* Could not get space */
132
RFCNB_errno = RFCNBE_NoSpace;
133
RFCNB_saved_errno = errno;
137
memcpy((char *) &(redir_addr->ip_addr), (char *) &Dest_IP, sizeof(Dest_IP));
138
redir_addr->port = port;
139
redir_addr->next = NULL;
141
if (con->redirect_list == NULL) { /* Stick on head */
143
con->redirect_list = con->last_addr = redir_addr;
147
con->last_addr->next = redir_addr;
148
con->last_addr = redir_addr;
152
/* Now, make that connection */
154
if ((Client = RFCNB_IP_Connect(Dest_IP, port)) < 0) { /* Error */
156
/* No need to modify RFCNB_errno as it was done by RFCNB_IP_Connect */
163
/* Now send and handle the RFCNB session request */
164
/* If we get a redirect, we will comeback with redirect true
165
* and a new IP address in DEST_IP */
167
if ((errno = RFCNB_Session_Req(con,
170
&redirect, &Dest_IP, &port)) < 0) {
172
/* No need to modify RFCNB_errno as it was done by RFCNB_Session.. */
179
/* We have to close the connection, and then try again */
183
RFCNB_Close(con->fd); /* Close it */
192
/* We send a packet to the other end ... for the moment, we treat the
193
* data as a series of pointers to blocks of data ... we should check the
197
RFCNB_Send(struct RFCNB_Con *Con_Handle, struct RFCNB_Pkt *udata, int Length)
199
struct RFCNB_Pkt *pkt;
203
/* Plug in the header and send the data */
205
pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len);
209
RFCNB_errno = RFCNBE_NoSpace;
210
RFCNB_saved_errno = errno;
214
pkt->next = udata; /* The user data we want to send */
218
/* Following crap is for portability across multiple UNIX machines */
220
*(hdr + RFCNB_Pkt_Type_Offset) = RFCNB_SESSION_MESSAGE;
221
RFCNB_Put_Pkt_Len(hdr, Length);
225
fprintf(stderr, "Sending packet: ");
229
if ((len = RFCNB_Put_Pkt(Con_Handle, pkt, Length + RFCNB_Pkt_Hdr_Len)) < 0) {
231
/* No need to change RFCNB_errno as it was done by put_pkt ... */
233
return (RFCNBE_Bad); /* Should be able to write that lot ... */
236
/* Now we have sent that lot, let's get rid of the RFCNB Header and return */
246
/* We pick up a message from the internet ... We have to worry about
247
* non-message packets ... */
250
RFCNB_Recv(void *con_Handle, struct RFCNB_Pkt *Data, int Length)
252
struct RFCNB_Pkt *pkt;
255
if (con_Handle == NULL) {
257
RFCNB_errno = RFCNBE_BadHandle;
258
RFCNB_saved_errno = errno;
262
/* Now get a packet from below. We allocate a header first */
264
/* Plug in the header and send the data */
266
pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len);
270
RFCNB_errno = RFCNBE_NoSpace;
271
RFCNB_saved_errno = errno;
275
pkt->next = Data; /* Plug in the data portion */
277
if ((ret_len = RFCNB_Get_Pkt(con_Handle, pkt, Length + RFCNB_Pkt_Hdr_Len)) < 0) {
280
fprintf(stderr, "Bad packet return in RFCNB_Recv... \n");
286
/* We should check that we go a message and not a keep alive */
296
/* We just disconnect from the other end, as there is nothing in the RFCNB */
297
/* protocol that specifies any exchange as far as I can see */
300
RFCNB_Hangup(struct RFCNB_Con *con_Handle)
303
if (con_Handle != NULL) {
304
RFCNB_Close(con_Handle->fd); /* Could this fail? */
312
/* Set TCP_NODELAY on the socket */
315
RFCNB_Set_Sock_NoDelay(struct RFCNB_Con *con_Handle, BOOL yn)
318
return (setsockopt(con_Handle->fd, IPPROTO_TCP, TCP_NODELAY,
319
(char *) &yn, sizeof(yn)));
324
/* Listen for a connection on a port???, when */
325
/* the connection comes in, we return with the connection */
330
fprintf(stderr, "RFCNB_Listen NOT IMPLEMENTED as yet!\n");
334
/* Pick up the last error response as a string, hmmm, this routine should */
335
/* have been different ... */
338
RFCNB_Get_Error(char *buffer, int buf_len)
341
if (RFCNB_saved_errno <= 0) {
342
sprintf(buffer, "%s", RFCNB_Error_Strings[RFCNB_errno]);
344
sprintf(buffer, "%s\n\terrno:%s", RFCNB_Error_Strings[RFCNB_errno],
345
strerror(RFCNB_saved_errno));
350
/* Pick up the last error response and returns as a code */
353
RFCNB_Get_Last_Error()
356
return (RFCNB_errno);
360
/* Pick up saved errno as well */
363
RFCNB_Get_Last_Errno()
366
return (RFCNB_saved_errno);
370
/* Pick up the last error response and return in string ... */
373
RFCNB_Get_Error_Msg(int code, char *msg_buf, int len)
376
strncpy(msg_buf, RFCNB_Error_Strings[abs(code)], len);
380
/* Register a higher level protocol print routine */
383
RFCNB_Register_Print_Routine(void (*fn) ())
386
Prot_Print_Routine = fn;